增加心率血氧响应回复,佩戴检测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();
// }
// }, 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

View File

@ -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'字符

View File

@ -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;
// 解析主要值心率或血氧只取第一个字节

View File

@ -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;