From 26dce9ea5dfa1db2005f4afd87d6b78fe484c1c2 Mon Sep 17 00:00:00 2001 From: H Vs Date: Fri, 26 Jul 2024 14:18:28 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Biz/db/TDengineService.cs | 2 +- .../Cache/DeviceCacheManager.cs | 22 +- .../Cache/FetalHeartRateCacheManager.cs | 94 +++ .../Cache/FetalMovementCacheManager.cs | 14 +- .../Cache/RedisHelperDb10.cs | 11 + .../Resolver/PregnancyHeartRateResolver.cs | 626 +++++++++++++----- HealthMonitor.WebApi/Program.cs | 8 + HealthMonitor.WebApi/Worker.cs | 4 +- 8 files changed, 595 insertions(+), 186 deletions(-) create mode 100644 HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs create mode 100644 HealthMonitor.Service/Cache/RedisHelperDb10.cs diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs index 6feb925..de434d0 100644 --- a/HealthMonitor.Service/Biz/db/TDengineService.cs +++ b/HealthMonitor.Service/Biz/db/TDengineService.cs @@ -825,7 +825,7 @@ namespace HealthMonitor.Service.Biz.db #region 胎心算法 /// - /// 计算个人一般心率 + /// 计算个人一般心率(最大值,最大值,最小值) /// /// /// diff --git a/HealthMonitor.Service/Cache/DeviceCacheManager.cs b/HealthMonitor.Service/Cache/DeviceCacheManager.cs index 8b3c533..857a1b5 100644 --- a/HealthMonitor.Service/Cache/DeviceCacheManager.cs +++ b/HealthMonitor.Service/Cache/DeviceCacheManager.cs @@ -1,20 +1,15 @@ -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; +using HealthMonitor.Model.Service.Mapper; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TDengineTMQ; -using System.Web; -using HealthMonitor.Model.Service.Mapper; +using Newtonsoft.Json.Linq; +using TelpoDataService.Util.Entities.GpsCard; namespace HealthMonitor.Service.Cache { public class DeviceCacheManager { private readonly ILogger _logger; + private const string CACHE_KEY_DEVICE = "Device_"; private const string CACHE_KEY_GPSDEVICE_WATCH_CONFIG = "#GPSDEVICE_WATCH_CONFIG_HASH"; @@ -24,6 +19,13 @@ namespace HealthMonitor.Service.Cache } + public async Task GetDeviceBySerialNoAsync(string sn) + { + string key = CACHE_KEY_DEVICE + sn; + var device = await RedisHelperDb10.GetAsync(key).ConfigureAwait(false); + return device; + } + /// /// /// diff --git a/HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs b/HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs new file mode 100644 index 0000000..a0286ee --- /dev/null +++ b/HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs @@ -0,0 +1,94 @@ +using HealthMonitor.Common; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelpoDataService.Util.Clients; +using TelpoDataService.Util.Entities.GpsLocationHistory; +using TelpoDataService.Util.Models; +using TelpoDataService.Util.QueryObjects; + +namespace HealthMonitor.Service.Cache +{ + public class FetalHeartRateCacheManager + { + private readonly ILogger _logger; + + private readonly GpsLocationHistoryAccessorClient _hisFetalHeartRateApiClient; + + private const string CACHE_KEY_FETALHEARTRATE = "FHR_"; + + public FetalHeartRateCacheManager(ILogger logger, GpsLocationHistoryAccessorClient hisFetalHeartRateApiClient) + { + _logger = logger; + _hisFetalHeartRateApiClient = hisFetalHeartRateApiClient; + } + + public async Task SetFetalHeartRateAsync(string serialNo, string sampleTime) + { + try + { + var key = $"{CACHE_KEY_FETALHEARTRATE}_{serialNo}_{sampleTime}"; + var time = long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime); + var value = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(time).ToString("yyyy-MM-dd HH:mm:ss"); + await RedisHelper.SetAsync(key, value, 7200).ConfigureAwait(false); + } + catch (Exception ex) + { + + _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}"); + } + } + + public async Task FetalHeartRateIsExistedAsync(string serialNo, string sampleTime) + { + try + { + var key = $"{CACHE_KEY_FETALHEARTRATE}_{serialNo}_{sampleTime}"; + var res = await RedisHelper.GetAsync(key).ConfigureAwait(false); + + if (string.IsNullOrEmpty(res)) + { + GeneralParam param = new() + { + Filters = new List + { + new () + { + Key=nameof(HisGpsFetalHeartRate.Serialno), + Value=serialNo, + ValueType=QueryValueTypeEnum.String, + Operator=QueryOperatorEnum.Equal + }, + new () + { + Key=nameof(HisGpsFetalHeartRate.SampleTime), + Value=sampleTime, + ValueType=QueryValueTypeEnum.String, + Operator=QueryOperatorEnum.Equal + }, + } + }; + var isFetalMovementExist = await _hisFetalHeartRateApiClient.GetFirstAsync(param, serialNo[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") }); + if (isFetalMovementExist != null) + { + await SetFetalHeartRateAsync(serialNo, sampleTime); + return true; + } + } + else + { + return true; + } + + } + catch (Exception ex) + { + _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}"); + } + return false; + } + } +} diff --git a/HealthMonitor.Service/Cache/FetalMovementCacheManager.cs b/HealthMonitor.Service/Cache/FetalMovementCacheManager.cs index 606bada..ed84e69 100644 --- a/HealthMonitor.Service/Cache/FetalMovementCacheManager.cs +++ b/HealthMonitor.Service/Cache/FetalMovementCacheManager.cs @@ -27,14 +27,17 @@ namespace HealthMonitor.Service.Cache _logger = logger; _hisFetalMovementApiClient = hisFetalMovementApiClient; } - public async Task SetFetalMovementAsync(string serialNo, string sampleTime) + public async Task SetFetalMovementAsync(string serialNo, string sampleTime, HisGpsFetalMovement fm) { try { var key = $"{CACHE_KEY_FETALMOVEMENT}_{serialNo}_{sampleTime}"; var time = long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime); var value = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(time).ToString("yyyy-MM-dd HH:mm:ss"); - await RedisHelper.SetAsync(key, value, 2 * 3600).ConfigureAwait(false); + + fm.SampleTime = value; + + await RedisHelper.SetAsync(key, JsonConvert.SerializeObject(fm), 7200).ConfigureAwait(false); } catch (Exception ex) { @@ -43,7 +46,6 @@ namespace HealthMonitor.Service.Cache } } - public async Task FetalMovementIsExistedAsync(string serialNo, string sampleTime) { try @@ -59,14 +61,14 @@ namespace HealthMonitor.Service.Cache { new () { - Key=nameof(HisGpsFetalHeartRate.Serialno), + Key=nameof(HisGpsFetalMovement.Serialno), Value=serialNo, ValueType=QueryValueTypeEnum.String, Operator=QueryOperatorEnum.Equal }, new () { - Key=nameof(HisGpsFetalHeartRate.SampleTime), + Key=nameof(HisGpsFetalMovement.SampleTime), Value=sampleTime, ValueType=QueryValueTypeEnum.String, Operator=QueryOperatorEnum.Equal @@ -76,7 +78,7 @@ namespace HealthMonitor.Service.Cache var isFetalMovementExist = await _hisFetalMovementApiClient.GetFirstAsync(param, serialNo[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") }); if (isFetalMovementExist != null) { - await SetFetalMovementAsync(serialNo,sampleTime); + await SetFetalMovementAsync(serialNo, sampleTime, isFetalMovementExist); return true; } } diff --git a/HealthMonitor.Service/Cache/RedisHelperDb10.cs b/HealthMonitor.Service/Cache/RedisHelperDb10.cs new file mode 100644 index 0000000..89af6ab --- /dev/null +++ b/HealthMonitor.Service/Cache/RedisHelperDb10.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HealthMonitor.Service.Cache +{ + public abstract class RedisHelperDb10: RedisHelper { } + +} diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs index 6b14383..92f4cf6 100644 --- a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs +++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs @@ -45,13 +45,14 @@ namespace HealthMonitor.Service.Resolver private readonly FetalMovementNormalValueRangeCacheManager _mgrFetalMovementNormalValueRangeCache; private readonly FetalMovementCacheManager _mgrFetalMovement; + private readonly FetalHeartRateCacheManager _mgrFetalHeartRateCache; public PregnancyHeartRateResolver(ILogger logger, HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr, IotApiService iotApiService, TDengineService serviceDengine, FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr, GpsLocationHistoryAccessorClient hisFetalHeartApiClient, - FetalMovementCacheManager fetalMovementCacheManager, + FetalMovementCacheManager fetalMovementCacheManager, FetalHeartRateCacheManager fetalHeartRateCacheManager, GpsLocationHistoryAccessorClient hisFetalMovementApiClient ) { @@ -65,6 +66,7 @@ namespace HealthMonitor.Service.Resolver _hisFetalMovementApiClient = hisFetalMovementApiClient; _mgrFetalMovementNormalValueRangeCache = fetalMovementNormalValueRangeCacheMgr; _mgrFetalMovement = fetalMovementCacheManager; + _mgrFetalHeartRateCache = fetalHeartRateCacheManager; } public void SetResolveInfo(PackageMsgModel msg) @@ -90,11 +92,9 @@ namespace HealthMonitor.Service.Resolver public async Task ExecuteMessageAsync() { - //throw new NotImplementedException(); var messageId = _messageId.Value; var heartRate = _msgData.Value!; - var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(heartRate.Serialno, "0067"); var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; @@ -116,104 +116,305 @@ namespace HealthMonitor.Service.Resolver var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; // EDOC var edoc = DateTimeUtil.ToDateTime(watchConfig!["EDOC"]!.ToString()); + // interval (分钟) + var intervalFHR= (int)watchConfig["interval"]!; + var fetalHeartRateIsAbnormal = 0; var phr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); if (phr.Count >= 30) { - #region 高频心率计算 - // 获取最近的两个记录,并计算它们的 LastUpdate 时间差 - var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList(); - var timeDiff = firstTwoPhr[0] - firstTwoPhr[1]; + /** + var commonPHR = await _serviceTDengine.GetLastAsync(heartRate.Serialno); + 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} 计算胎心数据 "); - // 如果需要,将时间差转换为秒 - var timeDiffInSeconds = timeDiff.TotalSeconds; - + var fhrNow = lastUpdateNow; - // 高频心率启动 - 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)) + TimeSpan fhrTS = fhrNow - midNight; + // 当天每隔intervalFHR 分钟的段数,取整数部分 + int segmentCountFHR = (int)(fhrTS.TotalMinutes / intervalFHR); + for (int i = 0; i < segmentCountFHR; i++) { - var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average(); - // 计算一般心率得到胎心系数 - await SaveAndPushFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr); + // 每intervalFHR * i分钟 + var fhrSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddMinutes(intervalFHR * i)).ToString()[..10]; + // 统计开始时间 + var statStartTimeFHR = midNight.AddMinutes(intervalFHR * i); + // 统计结束时间 + var statEndTimeFHR = midNight.AddMinutes(intervalFHR * (i + 1)); + + 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} "); + + if (!isFHRExisted) + { + // 开始计算 ,每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); + + // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig + await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, fhrSampleTime, fetalHeartRateIsAbnormal); + + // 推送到微信 + + + // 设置入库缓存记录 + await _mgrFetalHeartRateCache.SetFetalHeartRateAsync(heartRate.Serialno, fhrSampleTime); + } } + #endregion - } - // 高频心率结束 - else - { - var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - if (phrFreqstatus != null) + + #region 计算胎动数据 + _logger.LogInformation($"{heartRate.Serialno} 计算胎动数据 "); + + var fmNow = lastUpdateNow; + + TimeSpan fmTS = fmNow - midNight; + + // 当天每隔2小时的段数,取整数部分 + int segmentCountFM = (int)(fmTS.TotalHours / 2); + + for (int i = 0; i < segmentCountFM; i++) { - /// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), - /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig - if (highFreqSampleTimes==0) - { - // if (phr.OrderByDescending(i => i.Timestamp) - //.Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) - //.Skip(1) // 去除首条 - //.All(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHig)) - // { - // var avgPhr = phr.Select(i => i.PregnancyHeartRate).Average(); - - // // 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig - // // 计算一般心率得到胎心系数 - // } - - 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); + // 每两小时 + var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddHours(2 * i)).ToString()[..10]; - } + // 统计开始时间 + var statStartTime = midNight.AddHours(2 * i); + // 统计结束时间 + var statEndTime = midNight.AddHours(2 * (i + 1)); - /// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), - /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig - if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate + TimeSpan.FromSeconds(highFreqSampleTimes))) + //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); + + if (!isFetalMovementExisted) { + /// 开始计算 + var phrRange = phr.Where(i => i.LastUpdate >= statStartTime && i.LastUpdate <= statEndTime) + .OrderByDescending(i => i.LastUpdate) + .Select(i => i.LastUpdate) + .ToList(); - 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); - } + 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) + { + 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}"); - // 删除高频状态的首条记录 - await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + // 获取胎心数据状态与胎动数据状态一致 + //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); + + // 设置入库缓存记录 + await _mgrFetalMovement.SetFetalMovementAsync(heartRate.Serialno, fetalMovementSampleTime); + } + } + } - /// 设置高频状态 - _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); } + #endregion } + */ + + + #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 SaveAndPushFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr); + + // } + // #endregion + //} + //// 高频心率结束 + //else + //{ + // var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + // if (phrFreqstatus != null) + // { + // /// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig), + // /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig + // if (highFreqSampleTimes==0) + // { + // // if (phr.OrderByDescending(i => i.Timestamp) + // //.Where(i => i.Timestamp >= phrFreqstatus?.Timestamp) + // //.Skip(1) // 去除首条 + // //.All(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHig)) + // // { + // // var avgPhr = phr.Select(i => i.PregnancyHeartRate).Average(); + + // // // 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig + // // // 计算一般心率得到胎心系数 + // // } + + // 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); + + // } + + // /// 在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 _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); + + // /// 设置高频状态 + // _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); + // } + //} + #endregion #region 计算胎心和胎动数据 @@ -222,69 +423,156 @@ namespace HealthMonitor.Service.Resolver { #region 计算胎心数据 - _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据 "); - // 上15分钟的数据 - // 获取当前时间 - DateTime nowQuarter = (DateTime)heartRate.LastUpdate!; - - // 计算last_update到上一刻钟的分钟数 - int minutesToSubtract = nowQuarter.Minute % 15; - - // 计算上一刻钟的时间 - DateTime previousQuarter = nowQuarter.AddMinutes(-minutesToSubtract).AddSeconds(-nowQuarter.Second).AddMilliseconds(-nowQuarter.Millisecond); - - // 使用 last_update 上一刻 - var sampleTime = DateTimeUtil.ConvertToTimeStamp(previousQuarter).ToString(); - - // 计算last_update到下一刻钟的分钟数 - int minutesToAdd = 15 - (nowQuarter.Minute % 15); - if (minutesToAdd == 15) + + // 获取最近的两个记录,并计算它们的 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) { - minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 + + 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 SaveAndPushFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr); + + } + #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); + + } - // 计算下一刻钟的时间 - DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) - .AddSeconds(-nowQuarter.Second) - .AddMilliseconds(-nowQuarter.Millisecond); + /// 在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); + } - var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); + // 删除高频状态的首条记录 + await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno); - var filteredPhr = daysPhr - // 使用 last_update 下一刻 - .Where(i => i.LastUpdate <= nextQuarter && i.LastUpdate >= nextQuarter.AddMinutes(-15)) - .ToList(); + /// 设置高频状态 + _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); + } + // 正常心率 + else + { + _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据"); + // 上15分钟的数据 + // 获取当前时间 + DateTime nowInterval = (DateTime)heartRate.LastUpdate!; - var qarterPhrValue = filteredPhr.Count == 1 - ? filteredPhr.First().PregnancyHeartRate - : filteredPhr.Average(i => i.PregnancyHeartRate); + // 计算last_update到上一刻钟的分钟数 + int minutesToSubtract = nowInterval.Minute % intervalFHR; - var fetalHeartRate = SafeType.SafeInt(qarterPhrValue * commonPHR?.StatModeAvgFprCoefficient!); + // 计算上一刻钟的时间 + 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 filteredPhr = daysPhr + // 使用 last_update 下一刻 + .Where(i => i.LastUpdate <= nextInterval && i.LastUpdate >= nextInterval.AddMinutes(-intervalFHR)) + .ToList(); + + 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); + + } + } - 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 = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime, - 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, sampleTime, fetalHeartRateIsAbnormal); #endregion #region 计算胎动数据 @@ -297,9 +585,9 @@ namespace HealthMonitor.Service.Resolver TimeSpan fetalMovementTS = fetalMovementNow - midNight; // 当天每隔2小时的段数,取整数部分 - int segmentCount = (int)(fetalMovementTS.TotalHours / 2); + int segmentCountFM = (int)(fetalMovementTS.TotalHours / 2); - for (int i = 0; i < segmentCount; i++) + for (int i = 0; i < segmentCountFM; i++) { // 每两小时 var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(midNight.AddHours(2 * i)).ToString()[..10]; @@ -311,7 +599,8 @@ namespace HealthMonitor.Service.Resolver //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); - + //_logger.LogInformation($"{heartRate.Serialno} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime}, "); + if (!isFetalMovementExisted) { /// 开始计算 @@ -319,7 +608,7 @@ namespace HealthMonitor.Service.Resolver .OrderByDescending(i => i.LastUpdate) .Select(i => i.LastUpdate) .ToList(); - + // 判断是否有持续佩戴 if (phrRange.Count >= 2) { var duringMins = Math.Abs((phrRange.First()- statStartTime).TotalMinutes); @@ -347,18 +636,17 @@ namespace HealthMonitor.Service.Resolver ; var fetalMovementValue = (fetalMovementMapValue * duringMins * 2) / 120; - - // 四舍五入 var fetalMovement = (int)Math.Round(fetalMovementValue, 0, MidpointRounding.AwayFromZero); - // _logger.LogInformation($"{heartRate.Serialno} segmentCountIndex: {i} -- fetalMovementSampleTime:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")} -- statStartTime: {statStartTime} -- statEndTime: {statEndTime}-- isFetalMovementExisted: {isFetalMovementExisted} "); + // _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数据库 @@ -378,16 +666,25 @@ namespace HealthMonitor.Service.Resolver await _hisFetalMovementApiClient.AddAsync(fm).ConfigureAwait(false); // 设置入库缓存记录 - await _mgrFetalMovement.SetFetalMovementAsync(heartRate.Serialno, fetalMovementSampleTime); + await _mgrFetalMovement.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 } #endregion - + #region 定时计算胎心数据触发器 {interval} 秒后 @@ -397,21 +694,21 @@ namespace HealthMonitor.Service.Resolver #region 定时计算胎心数据触发器下一刻钟后 //// 获取当前时间 - //DateTime nowQuarter = DateTime.Now; + //DateTime nowInterval = DateTime.Now; //// 计算下一个15分钟的刻钟 - //int minutesToAdd = 15 - (nowQuarter.Minute % 15); + //int minutesToAdd = 15 - (nowInterval.Minute % 15); //if (minutesToAdd == 15) //{ // minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 //} //// 计算下一刻钟的时间 - //DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) - // .AddSeconds(-nowQuarter.Second) - // .AddMilliseconds(-nowQuarter.Millisecond); + //DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd) + // .AddSeconds(-nowInterval.Second) + // .AddMilliseconds(-nowInterval.Millisecond); //// 计算时间差 - //TimeSpan timeDifference = nextQuarter - nowQuarter; + //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); @@ -481,7 +778,7 @@ namespace HealthMonitor.Service.Resolver var pushSec = rand.Next(59); int pushMin= int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10; // 计算距离下一个$interval天后的8点的时间间隔 - DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 18, pushMin, pushSec).AddDays(interval); + DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 0, pushMin, pushSec).AddDays(interval); TimeSpan timeUntilNextRun = nextRunTime - now; @@ -545,6 +842,17 @@ namespace HealthMonitor.Service.Resolver // 推送到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="" + }; } } @@ -568,22 +876,6 @@ namespace HealthMonitor.Service.Resolver } } - public static bool IsNowInTimeRanges() - { - var now = DateTime.Now.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); - } - public static bool IsLastUpdateInTimeRanges(DateTime lastUpdate) { var now = lastUpdate.TimeOfDay; diff --git a/HealthMonitor.WebApi/Program.cs b/HealthMonitor.WebApi/Program.cs index 226df70..d081961 100644 --- a/HealthMonitor.WebApi/Program.cs +++ b/HealthMonitor.WebApi/Program.cs @@ -174,6 +174,7 @@ namespace HealthMonitor.WebApi .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton(); @@ -286,6 +287,13 @@ namespace HealthMonitor.WebApi var csredisDb7 = new CSRedis.CSRedisClient(csredisDb7Con.ToString()); RedisHelperDb7.Initialization(csredisDb7); + // redis db10 + var csredisDb10Con = app.Services.GetService>()!.Value; + csredisDb10Con.DefaultDatabase = 10; + csredisDb10Con.Prefix = "_GW_"; + var csredisDb10 = new CSRedis.CSRedisClient(csredisDb10Con.ToString()); + RedisHelperDb10.Initialization(csredisDb10); + app.UseHttpsRedirection(); diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs index 2be6dfd..68b885e 100644 --- a/HealthMonitor.WebApi/Worker.cs +++ b/HealthMonitor.WebApi/Worker.cs @@ -218,8 +218,8 @@ namespace HealthMonitor.WebApi var pushSec = rand.Next(59); int pushMin = int.TryParse(imeiDel.AsSpan(imeiDel.Length - 1), out pushMin) ? pushMin : 10; - // 计算距离下一个$interval天后的8点的时间间隔 - DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 18, pushMin, pushSec).AddDays(interval); + // 计算距离下一个$interval天后的0点的时间间隔 + DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 0, pushMin, pushSec).AddDays(interval); TimeSpan timeUntilNextRun = nextRunTime - now; // 如果当前时间已经超过了8点,将等待到明天后的8点