diff --git a/app/src/main/java/com/ismart/ib86/app/MainActivity.java b/app/src/main/java/com/ismart/ib86/app/MainActivity.java index 2983973..c24b61d 100644 --- a/app/src/main/java/com/ismart/ib86/app/MainActivity.java +++ b/app/src/main/java/com/ismart/ib86/app/MainActivity.java @@ -262,16 +262,20 @@ public class MainActivity extends AppCompatActivity { // deviceManager.queryBtVersion(); // } // }, 2000); - deviceManager.stopGH3220Measure(ASR5515Protocol.GH3220MeasureType.HR); - deviceManager.stopGH3220Measure(ASR5515Protocol.GH3220MeasureType.SPO2); + +// deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.ADT); + deviceManager.stopGH3220Measure(ASR5515Protocol.GH3220MeasureType.LEAD); + deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.ADT); +// deviceManager.stopGH3220Measure(ASR5515Protocol.GH3220MeasureType.HR); +// deviceManager.stopGH3220Measure(ASR5515Protocol.GH3220MeasureType.SPO2); // handler.postDelayed(new Runnable() { // @Override // public void run() { -// deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.HR); +// deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.SPO2); // } // }, 1000); - - handler.postDelayed(wearDetectionRunnable, 1000); +// deviceManager.sendWearDetectionRequest(); +// handler.postDelayed(wearDetectionRunnable, 1000); } @Override diff --git a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515DeviceManager.java b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515DeviceManager.java index a7a7279..cff1caf 100644 --- a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515DeviceManager.java +++ b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515DeviceManager.java @@ -533,12 +533,11 @@ public class ASR5515DeviceManager { /** * 设置采集频率 - * @param len 长度 * @param freq 频率值 */ - public void setCollectFreq(byte len, byte freq) { + public void setCollectFreq(byte freq) { wakeupDevice(); - serialPortHelper.setCollectFreq(len, freq); + serialPortHelper.setCollectFreq(freq); } /** @@ -591,6 +590,48 @@ public class ASR5515DeviceManager { serialPortHelper.stopGH3220Measure(type); } + /** + * 发送心率接收确认 + * @param sn 序列号 + * @return true 如果发送成功 + */ + public boolean onHeartRateDataReceived(short sn) { + if (!isDeviceReady()) { + LogManager.e(TAG, "设备未就绪,无法发送心率接收确认"); + return false; + } + + try { + wakeupDevice(); + byte[] request = ASR5515Protocol.createHeartRateReceivedRequest(sn); + return safeSendData(request); + } catch (Exception e) { + LogManager.e(TAG, "发送心率接收确认失败: " + e.getMessage()); + return false; + } + } + + /** + * 发送血氧接收确认 + * @param sn 序列号 + * @return true 如果发送成功 + */ + public boolean onSpO2DataReceived(short sn) { + if (!isDeviceReady()) { + LogManager.e(TAG, "设备未就绪,无法发送血氧接收确认"); + return false; + } + + try { + wakeupDevice(); + byte[] request = ASR5515Protocol.createSpO2ReceivedRequest(sn); + return safeSendData(request); + } catch (Exception e) { + LogManager.e(TAG, "发送血氧接收确认失败: " + e.getMessage()); + return false; + } + } + /** * 唤醒设备 * 通过GPIO33唤醒蓝牙,ASR休眠时会自动发送'w'字符 diff --git a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515Protocol.java b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515Protocol.java index eb61be8..ce010b0 100644 --- a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515Protocol.java +++ b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/ASR5515Protocol.java @@ -159,26 +159,24 @@ public class ASR5515Protocol { } // 创建设备重启请求帧 - public static byte[] createRebootRequest(byte sn) { - return createFrame(Commands.CMD_DEVICE_REBOOT, new byte[]{sn, 0}); + public static byte[] createRebootRequest(short sn) { + return createFrame(Commands.CMD_DEVICE_REBOOT, sn, new byte[]{}); } // 创建时间同步请求帧 - public static byte[] createTimeSyncRequest(byte sn, byte len, int timestamp) { - byte[] data = new byte[6]; - data[0] = sn; - data[1] = len; - // 将timestamp转换为4字节数组 - data[2] = (byte) (timestamp >> 24); - data[3] = (byte) (timestamp >> 16); - data[4] = (byte) (timestamp >> 8); - data[5] = (byte) timestamp; - return createFrame(Commands.CMD_TIME_SYNC, data); + public static byte[] createTimeSyncRequest(short sn, byte len, int timestamp) { + byte[] data = new byte[4]; + // 将timestamp转换为4字节数组 + data[0] = (byte) (timestamp >> 24); + data[1] = (byte) (timestamp >> 16); + data[2] = (byte) (timestamp >> 8); + data[3] = (byte) timestamp; + return createFrame(Commands.CMD_TIME_SYNC, sn, data); } // 创建日志打印控制请求帧 - public static byte[] createLogControlRequest(byte sn, byte len, byte enable) { - return createFrame(Commands.CMD_LOG_CONTROL, new byte[]{sn, len, enable}); + public static byte[] createLogControlRequest(byte enable) { + return createFrame(Commands.CMD_LOG_CONTROL, (short) 0, new byte[]{enable}); } public static class Commands { @@ -210,35 +208,36 @@ public class ASR5515Protocol { public static final short CMD_DYNAMIC_MEASURE = 0x00CF; // 动态测量 [207 0 0] public static final short CMD_DYNAMIC_MEASURE_RESP = 0x00D0; // 动态测量响应 [208 sn 0] public static final short CMD_WEAR_DETECTION = 0x0105; // 佩戴检测查询 [261 0 0] - public static final short CMD_WEAR_DETECTION_RESP = 0x0106; // 佩戴检测响应 [262 sn len 0/1] + public static final short CMD_WEAR_DETECTION_RESP = 0x0108; // 佩戴检测响应 [264 sn len 0/1] public static final short CMD_GH3220_MEASURE_START = 0x01F5; // GH3220开启测量 [501 0 len type] public static final short CMD_GH3220_MEASURE_START_RESP = 0x01F6; // GH3220开启测量响应 [502 sn len status] public static final short CMD_GH3220_MEASURE_STOP = 0x01F7; // GH3220停止测量 [503 0 len type] public static final short CMD_GH3220_MEASURE_STOP_RESP = 0x01F8; // GH3220停止测量响应 [504 sn len status] - public static final short CMD_ALGO_RESULT = 0x01FE; // 主动上报算法结果(心率) [510 sn len AlgoResult] + public static final short CMD_HEART_RATE_RESULT = 0x01FE; // 主动上报算法结果(心率) [510 sn len AlgoResult] + public static final short CMD_HEART_RATE_RECEIVED = 0x01FF; // 心率接收确认 [511 sn 0] public static final short CMD_SPO2_RESULT = 0x0200; // 主动上报算法结果(血氧) [512 sn len AlgoResult] + public static final short CMD_SPO2_RECEIVED = 0x0201; // 血氧接收确认 [513 sn 0] } public static class Frame { public short command; // 修改为short类型以支持2字节命令 + public short sn; // 序列号,两字节(uint16_t) public byte[] data; public byte[] remainingData; // 解析后剩余的数据 - public Frame(short command, byte[] data) { + public Frame(short command, short sn, byte[] data) { this.command = command; + this.sn = sn; this.data = data; } } public static byte[] createDeviceCheckRequest() { - // 发送格式:[101 0 0] - byte[] data = new byte[2]; // 两个0 - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_CHECK_DEVICE, data); + // 发送格式:[101 0 0] + return createFrame(Commands.CMD_CHECK_DEVICE, (short) 0, new byte[]{}); } - public static byte[] createFrame(short command, byte[] data) { + public static byte[] createFrame(short command, short sn, byte[] data) { //LogManager.d(TAG, "LEN :" + data.length); int frameLength = 1 + 2 + 2 + 2 + data.length + 1; // start + command(2bytes) + sn(2bytes) + len(2bytes) + data + end ByteBuffer buffer = ByteBuffer.allocate(frameLength); @@ -246,10 +245,10 @@ public class ASR5515Protocol { buffer.put(FRAME_START); // 添加帧起始符'[' buffer.put((byte)(command & 0xFF)); // 命令字节低位 buffer.put((byte)((command >> 8) & 0xFF)); // 命令字节高位 - buffer.put((byte)0x00); // sn - buffer.put((byte)0x00); //sn - buffer.put((byte)(data.length & 0xFF)); // len - buffer.put((byte)((data.length >> 8) & 0xFF)); //len + buffer.put((byte)(sn & 0xFF)); // sn低字节 + buffer.put((byte)((sn >> 8) & 0xFF)); // sn高字节 + buffer.put((byte)(data.length & 0xFF)); // len低字节 + buffer.put((byte)((data.length >> 8) & 0xFF)); // len高字节 if(data.length > 0){ buffer.put(data); // 数据部分 } @@ -309,8 +308,8 @@ public class ASR5515Protocol { frameData = new byte[0]; } - // 创建帧对象 - Frame frame = new Frame(type, frameData); + // 创建帧对象,传递完整的short类型sn + Frame frame = new Frame(type, sn, frameData); // 如果还有剩余数据,保存到remainingData if (startIndex + totalFrameLength < data.length) { @@ -380,12 +379,12 @@ public class ASR5515Protocol { // 创建蓝牙版本请求帧 public static byte[] createBtVersionRequest() { - return createFrame(Commands.CMD_BT_VERSION, new byte[]{}); + return createFrame(Commands.CMD_BT_VERSION, (short) 0, new byte[]{}); } // 创建设备重启请求帧 public static byte[] createDeviceRestartRequest() { - return createFrame(Commands.CMD_RESTART_DEVICE, new byte[]{}); + return createFrame(Commands.CMD_RESTART_DEVICE, (short) 0, new byte[]{}); } // 解析设备重启响应帧 @@ -415,10 +414,7 @@ public class ASR5515Protocol { // 创建本地、蓝牙升级请求帧 public static byte[] createBtUpgradeRequest() { // 发送格式:[113 0 0] - byte[] data = new byte[2]; // 两个0 - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_BT_UPGRADE, data); + return createFrame(Commands.CMD_BT_UPGRADE, (short) 0, new byte[]{}); } // 解析本地、蓝牙升级响应帧 @@ -459,55 +455,35 @@ public class ASR5515Protocol { } // 创建主机状态同步请求帧 - public static byte[] createHostStatusRequest(boolean screenOn) { + public static byte[] createHostStatusRequest(byte screenOn) { // 发送格式:[121 0 len 0/1],其中0/1表示屏幕状态(灭/亮) - byte[] data = new byte[3]; - data[0] = 0; // 保留字节 - data[1] = 1; - data[2] = (byte)(screenOn ? 1 : 0); // 1表示亮屏,0表示灭屏 - return createFrame(Commands.CMD_HOST_STATUS, data); + return createFrame(Commands.CMD_HOST_STATUS, (short) 0, new byte[]{screenOn}); } // 创建boot bin检查请求帧 [125 0 0] public static byte[] createBootBinCheckRequest() { - byte[] data = new byte[2]; - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_BOOT_BIN_CHECK, data); + return createFrame(Commands.CMD_BOOT_BIN_CHECK, (short) 0, new byte[]{}); } // 创建采集频率设置请求帧 [201 0 len 32] - public static byte[] createCollectFreqSetRequest(byte len, byte freq) { - byte[] data = new byte[3]; - data[0] = 0; // 保留字节 - data[1] = len; - data[2] = freq; - return createFrame(Commands.CMD_COLLECT_FREQ_SET, data); + public static byte[] createCollectFreqSetRequest(byte freq) { + return createFrame(Commands.CMD_COLLECT_FREQ_SET, (short) 0, new byte[]{(byte) freq}); } // 创建HrBpBo自动测量请求帧 [203 0 0] public static byte[] createHrBpBoAutoMeasureRequest() { - byte[] data = new byte[2]; - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_HRBPBO_AUTO_MEASURE, data); - } + return createFrame(Commands.CMD_HRBPBO_AUTO_MEASURE, (short) 0, new byte[]{}); + } // 创建HrBpBo手动测量请求帧 [205 0 0] public static byte[] createHrBpBoManualMeasureRequest() { - byte[] data = new byte[2]; - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_HRBPBO_MANUAL_MEASURE, data); - } + return createFrame(Commands.CMD_HRBPBO_MANUAL_MEASURE, (short) 0, new byte[]{}); + } // 创建动态测量请求帧 [207 0 0] public static byte[] createDynamicMeasureRequest() { - byte[] data = new byte[2]; - data[0] = 0; - data[1] = 0; - return createFrame(Commands.CMD_DYNAMIC_MEASURE, data); - } + return createFrame(Commands.CMD_DYNAMIC_MEASURE, (short) 0, new byte[]{}); + } // 解析主机状态同步响应帧 public static class HostStatusResponse { @@ -622,7 +598,7 @@ public class ASR5515Protocol { // 创建佩戴检测查询请求帧 [261 0 0] public static byte[] createWearDetectionRequest() { - return createFrame(Commands.CMD_WEAR_DETECTION, new byte[]{}); + return createFrame(Commands.CMD_WEAR_DETECTION, (short) 0, new byte[]{}); } // 佩戴检测响应类 @@ -660,16 +636,22 @@ public class ASR5515Protocol { // 创建GH3220开启测量请求帧 [501 0 len type] public static byte[] createGH3220MeasureStartRequest(byte type) { - byte[] data = new byte[1]; - data[0] = type; // 测量类型 - return createFrame(Commands.CMD_GH3220_MEASURE_START, data); + return createFrame(Commands.CMD_GH3220_MEASURE_START, (short) 0, new byte[]{(byte)type}); } // 创建GH3220停止测量请求帧 [503 0 len type] public static byte[] createGH3220MeasureStopRequest(byte type) { - byte[] data = new byte[1]; - data[0] = type; // 测量类型 - return createFrame(Commands.CMD_GH3220_MEASURE_STOP, data); + return createFrame(Commands.CMD_GH3220_MEASURE_STOP, (short) 0, new byte[]{(byte)type}); + } + + // 创建心率接收确认请求帧 [511 sn 0] + public static byte[] createHeartRateReceivedRequest(short sn) { + return createFrame(Commands.CMD_HEART_RATE_RECEIVED, sn, new byte[]{}); + } + + // 创建血氧接收确认请求帧 [513 sn 0] + public static byte[] createSpO2ReceivedRequest(short sn) { + return createFrame(Commands.CMD_SPO2_RECEIVED, sn, new byte[]{}); } // GH3220测量响应类 @@ -783,7 +765,7 @@ public class ASR5515Protocol { try { // 根据命令类型确定是心率还是血氧 - int type = (frame.command == Commands.CMD_ALGO_RESULT) ? + int type = (frame.command == Commands.CMD_HEART_RATE_RESULT) ? AlgoResultResponse.TYPE_HEART_RATE : AlgoResultResponse.TYPE_SPO2; // 解析主要值(心率或血氧),只取第一个字节 diff --git a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/SerialPortHelper.java b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/SerialPortHelper.java index f2d9043..6733f77 100644 --- a/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/SerialPortHelper.java +++ b/app/src/main/java/com/ismart/ib86/feature/serial/SerialPort/SerialPortHelper.java @@ -211,7 +211,7 @@ public class SerialPortHelper { } public void setLogControl(boolean enable) { - byte[] data = ASR5515Protocol.createLogControlRequest((byte)0, (byte)1, (byte)(enable ? 1 : 0)); + byte[] data = ASR5515Protocol.createLogControlRequest((byte) (enable ? 1 : 0)); sendData(data, null); } @@ -233,7 +233,7 @@ public class SerialPortHelper { * @param screenOn 屏幕状态(true:亮屏,false:灭屏) */ public void syncHostStatus(boolean screenOn) { - byte[] data = ASR5515Protocol.createHostStatusRequest(screenOn); + byte[] data = ASR5515Protocol.createHostStatusRequest((byte) (screenOn ? 1 : 0)); sendData(data, null); } @@ -247,11 +247,10 @@ public class SerialPortHelper { /** * 设置采集频率 - * @param len 长度 * @param freq 频率值 */ - public void setCollectFreq(byte len, byte freq) { - byte[] data = ASR5515Protocol.createCollectFreqSetRequest(len, freq); + public void setCollectFreq(byte freq) { + byte[] data = ASR5515Protocol.createCollectFreqSetRequest(freq); sendData(data, null); } @@ -297,6 +296,24 @@ public class SerialPortHelper { sendData(data, null); } + /** + * 发送心率接收确认 + * @param sn 序列号 + * @return true 如果发送成功 + */ + public void onHeartRateDataReceived(short sn) { + byte[] data = ASR5515Protocol.createHeartRateReceivedRequest((byte)sn); + sendData(data, null); + } + /** + * 发送血氧接收确认 + * @param sn 序列号 + * @return true 如果发送成功 + */ + public void onSpO2DataReceived(short sn) { + byte[] data = ASR5515Protocol.createSpO2ReceivedRequest((byte)sn); + sendData(data, null); + } /** * 发送佩戴检测查询请求 */ @@ -648,11 +665,17 @@ public class SerialPortHelper { gh3220MeasureCallback.onGH3220MeasureStopResponse(gh3220StopResponse); } break; - - case ASR5515Protocol.Commands.CMD_ALGO_RESULT: + case ASR5515Protocol.Commands.CMD_HEART_RATE_RESULT: case ASR5515Protocol.Commands.CMD_SPO2_RESULT: ASR5515Protocol.AlgoResultResponse algoResultResponse = ASR5515Protocol.parseAlgoResultResponse(frame); if (algoResultResponse != null && algoResultCallback != null) { + // 发送接收确认 + byte[] confirmData; + if(frame.command == ASR5515Protocol.Commands.CMD_HEART_RATE_RESULT) + onHeartRateDataReceived(frame.sn); + else if(frame.command == ASR5515Protocol.Commands.CMD_SPO2_RESULT) + onSpO2DataReceived(frame.sn); + algoResultCallback.onAlgoResultReceived(algoResultResponse); } break;