This commit is contained in:
tanglong 2026-02-28 11:42:01 +08:00
parent fbbc82d081
commit aa2d4b8c22
28 changed files with 59 additions and 50 deletions

View File

@ -1,6 +0,0 @@
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Dto.ResponseMsg 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.MemoryCaches.MemoryCacheSetup 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Middlewares.SystemExceptionApplicationBuilderExtensions 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Utils.Util 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 正在跳过 method System.Int32 YD_AllHeartRates.Commons.Utils.Util.GetRank(!!0 score),method System.Int32 YD_AllHeartRates.Commons.Utils.Util.GetRank(!!0 score) unstubbable: 无法同时指定类约束和 "class" 或 "struct" 约束
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 正在跳过 method System.String YD_AllHeartRates.Commons.Utils.Util.GetRankStr(!!0 score),method System.String YD_AllHeartRates.Commons.Utils.Util.GetRankStr(!!0 score) unstubbable: 无法同时指定类约束和 "class" 或 "struct" 约束

View File

@ -186,29 +186,26 @@ namespace YD_AllHeartRates.Api.Mqtt
RedisHelper.SAdd($"school:{student.SchoolCode}:students", student.StudentNo);
}
else if (ble.bs_name.Contains("YD"))
if (ble.bs_name.Contains("YD") && FindYDPayload(data, data.Length, out int payloadStart, out int payloadLength))
{
if (!studentHMap.TryGetValue(ble.bs_name, out var student)) continue;
if (!studentHMap.TryGetValue(ble.bs_name, out var student))
return;
// 寻找有效载荷开头 ffff0170
int ydIndex = IndexOfSequence(data, new byte[] { 0xFF, 0xFF, 0x01, 0x70 });
if (ydIndex < 0 || data.Length < ydIndex + 17) continue;
if (payloadLength < 17) return; // payload 不够长,丢弃
int battery = data[ydIndex + 2];
int heartRate = data[ydIndex + 3];
int calorie = data[ydIndex + 4];
int hrv = data[ydIndex + 5];
int statusFlag = data[ydIndex + 6];
ushort vendorId = (ushort)(data[payloadStart] | (data[payloadStart + 1] << 8));
int battery = data[payloadStart + 2];
int heartRate = data[payloadStart + 3];
int calorie = data[payloadStart + 4];
int hrv = data[payloadStart + 5];
int statusFlag = data[payloadStart + 6];
int step = data[payloadStart + 7] | (data[payloadStart + 8] << 8);
int intensity = data[payloadStart + 9];
string deviceNo = Encoding.ASCII.GetString(data, payloadStart + 10, 7).TrimEnd('\0');
// 步数 2 个字节,小端
int step = data[ydIndex + 7] | (data[ydIndex + 8] << 8);
Console.WriteLine($"HR={heartRate}, Battery={battery}, Step={step}, Intensity={intensity}, Device={deviceNo}");
int intensity = data[ydIndex + 9];
// 设备编号 7 个字节 ASCII
string deviceNo = Encoding.ASCII.GetString(data, ydIndex + 10, 7).Trim('\0');
if (heartRate == 0) continue;
if (heartRate <= 30 || heartRate > 220) return;
var entity = new HeartRateData
{
@ -221,19 +218,9 @@ namespace YD_AllHeartRates.Api.Mqtt
SchoolCode = student.SchoolCode ?? "",
Sex = student.Sex,
Value = heartRate,
QuantityOfElectricity = battery,
StudentNo = student.StudentNo,
StudentName = student.StudentName,
// 强度算法 —— 与 GTY 类似,用年龄计算
Strength = (int)Math.Round(((double)heartRate / (220 - student.Age)) * 100),
// 可扩展字段(如果 HeartRateData 未包含可删除)
//Calorie = calorie,
//HRV = hrv,
//Step = step,
//StatusFlag = statusFlag,
//DeviceNo = deviceNo
};
heartRateEntities.Add(entity);
@ -241,6 +228,8 @@ namespace YD_AllHeartRates.Api.Mqtt
RedisHelper.SAdd($"school:{student.SchoolCode}:students", student.StudentNo);
}
else if (ble.bs_name.Contains("RS207"))
{
//if (!deviceJMap.TryGetValue(ble.bs_name, out var studentNo)) continue;
@ -346,6 +335,32 @@ namespace YD_AllHeartRates.Api.Mqtt
//});
}
}
private bool FindYDPayload(byte[] data, int length, out int payloadStart, out int payloadLength)
{
payloadStart = 0;
payloadLength = 0;
int idx = 0;
while (idx < length - 1)
{
byte len = data[idx++]; // 段长度
if (len == 0 || idx + len > length) break; // 越界或无效
byte type = data[idx]; // 段类型
if (type == 0xFF) // 找到有效心率段
{
payloadStart = idx + 1; // payload 从 type 后开始
payloadLength = len - 1; // payload 长度 = len - 1
return true;
}
idx += len; // 跳过当前段,idx 指向下一段的长度字节
}
return false; // 没有找到
}
private async Task RunJumpSyncLoopAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)

View File

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+011f3fa3a42013578e38a444dc772a11385294fb")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+fbbc82d081e7c14f3d246fdb15f29774fb4fd41e")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
ecffa5d967cb875f0853baf5a760205cf86862807fa88bc6d1529980a4227736
f9eea44a98bf376bb2f8890ab4c3c87fa8d16664165f54018419ee516972ba74

View File

@ -49,7 +49,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
"SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net6.0": {
@ -143,7 +143,7 @@
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.101\\RuntimeIdentifierGraph.json"
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json"
}
}
},
@ -188,7 +188,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
"SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net6.0": {
@ -235,7 +235,7 @@
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.101\\RuntimeIdentifierGraph.json"
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json"
}
}
}

View File

@ -7246,7 +7246,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
"SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net6.0": {
@ -7340,7 +7340,7 @@
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.101\\RuntimeIdentifierGraph.json"
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json"
}
}
}

View File

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "INeCvY02y7M=",
"dgSpecHash": "EFwpte+qrlo=",
"success": true,
"projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api.csproj",
"expectedPackageFiles": [

View File

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+011f3fa3a42013578e38a444dc772a11385294fb")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+fbbc82d081e7c14f3d246fdb15f29774fb4fd41e")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
9f65588d9b03ce7a818fcd204c4449109376bfc3f4de79f74a9fc3bf306fd9f5
2aabbaeac0feb6959ed77d1ee78aac4457b81ca7a062abeb053bdd27a5188c3b

View File

@ -45,7 +45,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
"SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net6.0": {
@ -92,7 +92,7 @@
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.101\\RuntimeIdentifierGraph.json"
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json"
}
}
}

View File

@ -1007,7 +1007,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
"SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net6.0": {
@ -1054,7 +1054,7 @@
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.101\\RuntimeIdentifierGraph.json"
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json"
}
}
}

View File

@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "ooOpzCmP9kE=",
"dgSpecHash": "l9MQglnqMP4=",
"success": true,
"projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj",
"expectedPackageFiles": [