diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs index 42ea17f..f657b27 100644 --- a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs +++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs @@ -130,202 +130,400 @@ namespace HealthMonitor.Service.Resolver var phr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); if (phr.Count >= 30) { - /** + #region 计算胎心和胎动数据 var commonPHR = await _serviceTDengine.GetLastAsync(heartRate.Serialno); - if (commonPHR != null) + if (commonPHR == null) { - var lastUpdateNow = (DateTime)heartRate.LastUpdate!; - var midNight = new DateTime(lastUpdateNow.Year, lastUpdateNow.Month, lastUpdateNow.Day, 0, 0, 0); - #region 计算胎心数据 - _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据 "); + // 处理孕妇业务,计算一般心率并下发 + commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno); + // 建模完成 + var flag = await _serviceIotApi.SetFetalConfig(heartRate.Serialno, 1, commonPHR!.MaxValue, commonPHR!.MinValue); + _logger.LogInformation($"{heartRate.Serialno} 记录数量足够,建模完成"); + // 保存到TDengine数据库 + await _serviceTDengine.InsertAsync("hm_pchr", commonPHR!); + _logger.LogInformation($"保存TDengine完成"); + } + #region 计算胎心数据(按心率时间LastUpdate) - var fhrNow = lastUpdateNow; + // 获取最近的两个记录,并计算它们的 LastUpdate 时间差 + var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList(); + var timeDiff = firstTwoPhr[0] - firstTwoPhr[1]; - TimeSpan fhrTS = fhrNow - midNight; - // 当天每隔intervalFHR 分钟的段数,取整数部分 - int segmentCountFHR = (int)(fhrTS.TotalMinutes / intervalFHR); - for (int i = 0; i < segmentCountFHR; i++) - { - // 每intervalFHR * i分钟 - var fhrSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddMinutes(intervalFHR * i)).ToString()[..10]; + // 如果需要,将时间差转换为秒 + var timeDiffInSeconds = timeDiff.TotalSeconds; - // 统计开始时间 - var statStartTimeFHR = midNight.AddMinutes(intervalFHR * i); - // 统计结束时间 - var statEndTimeFHR = midNight.AddMinutes(intervalFHR * (i + 1)); + // 高频心率启动 + if (timeDiffInSeconds <= highFreqSampleInterval) + { - var isFHRExisted =await _mgrFetalHeartRateCache.FetalHeartRateIsExistedAsync(heartRate.Serialno, fhrSampleTime); - - _logger.LogInformation($"{heartRate.Serialno} 胎心数据采样时间:{fhrSampleTime}|{midNight.AddMinutes(intervalFHR * i).ToString("yyyy-MM-dd HH:mm:ss")}, 采样周期:{statStartTimeFHR}-{statEndTimeFHR},isFHRExisted:{isFHRExisted} "); + var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + if (phrFreqstatus == null) + { + /// 设置高频状态 + _logger.LogInformation($"进入高频心率启动状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); + // 设置高频状态 + var freqFirstPhr = phr.OrderByDescending(i => i.Timestamp).First(); + await _deviceCacheMgr.SetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno, freqFirstPhr); + //phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + } + /// phr PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), + /// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig + #region 检查是否连续12个值都是正常的 + // 获取最近连续正常次数个心率记录 + var lastPhr = phr.OrderByDescending(i => i.Timestamp).Take(stopHighFreqSampleCount).ToList(); + + // 检查是否连续12个值都是正常的 + if (lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)) + { + var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average(); + // 计算一般心率得到胎心系数 + await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); - if (!isFHRExisted) + } + #endregion + } + // 高频心率结束或正常心率 + else + { + var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + if (phrFreqstatus != null) + { + /// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), + /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig + if (highFreqSampleTimes == 0) { - // 开始计算 ,每intervalFHR分钟计算一个 - var phrRange = phr.Where(i => i.LastUpdate >= statStartTimeFHR && i.LastUpdate <= statEndTimeFHR) - .OrderByDescending(i => i.LastUpdate) - .ToList(); - - // 胎心数据每intervalFHR分钟计算1个值,采集的数据多于1个取平均值再*胎心系数。 - var phrValue = phrRange.Count == 1 - ? phrRange.First().PregnancyHeartRate - : phrRange.Average(i => i.PregnancyHeartRate); - // 当天的系数,没有的就实时计算 - var fprCoefficient = 0f; - - //if (commonPHR.CreateTime.Year == lastUpdateNow.Year && - // commonPHR.CreateTime.Month == lastUpdateNow.Month && - // commonPHR.CreateTime.Day == lastUpdateNow.Day - // ) - //{ - // fprCoefficient = (float)commonPHR?.StatModeAvgFprCoefficient!; - //} - //else - //{ - // //var daysDiff = 7 - (DateTime.Now.Day - lastUpdateNow.Day); - // //var realtimePCHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno, daysDiff); - // //fprCoefficient = realtimePCHR!.StatModeAvgFprCoefficient; - // var pchr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno); - // var dayPCHR = pchr.Where(i => i.CreateTime.Year == lastUpdateNow.Year && i.CreateTime.Month == lastUpdateNow.Month && i.CreateTime.Day == i.CreateTime.Day); - // fprCoefficient=dayPCHR.First().StatModeAvgFprCoefficient; - //} - - fprCoefficient = (float)commonPHR?.StatModeAvgFprCoefficient!; - - var fetalHeartRate = SafeType.SafeInt(phrValue * fprCoefficient); - - var 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 = fhrSampleTime.Length > 10 ? fhrSampleTime.Substring(0, 10) : fhrSampleTime, - IsAbnormal = fetalHeartRateIsAbnormal, - StatStartTime = phrRange.OrderBy(i => i.LastUpdate).First().LastUpdate, - StatEndTime = phrRange.OrderBy(i => i.LastUpdate).Last().LastUpdate, - CreateTime = DateTime.Now, - Method = 1, - IsDisplay = 1, - DeviceKey = commonPHR!.DeviceKey - }; - // 保存到 数据服务 MySQL 数据库 - await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false); + var avgPhr = phr.OrderByDescending(i => i.Timestamp) + .Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) + .Skip(1) // 去除首条 + .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()); - // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig - await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, fhrSampleTime, fetalHeartRateIsAbnormal); + } - // 推送到微信 + /// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), + /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig + if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate + TimeSpan.FromSeconds(highFreqSampleTimes))) + { + var avgPhr = phr + .Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) + .Skip(1) // 去除首条 + .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 _mgrFetalHeartRateCache.SetFetalHeartRateAsync(heartRate.Serialno, fhrSampleTime); } + + // 删除高频状态的首条记录 + await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + + /// 设置高频状态 + _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); } + // 正常心率 + else + { - #endregion + // 上15分钟的数据 + // 获取当前时间 + DateTime nowInterval = (DateTime)heartRate.LastUpdate!; - #region 计算胎动数据 - _logger.LogInformation($"{heartRate.Serialno} 计算胎动数据 "); + // 计算last_update到上一刻钟的分钟数 + int minutesToSubtract = nowInterval.Minute % intervalFHR; - var fmNow = lastUpdateNow; + // 计算上一刻钟的时间 + DateTime previousInterval = nowInterval.AddMinutes(-minutesToSubtract).AddSeconds(-nowInterval.Second).AddMilliseconds(-nowInterval.Millisecond); - TimeSpan fmTS = fmNow - midNight; + // 使用 last_update 上一刻 + var sampleTimeFHR = DateTimeUtil.ConvertToTimeStamp(previousInterval).ToString(); - // 当天每隔2小时的段数,取整数部分 - int segmentCountFM = (int)(fmTS.TotalHours / 2); + // 计算last_update到下一刻钟的分钟数 + int minutesToAdd = intervalFHR - (nowInterval.Minute % intervalFHR); + if (minutesToAdd == intervalFHR) + { + minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 + } - for (int i = 0; i < segmentCountFM; i++) - { - // 每两小时 - var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddHours(2 * i)).ToString()[..10]; + // 计算下一刻钟的时间 + DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) + .AddSeconds(-nowInterval.Second) + .AddMilliseconds(-nowInterval.Millisecond); - // 统计开始时间 - var statStartTime = midNight.AddHours(2 * i); - // 统计结束时间 - var statEndTime = midNight.AddHours(2 * (i + 1)); - //var isFetalMovementExist = await _hisFetalMovementApiClient.GetFirstAsync(param, heartRate.Serialno[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") }); - var isFetalMovementExisted = await _mgrFetalMovement.FetalMovementIsExistedAsync(heartRate.Serialno, fetalMovementSampleTime); + var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); - if (!isFetalMovementExisted) - { - /// 开始计算 - var phrRange = phr.Where(i => i.LastUpdate >= statStartTime && i.LastUpdate <= statEndTime) - .OrderByDescending(i => i.LastUpdate) - .Select(i => i.LastUpdate) + 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!); - 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(fmNow); - int pregnancyWeeks = (DateTime.Now - edoc.AddDays(-280)).Days / 7; - if (pregnancyWeeks >= 12 && pregnancyWeeks <= 50) + 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 { - var fetalMovementMap = _mgrFetalMovementNormalValueRangeCache.GetFetalMovements(); + 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); + } + } + } - 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() - ; + #endregion - var fetalMovementValue = (fetalMovementMapValue * duringMins * 2) / 120; + #region 计算胎动数据(按心率时间LastUpdate) + /** + _logger.LogInformation($"{heartRate.Serialno} 计算胎动数据 "); + var fetalMovementNow = (DateTime)heartRate.LastUpdate!; - // 四舍五入 - 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} "); + var midNight = new DateTime(fetalMovementNow.Year, fetalMovementNow.Month, fetalMovementNow.Day, 0, 0, 0); - _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}"); + TimeSpan fetalMovementTS = fetalMovementNow - midNight; - // 获取胎心数据状态与胎动数据状态一致 - //var feltalMovementIsAbnormal = fetalHeartRateIsAbnormal; - var feltalMovementIsAbnormal = 0; - // 推送到api/v1/open/OpenIot/SetFetalMovementConfig + // 当天每隔2小时的段数,取整数部分 + int segmentCountFM = (int)(fetalMovementTS.TotalHours / 2); - await _serviceIotApi.SetFetalMovementConfig(heartRate.Serialno, fetalMovement, fetalMovementSampleTime, feltalMovementIsAbnormal); + 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); - // 保存到MySQL数据库 - HisGpsFetalMovement fm = new() + int pregnancyWeeks = (DateTime.Now - edoc.AddDays(-280)).Days / 7; + if (pregnancyWeeks >= 12 && pregnancyWeeks <= 50) + { + 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 { - 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 + 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 _hisFetalMovementApiClient.AddAsync(fm).ConfigureAwait(false); - - // 设置入库缓存记录 - await _mgrFetalMovement.SetFetalMovementAsync(heartRate.Serialno, fetalMovementSampleTime); + await _serviceMqProcess.ProcessIMEIEventMessageAsync(fmMsgId, topic, fmMsg).ConfigureAwait(false); } + // 设置入库缓存记录 + await _deviceCacheMgr.SetFetalMovementAsync(heartRate.Serialno, fetalMovementSampleTime,fm); + + } + else + { + _logger.LogWarning($"{heartRate.Serialno} 孕周 {pregnancyWeeks},超出胎动计算范围"); } } + else + { + _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 不足两条,不能判断是否持续佩戴"); + } } - #endregion + else + { + _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 已处理"); + } + } */ + #endregion + + #endregion + + #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 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; + + await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl); + } + #endregion + #region 定时计算胎心数据触发器 {interval} 秒后 + //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; + //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, 60 * 15); + #endregion + + #region 定时计算胎心数据触发器下一刻钟后 + //// 获取当前时间 + //DateTime nowInterval = DateTime.Now; + + //// 计算下一个15分钟的刻钟 + //int minutesToAdd = 15 - (nowInterval.Minute % 15); + //if (minutesToAdd == 15) + //{ + // minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 + //} + //// 计算下一刻钟的时间 + //DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) + // .AddSeconds(-nowInterval.Second) + // .AddMilliseconds(-nowInterval.Millisecond); + + //// 计算时间差 + //TimeSpan timeDifference = nextInterval - nowInterval; + + //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; + //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); + #endregion #region 高频心率计算 @@ -422,397 +620,12 @@ namespace HealthMonitor.Service.Resolver //} #endregion - - #region 计算胎心和胎动数据 - var commonPHR = await _serviceTDengine.GetLastAsync(heartRate.Serialno); - if (commonPHR != null) - { - - #region 计算胎心数据 - - // 获取最近的两个记录,并计算它们的 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; - - // 高频心率启动 - if (timeDiffInSeconds <= highFreqSampleInterval) - { - - var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - if (phrFreqstatus == null) - { - /// 设置高频状态 - _logger.LogInformation($"进入高频心率启动状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); - // 设置高频状态 - var freqFirstPhr = phr.OrderByDescending(i => i.Timestamp).First(); - await _deviceCacheMgr.SetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno, freqFirstPhr); - //phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - } - /// phr PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), - /// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig - #region 检查是否连续12个值都是正常的 - // 获取最近连续正常次数个心率记录 - var lastPhr = phr.OrderByDescending(i => i.Timestamp).Take(stopHighFreqSampleCount).ToList(); - - // 检查是否连续12个值都是正常的 - if (lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)) - { - var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average(); - // 计算一般心率得到胎心系数 - await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString()); - - } - #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.Timestamp) - .Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) - .Skip(1) // 去除首条 - .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()); - - } - - /// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), - /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig - if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate + TimeSpan.FromSeconds(highFreqSampleTimes))) - { - - var avgPhr = phr - .Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) - .Skip(1) // 去除首条 - .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 _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - - /// 设置高频状态 - _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); - } - // 正常心率 - 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); - } - - - } - } - - #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 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); - - } - else - { - _logger.LogWarning($"{heartRate.Serialno} 孕周 {pregnancyWeeks},超出胎动计算范围"); - } - } - else - { - _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 不足两条,不能判断是否持续佩戴"); - - } - } - else - { - _logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 已处理"); - } - - } - */ - #endregion - } - #endregion - - - - #region 定时计算胎心数据触发器 {interval} 秒后 - //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; - //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, 60 * 15); - #endregion - - #region 定时计算胎心数据触发器下一刻钟后 - //// 获取当前时间 - //DateTime nowInterval = DateTime.Now; - - //// 计算下一个15分钟的刻钟 - //int minutesToAdd = 15 - (nowInterval.Minute % 15); - //if (minutesToAdd == 15) - //{ - // minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 - //} - //// 计算下一刻钟的时间 - //DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) - // .AddSeconds(-nowInterval.Second) - // .AddMilliseconds(-nowInterval.Millisecond); - - //// 计算时间差 - //TimeSpan timeDifference = nextInterval - nowInterval; - - //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; - //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); - #endregion - - #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 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; - - await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl); - } - #endregion + } + else + { + // 建模中 + //var flag = await _serviceIotApi.SetFetalConfig(heartRate.Serialno); + _logger.LogInformation($"{heartRate.Serialno} 记录不足30条,建模中"); } #region 定时下发触发器(定时建模) @@ -884,11 +697,8 @@ namespace HealthMonitor.Service.Resolver } #endregion - } - - } private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, double avgPhr)