Browse Source

高频时长不足10分钟,都不产生告警信息

datasub12_fetal_heart_rate_1
H Vs 1 month ago
parent
commit
6162a68adf
3 changed files with 518 additions and 14 deletions
  1. +9
    -1
      HealthMonitor.Common/DateTimeUtil.cs
  2. +280
    -12
      HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
  3. +229
    -1
      HealthMonitor.WebApi/Worker.cs

+ 9
- 1
HealthMonitor.Common/DateTimeUtil.cs View File

@@ -713,7 +713,15 @@ namespace HealthMonitor.Common
return sRet;
}

public static double GetTimeDifferenceInSeconds( DateTime end,DateTime start)
{
// 获取时间差
TimeSpan timeDifference = end - start;

// 返回时间差的总秒数
return timeDifference.TotalSeconds;
}


///// <summary>
///// 是否为日期型字符串


+ 280
- 12
HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs View File

@@ -165,7 +165,8 @@ namespace HealthMonitor.Service.Resolver
//停止高频心率采样心率连续正常次数
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!;
// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长
var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!;
//var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!;
var highFreqSampleTimes = 540;
// 告警上限阀值
var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!;
// 告警下限阀值
@@ -351,8 +352,19 @@ namespace HealthMonitor.Service.Resolver
if (string.IsNullOrEmpty(freqSaveAndPushFetalHeartRate))
{
//await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

heartRate.HeartRate = (int)avgPhr;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
//await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
// 判断是否够highFreqSampleTimes,540s
if (ts < highFreqSampleTimes)
{
/// 不够10分钟最近12个数据的最小值生成胎心值
heartRate.HeartRate = lastPhr.Select(i=>i.PregnancyHeartRate).Min();
}
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR,highFreqSampleTimes ,upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
// 删除高频状态的首条记录
await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
// 设置15分的SaveAndPushFetalHeartRate业务间隔
@@ -382,11 +394,14 @@ namespace HealthMonitor.Service.Resolver
/// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig
if (highFreqSampleTimes == 0)
{
var avgPhr = phr.OrderByDescending(i => i.LastUpdate)
var lastPhr = 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();
.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh);
//.Select(i => i.PregnancyHeartRate);
//.Average();

var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average();
// 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig
// 计算一般心率得到胎心系数
// 高频数据不建模
@@ -397,7 +412,16 @@ namespace HealthMonitor.Service.Resolver
//await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

heartRate.HeartRate = (int)avgPhr;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
//await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
// 判断是否够highFreqSampleTimes,540s
if (ts < highFreqSampleTimes)
{
/// 不够10分钟最近12个数据的最小值生成胎心值
heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
}
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

}

/// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig),
@@ -428,7 +452,20 @@ namespace HealthMonitor.Service.Resolver
//计算高频
//await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
heartRate.HeartRate = (int)avgPhr;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
//await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

// 判断是否够highFreqSampleTimes,540s
var lastPhr = filterPhr
.OrderByDescending(i => i.LastUpdate)
.Take(stopHighFreqSampleCount);
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
if (ts < highFreqSampleTimes)
{
/// 不够10分钟最近12个数据的最小值生成胎心值
heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
}
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
}
else
{
@@ -483,11 +520,23 @@ namespace HealthMonitor.Service.Resolver
.Take(stopHighFreqSampleCount) // 计算最后12条
.Select(i => i.PregnancyHeartRate).Average();

//await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), freqCollection.Last().LastUpdate, freqCollection.First().LastUpdate);
heartRate.HeartRate = (int)avgPhr;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
_logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate},高频心率平均值:{(int)avgPhr}");
// await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
//_logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate},高频心率平均值:{(int)avgPhr}");

// 判断是否够highFreqSampleTimes,540s
var lastPhr = freqCollection
.OrderByDescending(i => i.LastUpdate)
.Take(stopHighFreqSampleCount);
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
if (ts < highFreqSampleTimes)
{
/// 不够10分钟最近12个数据的最小值生成胎心值
heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
}
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

_logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate},时间倒叙");
}
else
{
@@ -599,6 +648,7 @@ namespace HealthMonitor.Service.Resolver
/// <param name="intervalFHR"></param>
/// <param name="commonPHR"></param>
/// <returns></returns>
/**
private async Task CalculateNormalFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, int intervalFHR, PregnancyCommonHeartRateModel? commonPHR)
{
// 上15分钟的数据
@@ -653,9 +703,13 @@ namespace HealthMonitor.Service.Resolver
//await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR);
//await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime);
heartRate.HeartRate = (int)phrValue;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime);
//await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime);
}

*/
/// <summary>
/// 延时计算
/// </summary>
@@ -1103,6 +1157,220 @@ namespace HealthMonitor.Service.Resolver
}
}

private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int highFreqSampleTimes, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime)
{
// 计算胎心=孕妇心率*系数

#region 胎心系数使用基于心率与中位数对比
var coefficient = 0f;
// 孕妇心率少于中位数,取StatMinValueFprCoefficient
if (heartRate.HeartRate < commonPHR!.Mode)
{
coefficient = commonPHR.StatMinValueFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}");
}
// 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个
else if (heartRate.HeartRate > commonPHR.Mode)
{
if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient)
{
coefficient = commonPHR.StatMaxValueFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}");
}
else
{
coefficient = commonPHR.StatModeAvgFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}");
}
}
else
{
coefficient = commonPHR.StatModeAvgFprCoefficient;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}");
}
#endregion

var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient);
// 胎心的最大值调整为220,超过都按该值220输出
// fetalHeartRate = fetalHeartRate>= 220 ? 220 : fetalHeartRate;

var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);

#region 判断是否够highFreqSampleTimes,540s
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
// 判断是否够highFreqSampleTimes,540s
///高频时长不足10分钟停止高频的胎心值生成说明:最近12个数据的最小值生成胎心值,
///对于小于高频下限阀值取高频下限阀值进行转换;
///对于高于高频上限阀值取高频上限阀值进行转换。并输出相关日志后续进行数据分析。
if (ts < highFreqSampleTimes)
{
if (fetalHeartRate > upperAlarmThreshold)
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 高于高频警告上限阀值{upperAlarmThreshold},最后胎心值{upperAlarmThreshold}");
fetalHeartRate = upperAlarmThreshold;

}
else if (fetalHeartRate < lowerAlarmThreshold)
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 低于高频警告下限阀值 {lowerAlarmThreshold},最后胎心值{lowerAlarmThreshold}");
fetalHeartRate = lowerAlarmThreshold;
}
else
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,在高频警告下限阀值 {lowerAlarmThreshold} 和 高频警告上限阀值:{upperAlarmThreshold}之间,最后胎心值{fetalHeartRate}");
}
}
// 超过highFreqSampleTimes,540s
else
{
if (fetalHeartRate > 220)
{
fetalHeartRate = 220;
_logger.LogWarning($"{heartRate.Serialno} 大于220,按220输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
}

// 胎心的最小值调整为90,超过都按该值90
if (fetalHeartRate < 90)
{
fetalHeartRate = 90;
_logger.LogWarning($"{heartRate.Serialno} 小于90,按90输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
}

}
#endregion


var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 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)
//{
// statStartTime = heartRate.LastUpdate;
//
//}
// 保存到 数据服务 MySQL 数据库
HisGpsFetalHeartRate gpsFetalHeartRate = new()
{
FetalHeartRateId = Guid.NewGuid().ToString("D"),
PersonId = commonPHR!.PersonId,
Serialno = heartRate.Serialno,
HeartRate = fetalHeartRate,
SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
IsAbnormal = isAbnormal,
StatStartTime = statStartTime,
StatEndTime = statEndTime,//commonPHR.StatEndTime,
CreateTime = DateTime.Now,
Method = 1,
IsDisplay = 1,
DeviceKey = commonPHR!.DeviceKey
};
await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false);

// 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
// 推送最后一条常规心率计算的胎心数据到iot设备
#region 推送最后一条常规心率计算的胎心数据到iot设备

// 高频(<=12)-常规
var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(heartRate.Serialno);
if (lastPhr.MessageId == heartRate.MessageId && phrFreqstatus == null)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
_logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(<=12)-常规");
}
// 高频(13)-常规-高频(13)
if (phrFreqstatus != null)
{
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 1);
phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
// 获取高频数据
var freqCollection = new List<PregnancyHeartRateModel>();
PregnancyHeartRateModel? previousItem = null;
foreach (var item in phr)
{
if (previousItem != null)
{
var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
if (timeNextDiff <= 60)
{
freqCollection.Add(item);
}
}
// 高频最后一条
if (lastPhr.MessageId == item.MessageId)
{
freqCollection.Add(item);
}

previousItem = item;
}
//去除高频
foreach (var item in freqCollection)
{
phr.Remove(item);
}
lastPhr = phr.FirstOrDefault();
if (lastPhr?.MessageId == heartRate.MessageId)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
_logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(13)-常规-高频(13)");
}
}

#endregion

#region 高频心率计算胎心数据到iot设备
// 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot
if (phrFreqstatus != null && isAbnormal != 0)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
}
#endregion
var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
var fhrMsgId = $"{heartRate.Serialno}-{sampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
var fhrMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
// 胎心数据推送到第三方
var topic = "topic.push.third";
var fhrThridMsg = new
{
messageId = fhrMsgId,
topic = topic,
time = fhrMsgTime,
data = new
{
imei = heartRate.Serialno,
value = fetalHeartRate,
isAbnormal,
type = "fetalHeart"
}
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false);

// 胎心数据推送到微信
if (isAbnormal != 0)
{

topic = "topic.push.wx";
var fhrMsg = new
{
messageId = fhrMsgId,
topic = topic,
time = fhrMsgTime,
data = new
{
deviceId = device?.DeviceId,
imei = heartRate.Serialno,
alarmTypeId = 12,
alarmDeviceName = heartRate.Serialno,
alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = isAbnormal }),
address = string.Empty,
deviceKey = device?.DeviceId
}
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);

}
}

private async Task SetIntervalTriggerAsync(string key, string imei, long interval, HisGpsHeartRate heartRate)
{


+ 229
- 1
HealthMonitor.WebApi/Worker.cs View File

@@ -312,6 +312,10 @@ namespace HealthMonitor.WebApi
//停止高频心率采样心率连续正常次数
var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!;

// 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长
//var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!;
var highFreqSampleTimes = 540;

var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(imeiDel);


@@ -337,7 +341,17 @@ namespace HealthMonitor.WebApi

//await SaveAndPushFetalHeartRateAsync(triggerHeartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
triggerHeartRate.HeartRate = (int)avgPhr;
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(triggerHeartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
//await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(triggerHeartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

// 判断是否够highFreqSampleTimes,540s
var lastPhr = phrInFreqstatus;
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)triggerHeartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
if (ts < highFreqSampleTimes)
{
/// 不够10分钟最近12个数据的最小值生成胎心值
triggerHeartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
}
await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(triggerHeartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
}
else
{
@@ -2339,6 +2353,220 @@ namespace HealthMonitor.WebApi
}
}

private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int highFreqSampleTimes, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime)
{
// 计算胎心=孕妇心率*系数

#region 胎心系数使用基于心率与中位数对比
var coefficient = 0f;
// 孕妇心率少于中位数,取StatMinValueFprCoefficient
if (heartRate.HeartRate < commonPHR!.Mode)
{
coefficient = commonPHR.StatMinValueFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}");
}
// 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个
else if (heartRate.HeartRate > commonPHR.Mode)
{
if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient)
{
coefficient = commonPHR.StatMaxValueFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}");
}
else
{
coefficient = commonPHR.StatModeAvgFprCoefficient!;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}");
}
}
else
{
coefficient = commonPHR.StatModeAvgFprCoefficient;
_logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}");
}
#endregion

var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient);
// 胎心的最大值调整为220,超过都按该值220输出
// fetalHeartRate = fetalHeartRate>= 220 ? 220 : fetalHeartRate;

var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);

#region 判断是否够highFreqSampleTimes,540s
var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
// 判断是否够highFreqSampleTimes,540s
///高频时长不足10分钟停止高频的胎心值生成说明:最近12个数据的最小值生成胎心值,
///对于小于高频下限阀值取高频下限阀值进行转换;
///对于高于高频上限阀值取高频上限阀值进行转换。并输出相关日志后续进行数据分析。
if (ts < highFreqSampleTimes)
{
if (fetalHeartRate > upperAlarmThreshold)
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 高于高频警告上限阀值{upperAlarmThreshold},最后胎心值{upperAlarmThreshold}");
fetalHeartRate = upperAlarmThreshold;

}
else if (fetalHeartRate < lowerAlarmThreshold)
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 低于高频警告下限阀值 {lowerAlarmThreshold},最后胎心值{lowerAlarmThreshold}");
fetalHeartRate = lowerAlarmThreshold;
}
else
{
_logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,在高频警告下限阀值 {lowerAlarmThreshold} 和 高频警告上限阀值:{upperAlarmThreshold}之间,最后胎心值{fetalHeartRate}");
}
}
// 超过highFreqSampleTimes,540s
else
{
if (fetalHeartRate > 220)
{
fetalHeartRate = 220;
_logger.LogWarning($"{heartRate.Serialno} 大于220,按220输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
}

// 胎心的最小值调整为90,超过都按该值90
if (fetalHeartRate < 90)
{
fetalHeartRate = 90;
_logger.LogWarning($"{heartRate.Serialno} 小于90,按90输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
}

}
#endregion


var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 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)
//{
// statStartTime = heartRate.LastUpdate;
//
//}
// 保存到 数据服务 MySQL 数据库
HisGpsFetalHeartRate gpsFetalHeartRate = new()
{
FetalHeartRateId = Guid.NewGuid().ToString("D"),
PersonId = commonPHR!.PersonId,
Serialno = heartRate.Serialno,
HeartRate = fetalHeartRate,
SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
IsAbnormal = isAbnormal,
StatStartTime = statStartTime,
StatEndTime = statEndTime,//commonPHR.StatEndTime,
CreateTime = DateTime.Now,
Method = 1,
IsDisplay = 1,
DeviceKey = commonPHR!.DeviceKey
};
await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false);

// 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
// 推送最后一条常规心率计算的胎心数据到iot设备
#region 推送最后一条常规心率计算的胎心数据到iot设备

// 高频(<=12)-常规
var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(heartRate.Serialno);
if (lastPhr.MessageId == heartRate.MessageId && phrFreqstatus == null)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
_logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(<=12)-常规");
}
// 高频(13)-常规-高频(13)
if (phrFreqstatus != null)
{
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 1);
phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
// 获取高频数据
var freqCollection = new List<PregnancyHeartRateModel>();
PregnancyHeartRateModel? previousItem = null;
foreach (var item in phr)
{
if (previousItem != null)
{
var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
if (timeNextDiff <= 60)
{
freqCollection.Add(item);
}
}
// 高频最后一条
if (lastPhr.MessageId == item.MessageId)
{
freqCollection.Add(item);
}

previousItem = item;
}
//去除高频
foreach (var item in freqCollection)
{
phr.Remove(item);
}
lastPhr = phr.FirstOrDefault();
if (lastPhr?.MessageId == heartRate.MessageId)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
_logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(13)-常规-高频(13)");
}
}

#endregion

#region 高频心率计算胎心数据到iot设备
// 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot
if (phrFreqstatus != null && isAbnormal != 0)
{
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
}
#endregion
var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
var fhrMsgId = $"{heartRate.Serialno}-{sampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
var fhrMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
// 胎心数据推送到第三方
var topic = "topic.push.third";
var fhrThridMsg = new
{
messageId = fhrMsgId,
topic = topic,
time = fhrMsgTime,
data = new
{
imei = heartRate.Serialno,
value = fetalHeartRate,
isAbnormal,
type = "fetalHeart"
}
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false);

// 胎心数据推送到微信
if (isAbnormal != 0)
{

topic = "topic.push.wx";
var fhrMsg = new
{
messageId = fhrMsgId,
topic = topic,
time = fhrMsgTime,
data = new
{
deviceId = device?.DeviceId,
imei = heartRate.Serialno,
alarmTypeId = 12,
alarmDeviceName = heartRate.Serialno,
alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = isAbnormal }),
address = string.Empty,
deviceKey = device?.DeviceId
}
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);

}
}





Loading…
Cancel
Save