diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs index ddf3688..e68c1cf 100644 --- a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs +++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs @@ -165,7 +165,7 @@ namespace HealthMonitor.Service.Resolver // interval (分钟) var intervalFHR = (int)watchConfig["interval"]!; - var fetalHeartRateIsAbnormal = 0; + var phr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); if (phr.Count >= 30) @@ -196,7 +196,7 @@ namespace HealthMonitor.Service.Resolver } #endregion - #region 计算胎心和胎动数据 + #region 计算胎心数据(按心率时间LastUpdate) var commonPHR = await _serviceTDengine.GetLastAsync(heartRate.Serialno); if (commonPHR == null) { @@ -209,8 +209,7 @@ namespace HealthMonitor.Service.Resolver await _serviceTDengine.InsertAsync("hm_pchr", commonPHR!); _logger.LogInformation($"保存TDengine完成"); } - #region 计算胎心数据(按心率时间LastUpdate) - + // 获取最近的两个记录,并计算它们的 LastUpdate 时间差 var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList(); var timeDiff = firstTwoPhr[0] - firstTwoPhr[1]; @@ -220,6 +219,8 @@ namespace HealthMonitor.Service.Resolver // 高频统计结束时间 var FreqStatsEnd = DateTime.Now; + + // 高频心率启动 if (timeDiffInSeconds <= highFreqSampleInterval) { @@ -249,7 +250,8 @@ namespace HealthMonitor.Service.Resolver // 高频数据不建模 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 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); // 删除高频状态的首条记录 await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); @@ -259,10 +261,11 @@ namespace HealthMonitor.Service.Resolver } #endregion } - // 高频心率结束或正常心率 + // 高频心率结束或平常心率 else { var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + // 高频心率结束 if (phrFreqstatus != null) { /// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), @@ -282,7 +285,8 @@ namespace HealthMonitor.Service.Resolver FreqStatsEnd = firstTwoPhr[1]; _logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,highFreqSampleTimes={highFreqSampleTimes}秒,即将结束高频状态,将下发指令"); - await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString()); + //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); } @@ -290,279 +294,77 @@ namespace HealthMonitor.Service.Resolver /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate.AddSeconds(highFreqSampleTimes))) { - var filterPhr = phr - .Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate); - - var avgPhr = filterPhr - .OrderByDescending(i => i.LastUpdate) - .Skip(1) // 去除首条 - .Take(12) // 计算最后12条 - //.Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh) - .Select(i => i.PregnancyHeartRate).Average(); - // 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig - // 计算一般心率得到胎心系数 - //await SaveAndPushFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr); - //await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); - //await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); - // 高频数据不建模 - FreqStatsEnd = firstTwoPhr[1]; - _logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,超过约定的 {highFreqSampleTimes} 秒,即将结束高频状态,将下发指令"); - - await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString()); - } - - // 删除高频状态的首条记录 - await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - - _logger.LogInformation($"{heartRate.Serialno} 超时结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒"); - } - // 正常心率 - else - { - - // 上15分钟的数据 - // 获取当前时间 - DateTime nowInterval = (DateTime)heartRate.LastUpdate!; - - // 计算last_update到上一间隔的分钟数 - int minutesToSubtract = nowInterval.Minute % intervalFHR; - - // 计算上一间隔的时间 - DateTime previousInterval = nowInterval.AddMinutes(-minutesToSubtract).AddSeconds(-nowInterval.Second).AddMilliseconds(-nowInterval.Millisecond); - - // 使用 last_update 上一刻 - var sampleTimeFHR = DateTimeUtil.ConvertToTimeStamp(previousInterval).ToString(); - - // 计算last_update到下一间隔的分钟数 - int minutesToAdd = intervalFHR - (nowInterval.Minute % intervalFHR); - if (minutesToAdd == intervalFHR) - { - minutesToAdd = 0; // 如果已经是间隔,则不需要增加分钟 - } - - // 计算下一间隔的时间 - DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) - .AddSeconds(-nowInterval.Second) - .AddMilliseconds(-nowInterval.Millisecond); - - - var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); - - var normalPhrStatStartTime = nextInterval; - - var normalPhrStatEndTime = nextInterval.AddMinutes(-intervalFHR); - - _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据, 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} "); - var filteredPhr = daysPhr - // 使用 last_update 下一刻 - .Where(i => i.LastUpdate <= normalPhrStatStartTime && i.LastUpdate >= normalPhrStatEndTime) - .ToList(); - if (filteredPhr.Count == 0) - { - _logger.LogWarning($"{heartRate.Serialno} 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} 孕妇心率数据不足,{filteredPhr.Count}条记录"); - return; - } - var phrValue = filteredPhr.Count == 1 - ? filteredPhr.First().PregnancyHeartRate - : filteredPhr.Average(i => i.PregnancyHeartRate); - - var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!); - - - fetalHeartRateIsAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); - fetalHeartRateIsAbnormal = 0;// 不是高频数据,按正常值 - /* HisGpsFetalHeartRate gpsFetalHeartRate = new() - { - FetalHeartRateId = Guid.NewGuid().ToString("D"), - PersonId = commonPHR!.PersonId, - Serialno = heartRate.Serialno, - HeartRate = fetalHeartRate, - SampleTime = sampleTimeFHR.Length > 10 ? sampleTimeFHR.Substring(0, 10) : sampleTimeFHR, - IsAbnormal = fetalHeartRateIsAbnormal, - StatStartTime = filteredPhr.OrderBy(i => i.LastUpdate).First().LastUpdate, - StatEndTime = filteredPhr.OrderBy(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, sampleTimeFHR, fetalHeartRateIsAbnormal); - - // 推送送微信 - if (fetalHeartRateIsAbnormal != 0) - { - var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false); - var fhrMsgId = $"{heartRate.Serialno}-{sampleTimeFHR}-{Guid.NewGuid().ToString("D")[^3..]}"; - var topic = "topic.push.wx"; - var fhrMsg = new - { - messageId = fhrMsgId, - topic = topic, - time = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTimeFHR.Length < 13 ? sampleTimeFHR.PadRight(13, '0') : sampleTimeFHR)).ToString("yyyy-MM-dd HH:mm:ss"), - data = new - { - deviceId = device?.DeviceId, - imei = heartRate.Serialno, - alarmTypeId = 12, - alarmDeviceName = heartRate.Serialno, - alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = fetalHeartRateIsAbnormal }), - address = string.Empty, - deviceKey = device?.DeviceId - } - }; - await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false); - } - - */ - await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR, false); - - - } - } - - #endregion - - #region 计算胎动数据(按心率时间LastUpdate) - /** - _logger.LogInformation($"{heartRate.Serialno} 计算胎动数据 "); - - var fetalMovementNow = (DateTime)heartRate.LastUpdate!; - - var midNight = new DateTime(fetalMovementNow.Year, fetalMovementNow.Month, fetalMovementNow.Day, 0, 0, 0); - - TimeSpan fetalMovementTS = fetalMovementNow - midNight; - - // 当天每隔2小时的段数,取整数部分 - int segmentCountFM = (int)(fetalMovementTS.TotalHours / 2); - - for (int i = 0; i < segmentCountFM; i++) - { - // 每两小时 - var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddHours(2 * i)).ToString()[..10]; - - // 统计开始时间 - var statStartTime = midNight.AddHours(2 * i); - // 统计结束时间 - var statEndTime = midNight.AddHours(2 * (i+1)); - - var isFetalMovementExisted = await _deviceCacheMgr.FetalMovementIsExistedAsync(heartRate.Serialno, fetalMovementSampleTime); - _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 开始"); - - if (!isFetalMovementExisted) - { - /// 开始计算 - var phrRange = phr.Where(i => i.LastUpdate >= statStartTime && i.LastUpdate<= statEndTime) - .OrderByDescending(i => i.LastUpdate) - .Select(i => i.LastUpdate) - .ToList(); - // 判断是否有持续佩戴 - if (phrRange.Count >= 2) - { - var duringMins = Math.Abs((phrRange.First()- statStartTime).TotalMinutes); - //在餐后时间段(8:00~10:00,12:00~14:00,18:00~20:00,22:00~24:00)取中间值。其他时间段取正常起始值 - bool isInTimeRanges = IsLastUpdateInTimeRanges(fetalMovementNow); - int pregnancyWeeks = (DateTime.Now - edoc.AddDays(-280)).Days / 7; - if (pregnancyWeeks >= 12 && pregnancyWeeks <= 50) + + // 获取高频心率数据个数 + var filterPhr = phr + .Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate) + .Skip(1) + .ToList(); + + //var freqCollection = new List(); + //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 fetalMovementMap = _mgrFetalMovementNormalValueRangeCache.GetFetalMovements(); - - var fetalMovementMapValue = isInTimeRanges ? fetalMovementMap - .Where(i => - i.PregnancyPeriod![0] <= pregnancyWeeks && - i.PregnancyPeriod[1] >= pregnancyWeeks) - .Select(i => i.MedianMovement) - .FirstOrDefault() - : - fetalMovementMap - .Where(i => - i.PregnancyPeriod![0] <= pregnancyWeeks && - i.PregnancyPeriod[1] >= pregnancyWeeks) - .Select(i => i.InitialMovement) - .FirstOrDefault() - ; - - var fetalMovementValue = (fetalMovementMapValue * duringMins * 2) / 120; - // 四舍五入 - var fetalMovement = (int)Math.Round(fetalMovementValue, 0, MidpointRounding.AwayFromZero); - // _logger.LogInformation($"{heartRate.Serialno} segmentCountFMIndex: {i} -- fetalMovementSampleTime:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")} -- statStartTime: {statStartTime} -- statEndTime: {statEndTime}-- isFetalMovementExisted: {isFetalMovementExisted} "); - - _logger.LogInformation($"{heartRate.Serialno} 胎动数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 采样周期:{statStartTime}-{statEndTime}, 原始胎动值:{fetalMovementMapValue}, 佩戴时间 :{duringMins}|{statStartTime}-{phrRange.First()}, 胎动计算值:{fetalMovementValue}, 胎动最终值:{fetalMovement} 已完成."); - - // 获取胎心数据状态与胎动数据状态一致 - var feltalMovementIsAbnormal = fetalHeartRateIsAbnormal; - //var feltalMovementIsAbnormal = 0; - // 推送到api/v1/open/OpenIot/SetFetalMovementConfig - - await _serviceIotApi.SetFetalMovementConfig(heartRate.Serialno, fetalMovement, fetalMovementSampleTime, feltalMovementIsAbnormal); - - // 保存到MySQL数据库 - HisGpsFetalMovement fm = new() - { - FetalMovementId = Guid.NewGuid().ToString("D"), - PersonId = commonPHR!.PersonId, - Serialno = heartRate.Serialno, - CreateTime = DateTime.Now, - IsAbnormal = feltalMovementIsAbnormal, - FetalMovementValue = fetalMovement, - SampleTime = fetalMovementSampleTime, - Method = 1, - IsDisplay = 1, - DeviceKey = commonPHR!.DeviceKey - }; - await _hisFetalMovementApiClient.AddAsync(fm).ConfigureAwait(false); - - // 发送到微信 - if (feltalMovementIsAbnormal != 0) - { - var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false); - var fmMsgId = $"{heartRate.Serialno}-{fetalMovementSampleTime}-{Guid.NewGuid().ToString("D")[^3..]}"; - var topic = "topic.push.wx"; - var fmMsg = new - { - messageId = Guid.NewGuid().ToString("D"), - topic = topic, - time = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(fetalMovementSampleTime.Length < 13 ? fetalMovementSampleTime.PadRight(13, '0') : fetalMovementSampleTime)).ToString("yyyy-MM-dd HH:mm:ss"), - data = new - { - deviceId = device?.DeviceId, - imei = heartRate.Serialno, - alarmTypeId = 12, - alarmDeviceName = heartRate.Serialno, - alarmRemarks = JsonConvert.SerializeObject(new { fetalMovementValue = fetalMovement, isAbnormal = feltalMovementIsAbnormal }), - address = string.Empty, - deviceKey = device?.DeviceId - } - }; - await _serviceMqProcess.ProcessIMEIEventMessageAsync(fmMsgId, topic, fmMsg).ConfigureAwait(false); - } - // 设置入库缓存记录 - await _deviceCacheMgr.SetFetalMovementAsync(heartRate.Serialno, fetalMovementSampleTime,fm); - + 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 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); + } else { - _logger.LogWarning($"{heartRate.Serialno} 孕周 {pregnancyWeeks},超出胎动计算范围"); + _logger.LogInformation($"{heartRate.Serialno} 高频心率的数据不足{stopHighFreqSampleCount}条,不进行胎心计算"); + } } + //不满足持续10分钟highFreqSampleTimes else { - _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 不足两条,不能判断是否持续佩戴"); - + _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); + } + // 平常心率 else { - _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 已处理"); + // 计算本次平常心率的胎心数据 + await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR); } - } - */ - #endregion #endregion } @@ -588,68 +390,83 @@ namespace HealthMonitor.Service.Resolver //} } + /// + /// 平常心率计算胎心数据 + /// + /// + /// + /// + /// + /// + /// + private async Task CalculateNormalFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, int intervalFHR, PregnancyCommonHeartRateModel? commonPHR) + { + // 上15分钟的数据 + // 获取当前时间 + DateTime nowInterval = (DateTime)heartRate.LastUpdate!; - //private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, double avgPhr) - //{ - // var commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno); - // if (commonPHR != null) - // { - // // 保存到TDengine数据库 - // await _serviceTDengine.InsertAsync("hm_pchr", commonPHR); - // // 计算胎心=孕妇心率*系数 - // var fetalHeartRate = SafeType.SafeInt(avgPhr * commonPHR?.StatModeAvgFprCoefficient!); - // var sampleTime = DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString(); - // var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); - - // // 保存到 数据服务 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 = commonPHR.StatStartTime, - // StatEndTime = commonPHR.StatEndTime, - // CreateTime = DateTime.Now, - // Method = 1, - // IsDisplay = 1, - // DeviceKey = commonPHR!.DeviceKey - // }; - // await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false); - - // // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig - // await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal); - - // // 推送到微信 - // var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false); - - // var deviceId = device?.DeviceId; - // var msg = new - // { - // messageId = "", - // topic = "topic.push.wx", - // time="" - // }; - // } - //} + // 计算last_update到上一间隔的分钟数 + int minutesToSubtract = nowInterval.Minute % intervalFHR; + + // 计算上一间隔的时间 + DateTime previousInterval = nowInterval.AddMinutes(-minutesToSubtract).AddSeconds(-nowInterval.Second).AddMilliseconds(-nowInterval.Millisecond); + + // 使用 last_update 上一刻 + var sampleTimeFHR = DateTimeUtil.ConvertToTimeStamp(previousInterval).ToString(); + + // 计算last_update到下一间隔的分钟数 + int minutesToAdd = intervalFHR - (nowInterval.Minute % intervalFHR); + if (minutesToAdd == intervalFHR) + { + minutesToAdd = 0; // 如果已经是间隔,则不需要增加分钟 + } + + // 计算下一间隔的时间 + DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) + .AddSeconds(-nowInterval.Second) + .AddMilliseconds(-nowInterval.Millisecond); + + + var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); + + var normalPhrStatStartTime = nextInterval; + + var normalPhrStatEndTime = nextInterval.AddMinutes(-intervalFHR); + + _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据, 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} "); + var filteredPhr = daysPhr + // 使用 last_update 下一刻 + .Where(i => i.LastUpdate <= normalPhrStatStartTime && i.LastUpdate >= normalPhrStatEndTime) + .ToList(); + if (filteredPhr.Count == 0) + { + _logger.LogWarning($"{heartRate.Serialno} 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} 孕妇心率数据不足,{filteredPhr.Count}条记录"); + return; + } + var phrValue = filteredPhr.Count == 1 + ? filteredPhr.First().PregnancyHeartRate + : filteredPhr.Average(i => i.PregnancyHeartRate); + + //await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR); + await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime); + } /// - /// + /// /// /// /// /// /// - /// - /// 使用高频心率的首条last_update - /// + /// + /// + /// + /// /// - private async Task SaveAndPushFreqFetalHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, double phr,string sampleTime,bool isFreq = true) + private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, double phrValue, string sampleTime,DateTime statStartTime, DateTime statEndTime) { // 计算胎心=孕妇心率*系数 - var fetalHeartRate = SafeType.SafeInt(phr * commonPHR?.StatModeAvgFprCoefficient!); + var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!); //fetalHeartRate = fetalHeartRate > 220 ? 220 : fetalHeartRate; // 胎心的最大值调整为220,超过都按该值220输出 if (fetalHeartRate >= 220) { @@ -657,22 +474,27 @@ namespace HealthMonitor.Service.Resolver var statMaxValueFprCoefficient = commonPHR?.StatMaxValueFprCoefficient!; var statMinValueFprCoefficient = commonPHR?.StatMinValueFprCoefficient!; var coefficient = statMaxValueFprCoefficient < statMinValueFprCoefficient ? statMaxValueFprCoefficient : statMinValueFprCoefficient; - fetalHeartRate = SafeType.SafeInt(phr * coefficient); + fetalHeartRate = SafeType.SafeInt(phrValue * coefficient); if (fetalHeartRate < 220) { - // 倒推系数 _logger.LogWarning($"{heartRate.Serialno} 使用极值系数 {coefficient} ,建模数据可能出现异常,请检查"); } else { fetalHeartRate = 220; - // 倒推系数 _logger.LogWarning($"{heartRate.Serialno} 使用所有系数都不能放映实际,建模数据可能出现异常,请检查"); } } var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); - if (!isFreq) isAbnormal = 0; + var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + if (phrFreqstatus == null) isAbnormal = 0; + + //if (!isFreq) + //{ + // statStartTime = heartRate.LastUpdate; + // + //} // 保存到 数据服务 MySQL 数据库 HisGpsFetalHeartRate gpsFetalHeartRate = new() { @@ -682,8 +504,8 @@ namespace HealthMonitor.Service.Resolver HeartRate = fetalHeartRate, SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime, IsAbnormal = isAbnormal, - StatStartTime = commonPHR.StatStartTime, - StatEndTime = commonPHR.StatEndTime, + StatStartTime = statStartTime, + StatEndTime = statEndTime,//commonPHR.StatEndTime, CreateTime = DateTime.Now, Method = 1, IsDisplay = 1, @@ -705,14 +527,15 @@ namespace HealthMonitor.Service.Resolver messageId = fhrMsgId, topic = topic, time = fhrMsgTime, - data=new { + data = new + { imei = heartRate.Serialno, - value= fetalHeartRate, + value = fetalHeartRate, isAbnormal, - type= "fetalHeart" + type = "fetalHeart" } }; - await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31,fhrThridMsg).ConfigureAwait(false); + await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false); // 胎心数据推送到微信 if (isAbnormal != 0) @@ -739,6 +562,7 @@ namespace HealthMonitor.Service.Resolver } } + private async Task SetIntervalTriggerAsync(string key,string imei, long interval) { // var key = $"health_monitor/schedule_push/{type}/imei/{imei}"; @@ -758,21 +582,6 @@ namespace HealthMonitor.Service.Resolver await _serviceEtcd.PutValAsync(key, result, interval, false).ConfigureAwait(false); } } - - public static bool IsLastUpdateInTimeRanges(DateTime lastUpdate) - { - var now = lastUpdate.TimeOfDay; - - var timeRanges = new List<(TimeSpan Start, TimeSpan End)> - { - // 8:00~10:00,12:00~14:00,18:00~20:00,22:00~24:00 - (new TimeSpan(8, 0, 0), new TimeSpan(10, 0, 0)), - (new TimeSpan(12, 0, 0), new TimeSpan(14, 0, 0)), - (new TimeSpan(18, 0, 0), new TimeSpan(20, 0, 0)), - (new TimeSpan(22, 0, 0), new TimeSpan(24, 0, 0)) - }; - - return timeRanges.Any(range => now >= range.Start && now <= range.End); - } + } }