diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs index 32ae083..be74c33 100644 --- a/HealthMonitor.Service/Biz/db/TDengineService.cs +++ b/HealthMonitor.Service/Biz/db/TDengineService.cs @@ -721,7 +721,7 @@ namespace HealthMonitor.Service.Biz.db _clientSqlSugar.InsertableByObject(model).AS(tbFullName).ExecuteCommand(); } - public Task GetFirstAsync() where T : class + public Task GetLastAsync() where T : class { var tableName = typeof(T) .GetCustomAttribute()? diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs index 746894d..9aaddbc 100644 --- a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs +++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs @@ -85,10 +85,11 @@ namespace HealthMonitor.Service.Resolver if (isFetalHeartEnable) { - #region 高频心率计算 + 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]; @@ -194,44 +195,68 @@ namespace HealthMonitor.Service.Resolver _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}"); } } + #endregion + + #region 定时计算胎心数据触发器 {interval} 秒后 + var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; + var scheduleFetalPush = await _serviceEtcd.GetValAsync(fetalKey).ConfigureAwait(false); + if (string.IsNullOrWhiteSpace(scheduleFetalPush)) + { + var fetalInterval = (int)watchConfig["interval"]!; + + var fetalNow= DateTime.Now; + var fetalTimeNextRun = fetalNow.Add(TimeSpan.FromSeconds(fetalInterval)); + var fetalTTL = fetalInterval; + var data = new + { + imei = heartRate.Serialno, + create_time = fetalNow.ToString("yyyy-MM-dd HH:mm:ss"), + fetalTTL, + next_run_time = fetalTimeNextRun.ToString("yyyy-MM-dd HH:mm:ss") + }; + var result = JsonConvert.SerializeObject(data); + await _serviceEtcd.PutValAsync(fetalKey, result, fetalTTL, false).ConfigureAwait(false); + } + #endregion } - #endregion - } - #region 定时下发触发器 - var key = $"health_monitor/schedule_push/pregnancy_heart_rate/imei/{heartRate.Serialno}"; - var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); - if (string.IsNullOrWhiteSpace(schedule_push)) - { - // 注册首次下推 -#if DEBUG - // await _serviceEtcd.PutValAsync(key, result, 60*1, false).ConfigureAwait(false); - var interval = 0; - // 获取当前时间 - DateTime now = DateTime.Now; - // 计算距离下一个$interval天后的8点的时间间隔 - DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 1, 58).AddDays(interval); - TimeSpan timeUntilNextRun = nextRunTime - now; + #region 定时下发触发器(定时建模) + var key = $"health_monitor/schedule_push/pregnancy_heart_rate/imei/{heartRate.Serialno}"; + var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); - // 如果当前时间已经超过了8点,将等待到明天后的8点 - if (timeUntilNextRun < TimeSpan.Zero) + if (string.IsNullOrWhiteSpace(schedule_push)) { - timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1)); - nextRunTime += timeUntilNextRun; - } - var ttl = (long)timeUntilNextRun.TotalSeconds; - var data = new - { - imei = heartRate.Serialno, - create_time = now.ToString("yyyy-MM-dd HH:mm:ss"), - ttl, - next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss") - }; - var result = JsonConvert.SerializeObject(data); - await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false); + // 注册首次下推 +#if DEBUG + // await _serviceEtcd.PutValAsync(key, result, 60*1, false).ConfigureAwait(false); + + var interval = 0; + // 获取当前时间 + DateTime now = DateTime.Now; + + // 计算距离下一个$interval天后的8点的时间间隔 + DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 1, 58).AddDays(interval); + TimeSpan timeUntilNextRun = nextRunTime - now; + + // 如果当前时间已经超过了8点,将等待到明天后的8点 + if (timeUntilNextRun < TimeSpan.Zero) + { + timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1)); + nextRunTime += timeUntilNextRun; + } + var ttl = (long)timeUntilNextRun.TotalSeconds; + var data = new + { + imei = heartRate.Serialno, + create_time = now.ToString("yyyy-MM-dd HH:mm:ss"), + ttl, + next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss") + }; + var result = JsonConvert.SerializeObject(data); + await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false); #else @@ -264,9 +289,14 @@ namespace HealthMonitor.Service.Resolver await _serviceEtcd.PutValAsync(key, result,ttl, false).ConfigureAwait(false); #endif + } + + #endregion + } - #endregion + + } private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, double avgPhr) diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs index 83ca27a..184f63f 100644 --- a/HealthMonitor.WebApi/Worker.cs +++ b/HealthMonitor.WebApi/Worker.cs @@ -21,6 +21,8 @@ using System.Reflection; using System.Threading.Channels; using TDengineDriver; using TDengineTMQ; +using TelpoDataService.Util.Clients; +using TelpoDataService.Util.Entities.GpsLocationHistory; namespace HealthMonitor.WebApi { @@ -37,10 +39,18 @@ namespace HealthMonitor.WebApi private readonly BoodPressResolverConfig _configBoodPressResolver; private readonly BloodPressReferenceValueCacheManager _bpRefValCacheManager; private readonly PersonCacheManager _personCacheMgr; + private readonly DeviceCacheManager _deviceCacheMgr; + + private readonly GpsLocationHistoryAccessorClient _hisFetalHeartApiClient; private CancellationTokenSource _tokenSource = default!; - public Worker(ILogger logger, IServiceProvider services, PersonCacheManager personCacheMgr, BloodPressReferenceValueCacheManager bpRefValCacheManager, IotApiService IotApiService, IOptions optionBoodPressResolver, PackageProcess processor, TDengineDataSubcribe tdEngineDataSubcribe, TDengineService serviceDengine, HttpHelper httpHelper, EtcdService serviceEtcd) + public Worker(ILogger logger, IServiceProvider services, PersonCacheManager personCacheMgr, + BloodPressReferenceValueCacheManager bpRefValCacheManager, IotApiService IotApiService, + IOptions optionBoodPressResolver, PackageProcess processor, + TDengineDataSubcribe tdEngineDataSubcribe, TDengineService serviceDengine, + GpsLocationHistoryAccessorClient hisFetalHeartApiClient, + HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr) { _logger = logger; _tdEngineDataSubcribe = tdEngineDataSubcribe; @@ -53,6 +63,8 @@ namespace HealthMonitor.WebApi _configBoodPressResolver = optionBoodPressResolver.Value; _bpRefValCacheManager = bpRefValCacheManager; _personCacheMgr = personCacheMgr; + _deviceCacheMgr = deviceCacheMgr; + _hisFetalHeartApiClient = hisFetalHeartApiClient; } public override Task StartAsync(CancellationToken cancellationToken) @@ -222,6 +234,82 @@ namespace HealthMonitor.WebApi await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false); #endif #endregion + } + // health_monitor/schedule_push/cal_fetal_heart_rate/imei/ + else if (key.Contains("health_monitor/schedule_push/cal_fetal_heart_rate/imei/")) + { + + var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067"); + var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1; + + if (isFetalHeartEnable) + { + // 处理胎心计算业务,计算一般心率获取胎心系数 + var commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(imeiDel); + if (commonPHR != null) + { + # region 计算胎心数据 + // 告警上限阀值 + var upperAlarmThreshold = (int)watchConfig!["upperAlarmThreshold"]!; + // 告警下限阀值 + var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; + + var lastPhr = await _serviceTDengine.GetLastAsync(); + // 计算胎心=孕妇心率*系数 + var fetalHeartRate = SafeType.SafeInt(lastPhr.PregnancyHeartRate * commonPHR?.StatModeAvgFprCoefficient!); + + var sampleTime = DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString(); + + var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); + + HisGpsFetalHeartRate gpsFetalHeartRate = new() + { + FetalHeartRateId = Guid.NewGuid().ToString("D"), + PersonId = commonPHR!.PersonId, + Serialno = imeiDel, + HeartRate = fetalHeartRate, + SampleTime = sampleTime, + IsAbnormal = isAbnormal, + StatStartTime = commonPHR.StatStartTime, + StatEndTime = commonPHR.StatEndTime, + 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(imeiDel, fetalHeartRate, sampleTime, isAbnormal); + #endregion + + #region 注册定时计算胎心数据触发器 {interval} 秒后 + //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{imeiDel}"; + var fetalKey = key; + var scheduleFetalPush = await _serviceEtcd.GetValAsync(fetalKey).ConfigureAwait(false); + if (string.IsNullOrWhiteSpace(scheduleFetalPush)) + { + var fetalInterval = (int)watchConfig!["interval"]!; + + var fetalNow = DateTime.Now; + var fetalTimeNextRun = fetalNow.Add(TimeSpan.FromSeconds(fetalInterval)); + var fetalTTL = fetalInterval; + var data = new + { + imei = imeiDel, + create_time = fetalNow.ToString("yyyy-MM-dd HH:mm:ss"), + fetalTTL, + next_run_time = fetalTimeNextRun.ToString("yyyy-MM-dd HH:mm:ss") + }; + var result = JsonConvert.SerializeObject(data); + await _serviceEtcd.PutValAsync(fetalKey, result, fetalTTL, false).ConfigureAwait(false); + } + #endregion + } + } + + } else {