added remote control feedback info
This commit is contained in:
@@ -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.
|
||||||
@@ -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;
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
1
arduino-example/README.md
Normal file
1
arduino-example/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# IRext Arduino Example
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user