增加心率血氧响应回复,佩戴检测ok

This commit is contained in:
peng 2025-07-08 11:18:54 +08:00
parent 3e8cefab49
commit be97ea91d8
4 changed files with 139 additions and 89 deletions

View File

@ -262,16 +262,20 @@ public class MainActivity extends AppCompatActivity {
// deviceManager.queryBtVersion(); // deviceManager.queryBtVersion();
// } // }
// }, 2000); // }, 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() { // handler.postDelayed(new Runnable() {
// @Override // @Override
// public void run() { // public void run() {
// deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.HR); // deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.SPO2);
// } // }
// }, 1000); // }, 1000);
// deviceManager.sendWearDetectionRequest();
handler.postDelayed(wearDetectionRunnable, 1000); // handler.postDelayed(wearDetectionRunnable, 1000);
} }
@Override @Override

View File

@ -533,12 +533,11 @@ public class ASR5515DeviceManager {
/** /**
* 设置采集频率 * 设置采集频率
* @param len 长度
* @param freq 频率值 * @param freq 频率值
*/ */
public void setCollectFreq(byte len, byte freq) { public void setCollectFreq(byte freq) {
wakeupDevice(); wakeupDevice();
serialPortHelper.setCollectFreq(len, freq); serialPortHelper.setCollectFreq(freq);
} }
/** /**
@ -591,6 +590,48 @@ public class ASR5515DeviceManager {
serialPortHelper.stopGH3220Measure(type); 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'字符 * 通过GPIO33唤醒蓝牙ASR休眠时会自动发送'w'字符

View File

@ -159,26 +159,24 @@ public class ASR5515Protocol {
} }
// 创建设备重启请求帧 // 创建设备重启请求帧
public static byte[] createRebootRequest(byte sn) { public static byte[] createRebootRequest(short sn) {
return createFrame(Commands.CMD_DEVICE_REBOOT, new byte[]{sn, 0}); return createFrame(Commands.CMD_DEVICE_REBOOT, sn, new byte[]{});
} }
// 创建时间同步请求帧 // 创建时间同步请求帧
public static byte[] createTimeSyncRequest(byte sn, byte len, int timestamp) { public static byte[] createTimeSyncRequest(short sn, byte len, int timestamp) {
byte[] data = new byte[6]; byte[] data = new byte[4];
data[0] = sn; // 将timestamp转换为4字节数组
data[1] = len; data[0] = (byte) (timestamp >> 24);
// 将timestamp转换为4字节数组 data[1] = (byte) (timestamp >> 16);
data[2] = (byte) (timestamp >> 24); data[2] = (byte) (timestamp >> 8);
data[3] = (byte) (timestamp >> 16); data[3] = (byte) timestamp;
data[4] = (byte) (timestamp >> 8); return createFrame(Commands.CMD_TIME_SYNC, sn, data);
data[5] = (byte) timestamp;
return createFrame(Commands.CMD_TIME_SYNC, data);
} }
// 创建日志打印控制请求帧 // 创建日志打印控制请求帧
public static byte[] createLogControlRequest(byte sn, byte len, byte enable) { public static byte[] createLogControlRequest(byte enable) {
return createFrame(Commands.CMD_LOG_CONTROL, new byte[]{sn, len, enable}); return createFrame(Commands.CMD_LOG_CONTROL, (short) 0, new byte[]{enable});
} }
public static class Commands { 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 = 0x00CF; // 动态测量 [207 0 0]
public static final short CMD_DYNAMIC_MEASURE_RESP = 0x00D0; // 动态测量响应 [208 sn 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 = 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 = 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_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 = 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_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_RESULT = 0x0200; // 主动上报算法结果血氧 [512 sn len AlgoResult]
public static final short CMD_SPO2_RECEIVED = 0x0201; // 血氧接收确认 [513 sn 0]
} }
public static class Frame { public static class Frame {
public short command; // 修改为short类型以支持2字节命令 public short command; // 修改为short类型以支持2字节命令
public short sn; // 序列号两字节(uint16_t)
public byte[] data; public byte[] data;
public byte[] remainingData; // 解析后剩余的数据 public byte[] remainingData; // 解析后剩余的数据
public Frame(short command, byte[] data) { public Frame(short command, short sn, byte[] data) {
this.command = command; this.command = command;
this.sn = sn;
this.data = data; this.data = data;
} }
} }
public static byte[] createDeviceCheckRequest() { public static byte[] createDeviceCheckRequest() {
// 发送格式[101 0 0] // 发送格式[101 0 0]
byte[] data = new byte[2]; // 两个0 return createFrame(Commands.CMD_CHECK_DEVICE, (short) 0, new byte[]{});
data[0] = 0;
data[1] = 0;
return createFrame(Commands.CMD_CHECK_DEVICE, data);
} }
public static byte[] createFrame(short command, byte[] data) { public static byte[] createFrame(short command, short sn, byte[] data) {
//LogManager.d(TAG, "LEN :" + data.length); //LogManager.d(TAG, "LEN :" + data.length);
int frameLength = 1 + 2 + 2 + 2 + data.length + 1; // start + command(2bytes) + sn(2bytes) + len(2bytes) + data + end int frameLength = 1 + 2 + 2 + 2 + data.length + 1; // start + command(2bytes) + sn(2bytes) + len(2bytes) + data + end
ByteBuffer buffer = ByteBuffer.allocate(frameLength); ByteBuffer buffer = ByteBuffer.allocate(frameLength);
@ -246,10 +245,10 @@ public class ASR5515Protocol {
buffer.put(FRAME_START); // 添加帧起始符'[' buffer.put(FRAME_START); // 添加帧起始符'['
buffer.put((byte)(command & 0xFF)); // 命令字节低位 buffer.put((byte)(command & 0xFF)); // 命令字节低位
buffer.put((byte)((command >> 8) & 0xFF)); // 命令字节高位 buffer.put((byte)((command >> 8) & 0xFF)); // 命令字节高位
buffer.put((byte)0x00); // sn buffer.put((byte)(sn & 0xFF)); // sn低字节
buffer.put((byte)0x00); //sn buffer.put((byte)((sn >> 8) & 0xFF)); // sn高字节
buffer.put((byte)(data.length & 0xFF)); // len buffer.put((byte)(data.length & 0xFF)); // len低字节
buffer.put((byte)((data.length >> 8) & 0xFF)); //len buffer.put((byte)((data.length >> 8) & 0xFF)); // len高字节
if(data.length > 0){ if(data.length > 0){
buffer.put(data); // 数据部分 buffer.put(data); // 数据部分
} }
@ -309,8 +308,8 @@ public class ASR5515Protocol {
frameData = new byte[0]; frameData = new byte[0];
} }
// 创建帧对象 // 创建帧对象传递完整的short类型sn
Frame frame = new Frame(type, frameData); Frame frame = new Frame(type, sn, frameData);
// 如果还有剩余数据保存到remainingData // 如果还有剩余数据保存到remainingData
if (startIndex + totalFrameLength < data.length) { if (startIndex + totalFrameLength < data.length) {
@ -380,12 +379,12 @@ public class ASR5515Protocol {
// 创建蓝牙版本请求帧 // 创建蓝牙版本请求帧
public static byte[] createBtVersionRequest() { 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() { 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() { public static byte[] createBtUpgradeRequest() {
// 发送格式[113 0 0] // 发送格式[113 0 0]
byte[] data = new byte[2]; // 两个0 return createFrame(Commands.CMD_BT_UPGRADE, (short) 0, new byte[]{});
data[0] = 0;
data[1] = 0;
return createFrame(Commands.CMD_BT_UPGRADE, data);
} }
// 解析本地蓝牙升级响应帧 // 解析本地蓝牙升级响应帧
@ -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表示屏幕状态/ // 发送格式[121 0 len 0/1]其中0/1表示屏幕状态/
byte[] data = new byte[3]; return createFrame(Commands.CMD_HOST_STATUS, (short) 0, new byte[]{screenOn});
data[0] = 0; // 保留字节
data[1] = 1;
data[2] = (byte)(screenOn ? 1 : 0); // 1表示亮屏0表示灭屏
return createFrame(Commands.CMD_HOST_STATUS, data);
} }
// 创建boot bin检查请求帧 [125 0 0] // 创建boot bin检查请求帧 [125 0 0]
public static byte[] createBootBinCheckRequest() { public static byte[] createBootBinCheckRequest() {
byte[] data = new byte[2]; return createFrame(Commands.CMD_BOOT_BIN_CHECK, (short) 0, new byte[]{});
data[0] = 0;
data[1] = 0;
return createFrame(Commands.CMD_BOOT_BIN_CHECK, data);
} }
// 创建采集频率设置请求帧 [201 0 len 32] // 创建采集频率设置请求帧 [201 0 len 32]
public static byte[] createCollectFreqSetRequest(byte len, byte freq) { public static byte[] createCollectFreqSetRequest(byte freq) {
byte[] data = new byte[3]; return createFrame(Commands.CMD_COLLECT_FREQ_SET, (short) 0, new byte[]{(byte) freq});
data[0] = 0; // 保留字节
data[1] = len;
data[2] = freq;
return createFrame(Commands.CMD_COLLECT_FREQ_SET, data);
} }
// 创建HrBpBo自动测量请求帧 [203 0 0] // 创建HrBpBo自动测量请求帧 [203 0 0]
public static byte[] createHrBpBoAutoMeasureRequest() { public static byte[] createHrBpBoAutoMeasureRequest() {
byte[] data = new byte[2]; return createFrame(Commands.CMD_HRBPBO_AUTO_MEASURE, (short) 0, new byte[]{});
data[0] = 0; }
data[1] = 0;
return createFrame(Commands.CMD_HRBPBO_AUTO_MEASURE, data);
}
// 创建HrBpBo手动测量请求帧 [205 0 0] // 创建HrBpBo手动测量请求帧 [205 0 0]
public static byte[] createHrBpBoManualMeasureRequest() { public static byte[] createHrBpBoManualMeasureRequest() {
byte[] data = new byte[2]; return createFrame(Commands.CMD_HRBPBO_MANUAL_MEASURE, (short) 0, new byte[]{});
data[0] = 0; }
data[1] = 0;
return createFrame(Commands.CMD_HRBPBO_MANUAL_MEASURE, data);
}
// 创建动态测量请求帧 [207 0 0] // 创建动态测量请求帧 [207 0 0]
public static byte[] createDynamicMeasureRequest() { public static byte[] createDynamicMeasureRequest() {
byte[] data = new byte[2]; return createFrame(Commands.CMD_DYNAMIC_MEASURE, (short) 0, new byte[]{});
data[0] = 0; }
data[1] = 0;
return createFrame(Commands.CMD_DYNAMIC_MEASURE, data);
}
// 解析主机状态同步响应帧 // 解析主机状态同步响应帧
public static class HostStatusResponse { public static class HostStatusResponse {
@ -622,7 +598,7 @@ public class ASR5515Protocol {
// 创建佩戴检测查询请求帧 [261 0 0] // 创建佩戴检测查询请求帧 [261 0 0]
public static byte[] createWearDetectionRequest() { 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] // 创建GH3220开启测量请求帧 [501 0 len type]
public static byte[] createGH3220MeasureStartRequest(byte type) { public static byte[] createGH3220MeasureStartRequest(byte type) {
byte[] data = new byte[1]; return createFrame(Commands.CMD_GH3220_MEASURE_START, (short) 0, new byte[]{(byte)type});
data[0] = type; // 测量类型
return createFrame(Commands.CMD_GH3220_MEASURE_START, data);
} }
// 创建GH3220停止测量请求帧 [503 0 len type] // 创建GH3220停止测量请求帧 [503 0 len type]
public static byte[] createGH3220MeasureStopRequest(byte type) { public static byte[] createGH3220MeasureStopRequest(byte type) {
byte[] data = new byte[1]; return createFrame(Commands.CMD_GH3220_MEASURE_STOP, (short) 0, new byte[]{(byte)type});
data[0] = type; // 测量类型 }
return createFrame(Commands.CMD_GH3220_MEASURE_STOP, data);
// 创建心率接收确认请求帧 [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测量响应类 // GH3220测量响应类
@ -783,7 +765,7 @@ public class ASR5515Protocol {
try { 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; AlgoResultResponse.TYPE_HEART_RATE : AlgoResultResponse.TYPE_SPO2;
// 解析主要值心率或血氧只取第一个字节 // 解析主要值心率或血氧只取第一个字节

View File

@ -211,7 +211,7 @@ public class SerialPortHelper {
} }
public void setLogControl(boolean enable) { 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); sendData(data, null);
} }
@ -233,7 +233,7 @@ public class SerialPortHelper {
* @param screenOn 屏幕状态true亮屏false灭屏 * @param screenOn 屏幕状态true亮屏false灭屏
*/ */
public void syncHostStatus(boolean screenOn) { public void syncHostStatus(boolean screenOn) {
byte[] data = ASR5515Protocol.createHostStatusRequest(screenOn); byte[] data = ASR5515Protocol.createHostStatusRequest((byte) (screenOn ? 1 : 0));
sendData(data, null); sendData(data, null);
} }
@ -247,11 +247,10 @@ public class SerialPortHelper {
/** /**
* 设置采集频率 * 设置采集频率
* @param len 长度
* @param freq 频率值 * @param freq 频率值
*/ */
public void setCollectFreq(byte len, byte freq) { public void setCollectFreq(byte freq) {
byte[] data = ASR5515Protocol.createCollectFreqSetRequest(len, freq); byte[] data = ASR5515Protocol.createCollectFreqSetRequest(freq);
sendData(data, null); sendData(data, null);
} }
@ -297,6 +296,24 @@ public class SerialPortHelper {
sendData(data, null); 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); gh3220MeasureCallback.onGH3220MeasureStopResponse(gh3220StopResponse);
} }
break; break;
case ASR5515Protocol.Commands.CMD_HEART_RATE_RESULT:
case ASR5515Protocol.Commands.CMD_ALGO_RESULT:
case ASR5515Protocol.Commands.CMD_SPO2_RESULT: case ASR5515Protocol.Commands.CMD_SPO2_RESULT:
ASR5515Protocol.AlgoResultResponse algoResultResponse = ASR5515Protocol.parseAlgoResultResponse(frame); ASR5515Protocol.AlgoResultResponse algoResultResponse = ASR5515Protocol.parseAlgoResultResponse(frame);
if (algoResultResponse != null && algoResultCallback != null) { 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); algoResultCallback.onAlgoResultReceived(algoResultResponse);
} }
break; break;