added remote control feedback info

This commit is contained in:
strawmanbobi
2026-01-29 10:29:35 +08:00
parent 085e1b0787
commit 0b72adcd3a
8 changed files with 125 additions and 26 deletions

View File

@@ -1,5 +1,52 @@
# irext-example-android # IRext Android APP Example
IR decode example for Android application
Please refer to the usage documents in /decodesdk This project shows how can you develop an Android APP remote controller quickly.
The key components of the Android remote example includes:
## The Cloud-SDK
The Cloud SDK calls the Rest API provided by the IRext index service to complete the APP login and
help use indexing targeted remote controller from category to remote index.
To import the Android Cloud SDK, add following line to the build.gradle for the APP
```
implementation 'net.irext.webapi:irext-androidapi:1.5.2
```
And then add the meta-data in your AndroidManifest.xml to make the Cloud SDK login to the indexing server for the access token
```xml
<meta-data
android:name="irext_app_key"
android:value="c49c3bd5ff6b3efb67d8af2c" />
<meta-data
android:name="irext_app_secret"
android:value="194f9cb578c458ace2284f16" />
```
Follow the examples of calling `mApp.mWeAPIs` in corresponding UI flows in order to find the targeted remote index, download the remote control binary file.
## Use Mobile Phone as Remote Control
After the remote index binary code is downloaded, you can see the remote control panel,
by pressing control buttons, the binary code would be decoded into IR timing series. If you have an Android phone with IR transmitter,
you can send the 38KHz infra-red waves directly to control the home appliances.
As a reference, you need to integrate the IR decode library, see the shared libraries in jniLibs directory into your project.
By calling API provided by the decode library in order to open and decode remote control binary files into infra-red timing series:
```java
```
## Working with Arduino Remote Control <img src='app/src/main/res/mipmap-xxhdpi/button_link.png' style='padding-top: 12px; height: 32px; width: 20px;'>
There is another example project <a href='https://opensource.irext.net/irext/examples/-/tree/master/arduino-example'>arduino-example</a> which can be co-worked with this
Android APP remote controller.
Well by connecting to the Arduino controller with IP address in the same LAN, the Android APP can send the downloaded remote control binary to it,
and then pass the remote control command by pressing buttons accordingly. The Arduino remote controller would decode the IR time series instead and send the
38KHz infra-red carrier waves to home appliances.

View File

@@ -15,6 +15,9 @@ import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.Socket; import java.net.Socket;
import java.util.Base64; import java.util.Base64;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Filename: ArduinoRemote.java * Filename: ArduinoRemote.java
@@ -44,6 +47,12 @@ public class ArduinoRemote extends Remote {
public static final String A_REQUEST_CTRL = "a_control"; public static final String A_REQUEST_CTRL = "a_control";
public static final String E_RESPONSE_CTRL = "e_control"; public static final String E_RESPONSE_CTRL = "e_control";
public static final String E_INDICATION_SUCCESS = "e_success";
public static final String E_INDICATION_FAILED = "e_failed";
private static final int CONTROL_COMMAND_TIMEOUT = 5;
private Socket emitterConn = null; private Socket emitterConn = null;
private int connectionStatus = EMITTER_DISCONNECTED; private int connectionStatus = EMITTER_DISCONNECTED;
private IRSocketEmitterCallback callback; private IRSocketEmitterCallback callback;
@@ -98,7 +107,7 @@ public class ArduinoRemote extends Remote {
connectionStatus = EMITTER_CONNECTED; connectionStatus = EMITTER_CONNECTED;
onConnected(); onConnected();
BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream()));
String response; String response;
while ((response = in.readLine()) != null) { while ((response = in.readLine()) != null) {
@@ -167,18 +176,14 @@ public class ArduinoRemote extends Remote {
} }
public void sendControlToEmitter(String command) { public void sendControlToEmitter(String command) {
String commandStr = A_REQUEST_CTRL + "," + command.length() + "," + command; String commandStr = A_REQUEST_CTRL + "," + command.length() + "," + command;
Log.d(TAG, "sending command in base64: " + commandStr); Log.d(TAG, "sending command in base64: " + commandStr);
new Thread(() -> { try {
try { PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true); out.println(commandStr);
out.println(commandStr); } catch (IOException e) {
} catch (IOException e) { Log.e(TAG, "Error sending control data: " + e.getMessage());
Log.e(TAG, "Error sending control data: " + e.getMessage()); }
}
}).start();
} }
public void sendDecodedToEmitter(String binContent) { public void sendDecodedToEmitter(String binContent) {
@@ -200,20 +205,23 @@ public class ArduinoRemote extends Remote {
} }
private void onResponse(String response) { private void onResponse(String response) {
Log.d(TAG, "the emitter is response: " + response);
if (response.startsWith(ArduinoRemote.E_RESPONSE_HELLO)) { if (response.startsWith(ArduinoRemote.E_RESPONSE_HELLO)) {
Log.d(TAG, "received e_hello"); Log.d(TAG, "received e_hello");
} else if (response.startsWith(ArduinoRemote.E_RESPONSE_BIN)) { } else if (response.startsWith(ArduinoRemote.E_RESPONSE_BIN)) {
Log.d(TAG, "received e_bin"); Log.d(TAG, "received e_bin");
} else if (response.startsWith(ArduinoRemote.E_RESPONSE_CTRL)) { } else if (response.startsWith(ArduinoRemote.E_RESPONSE_CTRL)) {
connectionStatus = EMITTER_WORKING; connectionStatus = EMITTER_WORKING;
} else if (response.startsWith(ArduinoRemote.E_INDICATION_SUCCESS) ||
response.startsWith(ArduinoRemote.E_INDICATION_FAILED)) {
Log.d(TAG, "received control indication : " + response);
} else { } else {
Log.e(TAG, "unexpected response : " + response); Log.e(TAG, "unexpected response : " + response);
} }
callback.onResponse(response); callback.onResponse(response);
} }
public int irControl(int category, int subCategory, int keyCode) {
public void irControl(int category, int subCategory, int keyCode) {
Log.d(TAG, "irControl, category = " + category + ", subCategory = " + subCategory + ", keyCode = " + keyCode); Log.d(TAG, "irControl, category = " + category + ", subCategory = " + subCategory + ", keyCode = " + keyCode);
@@ -223,8 +231,16 @@ public class ArduinoRemote extends Remote {
ArduinoControlCommand command = new ArduinoControlCommand(inputKeyCode, acStatus); ArduinoControlCommand command = new ArduinoControlCommand(inputKeyCode, acStatus);
String controlCommand = command.toString(); String controlCommand = command.toString();
sendControlToEmitter(controlCommand);
new Thread(() -> {
try {
sendControlToEmitter(controlCommand);
} catch (Exception e) {
callback.onResponse(E_INDICATION_FAILED);
}
}).start();
return 0;
} }
private static class ArduinoControlCommand extends ControlCommand { private static class ArduinoControlCommand extends ControlCommand {

View File

@@ -28,7 +28,7 @@ public class PhoneRemote extends Remote {
public PhoneRemote(Context context) { public PhoneRemote(Context context) {
mContext = context; mContext = context;
mIRDecode = new IRDecode(); mIRDecode = IRDecode.getInstance();
} }
public static PhoneRemote getInstance(Context context) { public static PhoneRemote getInstance(Context context) {
@@ -38,6 +38,10 @@ public class PhoneRemote extends Remote {
return mInstance; return mInstance;
} }
public int irOpen(String remoteBinFilePath, int category, int subCategory) {
return mIRDecode.openFile(category, subCategory, remoteBinFilePath);
}
public int irControl(int category, int subCategory, int keyCode) { public int irControl(int category, int subCategory, int keyCode) {
int []decoded; int []decoded;
StringBuilder debugStr = new StringBuilder(); StringBuilder debugStr = new StringBuilder();
@@ -55,4 +59,8 @@ public class PhoneRemote extends Remote {
ControlHelper.transmitIr(mContext, decoded); ControlHelper.transmitIr(mContext, decoded);
return 0; return 0;
} }
public void irClose() {
mIRDecode.closeBinary();
}
} }

View File

@@ -54,8 +54,6 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
private Long mRemoteID; private Long mRemoteID;
private RemoteControl mCurrentRemoteControl; private RemoteControl mCurrentRemoteControl;
// define the single instance of IRDecode
private IRDecode mIRDecode;
private EditText mEtEmitterIp; private EditText mEtEmitterIp;
private ImageButton mBtnConnect; private ImageButton mBtnConnect;
private View mVWConnectStatus; private View mVWConnectStatus;
@@ -67,7 +65,6 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
mIRDecode = IRDecode.getInstance();
mHandler = new MsgHandler(this); mHandler = new MsgHandler(this);
mParent = (ControlActivity)getActivity(); mParent = (ControlActivity)getActivity();
@@ -179,13 +176,13 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
mCurrentRemoteControl.getRemoteMap() + FileUtils.FILE_NAME_EXT; mCurrentRemoteControl.getRemoteMap() + FileUtils.FILE_NAME_EXT;
/* decode SDK - load binary file */ /* decode SDK - load binary file */
int ret = mIRDecode.openFile(category, mCurrentRemoteControl.getSubCategory(), binFileName); int ret = mPhoneRemote.irOpen(binFileName, category, mCurrentRemoteControl.getSubCategory());
Log.d(TAG, "binary opened : " + ret); Log.d(TAG, "binary opened : " + ret);
} }
} }
public void closeIRBinary() { public void closeIRBinary() {
mIRDecode.closeBinary(); mPhoneRemote.irClose();
} }
private void onEmitterConnected() { private void onEmitterConnected() {
@@ -221,7 +218,17 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
} }
private void processECtrl(String response) { private void processECtrl(String response) {
;
}
private void processControlResult(String response) {
mParent.runOnUiThread(() -> {
if (response.startsWith(ArduinoRemote.E_INDICATION_SUCCESS)) {
ToastUtils.showToast(mParent, mParent.getString(R.string.decode_and_send_success), null);
} else {
ToastUtils.showToast(mParent, mParent.getString(R.string.decode_and_send_failed), null);
}
});
} }
private void onEmitterResponse(String response) { private void onEmitterResponse(String response) {
@@ -231,6 +238,9 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
processEBin(response); processEBin(response);
} else if (response.startsWith(ArduinoRemote.E_RESPONSE_CTRL)) { } else if (response.startsWith(ArduinoRemote.E_RESPONSE_CTRL)) {
processECtrl(response); processECtrl(response);
} else if (response.startsWith(ArduinoRemote.E_INDICATION_SUCCESS) ||
response.startsWith(ArduinoRemote.E_INDICATION_FAILED)) {
processControlResult(response);
} else { } else {
Log.e(TAG, "unexpected response : " + response); Log.e(TAG, "unexpected response : " + response);
} }
@@ -242,6 +252,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
vibrate(mParent); vibrate(mParent);
Remote remote = null; Remote remote = null;
int keyCode = 0; int keyCode = 0;
int result = 0;
int id = v.getId(); int id = v.getId();
if (id == R.id.iv_power) { if (id == R.id.iv_power) {
keyCode = Remote.KEY_POWER; keyCode = Remote.KEY_POWER;
@@ -270,7 +281,12 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
if (mArduinoRemote.getConnectionStatus() == ArduinoRemote.EMITTER_WORKING) { if (mArduinoRemote.getConnectionStatus() == ArduinoRemote.EMITTER_WORKING) {
mArduinoRemote.irControl(mCurrentRemoteControl.getCategoryId(), mCurrentRemoteControl.getSubCategory(), keyCode); mArduinoRemote.irControl(mCurrentRemoteControl.getCategoryId(), mCurrentRemoteControl.getSubCategory(), keyCode);
} else { } else {
mPhoneRemote.irControl(mCurrentRemoteControl.getCategoryId(), mCurrentRemoteControl.getSubCategory(), keyCode); result = mPhoneRemote.irControl(mCurrentRemoteControl.getCategoryId(), mCurrentRemoteControl.getSubCategory(), keyCode);
if (0 == result) {
ToastUtils.showToast(mParent, mParent.getString(R.string.decode_and_send_success), null);
} else {
ToastUtils.showToast(mParent, mParent.getString(R.string.decode_and_send_failed), null);
}
} }
} }

View File

@@ -45,5 +45,7 @@
<string name="status_not_connected">未连接</string> <string name="status_not_connected">未连接</string>
<string name="status_connected">已连接</string> <string name="status_connected">已连接</string>
<string name="file_could_not_open">编码文件无法打开</string> <string name="file_could_not_open">编码文件无法打开</string>
<string name="decode_and_send_success">遥控码发送成功</string>
<string name="decode_and_send_failed">遥控失败</string>
</resources> </resources>

View File

@@ -45,5 +45,7 @@
<string name="status_not_connected">Disconnected</string> <string name="status_not_connected">Disconnected</string>
<string name="status_connected">Connected</string> <string name="status_connected">Connected</string>
<string name="file_could_not_open">The IR binary file could not be opened</string> <string name="file_could_not_open">The IR binary file could not be opened</string>
<string name="decode_and_send_success">Remote control code sent</string>
<string name="decode_and_send_failed">Remote control failed</string>
</resources> </resources>

View File

@@ -0,0 +1 @@
# IRext Arduino Example

View File

@@ -48,6 +48,8 @@ auto *aControl = "a_control";
auto *eControl = "e_control"; auto *eControl = "e_control";
auto *aError = "a_error"; auto *aError = "a_error";
auto *eError = "e_error"; auto *eError = "e_error";
auto *eControlSuccess = "e_success";
auto *eControlFailed = "e_failed";
int status = WL_IDLE_STATUS; int status = WL_IDLE_STATUS;
unsigned long lastStatusCheck = 0; unsigned long lastStatusCheck = 0;
@@ -172,7 +174,12 @@ void onCommand(WiFiClient *client, const String *command) {
#endif #endif
} else if (command->startsWith(aControl)) { } else if (command->startsWith(aControl)) {
serialPrint(LOG_DEBUG, "Received control command"); serialPrint(LOG_DEBUG, "Received control command");
remoteControl(command->c_str()); if (0 == remoteControl(command->c_str())) {
serialPrint(LOG_INFO, "Remote control successfully");
sendToClient(client, eControlSuccess);
} else {
sendToClient(client, eControlFailed);
}
} else if (command->startsWith(aError)) { } else if (command->startsWith(aError)) {
serialPrint(LOG_DEBUG, "Received error command"); serialPrint(LOG_DEBUG, "Received error command");
onError(client); onError(client);