updated win32 example with latest decode lib

This commit is contained in:
strawmanbobi
2026-01-10 19:47:47 +08:00
parent bf075bdec8
commit 9d25fa7145
24 changed files with 877 additions and 275 deletions

View File

@@ -3,7 +3,6 @@ package net.irext.ircontrol.ui.fragment;
import android.content.Context;
import android.graphics.Color;
import android.hardware.ConsumerIrManager;
import android.net.InetAddresses;
import android.os.*;
import android.util.Log;
import android.view.LayoutInflater;
@@ -23,15 +22,13 @@ import net.irext.ircontrol.utils.FileUtils;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.ToastUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.util.Base64;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Objects;
import net.irext.ircontrol.utils.IRSocketEmitter;
/**
* Filename: ControlFragment.java
* Revised: Date: 2017-04-22
@@ -63,24 +60,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
private static final int KEY_HOME = 9;
private static final int KEY_MENU = 10;
private static final int EMITTER_PORT = 8000;
private static final int EMITTER_DISCONNECTED = 0;
private static final int EMITTER_CONNECTED = 1;
private static final int EMITTER_AVAILABLE = 2;
private static final int EMITTER_BIN_RECEIVED = 3;
private Socket emitterConn = null;
private int emitterConnected = EMITTER_DISCONNECTED;
private static final String A_REQUEST_HELLO = "a_hello";
private static final String E_RESPONSE_HELLO = "e_hello";
private static final String A_REQUEST_BIN = "a_bin";
private static final String E_RESPONSE_BIN = "e_bin";
private static final String A_REQUEST_CTRL = "a_control";
private static final String E_RESPONSE_CTRL = "e_control";
private IRSocketEmitter mIRSocketEmitter;
private MsgHandler mHandler;
@@ -135,19 +115,35 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
mBtnConnect = view.findViewById(R.id.btn_connect_emitter);
mVWConnectStatus = view.findViewById(R.id.vw_connect_status);
// Initialize IRSocketEmitter with callback
mIRSocketEmitter = new IRSocketEmitter(new IRSocketEmitter.IRSocketEmitterCallback() {
@Override
public void onConnected() {
onEmitterConnected();
}
@Override
public void onDisconnected() {
onEmitterDisconnected();
}
@Override
public void onResponse(String response) {
onEmitterResponse(response);
}
});
mBtnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
vibrate(mParent);
String emitterIp = mEtEmitterIp.getText().toString();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (!InetAddresses.isNumericAddress(emitterIp)) {
ToastUtils.showToast(mParent, mParent.getString(R.string.input_emitter_ip_address), null);
return;
}
if (isIpAddress(emitterIp)) {
ToastUtils.showToast(mParent, mParent.getString(R.string.input_emitter_ip_address), null);
return;
}
connectToEmitter(emitterIp, String.valueOf(EMITTER_PORT));
mIRSocketEmitter.connectToEmitter(emitterIp, String.valueOf(IRSocketEmitter.EMITTER_PORT));
}
});
@@ -165,7 +161,6 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
} else {
getRemote();
}
}
private void getRemote() {
@@ -250,46 +245,38 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
/* translate key code for AC according to the mapping above */
/* ac status is useless for decoding devices other than AC, it's an optional parameter */
/* change wind dir is an optional parameter, set to 0 as default */
if (mIRSocketEmitter.getConnectionStatus() == IRSocketEmitter.EMITTER_CONNECTED) {
decodeOnBoard(inputKeyCode, acStatus, 0);
} else {
decodeInApp(inputKeyCode, acStatus, 0);
}
return mIRDecode.decodeBinary(inputKeyCode, acStatus, 0);
}
private void onEmitterConnected() {
Log.d(TAG, "the emitter is connected");
emitterConnected = EMITTER_CONNECTED;
mParent.runOnUiThread(() -> {
mBtnConnect.setImageDrawable(AppCompatResources.getDrawable(mParent, R.mipmap.button_unlink));
mVWConnectStatus.setBackgroundColor(Color.parseColor("#3FAFFF"));
});
}
private void onEmitterDisconnected() {
if (EMITTER_DISCONNECTED != emitterConnected) {
Log.d(TAG, "the emitter is disconnected");
} else {
Log.d(TAG, "the emitter is disconnected not status is not changed");
}
mParent.runOnUiThread(() -> {
if (EMITTER_DISCONNECTED != emitterConnected) {
ToastUtils.showToast(mParent, mParent.getString(R.string.connect_failed), Toast.LENGTH_SHORT);
} else {
ToastUtils.showToast(mParent, mParent.getString(R.string.connect_disconnected), Toast.LENGTH_SHORT);
}
ToastUtils.showToast(mParent, mParent.getString(R.string.connect_disconnected), Toast.LENGTH_SHORT);
mBtnConnect.setImageDrawable(AppCompatResources.getDrawable(mParent, R.mipmap.button_link));
mVWConnectStatus.setBackgroundColor(Color.parseColor("#FF7F7F"));
});
emitterConnected = EMITTER_DISCONNECTED;
}
private void processEHello(String response) {
sendHelloToEmitter();
mIRSocketEmitter.sendHelloToEmitter();
}
private void processEBin(String response) {
String binFileName = FileUtils.binDir + FileUtils.FILE_NAME_PREFIX +
mCurrentRemoteControl.getRemoteMap() + FileUtils.FILE_NAME_EXT;
byte []binContent = FileUtils.getByteArrayFromFile(binFileName);
sendBinToEmitter(binContent);
mIRSocketEmitter.sendBinToEmitter(binContent, mCurrentRemoteControl.getCategoryId(), mCurrentRemoteControl.getSubCategory());
}
private void processECtrl(String response) {
@@ -298,90 +285,17 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
private void onEmitterResponse(String response) {
Log.d(TAG, "emitter: " + response);
if (response.startsWith(E_RESPONSE_HELLO)) {
if (response.startsWith(IRSocketEmitter.E_RESPONSE_HELLO)) {
processEHello(response);
} else if (response.startsWith(E_RESPONSE_BIN)) {
} else if (response.startsWith(IRSocketEmitter.E_RESPONSE_BIN)) {
processEBin(response);
} else if (response.startsWith(E_RESPONSE_CTRL)) {
} else if (response.startsWith(IRSocketEmitter.E_RESPONSE_CTRL)) {
processECtrl(response);
} else {
Log.e(TAG, "unexpected response : " + response);
}
}
private void sendHelloToEmitter() {
new Thread(() -> {
try {
Log.d(TAG, "sending a_hello to emitter");
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
out.println(A_REQUEST_HELLO);
} catch (IOException e) {
e.getMessage();
}
}).start();
}
private void sendDecodedToEmitter(String value) {
new Thread(() -> {
try {
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
out.println(value);
} catch (IOException e) {
e.getMessage();
}
}).start();
}
private void sendBinToEmitter(byte[] binContent) {
if (null == binContent) {
Log.e(TAG, "binary bytes is null");
return;
}
int categoryId = mCurrentRemoteControl.getCategoryId();
int subCate = mCurrentRemoteControl.getSubCategory();
String binBase64 = Base64.getEncoder().encodeToString(binContent);
String binStr = A_REQUEST_BIN + "," + categoryId + "," + subCate + "," + binBase64.length() + "," + binBase64;
Log.d(TAG, "sending bin in base64: " + binStr);
new Thread(() -> {
try {
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
out.println(binStr);
} catch (IOException e) {
e.getMessage();
}
}).start();
}
private void connectToEmitter(String ipAddress, String port) {
if (EMITTER_DISCONNECTED == emitterConnected) {
if (null == ipAddress || null == port) {
return;
}
new Thread(() -> {
try {
emitterConn = new Socket(ipAddress, Integer.parseInt(port));
emitterConn.setKeepAlive(true);
onEmitterConnected();
BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream()));
String response = "";
while ((response = in.readLine()) != null) {
onEmitterResponse(response);
}
onEmitterDisconnected();
} catch (IOException ioException) {
onEmitterDisconnected();
}
}).start();
} else {
try {
emitterConnected = EMITTER_DISCONNECTED;
emitterConn.close();
} catch(IOException e) {
e.getMessage();
}
}
}
// control
@Override
public void onClick(View v) {
@@ -420,9 +334,9 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
decodedValue.append(",");
}
Log.d(TAG, "decodedValue : " + decodedValue);
if (EMITTER_AVAILABLE == emitterConnected) {
if (mIRSocketEmitter.isConnected()) {
Log.d(TAG, "emitter available, send decoded to emitter");
sendDecodedToEmitter(decodedValue.toString());
mIRSocketEmitter.sendDecodedToEmitter(decodedValue.toString());
}
// send decoded integer array to IR emitter
ConsumerIrManager irEmitter =
@@ -436,6 +350,15 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
}
}
private boolean isIpAddress(String ipAddress) {
try {
InetAddress inetAddress = InetAddress.getByName(ipAddress);
return Objects.equals(inetAddress.getHostAddress(), ipAddress);
} catch (UnknownHostException e) {
return false;
}
}
private static class MsgHandler extends Handler {
WeakReference<ControlFragment> mMainFragment;

View File

@@ -0,0 +1,167 @@
package net.irext.ircontrol.utils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Base64;
/**
* Filename: IRSocketEmitter.java
* Description: Handle socket communication with external IR emitter
*/
public class IRSocketEmitter {
private static final String TAG = IRSocketEmitter.class.getSimpleName();
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_PORT = 8000;
public static final String A_REQUEST_HELLO = "a_hello";
public static final String E_RESPONSE_HELLO = "e_hello";
public static final String A_REQUEST_BIN = "a_bin";
public static final String E_RESPONSE_BIN = "e_bin";
public static final String A_REQUEST_CTRL = "a_control";
public static final String E_RESPONSE_CTRL = "e_control";
private Socket emitterConn = null;
private int connectionStatus = EMITTER_DISCONNECTED;
private IRSocketEmitterCallback callback;
public interface IRSocketEmitterCallback {
void onConnected();
void onDisconnected();
void onResponse(String response);
}
public IRSocketEmitter(IRSocketEmitterCallback callback) {
this.callback = callback;
}
public void setCallback(IRSocketEmitterCallback callback) {
this.callback = callback;
}
public int getConnectionStatus() {
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) {
return;
}
new Thread(() -> {
try {
emitterConn = new Socket(ipAddress, Integer.parseInt(port));
emitterConn.setKeepAlive(true);
connectionStatus = EMITTER_CONNECTED;
if (callback != null) {
callback.onConnected();
}
BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream()));
String response;
while ((response = in.readLine()) != null) {
if (callback != null) {
callback.onResponse(response);
}
}
if (callback != null) {
callback.onDisconnected();
}
connectionStatus = EMITTER_DISCONNECTED;
} catch (IOException ioException) {
Log.e(TAG, "Connection error: " + ioException.getMessage());
if (callback != null) {
callback.onDisconnected();
}
connectionStatus = EMITTER_DISCONNECTED;
}
}).start();
} else {
disconnect();
}
}
public void disconnect() {
try {
if (emitterConn != null && !emitterConn.isClosed()) {
emitterConn.close();
}
connectionStatus = EMITTER_DISCONNECTED;
} catch (IOException e) {
Log.e(TAG, "Error closing connection: " + e.getMessage());
}
}
public void sendHelloToEmitter() {
new Thread(() -> {
try {
Log.d(TAG, "sending a_hello to emitter");
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
out.println(A_REQUEST_HELLO);
} catch (IOException e) {
Log.e(TAG, "Error sending hello: " + e.getMessage());
}
}).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);
new Thread(() -> {
try {
PrintWriter out = new PrintWriter(emitterConn.getOutputStream(), true);
out.println(binStr);
} catch (IOException e) {
Log.e(TAG, "Error sending binary data: " + e.getMessage());
}
}).start();
}
public void processEHello(String response) {
sendHelloToEmitter();
}
public void processEBin(String response, byte[] binContent, int categoryId, int subCate) {
sendBinToEmitter(binContent, categoryId, subCate);
}
public void processECtrl(String response) {
// Handle control response if needed
}
}

View File

@@ -33,7 +33,7 @@
<string name="ir_not_supported">该设备不支持红外发射, 请连接外部模块进行发射</string>
<string name="emitter_ip">发射端 IP</string>
<string name="default_ip">192.168.2.85</string>
<string name="default_ip">192.168.1.40</string>
<string name="connect">连接</string>
<string name="decode_on_board">在单片机上解码</string>
<string name="input_emitter_ip_address">请输入接收器的 IP 地址</string>

View File

@@ -33,7 +33,7 @@
<string name="ir_not_supported">IR emitter is not supported in this device, please try with external emitters</string>
<string name="emitter_ip">Emitter IP</string>
<string name="default_ip">192.168.2.85</string>
<string name="default_ip">192.168.1.40</string>
<string name="connect">connect</string>
<string name="decode_on_board">Decode On Board</string>
<string name="input_emitter_ip_address">Please input IP address of emitter</string>