diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs index 405be8d..0e483be 100644 --- a/HealthMonitor.WebApi/Worker.cs +++ b/HealthMonitor.WebApi/Worker.cs @@ -1763,246 +1763,117 @@ namespace HealthMonitor.WebApi } - private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime) + + /// + /// 高频胎心处理 + /// 1. 高频数据触发连续12个值都是正常的的高频心率处理 + /// 2. 高频结束后的highFreqSampleTimes=0的高频心率处理 + /// 3. 高频结束后的在highFreqSampleTimes>0 正常心率触发的高频心率处理(常态) + /// 4. 高频结束后的时间倒序的正常心率触发的高频心率处理 + /// 5. 高频结束后计算胎心数据,防止结束后与常规心理的胎心处理过长,定时器时长highFreqSampleInterval触发的高频心率处理 + /// 高频结束后超过9分钟且不在阈值内才告警 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int highFreqSampleTimes, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime) { // 计算胎心=孕妇心率*系数 - /** - var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!); - fetalHeartRate = fetalHeartRate > 220 ? 220 : fetalHeartRate; // 胎心的最大值调整为220,超过都按该值220输出 - if (fetalHeartRate >= 220) - { - // 先使用最小系数计算 - var statMaxValueFprCoefficient = commonPHR?.StatMaxValueFprCoefficient!; - var statMinValueFprCoefficient = commonPHR?.StatMinValueFprCoefficient!; - var coefficient = statMaxValueFprCoefficient < statMinValueFprCoefficient ? statMaxValueFprCoefficient : statMinValueFprCoefficient; - fetalHeartRate = SafeType.SafeInt(phrValue * coefficient); - if (fetalHeartRate < 220) - { - _logger.LogWarning($"{heartRate.Serialno} 使用极值系数 {coefficient} ,建模数据可能出现异常,请检查"); - } - else - { - fetalHeartRate = 220; - _logger.LogWarning($"{heartRate.Serialno} 使用所有系数都不能放映实际,建模数据可能出现异常,请检查"); - } - } - */ - #region 胎心系数使用基于心率与中位数对比 + #region 胎心系数使用基于心率与众数对比 var coefficient = 0f; - // 孕妇心率少于中位数,取StatMinValueFprCoefficient + /** + // 孕妇心率少于众数,取StatMinValueFprCoefficient if (heartRate.HeartRate < commonPHR!.Mode) { coefficient = commonPHR.StatMinValueFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于众数,使用最小值系数 {coefficient}"); } - // 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个 + // 孕妇心率大于众数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个 else if (heartRate.HeartRate > commonPHR.Mode) { if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient) { coefficient = commonPHR.StatMaxValueFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于众数,使用最大值系数 {coefficient}"); } else { coefficient = commonPHR.StatModeAvgFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于众数,使用均值系数 {coefficient}"); } } else { coefficient = commonPHR.StatModeAvgFprCoefficient; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于众数,使用均值系数 {coefficient}"); } - #endregion + */ - var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient); - // 胎心的最大值调整为220,超过都按该值220输出 - fetalHeartRate = fetalHeartRate >= 220 ? 220 : fetalHeartRate; - var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); - var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - 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); + ///1、高频最小值>心率,取高频最小值系数 + ///2、高频最小值 < 心率 < 众数,取众数系数与高频最小值系数较小值 + ///3、众数 < 心率 < 高频最大值,取众数系数与高频最大值系数较小值 + ///4、心率 > 高频最大值,取高频最大值系数 - // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig - // 推送最后一条常规心率计算的胎心数据到iot设备 - #region 推送最后一条常规心率计算的胎心数据到iot设备 - - // 高频(<=12)-常规 - var lastPhr = await _serviceTDengine.GetLastAsync(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) + // 1、高频最小值>心率,取高频最小值系数 + if (commonPHR.MinValue > heartRate.HeartRate) { - var phr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 1); - phr = phr.OrderByDescending(i => i.LastUpdate).ToList(); - // 获取高频数据 - var freqCollection = new List(); - 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)"); - } + coefficient = commonPHR.StatMinValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值>心率,取高频最小值系数 {coefficient}"); } - #endregion - - #region 高频心率计算胎心数据到iot设备 - // 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot - if (phrFreqstatus != null && isAbnormal != 0) + // 2、高频最小值 < 心率 < 众数,取众数系数与高频最小值系数较小值 + if (commonPHR.MinValue < heartRate.HeartRate && heartRate.HeartRate < commonPHR.Mode) { - 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 + if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMinValueFprCoefficient) { - imei = heartRate.Serialno, - value = fetalHeartRate, - isAbnormal, - type = "fetalHeart" + coefficient = commonPHR.StatMinValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值 < 心率 < 众数,平均值系数大于最小值系数,使用最小值系数 {coefficient}"); } - }; - await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false); - - // 胎心数据推送到微信 - if (isAbnormal != 0) - { - - topic = "topic.push.wx"; - var fhrMsg = new + else { - 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); - + coefficient = commonPHR.StatModeAvgFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值 < 心率 < 众数,平均值系数小于最小值系数,使用均值系数 {coefficient}"); + } } - } - - /// - /// 高频胎心处理 - /// 1. 高频数据触发连续12个值都是正常的的高频心率处理 - /// 2. 高频结束后的highFreqSampleTimes=0的高频心率处理 - /// 3. 高频结束后的在highFreqSampleTimes>0 正常心率触发的高频心率处理(常态) - /// 4. 高频结束后的时间倒序的正常心率触发的高频心率处理 - /// 5. 高频结束后计算胎心数据,防止结束后与常规心理的胎心处理过长,定时器时长highFreqSampleInterval触发的高频心率处理 - /// 高频结束后超过9分钟且不在阈值内才告警 - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - 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) + // 3、众数 < 心率 < 高频最大值,取众数系数与高频最大值系数较小值 + if (commonPHR.Mode < heartRate.HeartRate && heartRate.HeartRate < commonPHR.MaxValue) { if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient) { coefficient = commonPHR.StatMaxValueFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 众数 < 心率 < 高频最大值,平均值系数大于最最大值系数,使用最大值系数 {coefficient}"); } else { coefficient = commonPHR.StatModeAvgFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 众数 < 心率 < 高频最大值,平均值系数小于最小值系数,使用均值系数 {coefficient}"); } } - else + + // 4、心率 > 高频最大值,取高频最大值系数 + + if (heartRate.HeartRate > commonPHR.MaxValue) { - coefficient = commonPHR.StatModeAvgFprCoefficient; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}"); + coefficient = commonPHR.StatMaxValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 心率 > 高频最大值,取高频最大值系数 {coefficient}"); + } + + if (heartRate.HeartRate == commonPHR.Mode) + { + coefficient = commonPHR.StatModeAvgFprCoefficient!; + + _logger.LogInformation($"{heartRate.Serialno} 心率 == 众数,取均值系数 {coefficient}"); } + #endregion var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient); @@ -2258,6 +2129,13 @@ namespace HealthMonitor.WebApi return freqCollection; } + /// + /// 周期性常规心率计算胎心值 + /// + /// + /// + /// + /// public async Task CalculateNormalFetalHeartRateIntervalAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR,int highFreqSampleInterval) { var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); @@ -2371,33 +2249,94 @@ namespace HealthMonitor.WebApi heartRate.HeartRate = (int)avgPhr; - #region 胎心系数使用基于心率与中位数对比 + #region 胎心系数使用基于心率与众数对比 var coefficient = 0f; - // 孕妇心率少于中位数,取StatMinValueFprCoefficient + /** + // 孕妇心率少于众数,取StatMinValueFprCoefficient if (heartRate.HeartRate < commonPHR!.Mode) { coefficient = commonPHR.StatMinValueFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于众数,使用最小值系数 {coefficient}"); } - // 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个 + // 孕妇心率大于众数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个 else if (heartRate.HeartRate > commonPHR.Mode) { if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient) { coefficient = commonPHR.StatMaxValueFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于众数,使用最大值系数 {coefficient}"); } else { coefficient = commonPHR.StatModeAvgFprCoefficient!; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于众数,使用均值系数 {coefficient}"); } } else { coefficient = commonPHR.StatModeAvgFprCoefficient; - _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}"); + _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于众数,使用均值系数 {coefficient}"); + } + */ + + + ///1、高频最小值>心率,取高频最小值系数 + ///2、高频最小值 < 心率 < 众数,取众数系数与高频最小值系数较小值 + ///3、众数 < 心率 < 高频最大值,取众数系数与高频最大值系数较小值 + ///4、心率 > 高频最大值,取高频最大值系数 + + // 1、高频最小值>心率,取高频最小值系数 + if (commonPHR.MinValue > heartRate.HeartRate) + { + coefficient = commonPHR.StatMinValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值>心率,取高频最小值系数 {coefficient}"); + } + + // 2、高频最小值 < 心率 < 众数,取众数系数与高频最小值系数较小值 + if (commonPHR.MinValue commonPHR.StatMinValueFprCoefficient) + { + coefficient = commonPHR.StatMinValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值 < 心率 < 众数,平均值系数大于最小值系数,使用最小值系数 {coefficient}"); + } + else + { + coefficient = commonPHR.StatModeAvgFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 高频最小值 < 心率 < 众数,平均值系数小于最小值系数,使用均值系数 {coefficient}"); + } } + + // 3、众数 < 心率 < 高频最大值,取众数系数与高频最大值系数较小值 + if (commonPHR.Mode < heartRate.HeartRate && heartRate.HeartRate < commonPHR.MaxValue) + { + if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient) + { + coefficient = commonPHR.StatMaxValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 众数 < 心率 < 高频最大值,平均值系数大于最最大值系数,使用最大值系数 {coefficient}"); + } + else + { + coefficient = commonPHR.StatModeAvgFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 众数 < 心率 < 高频最大值,平均值系数小于最小值系数,使用均值系数 {coefficient}"); + } + } + + // 4、心率 > 高频最大值,取高频最大值系数 + + if (heartRate.HeartRate > commonPHR.MaxValue) + { + coefficient = commonPHR.StatMaxValueFprCoefficient!; + _logger.LogInformation($"{heartRate.Serialno} 心率 > 高频最大值,取高频最大值系数 {coefficient}"); + } + + if (heartRate.HeartRate == commonPHR.Mode) + { + coefficient = commonPHR.StatModeAvgFprCoefficient!; + + _logger.LogInformation($"{heartRate.Serialno} 心率 == 众数,取均值系数 {coefficient}"); + } + #endregion #region 胎心阈值判断 @@ -3034,22 +2973,7 @@ namespace HealthMonitor.WebApi } } - //private DateTime GetSampleTimeFromLastUpdate(DateTime lastUpdate,int interval) - //{ - // DateTime nowInterval = lastUpdate; - // //if (nowInterval.Second > 0) - // //{ - // // nowInterval = nowInterval.AddMinutes(1); - // //} - // // 计算last_update到上一间隔的分钟数 - // int minutesToSubtract = nowInterval.Minute % interval; - - // // 计算上一间隔的时间 - // DateTime previousInterval = nowInterval.AddMinutes(-minutesToSubtract).AddSeconds(-nowInterval.Second).AddMilliseconds(-nowInterval.Millisecond); - - // return previousInterval; - //} - + public static DateTime GetSampleTimeFromLastUpdate(DateTime lastUpdate, int interval) { // 获取当前的分钟