|
|
@@ -102,313 +102,315 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
var messageId = _messageId.Value; |
|
|
|
var heartRate = _msgData.Value!; |
|
|
|
|
|
|
|
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(heartRate.Serialno, "0067"); |
|
|
|
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; |
|
|
|
|
|
|
|
if (isFetalHeartEnable) |
|
|
|
{ |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 计算胎心胎动启动"); |
|
|
|
#region 定时下发触发器(定时建模) |
|
|
|
var key = $"health_monitor/schedule_push/pregnancy_heart_rate/imei/{heartRate.Serialno}"; |
|
|
|
var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); |
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(schedule_push)) |
|
|
|
{ |
|
|
|
// 注册首次下推 |
|
|
|
var interval = 0; |
|
|
|
// 获取当前时间 |
|
|
|
DateTime now = DateTime.Now; |
|
|
|
var rand = new Random(); |
|
|
|
var pushSec = rand.Next(59); |
|
|
|
int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10; |
|
|
|
// 计算距离下一个$interval天后的8点的时间间隔 |
|
|
|
DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 6, pushMin, pushSec).AddDays(interval); |
|
|
|
TimeSpan timeUntilNextRun = nextRunTime - now; |
|
|
|
|
|
|
|
if (timeUntilNextRun < TimeSpan.Zero) |
|
|
|
{ |
|
|
|
timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1)); |
|
|
|
nextRunTime += TimeSpan.FromDays(1); |
|
|
|
} |
|
|
|
|
|
|
|
var ttl = (long)timeUntilNextRun.TotalSeconds; |
|
|
|
var data = new |
|
|
|
{ |
|
|
|
imei = heartRate.Serialno, |
|
|
|
create_time = now.ToString("yyyy-MM-dd HH:mm:ss"), |
|
|
|
ttl, |
|
|
|
next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss") |
|
|
|
}; |
|
|
|
var result = JsonConvert.SerializeObject(data); |
|
|
|
await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false); |
|
|
|
try |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(heartRate.Serialno, "0067"); |
|
|
|
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; |
|
|
|
|
|
|
|
#endregion |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 触发定时建模"); |
|
|
|
|
|
|
|
// 高频心率采样间隔 highFreqSampleInterval = highFreqSampleInterval+5,增加5秒兼容 |
|
|
|
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! + 5; |
|
|
|
// 触发高频监测的心率上限值 |
|
|
|
var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; |
|
|
|
// 触发高频监测的心率下限值 |
|
|
|
var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; |
|
|
|
//停止高频心率采样心率连续正常次数 |
|
|
|
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; |
|
|
|
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 |
|
|
|
var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!; |
|
|
|
// 告警上限阀值 |
|
|
|
var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; |
|
|
|
// 告警下限阀值 |
|
|
|
var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; |
|
|
|
// EDOC |
|
|
|
var edoc = DateTimeUtil.ToDateTime(watchConfig!["EDOC"]!.ToString()); |
|
|
|
// interval (分钟) 固定15分钟 |
|
|
|
var intervalFHR = 15;//int)watchConfig["interval"]!; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); |
|
|
|
if (phr.Count >= 30) |
|
|
|
if (isFetalHeartEnable) |
|
|
|
{ |
|
|
|
#region 定时计算胎动数据触发器两小时间隔开始 |
|
|
|
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}"; |
|
|
|
///// 计算 0 点秒数 |
|
|
|
var fetalMovementLastUpdate = (DateTime)heartRate.LastUpdate!; |
|
|
|
DateTime fmScheduleNow = DateTime.Now; |
|
|
|
// 小于两小时 |
|
|
|
if (fmScheduleNow > fetalMovementLastUpdate && (fmScheduleNow - fetalMovementLastUpdate).TotalHours <= 2) |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 计算胎心胎动启动"); |
|
|
|
#region 定时下发触发器(定时建模) |
|
|
|
var key = $"health_monitor/schedule_push/pregnancy_heart_rate/imei/{heartRate.Serialno}"; |
|
|
|
var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); |
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(schedule_push)) |
|
|
|
{ |
|
|
|
// 注册首次下推 |
|
|
|
var interval = 0; |
|
|
|
// 获取当前时间 |
|
|
|
DateTime now = DateTime.Now; |
|
|
|
var rand = new Random(); |
|
|
|
var pushSec = rand.Next(59); |
|
|
|
int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10; |
|
|
|
// 计算距离下一个$interval天后的8点的时间间隔 |
|
|
|
DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 6, pushMin, pushSec).AddDays(interval); |
|
|
|
TimeSpan timeUntilNextRun = nextRunTime - now; |
|
|
|
|
|
|
|
var scheduleHourDiff = SCHEDULE_HOUR |
|
|
|
.Where(h => h > fetalMovementLastUpdate.Hour) |
|
|
|
.OrderBy(h => h - fetalMovementLastUpdate.Hour) |
|
|
|
.FirstOrDefault() - fetalMovementLastUpdate.Hour; |
|
|
|
var scheduleTime = fetalMovementLastUpdate.AddHours(scheduleHourDiff); |
|
|
|
if (timeUntilNextRun < TimeSpan.Zero) |
|
|
|
{ |
|
|
|
timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1)); |
|
|
|
nextRunTime += TimeSpan.FromDays(1); |
|
|
|
} |
|
|
|
|
|
|
|
DateTime nextRunTime = new(scheduleTime.Year, scheduleTime.Month, scheduleTime.Day, scheduleTime.Hour, pushMin, pushSec); |
|
|
|
TimeSpan timeUntilNextRun = nextRunTime - fmScheduleNow; |
|
|
|
var ttl = (long)timeUntilNextRun.TotalSeconds; |
|
|
|
var data = new |
|
|
|
{ |
|
|
|
imei = heartRate.Serialno, |
|
|
|
create_time = now.ToString("yyyy-MM-dd HH:mm:ss"), |
|
|
|
ttl, |
|
|
|
next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss") |
|
|
|
}; |
|
|
|
var result = JsonConvert.SerializeObject(data); |
|
|
|
await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false); |
|
|
|
|
|
|
|
await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl); |
|
|
|
} |
|
|
|
#endregion |
|
|
|
|
|
|
|
#region 计算胎心数据(按心率时间LastUpdate) |
|
|
|
var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(heartRate.Serialno); |
|
|
|
if (commonPHR == null) |
|
|
|
#endregion |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 触发定时建模"); |
|
|
|
|
|
|
|
// 高频心率采样间隔 highFreqSampleInterval = highFreqSampleInterval+5,增加5秒兼容 |
|
|
|
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! + 5; |
|
|
|
// 触发高频监测的心率上限值 |
|
|
|
var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; |
|
|
|
// 触发高频监测的心率下限值 |
|
|
|
var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; |
|
|
|
//停止高频心率采样心率连续正常次数 |
|
|
|
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; |
|
|
|
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 |
|
|
|
var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!; |
|
|
|
// 告警上限阀值 |
|
|
|
var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; |
|
|
|
// 告警下限阀值 |
|
|
|
var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; |
|
|
|
// EDOC |
|
|
|
var edoc = DateTimeUtil.ToDateTime(watchConfig!["EDOC"]!.ToString()); |
|
|
|
// interval (分钟) 固定15分钟 |
|
|
|
var intervalFHR = 15;//int)watchConfig["interval"]!; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); |
|
|
|
if (phr.Count >= 30) |
|
|
|
{ |
|
|
|
// 处理孕妇业务,计算一般心率并下发 |
|
|
|
commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno, highFreqSampleInterval: highFreqSampleInterval); |
|
|
|
// 建模完成 |
|
|
|
var flag = await _serviceIotApi.SetFetalConfig(heartRate.Serialno, 1, commonPHR!.MaxValue, commonPHR!.MinValue); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 记录数量足够,建模完成"); |
|
|
|
// 保存到TDengine数据库 |
|
|
|
await _serviceTDengine.InsertAsync<PregnancyCommonHeartRateModel>("hm_pchr", commonPHR!); |
|
|
|
_logger.LogInformation($"保存TDengine完成"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取最近的两个记录,并计算它们的 LastUpdate 时间差 |
|
|
|
var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList(); |
|
|
|
var timeDiff = firstTwoPhr[0] - firstTwoPhr[1]; |
|
|
|
|
|
|
|
// 如果需要,将时间差转换为秒 |
|
|
|
var timeDiffInSeconds = timeDiff.TotalSeconds; |
|
|
|
#region 定时计算胎动数据触发器两小时间隔开始 |
|
|
|
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}"; |
|
|
|
///// 计算 0 点秒数 |
|
|
|
var fetalMovementLastUpdate = (DateTime)heartRate.LastUpdate!; |
|
|
|
DateTime fmScheduleNow = DateTime.Now; |
|
|
|
// 小于两小时 |
|
|
|
if (fmScheduleNow > fetalMovementLastUpdate && (fmScheduleNow - fetalMovementLastUpdate).TotalHours <= 2) |
|
|
|
{ |
|
|
|
var rand = new Random(); |
|
|
|
var pushSec = rand.Next(59); |
|
|
|
int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10; |
|
|
|
|
|
|
|
// 高频统计结束时间 |
|
|
|
var FreqStatsEnd = DateTime.Now; |
|
|
|
var scheduleHourDiff = SCHEDULE_HOUR |
|
|
|
.Where(h => h > fetalMovementLastUpdate.Hour) |
|
|
|
.OrderBy(h => h - fetalMovementLastUpdate.Hour) |
|
|
|
.FirstOrDefault() - fetalMovementLastUpdate.Hour; |
|
|
|
var scheduleTime = fetalMovementLastUpdate.AddHours(scheduleHourDiff); |
|
|
|
|
|
|
|
DateTime nextRunTime = new(scheduleTime.Year, scheduleTime.Month, scheduleTime.Day, scheduleTime.Hour, pushMin, pushSec); |
|
|
|
TimeSpan timeUntilNextRun = nextRunTime - fmScheduleNow; |
|
|
|
var ttl = (long)timeUntilNextRun.TotalSeconds; |
|
|
|
|
|
|
|
// 高频心率启动 |
|
|
|
if (timeDiffInSeconds <= highFreqSampleInterval) |
|
|
|
{ |
|
|
|
await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl); |
|
|
|
} |
|
|
|
#endregion |
|
|
|
|
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
if (phrFreqstatus == null) |
|
|
|
#region 计算胎心数据(按心率时间LastUpdate) |
|
|
|
var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(heartRate.Serialno); |
|
|
|
if (commonPHR == null) |
|
|
|
{ |
|
|
|
/// 设置高频状态 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 进入高频心率启动状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); |
|
|
|
// 设置高频状态 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} phr.Count {phr.Count}"); |
|
|
|
var freqFirstPhr = phr.OrderByDescending(i => i.LastUpdate).First(); |
|
|
|
await _deviceCacheMgr.SetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno, freqFirstPhr); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置高频状态"); |
|
|
|
phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 处理孕妇业务,计算一般心率并下发 |
|
|
|
commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno, highFreqSampleInterval: highFreqSampleInterval); |
|
|
|
// 建模完成 |
|
|
|
var flag = await _serviceIotApi.SetFetalConfig(heartRate.Serialno, 1, commonPHR!.MaxValue, commonPHR!.MinValue); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 记录数量足够,建模完成"); |
|
|
|
// 保存到TDengine数据库 |
|
|
|
await _serviceTDengine.InsertAsync<PregnancyCommonHeartRateModel>("hm_pchr", commonPHR!); |
|
|
|
_logger.LogInformation($"保存TDengine完成"); |
|
|
|
} |
|
|
|
/// phr PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
#region 检查是否连续12个心率值都是正常的 |
|
|
|
// 获取最近连续正常次数个心率记录 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 stopHighFreqSampleCount {stopHighFreqSampleCount}"); |
|
|
|
|
|
|
|
var lastPhr = phr.OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList(); |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 lastPhr {lastPhr.Count}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 triggerHighFreqLow {triggerHighFreqLow}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 triggerHighFreqHigh {triggerHighFreqHigh}"); |
|
|
|
// 检查是否连续12个值都是正常的 |
|
|
|
if (lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)) |
|
|
|
|
|
|
|
// 获取最近的两个记录,并计算它们的 LastUpdate 时间差 |
|
|
|
var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList(); |
|
|
|
var timeDiff = firstTwoPhr[0] - firstTwoPhr[1]; |
|
|
|
|
|
|
|
// 如果需要,将时间差转换为秒 |
|
|
|
var timeDiffInSeconds = timeDiff.TotalSeconds; |
|
|
|
|
|
|
|
// 高频统计结束时间 |
|
|
|
var FreqStatsEnd = DateTime.Now; |
|
|
|
|
|
|
|
|
|
|
|
// 高频心率启动 |
|
|
|
if (timeDiffInSeconds <= highFreqSampleInterval) |
|
|
|
{ |
|
|
|
var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
// 计算一般心率得到胎心系数 |
|
|
|
//await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); |
|
|
|
// 高频数据不建模 |
|
|
|
FreqStatsEnd = (DateTime)heartRate.LastUpdate!; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,连续 {stopHighFreqSampleCount} 次采样心率正常,将下发指令"); |
|
|
|
|
|
|
|
var freqSaveAndPushFetalHeartRate = await _deviceCacheMgr.GetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate"); |
|
|
|
// 高频不停,15分钟内只下发一条 |
|
|
|
if (string.IsNullOrEmpty(freqSaveAndPushFetalHeartRate)) |
|
|
|
|
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
if (phrFreqstatus == null) |
|
|
|
{ |
|
|
|
await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd); |
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 设置15分的SaveAndPushFetalHeartRate业务间隔 |
|
|
|
await _deviceCacheMgr.SetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,结束高频心率状态, timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{((DateTime)heartRate.LastUpdate - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
/// 设置高频状态 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 进入高频心率启动状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); |
|
|
|
// 设置高频状态 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} phr.Count {phr.Count}"); |
|
|
|
var freqFirstPhr = phr.OrderByDescending(i => i.LastUpdate).First(); |
|
|
|
await _deviceCacheMgr.SetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno, freqFirstPhr); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置高频状态"); |
|
|
|
phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
} |
|
|
|
else |
|
|
|
/// phr PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
#region 检查是否连续12个心率值都是正常的 |
|
|
|
// 获取最近连续正常次数个心率记录 |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 stopHighFreqSampleCount {stopHighFreqSampleCount}"); |
|
|
|
|
|
|
|
var lastPhr = phr.OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList(); |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 lastPhr {lastPhr.Count}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 triggerHighFreqLow {triggerHighFreqLow}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置 triggerHighFreqHigh {triggerHighFreqHigh}"); |
|
|
|
// 检查是否连续12个值都是正常的 |
|
|
|
if (lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)) |
|
|
|
{ |
|
|
|
_logger.LogWarning($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,设备端应该结束高频状态,但设备端没有结束高频,平台高频15分钟内已经下发过指令"); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 处于高频状态..."); |
|
|
|
} |
|
|
|
#endregion |
|
|
|
} |
|
|
|
// 高频心率结束或平常心率 |
|
|
|
else |
|
|
|
{ |
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 高频心率结束 |
|
|
|
if (phrFreqstatus != null) |
|
|
|
{ |
|
|
|
/// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
if (highFreqSampleTimes == 0) |
|
|
|
{ |
|
|
|
var avgPhr = phr.OrderByDescending(i => i.LastUpdate) |
|
|
|
.Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate) |
|
|
|
.Skip(1) // 去除首条 |
|
|
|
.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh) |
|
|
|
.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
// 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
// 计算一般心率得到胎心系数 |
|
|
|
//await SaveAndPushFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr); |
|
|
|
//await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); |
|
|
|
// 高频数据不建模 |
|
|
|
FreqStatsEnd = firstTwoPhr[1]; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,highFreqSampleTimes={highFreqSampleTimes}秒,即将结束高频状态,将下发指令"); |
|
|
|
FreqStatsEnd = (DateTime)heartRate.LastUpdate!; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,连续 {stopHighFreqSampleCount} 次采样心率正常,将下发指令"); |
|
|
|
|
|
|
|
//await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString()); |
|
|
|
await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd); |
|
|
|
var freqSaveAndPushFetalHeartRate = await _deviceCacheMgr.GetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate"); |
|
|
|
// 高频不停,15分钟内只下发一条 |
|
|
|
if (string.IsNullOrEmpty(freqSaveAndPushFetalHeartRate)) |
|
|
|
{ |
|
|
|
await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd); |
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 设置15分的SaveAndPushFetalHeartRate业务间隔 |
|
|
|
await _deviceCacheMgr.SetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,结束高频心率状态, timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{((DateTime)heartRate.LastUpdate - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogWarning($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,设备端应该结束高频状态,但设备端没有结束高频,平台高频15分钟内已经下发过指令"); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate.AddSeconds(highFreqSampleTimes))) |
|
|
|
else |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
// 获取高频心率数据个数 |
|
|
|
var filterPhr = phr |
|
|
|
.Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate) |
|
|
|
.Skip(1) |
|
|
|
.ToList(); |
|
|
|
|
|
|
|
//var freqCollection = new List<PregnancyHeartRateModel>(); |
|
|
|
//PregnancyHeartRateModel? previousItem = null; |
|
|
|
|
|
|
|
//foreach (var item in filterPhr) |
|
|
|
//{ |
|
|
|
// if (previousItem != null) |
|
|
|
// { |
|
|
|
// var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds; |
|
|
|
// if (timeNextDiff <= highFreqSampleInterval) |
|
|
|
// { |
|
|
|
// freqCollection.Add(item); |
|
|
|
// } |
|
|
|
// } |
|
|
|
// previousItem = item; |
|
|
|
//} |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} {phrFreqstatus?.LastUpdate.ToString("yyyy-MM-dd HH:mm:ss")}--{firstTwoPhr[1].ToString("yyyy-MM-dd HH:mm:ss")} 产生高频心率数量 {filterPhr.Count} 条"); |
|
|
|
|
|
|
|
// 高频心率数据大于等于stopHighFreqSampleCount/12个才计算胎心数据 |
|
|
|
if (filterPhr.Count >= stopHighFreqSampleCount) |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 处于高频状态..."); |
|
|
|
} |
|
|
|
#endregion |
|
|
|
} |
|
|
|
// 高频心率结束或平常心率 |
|
|
|
else |
|
|
|
{ |
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 高频心率结束 |
|
|
|
if (phrFreqstatus != null) |
|
|
|
{ |
|
|
|
/// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
if (highFreqSampleTimes == 0) |
|
|
|
{ |
|
|
|
var avgPhr = filterPhr |
|
|
|
.OrderByDescending(i => i.LastUpdate) |
|
|
|
.Take(stopHighFreqSampleCount) // 计算最后12条 |
|
|
|
//.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh) |
|
|
|
.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
|
|
|
|
var avgPhr = phr.OrderByDescending(i => i.LastUpdate) |
|
|
|
.Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate) |
|
|
|
.Skip(1) // 去除首条 |
|
|
|
.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh) |
|
|
|
.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
// 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
// 计算一般心率得到胎心系数 |
|
|
|
// 高频数据不建模 |
|
|
|
FreqStatsEnd = firstTwoPhr[1]; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,超过约定的 {highFreqSampleTimes} 秒,即将结束高频状态,将下发指令"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,highFreqSampleTimes={highFreqSampleTimes}秒,即将结束高频状态,将下发指令"); |
|
|
|
|
|
|
|
//await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString()); |
|
|
|
await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate.AddSeconds(highFreqSampleTimes))) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
// 获取高频心率数据个数 |
|
|
|
var filterPhr = phr |
|
|
|
.Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate) |
|
|
|
.Skip(1) |
|
|
|
.ToList(); |
|
|
|
|
|
|
|
//var freqCollection = new List<PregnancyHeartRateModel>(); |
|
|
|
//PregnancyHeartRateModel? previousItem = null; |
|
|
|
|
|
|
|
//foreach (var item in filterPhr) |
|
|
|
//{ |
|
|
|
// if (previousItem != null) |
|
|
|
// { |
|
|
|
// var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds; |
|
|
|
// if (timeNextDiff <= highFreqSampleInterval) |
|
|
|
// { |
|
|
|
// freqCollection.Add(item); |
|
|
|
// } |
|
|
|
// } |
|
|
|
// previousItem = item; |
|
|
|
//} |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} {phrFreqstatus?.LastUpdate.ToString("yyyy-MM-dd HH:mm:ss")}--{firstTwoPhr[1].ToString("yyyy-MM-dd HH:mm:ss")} 产生高频心率数量 {filterPhr.Count} 条"); |
|
|
|
|
|
|
|
// 高频心率数据大于等于stopHighFreqSampleCount/12个才计算胎心数据 |
|
|
|
if (filterPhr.Count >= stopHighFreqSampleCount) |
|
|
|
{ |
|
|
|
var avgPhr = filterPhr |
|
|
|
.OrderByDescending(i => i.LastUpdate) |
|
|
|
.Take(stopHighFreqSampleCount) // 计算最后12条 |
|
|
|
//.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh) |
|
|
|
.Select(i => i.PregnancyHeartRate).Average(); |
|
|
|
|
|
|
|
// 高频数据不建模 |
|
|
|
FreqStatsEnd = firstTwoPhr[1]; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,超过约定的 {highFreqSampleTimes} 秒,即将结束高频状态,将下发指令"); |
|
|
|
|
|
|
|
await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd); |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频心率的数据不足{stopHighFreqSampleCount}条,不进行胎心计算"); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
//不满足持续10分钟highFreqSampleTimes |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频心率的数据不足{stopHighFreqSampleCount}条,不进行胎心计算"); |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频持续时间不足{highFreqSampleTimes},只持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
} |
|
|
|
|
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 超时结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
|
|
|
|
// 计算本次平常心率的胎心数据 |
|
|
|
//await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
// 使用延后计算 |
|
|
|
var fhrScheduleKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; |
|
|
|
var fhrScheduleTTL = 10; |
|
|
|
await SetIntervalTriggerAsync(fhrScheduleKey, heartRate.Serialno, fhrScheduleTTL); |
|
|
|
} |
|
|
|
//不满足持续10分钟highFreqSampleTimes |
|
|
|
// 平常心率 |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频持续时间不足{highFreqSampleTimes},只持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
// 计算本次平常心率的胎心数据 |
|
|
|
//await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
// 使用延后计算 |
|
|
|
var fhrScheduleKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; |
|
|
|
var fhrScheduleTTL = 10; |
|
|
|
await SetIntervalTriggerAsync(fhrScheduleKey, heartRate.Serialno, fhrScheduleTTL); |
|
|
|
} |
|
|
|
|
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 超时结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
|
|
|
|
// 计算本次平常心率的胎心数据 |
|
|
|
await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
|
|
|
|
} |
|
|
|
// 平常心率 |
|
|
|
else |
|
|
|
{ |
|
|
|
// 计算本次平常心率的胎心数据 |
|
|
|
await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#endregion |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 记录不足30条,建模中"); |
|
|
|
#endregion |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 记录不足30条,建模中"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//try |
|
|
|
//{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
|
|
|
|
//} |
|
|
|
//catch (Exception ex) |
|
|
|
//{ |
|
|
|
|
|
|
|
// _logger.LogError($"{heartRate.Serialno} 处理孕妇心率数据异常 \n{ex.Message}\n{ex.StackTrace}"); |
|
|
|
//} |
|
|
|
_logger.LogError($"{heartRate.Serialno} 处理孕妇心率数据异常 \n{ex.Message}\n{ex.StackTrace}"); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
/// <summary> |
|
|
|