@@ -343,10 +343,10 @@ namespace HealthMonitor.Service.Biz | |||||
/// </summary> | /// </summary> | ||||
/// <param name="serialno"></param> | /// <param name="serialno"></param> | ||||
/// <param name="fhr">心率值</param> | /// <param name="fhr">心率值</param> | ||||
/// <param name="sampeTime">检测时间(时间戳)</param> | |||||
/// <param name="sampleTime">检测时间(时间戳)</param> | |||||
/// <param name="isAbnormal">0 //是否异常 0 表示正常;1表示偏高;2表示偏低</param> | /// <param name="isAbnormal">0 //是否异常 0 表示正常;1表示偏高;2表示偏低</param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public async Task<bool> SetFetalHeartRateConfig(string serialno, int fhr, string sampeTime, int isAbnormal) | |||||
public async Task<bool> SetFetalHeartRateConfig(string serialno, int fhr, string sampleTime, int isAbnormal) | |||||
{ | { | ||||
try | try | ||||
@@ -379,7 +379,7 @@ namespace HealthMonitor.Service.Biz | |||||
{ | { | ||||
imei = serialno, | imei = serialno, | ||||
heartValue = fhr, | heartValue = fhr, | ||||
sampeTime, | |||||
sampleTime, | |||||
isAbnormal | isAbnormal | ||||
}; | }; | ||||
@@ -739,6 +739,30 @@ namespace HealthMonitor.Service.Biz.db | |||||
return first; | return first; | ||||
} | } | ||||
public Task<T> GetLastAsync<T>(string serialNo) where T : class | |||||
{ | |||||
var tableName = typeof(T) | |||||
.GetCustomAttribute<STableAttribute>()? | |||||
.STableName; | |||||
// 创建表示 Timestamp 属性的表达式 | |||||
var parameter = Expression.Parameter(typeof(T), "x"); | |||||
var timestampProperty = Expression.Property(parameter, "Timestamp"); | |||||
var timestampLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(timestampProperty, typeof(object)), parameter); | |||||
// 创建表示 SerialNo 属性的表达式 | |||||
var serialNoProperty = Expression.Property(parameter, "SerialNumber"); | |||||
var serialNoConstant = Expression.Constant(serialNo); | |||||
var equalExpression = Expression.Equal(serialNoProperty, serialNoConstant); | |||||
var serialNoLambda = Expression.Lambda<Func<T, bool>>(equalExpression, parameter); | |||||
var first = _clientSqlSugar | |||||
.Queryable<T>() | |||||
.AS(tableName) | |||||
.Where(serialNoLambda) | |||||
.OrderByDescending(timestampLambda).FirstAsync(); | |||||
return first; | |||||
} | |||||
public async Task<List<T>> GetBySerialNoAsync<T>(string serialNo) where T : class | public async Task<List<T>> GetBySerialNoAsync<T>(string serialNo) where T : class | ||||
{ | { | ||||
var tableName = typeof(T) | var tableName = typeof(T) | ||||
@@ -86,7 +86,22 @@ namespace HealthMonitor.Service.Resolver | |||||
if (isFetalHeartEnable) | if (isFetalHeartEnable) | ||||
{ | { | ||||
// 高频心率采样间隔 | |||||
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]!; | |||||
// 触发高频监测的心率上限值 | |||||
var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; | |||||
// 触发高频监测的心率下限值 | |||||
var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; | |||||
//停止高频心率采样心率连续正常次数 | |||||
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; | |||||
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 | |||||
var highFreqSampleTimes = (int)watchConfig["stopHighFreqSampleCount"]!; | |||||
// 告警上限阀值 | |||||
var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; | |||||
// 告警下限阀值 | |||||
var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; | |||||
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); | var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); | ||||
if (phr.Count >= 30) | if (phr.Count >= 30) | ||||
{ | { | ||||
@@ -97,20 +112,7 @@ namespace HealthMonitor.Service.Resolver | |||||
// 如果需要,将时间差转换为秒 | // 如果需要,将时间差转换为秒 | ||||
var timeDiffInSeconds = timeDiff.TotalSeconds; | var timeDiffInSeconds = timeDiff.TotalSeconds; | ||||
// 高频心率采样间隔 | |||||
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]!; | |||||
// 触发高频监测的心率上限值 | |||||
var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; | |||||
// 触发高频监测的心率下限值 | |||||
var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; | |||||
//停止高频心率采样心率连续正常次数 | |||||
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; | |||||
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 | |||||
var highFreqSampleTimes = (int)watchConfig["stopHighFreqSampleCount"]!; | |||||
// 告警上限阀值 | |||||
var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; | |||||
// 告警下限阀值 | |||||
var lowerAlarmThreshold= (int)watchConfig["lowerAlarmThreshold"]!; | |||||
// 高频心率启动 | // 高频心率启动 | ||||
if (timeDiffInSeconds<=highFreqSampleInterval) | if (timeDiffInSeconds<=highFreqSampleInterval) | ||||
@@ -198,34 +200,108 @@ namespace HealthMonitor.Service.Resolver | |||||
} | } | ||||
#endregion | #endregion | ||||
#region 计算胎心数据 | |||||
var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(heartRate.Serialno); | |||||
if (commonPHR != null) | |||||
{ | |||||
#region 计算胎心数据 | |||||
// 上15分钟的数据 | |||||
// 获取当前时间 | |||||
DateTime nowQuarter = (DateTime)heartRate.LastUpdate!; | |||||
// 计算last_update到上一刻钟的分钟数 | |||||
int minutesToSubtract = nowQuarter.Minute % 15; | |||||
// 计算上一刻钟的时间 | |||||
DateTime previousQuarter = nowQuarter.AddMinutes(-minutesToSubtract).AddSeconds(-nowQuarter.Second).AddMilliseconds(-nowQuarter.Millisecond); | |||||
// 使用 last_update 上一刻 | |||||
var sampleTime = DateTimeUtil.ConvertToTimeStamp(previousQuarter).ToString(); | |||||
// 计算last_update到下一刻钟的分钟数 | |||||
int minutesToAdd = 15 - (nowQuarter.Minute % 15); | |||||
if (minutesToAdd == 15) | |||||
{ | |||||
minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 | |||||
} | |||||
// 计算下一刻钟的时间 | |||||
DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) | |||||
.AddSeconds(-nowQuarter.Second) | |||||
.AddMilliseconds(-nowQuarter.Millisecond); | |||||
var daysPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); | |||||
var filteredPhr = daysPhr | |||||
// 使用 last_update 下一刻 | |||||
.Where(i => i.LastUpdate <= nextQuarter && i.LastUpdate >= nextQuarter.AddMinutes(-15)) | |||||
.ToList(); | |||||
var qarterPhrValue = filteredPhr.Count == 1 | |||||
? filteredPhr.First().PregnancyHeartRate | |||||
: filteredPhr.Average(i => i.PregnancyHeartRate); | |||||
var fetalHeartRate = SafeType.SafeInt(qarterPhrValue * commonPHR?.StatModeAvgFprCoefficient!); | |||||
var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); | |||||
HisGpsFetalHeartRate gpsFetalHeartRate = new() | |||||
{ | |||||
FetalHeartRateId = Guid.NewGuid().ToString("D"), | |||||
PersonId = commonPHR!.PersonId, | |||||
Serialno = heartRate.Serialno, | |||||
HeartRate = fetalHeartRate, | |||||
SampleTime = sampleTime, | |||||
IsAbnormal = isAbnormal, | |||||
StatStartTime = filteredPhr.OrderByDescending(i => i.LastUpdate).First().LastUpdate, | |||||
StatEndTime = filteredPhr.OrderByDescending(i => i.LastUpdate).Last().LastUpdate, | |||||
CreateTime = DateTime.Now, | |||||
Method = 1, | |||||
IsDisplay = 1, | |||||
DeviceKey = commonPHR!.DeviceKey | |||||
}; | |||||
// 保存到 数据服务 MySQL 数据库 | |||||
await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false); | |||||
// 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig | |||||
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal); | |||||
#endregion | |||||
} | |||||
#endregion | |||||
#region 定时计算胎心数据触发器 {interval} 秒后 | #region 定时计算胎心数据触发器 {interval} 秒后 | ||||
//var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; | //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; | ||||
//await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, 60 * 15); | //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, 60 * 15); | ||||
#endregion | #endregion | ||||
#region 定时计算胎心数据触发器下一刻钟后 | #region 定时计算胎心数据触发器下一刻钟后 | ||||
// 获取当前时间 | |||||
DateTime nowQuarter = DateTime.Now; | |||||
//// 获取当前时间 | |||||
//DateTime nowQuarter = DateTime.Now; | |||||
// 计算下一个15分钟的刻钟 | |||||
int minutesToAdd = 15 - (nowQuarter.Minute % 15); | |||||
if (minutesToAdd == 15) | |||||
{ | |||||
minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 | |||||
} | |||||
// 计算下一刻钟的时间 | |||||
DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) | |||||
.AddSeconds(-nowQuarter.Second) | |||||
.AddMilliseconds(-nowQuarter.Millisecond); | |||||
//// 计算下一个15分钟的刻钟 | |||||
//int minutesToAdd = 15 - (nowQuarter.Minute % 15); | |||||
//if (minutesToAdd == 15) | |||||
//{ | |||||
// minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 | |||||
//} | |||||
//// 计算下一刻钟的时间 | |||||
//DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) | |||||
// .AddSeconds(-nowQuarter.Second) | |||||
// .AddMilliseconds(-nowQuarter.Millisecond); | |||||
// 计算时间差 | |||||
TimeSpan timeDifference = nextQuarter - nowQuarter; | |||||
//// 计算时间差 | |||||
//TimeSpan timeDifference = nextQuarter - nowQuarter; | |||||
var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; | |||||
await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); | |||||
//var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; | |||||
//await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); | |||||
#endregion | #endregion | ||||
#region 定时计算胎动数据触发器 0 点开始 | #region 定时计算胎动数据触发器 0 点开始 | ||||
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}"; | var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}"; | ||||
/// 计算 0 点秒数 | /// 计算 0 点秒数 | ||||
@@ -246,79 +246,79 @@ namespace HealthMonitor.WebApi | |||||
// health_monitor/schedule_push/cal_fetal_heart_rate/imei/ | // health_monitor/schedule_push/cal_fetal_heart_rate/imei/ | ||||
else if (key.Contains("health_monitor/schedule_push/cal_fetal_heart_rate/imei/")) | else if (key.Contains("health_monitor/schedule_push/cal_fetal_heart_rate/imei/")) | ||||
{ | { | ||||
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067"); | |||||
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; | |||||
if (isFetalHeartEnable) | |||||
{ | |||||
// 处理胎心计算业务,计算一般心率获取胎心系数 | |||||
var commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(imeiDel); | |||||
if (commonPHR != null) | |||||
{ | |||||
# region 计算上刻钟的胎心数据 | |||||
// 告警上限阀值 | |||||
var upperAlarmThreshold = (int)watchConfig!["upperAlarmThreshold"]!; | |||||
// 告警下限阀值 | |||||
var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; | |||||
//var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(); | |||||
// 计算胎心=孕妇心率*系数 | |||||
//var fetalHeartRate = SafeType.SafeInt(lastPhr.PregnancyHeartRate * commonPHR?.StatModeAvgFprCoefficient!); | |||||
// 上15分钟的数据 | |||||
// 获取当前时间 | |||||
DateTime now = DateTime.Now; | |||||
// 计算当前时间到上一刻钟的分钟数 | |||||
int minutesToSubtract = now.Minute % 15; | |||||
// 计算上一刻钟的时间 | |||||
DateTime previousQuarter = now.AddMinutes(-minutesToSubtract).AddSeconds(-now.Second).AddMilliseconds(-now.Millisecond); | |||||
var lastQuarterPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(imeiDel, 1); | |||||
var filteredPhr = lastQuarterPhr | |||||
.Where(i => i.LastUpdate <= previousQuarter && i.LastUpdate >= previousQuarter.AddMinutes(-15)) | |||||
.ToList(); | |||||
var lastQuarterPhrValue = filteredPhr.Count == 1 | |||||
? filteredPhr.First().PregnancyHeartRate | |||||
: filteredPhr.Average(i => i.PregnancyHeartRate); | |||||
var fetalHeartRate = SafeType.SafeInt(lastQuarterPhrValue * commonPHR?.StatModeAvgFprCoefficient!); | |||||
var sampleTime = DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString(); | |||||
var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); | |||||
HisGpsFetalHeartRate gpsFetalHeartRate = new() | |||||
{ | |||||
FetalHeartRateId = Guid.NewGuid().ToString("D"), | |||||
PersonId = commonPHR!.PersonId, | |||||
Serialno = imeiDel, | |||||
HeartRate = fetalHeartRate, | |||||
SampleTime = sampleTime, | |||||
IsAbnormal = isAbnormal, | |||||
StatStartTime = filteredPhr.OrderByDescending(i=>i.LastUpdate).First().LastUpdate, | |||||
StatEndTime = filteredPhr.OrderByDescending(i => i.LastUpdate).Last().LastUpdate, | |||||
CreateTime = DateTime.Now, | |||||
Method = 1, | |||||
IsDisplay = 1, | |||||
DeviceKey = commonPHR!.DeviceKey | |||||
}; | |||||
// 保存到 数据服务 MySQL 数据库 | |||||
await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false); | |||||
// 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig | |||||
await _serviceIotApi.SetFetalHeartRateConfig(imeiDel, fetalHeartRate, sampleTime, isAbnormal); | |||||
#endregion | |||||
#region 注册定时计算胎心数据触发器 {interval} 秒后 | |||||
//await SetIntervalTriggerAsync(key, imeiDel, 60 * 15); | |||||
#endregion | |||||
} | |||||
} | |||||
/** | |||||
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067"); | |||||
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; | |||||
if (isFetalHeartEnable) | |||||
{ | |||||
// 处理胎心计算业务,计算一般心率获取胎心系数 | |||||
var commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(imeiDel); | |||||
if (commonPHR != null) | |||||
{ | |||||
# region 计算上刻钟的胎心数据 | |||||
// 告警上限阀值 | |||||
var upperAlarmThreshold = (int)watchConfig!["upperAlarmThreshold"]!; | |||||
// 告警下限阀值 | |||||
var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; | |||||
//var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(); | |||||
// 计算胎心=孕妇心率*系数 | |||||
//var fetalHeartRate = SafeType.SafeInt(lastPhr.PregnancyHeartRate * commonPHR?.StatModeAvgFprCoefficient!); | |||||
// 上15分钟的数据 | |||||
// 获取当前时间 | |||||
DateTime now = DateTime.Now; | |||||
// 计算当前时间到上一刻钟的分钟数 | |||||
int minutesToSubtract = now.Minute % 15; | |||||
// 计算上一刻钟的时间 | |||||
DateTime previousQuarter = now.AddMinutes(-minutesToSubtract).AddSeconds(-now.Second).AddMilliseconds(-now.Millisecond); | |||||
var lastQuarterPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(imeiDel, 1); | |||||
var filteredPhr = lastQuarterPhr | |||||
.Where(i => i.LastUpdate <= previousQuarter && i.LastUpdate >= previousQuarter.AddMinutes(-15)) | |||||
.ToList(); | |||||
var lastQuarterPhrValue = filteredPhr.Count == 1 | |||||
? filteredPhr.First().PregnancyHeartRate | |||||
: filteredPhr.Average(i => i.PregnancyHeartRate); | |||||
var fetalHeartRate = SafeType.SafeInt(lastQuarterPhrValue * commonPHR?.StatModeAvgFprCoefficient!); | |||||
var sampleTime = DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString(); | |||||
var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); | |||||
HisGpsFetalHeartRate gpsFetalHeartRate = new() | |||||
{ | |||||
FetalHeartRateId = Guid.NewGuid().ToString("D"), | |||||
PersonId = commonPHR!.PersonId, | |||||
Serialno = imeiDel, | |||||
HeartRate = fetalHeartRate, | |||||
SampleTime = sampleTime, | |||||
IsAbnormal = isAbnormal, | |||||
StatStartTime = filteredPhr.OrderByDescending(i=>i.LastUpdate).First().LastUpdate, | |||||
StatEndTime = filteredPhr.OrderByDescending(i => i.LastUpdate).Last().LastUpdate, | |||||
CreateTime = DateTime.Now, | |||||
Method = 1, | |||||
IsDisplay = 1, | |||||
DeviceKey = commonPHR!.DeviceKey | |||||
}; | |||||
// 保存到 数据服务 MySQL 数据库 | |||||
await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false); | |||||
// 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig | |||||
await _serviceIotApi.SetFetalHeartRateConfig(imeiDel, fetalHeartRate, sampleTime, isAbnormal); | |||||
#endregion | |||||
#region 注册定时计算胎心数据触发器 {interval} 秒后 | |||||
//await SetIntervalTriggerAsync(key, imeiDel, 60 * 15); | |||||
#endregion | |||||
} | |||||
} | |||||
*/ | |||||
} | } | ||||
@@ -331,11 +331,11 @@ namespace HealthMonitor.WebApi | |||||
if (isFetalHeartEnable) | if (isFetalHeartEnable) | ||||
{ | { | ||||
// 检查胎心建模 | // 检查胎心建模 | ||||
var fchr = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(); | |||||
var fchr = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(imeiDel); | |||||
if (fchr != null) | if (fchr != null) | ||||
{ | { | ||||
// 获取孕妇心率数据接近最近2小时的数据 | // 获取孕妇心率数据接近最近2小时的数据 | ||||
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(imeiDel, 1); | |||||
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(imeiDel, 7); | |||||
var now = DateTime.Now; | var now = DateTime.Now; | ||||
var ago2hrs = now.AddHours(-2); | var ago2hrs = now.AddHours(-2); | ||||
var phrRange = phr.Where(i => i.LastUpdate >= ago2hrs) | var phrRange = phr.Where(i => i.LastUpdate >= ago2hrs) | ||||