添加血氧协议解析

This commit is contained in:
peng 2025-06-25 21:23:59 +08:00
parent 981a9b6b4d
commit c8aa3c46c3
4 changed files with 139 additions and 32 deletions

View File

@ -172,10 +172,22 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response) { public void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response) {
LogManager.d(TAG, "算法结果: " + response.toString()); LogManager.d(TAG, "算法结果: " + response.toString());
// 在这里处理心率结果
if (response.heartRate > 0) { // 根据类型处理不同的算法结果
LogManager.d(TAG, "心率值: " + response.heartRate); if (response.type == ASR5515Protocol.AlgoResultResponse.TYPE_HEART_RATE) {
// 处理心率结果
LogManager.d(TAG, "心率值: " + response.getHeartRate());
// LogManager.d(TAG, "信噪比: " + response.getSignalNoiseRatio());
LogManager.d(TAG, "置信度: " + response.getConfidence() + "%");
// 可以在这里更新UI或进行其他操作 // 可以在这里更新UI或进行其他操作
} else if (response.type == ASR5515Protocol.AlgoResultResponse.TYPE_SPO2) {
// 处理血氧结果
if (response.getSpo2() > 0) {
LogManager.d(TAG, "血氧值: " + response.getSpo2() + "%");
LogManager.d(TAG, "R值: " + response.getRValue());
LogManager.d(TAG, "置信度: " + response.getConfidence() + "%");
// 可以在这里更新UI或进行其他操作
}
} }
} }
}); });
@ -198,11 +210,12 @@ public class MainActivity extends AppCompatActivity {
// deviceManager.queryBtVersion(); // deviceManager.queryBtVersion();
// } // }
// }, 2000); // }, 2000);
deviceManager.stopGH3220Measure((byte) 0x02); 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((byte) 0x02); deviceManager.startGH3220Measure(ASR5515Protocol.GH3220MeasureType.SPO2);
} }
}, 1000); }, 1000);

View File

@ -88,8 +88,10 @@ public class ASR5515DeviceManager {
*/ */
public interface AlgoResultListener { public interface AlgoResultListener {
/** /**
* 接收到心率算法结果 * 接收到算法结果心率或血氧
* @param response 心率结果响应 * @param response 算法结果响应可以通过response.type判断是心率还是血氧数据
* 当type为TYPE_HEART_RATE时使用getHeartRate()和getSignalNoiseRatio()获取心率相关数据
* 当type为TYPE_SPO2时使用getSpo2()getRValue()获取血氧相关数据
*/ */
void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response); void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response);
} }

View File

@ -217,6 +217,7 @@ public class ASR5515Protocol {
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_ALGO_RESULT = 0x01FE; // 主动上报算法结果心率 [510 sn len AlgoResult]
public static final short CMD_SPO2_RESULT = 0x0200; // 主动上报算法结果血氧 [512 sn len AlgoResult]
} }
public static class Frame { public static class Frame {
@ -710,51 +711,140 @@ public class ASR5515Protocol {
return new GH3220MeasureResponse(frame.data[0], frame.data[1], frame.data[2]); return new GH3220MeasureResponse(frame.data[0], frame.data[1], frame.data[2]);
} }
// 算法结果响应类 [510 sn len AlgoResult] // 算法结果响应类 [510/512 sn len AlgoResult]
public static class AlgoResultResponse { public static class AlgoResultResponse {
public int heartRate; // 心率值 (snResult[0]) public static final int TYPE_HEART_RATE = 0; // 心率类型
public int confidence; // 置信度 (snResult[1]) public static final int TYPE_SPO2 = 1; // 血氧类型
public int signalNoiseRatio; // 信噪比 (snResult[2])
public AlgoResultResponse(int heartRate, int confidence, int signalNoiseRatio) { public int type; // 算法类型0-心率1-血氧
this.heartRate = heartRate; public int value; // 主要值心率值或血氧值
public int confidence; // 置信度
public int signalQuality; // 信号质量心率为信噪比血氧为R值
public int confidenceLevel; // 置信等级仅用于血氧范围-2到5
public AlgoResultResponse(int type, int value, int confidence, int signalQuality, int confidenceLevel) {
this.type = type;
this.value = value;
this.confidence = confidence; this.confidence = confidence;
this.signalNoiseRatio = signalNoiseRatio; this.signalQuality = signalQuality;
this.confidenceLevel = confidenceLevel;
}
// 获取心率值仅当type为TYPE_HEART_RATE时有效
public int getHeartRate() {
return type == TYPE_HEART_RATE ? value : 0;
}
// 获取信噪比仅当type为TYPE_HEART_RATE时有效
public int getSignalNoiseRatio() {
return type == TYPE_HEART_RATE ? signalQuality : 0;
}
// 获取血氧值仅当type为TYPE_SPO2时有效
public int getSpo2() {
return type == TYPE_SPO2 ? value : 0;
}
// 获取R值仅当type为TYPE_SPO2时有效
public int getRValue() {
return type == TYPE_SPO2 ? signalQuality : 0;
}
// 获取置信度
public int getConfidence() {
return confidence;
} }
@Override @Override
public String toString() { public String toString() {
return "AlgoResultResponse{" + if (type == TYPE_HEART_RATE) {
", heartRate=" + heartRate + return "AlgoResultResponse{" +
", confidence=" + confidence + "type=HeartRate" +
", signalNoiseRatio=" + signalNoiseRatio + ", heartRate=" + value +
'}'; ", confidence=" + confidence +
", signalNoiseRatio=" + signalQuality +
'}';
} else {
return "AlgoResultResponse{" +
"type=SpO2" +
", spo2=" + value +
", confidence=" + confidence +
", rValue=" + signalQuality +
", confidenceLevel=" + confidenceLevel +
'}';
}
} }
} }
// 解析算法结果响应帧 [updateFlag resultNum resultBit(2byte) heartRate(4) confidence(4) signalNoiseRatio(4)] // 解析算法结果响应帧 [updateFlag resultNum resultBit(2byte) value(4) confidence(4) signalQuality(4) confidenceLevel(4)]
public static AlgoResultResponse parseAlgoResultResponse(Frame frame) { public static AlgoResultResponse parseAlgoResultResponse(Frame frame) {
if (frame == null || frame.command != Commands.CMD_ALGO_RESULT || frame.data.length < 4) { if (frame == null || frame.data.length < 4) {
return null; return null;
} }
try { try {
// 解析心率值只取第一个字节 // 根据命令类型确定是心率还是血氧
int heartRate = frame.data[4]; int type = (frame.command == Commands.CMD_ALGO_RESULT) ?
AlgoResultResponse.TYPE_HEART_RATE : AlgoResultResponse.TYPE_SPO2;
// 解析主要值心率或血氧只取第一个字节
// int value = frame.data[4];
int value = (frame.data[7] & 0xFF) << 24 |
(frame.data[6] & 0xFF) << 16 |
(frame.data[5] & 0xFF) << 8 |
(frame.data[4] & 0xFF);
int confidence = 0; int confidence = 0;
int signalNoiseRatio = 0; int signalQuality = 0; // 信噪比或R值
int confidenceLevel = 0; // 血氧的置信等级
// 如果数据长度足够解析置信度只取第一个字节 // 如果数据长度足够解析置信度只取第一个字节
if (frame.data.length >= 8) { if (frame.data.length >= 12) {
confidence = frame.data[8]; if(type == AlgoResultResponse.TYPE_SPO2)
{
//R值
signalQuality = (frame.data[11] & 0xFF) << 24 |
(frame.data[10] & 0xFF) << 16 |
(frame.data[9] & 0xFF) << 8 |
(frame.data[8] & 0xFF);
}else{
confidence = (frame.data[11] & 0xFF) << 24 |
(frame.data[10] & 0xFF) << 16 |
(frame.data[9] & 0xFF) << 8 |
(frame.data[8] & 0xFF);
}
} }
// 如果数据长度足够解析信噪比只取第一个字节 // 如果数据长度足够解析信号质量只取第一个字节
if (frame.data.length >= 16) { if (frame.data.length >= 16) {
signalNoiseRatio = frame.data[16]; if(type == AlgoResultResponse.TYPE_SPO2)
{
//置信度
confidence = (frame.data[15] & 0xFF) << 24 |
(frame.data[14] & 0xFF) << 16 |
(frame.data[13] & 0xFF) << 8 |
(frame.data[12] & 0xFF);
}else{
signalQuality = (frame.data[15] & 0xFF) << 24 |
(frame.data[14] & 0xFF) << 16 |
(frame.data[13] & 0xFF) << 8 |
(frame.data[12] & 0xFF);
}
} }
return new AlgoResultResponse(heartRate, confidence, signalNoiseRatio);
// 如果是血氧数据且数据长度足够解析置信等级
if (type == AlgoResultResponse.TYPE_SPO2 && frame.data.length >= 20) {
confidenceLevel = (frame.data[19] & 0xFF) << 24 |
(frame.data[18] & 0xFF) << 16 |
(frame.data[17] & 0xFF) << 8 |
(frame.data[16] & 0xFF);
}
LogManager.d(TAG, "Parse algo result - type: " + (type == AlgoResultResponse.TYPE_HEART_RATE ? "HeartRate" : "SpO2") +
", value: " + value + ", confidence: " + confidence);
return new AlgoResultResponse(type, value, confidence, signalQuality, confidenceLevel);
} catch (Exception e) { } catch (Exception e) {
LogManager.e(TAG, "Parse algo result error: " + e.getMessage()); LogManager.e(TAG, "Parse algo result error: " + e.getMessage());
return null; return null;

View File

@ -113,8 +113,10 @@ public class SerialPortHelper {
*/ */
public interface AlgoResultCallback { public interface AlgoResultCallback {
/** /**
* 接收到心率算法结果 * 接收到算法结果心率或血氧
* @param response 心率结果响应 * @param response 算法结果响应可以通过response.type判断是心率还是血氧数据
* 当type为TYPE_HEART_RATE时使用getHeartRate()和getSignalNoiseRatio()获取心率相关数据
* 当type为TYPE_SPO2时使用getSpo2()getRValue()获取血氧相关数据
*/ */
void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response); void onAlgoResultReceived(ASR5515Protocol.AlgoResultResponse response);
} }
@ -549,7 +551,6 @@ public class SerialPortHelper {
if (receiveCallback != null) { if (receiveCallback != null) {
receiveCallback.onDataReceived(frame.command, frame.data); receiveCallback.onDataReceived(frame.command, frame.data);
} }
LogManager.d(TAG,"CMD TYPE:"+frame.command);
// 处理特定类型的响应 // 处理特定类型的响应
switch (frame.command) { switch (frame.command) {
case ASR5515Protocol.Commands.CMD_CHECK_DEVICE_RESP: case ASR5515Protocol.Commands.CMD_CHECK_DEVICE_RESP:
@ -650,6 +651,7 @@ public class SerialPortHelper {
break; break;
case ASR5515Protocol.Commands.CMD_ALGO_RESULT: case ASR5515Protocol.Commands.CMD_ALGO_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) {
algoResultCallback.onAlgoResultReceived(algoResultResponse); algoResultCallback.onAlgoResultReceived(algoResultResponse);