|
|
@@ -56,21 +56,21 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public PregnancyHeartRateResolver(ILogger<PregnancyHeartRateResolver> logger, |
|
|
|
public PregnancyHeartRateResolver(ILogger<PregnancyHeartRateResolver> logger, |
|
|
|
HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr, |
|
|
|
MqProcessLogic serviceMqProcess, |
|
|
|
IotApiService iotApiService, TDengineService serviceDengine, FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr, |
|
|
|
GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> hisFetalHeartApiClient, |
|
|
|
GpsLocationHistoryAccessorClient<HisGpsFetalMovement> hisFetalMovementApiClient |
|
|
|
) |
|
|
|
{ |
|
|
|
{ |
|
|
|
_logger = logger; |
|
|
|
_httpHelper = httpHelper; |
|
|
|
_serviceEtcd = serviceEtcd; |
|
|
|
_serviceTDengine = serviceDengine; |
|
|
|
_serviceTDengine = serviceDengine; |
|
|
|
_deviceCacheMgr = deviceCacheMgr; |
|
|
|
_serviceIotApi = iotApiService; |
|
|
|
_serviceMqProcess= serviceMqProcess; |
|
|
|
_serviceMqProcess = serviceMqProcess; |
|
|
|
_hisFetalHeartApiClient = hisFetalHeartApiClient; |
|
|
|
_hisFetalMovementApiClient = hisFetalMovementApiClient; |
|
|
|
_mgrFetalMovementNormalValueRangeCache = fetalMovementNormalValueRangeCacheMgr; |
|
|
@@ -85,7 +85,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
HeartRateId = topicHmPregnancyHeartRate!.PregnancyHeartRateId, |
|
|
|
MessageId = topicHmPregnancyHeartRate!.MessageId, |
|
|
|
Serialno = topicHmPregnancyHeartRate!.Serialno, |
|
|
|
HeartRate= topicHmPregnancyHeartRate.PregnancyHeartRate, |
|
|
|
HeartRate = topicHmPregnancyHeartRate.PregnancyHeartRate, |
|
|
|
LastUpdate = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.LastUpdate) / 1000000), |
|
|
|
CreateTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.CreateTime) / 1000000), |
|
|
|
Method = topicHmPregnancyHeartRate!.Method, |
|
|
@@ -153,13 +153,13 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 触发定时建模"); |
|
|
|
|
|
|
|
// 高频心率采样间隔 highFreqSampleInterval = highFreqSampleInterval+5,增加5秒兼容(最小highFreqSampleInterval=60) |
|
|
|
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! >= 60 ? (int)watchConfig!["highFreqSampleInterval"]! + 5: 60; |
|
|
|
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! >= 60 ? (int)watchConfig!["highFreqSampleInterval"]! + 5 : 60; |
|
|
|
// 触发高频监测的心率上限值 |
|
|
|
var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; |
|
|
|
// 触发高频监测的心率下限值 |
|
|
|
var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; |
|
|
|
// 暂时处理 |
|
|
|
triggerHighFreqLow = triggerHighFreqLow > 60 && triggerHighFreqLow < 67 ? 60: triggerHighFreqLow; |
|
|
|
triggerHighFreqLow = triggerHighFreqLow > 60 && triggerHighFreqLow < 67 ? 60 : triggerHighFreqLow; |
|
|
|
//停止高频心率采样心率连续正常次数 |
|
|
|
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; |
|
|
|
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 |
|
|
@@ -204,7 +204,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
TimeSpan timeUntilNextRun = nextRunTime - fmScheduleNow; |
|
|
|
var ttl = (long)timeUntilNextRun.TotalSeconds; |
|
|
|
|
|
|
|
await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl,heartRate); |
|
|
|
await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl, heartRate); |
|
|
|
} |
|
|
|
#endregion |
|
|
|
|
|
|
@@ -251,7 +251,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 设置高频状态"); |
|
|
|
phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// phr PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), |
|
|
|
/// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig |
|
|
|
#region 检查高频状态是否连续12个心率值都是正常的 |
|
|
@@ -259,14 +259,14 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
//_logger.LogInformation($"{heartRate.Serialno} 设置 stopHighFreqSampleCount {stopHighFreqSampleCount}"); |
|
|
|
|
|
|
|
//var lastPhr = phr.OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList(); |
|
|
|
var lastPhr = phr.Where(i=>i.LastUpdate>= phrFreqstatus!.LastUpdate) |
|
|
|
var lastPhr = phr.Where(i => i.LastUpdate >= phrFreqstatus!.LastUpdate) |
|
|
|
.OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList(); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} lastPhr.Count {lastPhr.Count},stopHighFreqSampleCount {stopHighFreqSampleCount}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} count :{lastPhr.Count >= stopHighFreqSampleCount}"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} All {lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)}"); |
|
|
|
|
|
|
|
// 检查是否连续12个值都是正常的 |
|
|
|
if ((lastPhr.Count >= stopHighFreqSampleCount) && |
|
|
|
if ((lastPhr.Count >= stopHighFreqSampleCount) && |
|
|
|
lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh) |
|
|
|
) |
|
|
|
{ |
|
|
@@ -332,57 +332,45 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
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) |
|
|
|
_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]; |
|
|
|
|
|
|
|
var avgPhr = filterPhr |
|
|
|
.OrderByDescending(i => i.LastUpdate) |
|
|
|
.Take(stopHighFreqSampleCount) // 计算最后12条 |
|
|
|
.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); |
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 计算本次常规心率的胎心数据(高频结束后,实时处理) |
|
|
|
await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频心率的数据不足{stopHighFreqSampleCount}条,不进行胎心计算"); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频心率的数据不大于{stopHighFreqSampleCount}条,不进行高频数据的胎心计算"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
// 计算本次常规心率的胎心数据(高频结束后,实时处理) |
|
|
|
await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
//不满足持续10分钟highFreqSampleTimes或出现时间倒叙 |
|
|
|
///不满足持续10分钟highFreqSampleTimes或出现时间倒叙 |
|
|
|
/// |
|
|
|
else |
|
|
|
{ |
|
|
|
|
|
|
@@ -413,7 +401,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
//} |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate}"); |
|
|
|
if (freqCollection.Count >= stopHighFreqSampleCount) |
|
|
|
if (freqCollection.Count > stopHighFreqSampleCount) |
|
|
|
{ |
|
|
|
// 计算高频产生的胎心 |
|
|
|
var avgPhr = freqCollection |
|
|
@@ -434,7 +422,6 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
else |
|
|
|
{ |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 高频持续时间不足{highFreqSampleTimes},只持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); |
|
|
|
|
|
|
|
} |
|
|
|
// 删除高频状态的首条记录 |
|
|
|
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
@@ -489,7 +476,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
_logger.LogInformation($"phrFreqstatus==null:{phrFreqstatus == null}"); |
|
|
|
_logger.LogInformation($"phrFreqstatus.LastUpdate < heartRate.LastUpdate:{phrFreqstatus?.LastUpdate < heartRate.LastUpdate}"); |
|
|
|
if (phrFreqstatus==null || phrFreqstatus.LastUpdate < heartRate.LastUpdate) |
|
|
|
if (phrFreqstatus == null || phrFreqstatus.LastUpdate < heartRate.LastUpdate) |
|
|
|
{ |
|
|
|
await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 计算常规心率"); |
|
|
@@ -566,14 +553,14 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
|
|
|
|
var daysPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7); |
|
|
|
|
|
|
|
var normalPhrStatStartTime = nextInterval.AddMinutes(-intervalFHR) ; |
|
|
|
var normalPhrStatStartTime = nextInterval.AddMinutes(-intervalFHR); |
|
|
|
|
|
|
|
var normalPhrStatEndTime = nextInterval; |
|
|
|
|
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 计算胎心数据, 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} "); |
|
|
|
var filteredPhr = daysPhr |
|
|
|
// 使用 last_update 下一刻 |
|
|
|
.Where(i => i.LastUpdate <= normalPhrStatEndTime && i.LastUpdate >= normalPhrStatStartTime) |
|
|
|
.Where(i => i.LastUpdate <= normalPhrStatEndTime && i.LastUpdate >= normalPhrStatStartTime) |
|
|
|
.ToList(); |
|
|
|
if (filteredPhr.Count == 0) |
|
|
|
{ |
|
|
@@ -600,7 +587,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
/// <param name="statStartTime"></param> |
|
|
|
/// <param name="statEndTime"></param> |
|
|
|
/// <returns></returns> |
|
|
|
private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, double phrValue, string sampleTime,DateTime statStartTime, DateTime statEndTime) |
|
|
|
private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, double phrValue, string sampleTime, DateTime statStartTime, DateTime statEndTime) |
|
|
|
{ |
|
|
|
// 计算胎心=孕妇心率*系数 |
|
|
|
var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!); |
|
|
@@ -625,7 +612,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
|
|
|
|
var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); |
|
|
|
var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); |
|
|
|
if (phrFreqstatus == null) isAbnormal = 0; |
|
|
|
if (phrFreqstatus == null) isAbnormal = 0; |
|
|
|
var statsusDesc = (phrFreqstatus == null) ? "常规" : "高频"; |
|
|
|
_logger.LogInformation($"{heartRate.Serialno} 在 {statsusDesc} 状态,生成胎心值:{fetalHeartRate},统计周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}"); |
|
|
|
//if (!isFreq) |
|
|
@@ -681,7 +668,7 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
} |
|
|
|
} |
|
|
|
// 高频最后一条 |
|
|
|
if (lastPhr.MessageId==item.MessageId) |
|
|
|
if (lastPhr.MessageId == item.MessageId) |
|
|
|
{ |
|
|
|
freqCollection.Add(item); |
|
|
|
} |
|
|
@@ -748,9 +735,9 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async Task SetIntervalTriggerAsync(string key,string imei, long interval,HisGpsHeartRate heartRate) |
|
|
|
private async Task SetIntervalTriggerAsync(string key, string imei, long interval, HisGpsHeartRate heartRate) |
|
|
|
{ |
|
|
|
// var key = $"health_monitor/schedule_push/{type}/imei/{imei}"; |
|
|
|
// var key = $"health_monitor/schedule_push/{type}/imei/{imei}"; |
|
|
|
var schedulePush = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); |
|
|
|
if (string.IsNullOrWhiteSpace(schedulePush)) |
|
|
|
{ |
|
|
@@ -762,13 +749,13 @@ namespace HealthMonitor.Service.Resolver |
|
|
|
create_time = now.ToString("yyyy-MM-dd HH:mm:ss"), |
|
|
|
ttl = interval, |
|
|
|
next_run_time = timeNextRun.ToString("yyyy-MM-dd HH:mm:ss"), |
|
|
|
trigger= heartRate, |
|
|
|
trigger = heartRate, |
|
|
|
|
|
|
|
}; |
|
|
|
var result = JsonConvert.SerializeObject(data); |
|
|
|
await _serviceEtcd.PutValAsync(key, result, interval, false).ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |