diff --git a/android-example/app/build.gradle b/android-example/app/build.gradle index cd8247c..9668410 100644 --- a/android-example/app/build.gradle +++ b/android-example/app/build.gradle @@ -45,6 +45,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.core:core:1.13.1' implementation 'com.google.android.material:material:1.13.0' + implementation 'com.google.code.gson:gson:2.13.2' implementation 'com.android.support:multidex:1.0.3' diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoControlCommand.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoControlCommand.java new file mode 100644 index 0000000..374cc8b --- /dev/null +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoControlCommand.java @@ -0,0 +1,51 @@ +package net.irext.ircontrol.controller; + +import com.google.gson.Gson; +import net.irext.decode.sdk.bean.ACStatus; +import net.irext.ircontrol.controller.base.ControlCommand; +import org.jspecify.annotations.NonNull; + +import java.util.Base64; + +/** + * Filename: ControlCommand.java + * Revised: Date: 2026-01-22 + * Revision: Revision: 1.0 + *

+ * Description: Remote command to Arduino remote + *

+ * Revision log: + * 2026-01-22: created by strawmanbobi + */ +public class ArduinoControlCommand extends ControlCommand { + + public ArduinoControlCommand(int keyCode, ACStatus acStatus) { + this.keyCode = keyCode; + this.acStatus = acStatus; + } + + public ArduinoControlCommand() { + } + + public int getKeyCode() { + return keyCode; + } + + public void setKeyCode(int keyCode) { + this.keyCode = keyCode; + } + + public ACStatus getAcStatus() { + return acStatus; + } + + public void setAcStatus(ACStatus acStatus) { + this.acStatus = acStatus; + } + + @Override + public @NonNull String toString() { + String jsonStr = new Gson().toJson(this); + return Base64.getEncoder().encodeToString(jsonStr.getBytes()); + } +} diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoRemote.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoRemote.java index d427487..0b14b91 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoRemote.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoRemote.java @@ -2,7 +2,10 @@ package net.irext.ircontrol.controller; import android.content.Context; import android.util.Log; -import net.irext.ircontrol.controller.implementable.IRemote; +import net.irext.decode.sdk.bean.ACStatus; +import net.irext.ircontrol.controller.base.IRemote; + +import static net.irext.ircontrol.controller.ArduinoSocket.*; /** * Filename: ArduinoRemote.java @@ -16,7 +19,7 @@ import net.irext.ircontrol.controller.implementable.IRemote; */ public class ArduinoRemote implements IRemote { - private static final String TAG = PhoneRemote.class.getSimpleName(); + private static final String TAG = ArduinoRemote.class.getSimpleName(); Context mContext; ArduinoSocket mArduinoSocket; @@ -28,7 +31,17 @@ public class ArduinoRemote implements IRemote { @Override public int irControl(int category, int subCategory, int keyCode) { + Log.d(TAG, "irControl, category = " + category + ", subCategory = " + subCategory + ", keyCode = " + keyCode); + + ACStatus acStatus = new ACStatus(); + + int inputKeyCode = ControlHelper.translateKeyCode(category, keyCode, acStatus); + + ArduinoControlCommand command = new ArduinoControlCommand(inputKeyCode, acStatus); + String controlCommand = command.toString(); + mArduinoSocket.sendControlToEmitter(controlCommand); + return 0; } } diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoSocket.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoSocket.java index c52c9af..a461577 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoSocket.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/ArduinoSocket.java @@ -25,8 +25,7 @@ public class ArduinoSocket { public static final int EMITTER_DISCONNECTED = 0; public static final int EMITTER_CONNECTED = 1; - public static final int EMITTER_AVAILABLE = 2; - public static final int EMITTER_BIN_RECEIVED = 3; + public static final int EMITTER_WORKING = 2; public static final int EMITTER_PORT = 8000; @@ -61,10 +60,6 @@ public class ArduinoSocket { return connectionStatus; } - public boolean isConnected() { - return connectionStatus == EMITTER_AVAILABLE; - } - public void connectToEmitter(String ipAddress, String port) { if (connectionStatus == EMITTER_DISCONNECTED) { if (ipAddress == null || port == null) { @@ -81,9 +76,7 @@ public class ArduinoSocket { BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream())); String response; while ((response = in.readLine()) != null) { - if (callback != null) { - callback.onResponse(response); - } + onResponse(response); } if (callback != null) { @@ -129,22 +122,12 @@ public class ArduinoSocket { }).start(); } - public void sendDecodedToEmitter(String value) { - new Thread(() -> { - try { - PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true); - out.println(value); - } catch (IOException e) { - Log.e(TAG, "Error sending decoded data: " + e.getMessage()); - } - }).start(); - } - public void sendBinToEmitter(byte[] binContent, int categoryId, int subCate) { if (binContent == null) { Log.e(TAG, "binary bytes is null"); return; } + String binBase64 = Base64.getEncoder().encodeToString(binContent); String binStr = A_REQUEST_BIN + "," + categoryId + "," + subCate + "," + binBase64.length() + "," + binBase64; Log.d(TAG, "sending bin in base64: " + binStr); @@ -152,23 +135,36 @@ public class ArduinoSocket { try { PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true); out.println(binStr); - } catch (IOException e) { + } catch (Exception e) { Log.e(TAG, "Error sending binary data: " + e.getMessage()); } }).start(); } - public void processEHello(String response) { - sendHelloToEmitter(); + public void sendControlToEmitter(String command) { + String commandStr = A_REQUEST_CTRL + "," + command.length() + "," + command; + Log.d(TAG, "sending command in base64: " + commandStr); + new Thread(() -> { + try { + PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true); + out.println(commandStr); + } catch (IOException e) { + Log.e(TAG, "Error sending control data: " + e.getMessage()); + } + }); } - public void processEBin(String response, byte[] binContent, int categoryId, int subCate) { - sendBinToEmitter(binContent, categoryId, subCate); + public void sendDecodedToEmitter(String binContent) { + new Thread(() -> { + try { + PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true); + out.println(binContent); + } catch (IOException e) { + Log.e(TAG, "Error sending decoded data: " + e.getMessage()); + } + }).start(); } - public void processECtrl(String response) { - // Handle control response if needed - } private void onConnected() { if (callback != null) { @@ -178,15 +174,15 @@ public class ArduinoSocket { } private void onResponse(String response) { - Log.d(TAG, "emitter: " + response); if (response.startsWith(ArduinoSocket.E_RESPONSE_HELLO)) { - processEHello(response); + ; } else if (response.startsWith(ArduinoSocket.E_RESPONSE_BIN)) { - + ; } else if (response.startsWith(ArduinoSocket.E_RESPONSE_CTRL)) { - processECtrl(response); + connectionStatus = EMITTER_WORKING; } else { Log.e(TAG, "unexpected response : " + response); } + callback.onResponse(response); } } \ No newline at end of file diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/ControlHelper.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/ControlHelper.java index 1f5f3e4..8e084d6 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/controller/ControlHelper.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/ControlHelper.java @@ -9,7 +9,7 @@ import net.irext.ircontrol.utils.ToastUtils; import java.util.Objects; -import static net.irext.ircontrol.controller.implementable.IRemote.*; +import static net.irext.ircontrol.controller.base.IRemote.*; /** * Filename: ControlHelper.java diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/PhoneRemote.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/PhoneRemote.java index a64b397..fc76ef0 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/controller/PhoneRemote.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/PhoneRemote.java @@ -4,7 +4,7 @@ import android.content.Context; import android.util.Log; import net.irext.decode.sdk.IRDecode; import net.irext.decode.sdk.bean.ACStatus; -import net.irext.ircontrol.controller.implementable.IRemote; +import net.irext.ircontrol.controller.base.IRemote; /** * Filename: PhoneRemote.java diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/base/ControlCommand.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/base/ControlCommand.java new file mode 100644 index 0000000..e143eb6 --- /dev/null +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/base/ControlCommand.java @@ -0,0 +1,22 @@ +package net.irext.ircontrol.controller.base; + +import net.irext.decode.sdk.bean.ACStatus; + +/** + * Filename: ControlCommand.java + * Revised: Date: 2026-01-22 + * Revision: Revision: 1.0 + *

+ * Description: ControlCommand base class + *

+ * Revision log: + * 2026-01-22: created by strawmanbobi + */ +public abstract class ControlCommand { + + protected int keyCode; + protected ACStatus acStatus; + + public abstract String toString(); + +} diff --git a/android-example/app/src/main/java/net/irext/ircontrol/controller/implementable/IRemote.java b/android-example/app/src/main/java/net/irext/ircontrol/controller/base/IRemote.java similarity index 93% rename from android-example/app/src/main/java/net/irext/ircontrol/controller/implementable/IRemote.java rename to android-example/app/src/main/java/net/irext/ircontrol/controller/base/IRemote.java index 3d702bc..a820535 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/controller/implementable/IRemote.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/controller/base/IRemote.java @@ -1,4 +1,4 @@ -package net.irext.ircontrol.controller.implementable; +package net.irext.ircontrol.controller.base; /** * Filename: IRemote.java diff --git a/android-example/app/src/main/java/net/irext/ircontrol/ui/fragment/ControlFragment.java b/android-example/app/src/main/java/net/irext/ircontrol/ui/fragment/ControlFragment.java index e768776..d6e4e83 100644 --- a/android-example/app/src/main/java/net/irext/ircontrol/ui/fragment/ControlFragment.java +++ b/android-example/app/src/main/java/net/irext/ircontrol/ui/fragment/ControlFragment.java @@ -17,10 +17,11 @@ import net.irext.ircontrol.bean.RemoteControl; import net.irext.ircontrol.controller.ArduinoRemote; import net.irext.ircontrol.controller.ArduinoSocket; import net.irext.ircontrol.controller.PhoneRemote; -import net.irext.ircontrol.controller.implementable.IRemote; +import net.irext.ircontrol.controller.base.IRemote; import net.irext.ircontrol.ui.activity.ControlActivity; import net.irext.ircontrol.utils.FileUtils; import net.irext.ircontrol.utils.MessageUtils; +import net.irext.ircontrol.utils.MiscUtils; import net.irext.ircontrol.utils.ToastUtils; import java.lang.ref.WeakReference; @@ -123,7 +124,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener { public void onClick(View v) { vibrate(mParent); String emitterIp = mEtEmitterIp.getText().toString(); - if (!ArduinoSocket.isValidIPv4(emitterIp)) { + if (!MiscUtils.isValidIPv4(emitterIp)) { Log.e(TAG, "IP address is invalid: " + emitterIp); ToastUtils.showToast(mParent, mParent.getString(R.string.input_emitter_ip_address), null); return; @@ -217,11 +218,10 @@ public class ControlFragment extends Fragment implements View.OnClickListener { } private void processECtrl(String response) { - + ; } private void onEmitterResponse(String response) { - Log.d(TAG, "emitter: " + response); if (response.startsWith(ArduinoSocket.E_RESPONSE_HELLO)) { processEHello(response); } else if (response.startsWith(ArduinoSocket.E_RESPONSE_BIN)) { @@ -264,7 +264,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener { keyCode = IRemote.KEY_MENU; } - if (mArduinoSocket.isConnected() && mArduinoSocket.getConnectionStatus() == ArduinoSocket.EMITTER_BIN_RECEIVED) { + if (mArduinoSocket.getConnectionStatus() == ArduinoSocket.EMITTER_WORKING) { remote = new ArduinoRemote(mParent, mArduinoSocket); } else { remote = new PhoneRemote(mParent); diff --git a/android-example/app/src/main/res/values-zh-rCN/strings.xml b/android-example/app/src/main/res/values-zh-rCN/strings.xml index 1d31e08..71208bd 100644 --- a/android-example/app/src/main/res/values-zh-rCN/strings.xml +++ b/android-example/app/src/main/res/values-zh-rCN/strings.xml @@ -33,7 +33,7 @@ 发射端 IP - 192.168.1.40 + 192.168.1.43 连接 在单片机上解码 diff --git a/android-example/app/src/main/res/values/strings.xml b/android-example/app/src/main/res/values/strings.xml index 29afde5..3e8b043 100644 --- a/android-example/app/src/main/res/values/strings.xml +++ b/android-example/app/src/main/res/values/strings.xml @@ -33,7 +33,7 @@ Emitter IP - 192.168.1.40 + 192.168.1.43 Connect Decode On Board