diff --git a/HealthMonitor.Service/Biz/IotApiService.cs b/HealthMonitor.Service/Biz/IotApiService.cs index 70b0545..2edd812 100644 --- a/HealthMonitor.Service/Biz/IotApiService.cs +++ b/HealthMonitor.Service/Biz/IotApiService.cs @@ -343,10 +343,10 @@ namespace HealthMonitor.Service.Biz /// /// /// 心率值 - /// 检测时间(时间戳) + /// 检测时间(时间戳) /// 0 //是否异常 0 表示正常;1表示偏高;2表示偏低 /// - public async Task SetFetalHeartRateConfig(string serialno, int fhr, string sampeTime, int isAbnormal) + public async Task SetFetalHeartRateConfig(string serialno, int fhr, string sampleTime, int isAbnormal) { try @@ -379,7 +379,7 @@ namespace HealthMonitor.Service.Biz { imei = serialno, heartValue = fhr, - sampeTime, + sampleTime, isAbnormal }; diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs index a6c1b57..55672b0 100644 --- a/HealthMonitor.Service/Biz/db/TDengineService.cs +++ b/HealthMonitor.Service/Biz/db/TDengineService.cs @@ -739,6 +739,30 @@ namespace HealthMonitor.Service.Biz.db return first; } + public Task GetLastAsync(string serialNo) where T : class + { + var tableName = typeof(T) + .GetCustomAttribute()? + .STableName; + // 创建表示 Timestamp 属性的表达式 + var parameter = Expression.Parameter(typeof(T), "x"); + var timestampProperty = Expression.Property(parameter, "Timestamp"); + var timestampLambda = Expression.Lambda>(Expression.Convert(timestampProperty, typeof(object)), parameter); + + // 创建表示 SerialNo 属性的表达式 + var serialNoProperty = Expression.Property(parameter, "SerialNumber"); + var serialNoConstant = Expression.Constant(serialNo); + var equalExpression = Expression.Equal(serialNoProperty, serialNoConstant); + var serialNoLambda = Expression.Lambda>(equalExpression, parameter); + + var first = _clientSqlSugar + .Queryable() + .AS(tableName) + .Where(serialNoLambda) + .OrderByDescending(timestampLambda).FirstAsync(); + return first; + } + public async Task> GetBySerialNoAsync(string serialNo) where T : class { var tableName = typeof(T) diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs index add3a5c..5c088cc 100644 --- a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs +++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs @@ -86,7 +86,22 @@ namespace HealthMonitor.Service.Resolver if (isFetalHeartEnable) { - + // 高频心率采样间隔 + var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]!; + // 触发高频监测的心率上限值 + var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; + // 触发高频监测的心率下限值 + var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; + //停止高频心率采样心率连续正常次数 + var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; + // 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 + var highFreqSampleTimes = (int)watchConfig["stopHighFreqSampleCount"]!; + // 告警上限阀值 + var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; + // 告警下限阀值 + var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!; + + var phr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); if (phr.Count >= 30) { @@ -97,20 +112,7 @@ namespace HealthMonitor.Service.Resolver // 如果需要,将时间差转换为秒 var timeDiffInSeconds = timeDiff.TotalSeconds; - // 高频心率采样间隔 - var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]!; - // 触发高频监测的心率上限值 - var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!; - // 触发高频监测的心率下限值 - var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!; - //停止高频心率采样心率连续正常次数 - var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!; - // 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长 - var highFreqSampleTimes = (int)watchConfig["stopHighFreqSampleCount"]!; - // 告警上限阀值 - var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!; - // 告警下限阀值 - var lowerAlarmThreshold= (int)watchConfig["lowerAlarmThreshold"]!; + // 高频心率启动 if (timeDiffInSeconds<=highFreqSampleInterval) @@ -198,34 +200,108 @@ namespace HealthMonitor.Service.Resolver } #endregion + #region 计算胎心数据 + var commonPHR = await _serviceTDengine.GetLastAsync(heartRate.Serialno); + if (commonPHR != null) + { + + #region 计算胎心数据 + // 上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) + { + minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 + } + + // 计算下一刻钟的时间 + DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) + .AddSeconds(-nowQuarter.Second) + .AddMilliseconds(-nowQuarter.Millisecond); + + + var daysPhr = await _serviceTDengine.GetBySerialNoAsync(heartRate.Serialno, 7); + + var filteredPhr = daysPhr + // 使用 last_update 下一刻 + .Where(i => i.LastUpdate <= nextQuarter && i.LastUpdate >= nextQuarter.AddMinutes(-15)) + .ToList(); + + var qarterPhrValue = filteredPhr.Count == 1 + ? filteredPhr.First().PregnancyHeartRate + : filteredPhr.Average(i => i.PregnancyHeartRate); + + var fetalHeartRate = SafeType.SafeInt(qarterPhrValue * commonPHR?.StatModeAvgFprCoefficient!); + + + var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0); + + HisGpsFetalHeartRate gpsFetalHeartRate = new() + { + FetalHeartRateId = Guid.NewGuid().ToString("D"), + PersonId = commonPHR!.PersonId, + Serialno = heartRate.Serialno, + HeartRate = fetalHeartRate, + SampleTime = sampleTime, + IsAbnormal = isAbnormal, + StatStartTime = filteredPhr.OrderByDescending(i => i.LastUpdate).First().LastUpdate, + StatEndTime = filteredPhr.OrderByDescending(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, isAbnormal); + #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 nowQuarter = DateTime.Now; + //// 获取当前时间 + //DateTime nowQuarter = DateTime.Now; - // 计算下一个15分钟的刻钟 - int minutesToAdd = 15 - (nowQuarter.Minute % 15); - if (minutesToAdd == 15) - { - minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 - } - // 计算下一刻钟的时间 - DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) - .AddSeconds(-nowQuarter.Second) - .AddMilliseconds(-nowQuarter.Millisecond); + //// 计算下一个15分钟的刻钟 + //int minutesToAdd = 15 - (nowQuarter.Minute % 15); + //if (minutesToAdd == 15) + //{ + // minutesToAdd = 0; // 如果已经是刻钟,则不需要增加分钟 + //} + //// 计算下一刻钟的时间 + //DateTime nextQuarter = nowQuarter.AddMinutes(minutesToAdd) + // .AddSeconds(-nowQuarter.Second) + // .AddMilliseconds(-nowQuarter.Millisecond); - // 计算时间差 - TimeSpan timeDifference = nextQuarter - nowQuarter; + //// 计算时间差 + //TimeSpan timeDifference = nextQuarter - nowQuarter; - var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; - await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); + //var fetalKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}"; + //await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds); #endregion - #region 定时计算胎动数据触发器 0 点开始 var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}"; /// 计算 0 点秒数 diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs index 630023e..1e1aae5 100644 --- a/HealthMonitor.WebApi/Worker.cs +++ b/HealthMonitor.WebApi/Worker.cs @@ -246,79 +246,79 @@ namespace HealthMonitor.WebApi // 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!); - - // 上15分钟的数据 - // 获取当前时间 - DateTime now = DateTime.Now; - - // 计算当前时间到上一刻钟的分钟数 - int minutesToSubtract = now.Minute % 15; - - // 计算上一刻钟的时间 - DateTime previousQuarter = now.AddMinutes(-minutesToSubtract).AddSeconds(-now.Second).AddMilliseconds(-now.Millisecond); - - var lastQuarterPhr = await _serviceTDengine.GetBySerialNoAsync(imeiDel, 1); - - var filteredPhr = lastQuarterPhr - .Where(i => i.LastUpdate <= previousQuarter && i.LastUpdate >= previousQuarter.AddMinutes(-15)) - .ToList(); - - var lastQuarterPhrValue = filteredPhr.Count == 1 - ? filteredPhr.First().PregnancyHeartRate - : filteredPhr.Average(i => i.PregnancyHeartRate); - - var fetalHeartRate = SafeType.SafeInt(lastQuarterPhrValue * 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 = filteredPhr.OrderByDescending(i=>i.LastUpdate).First().LastUpdate, - StatEndTime = filteredPhr.OrderByDescending(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(imeiDel, fetalHeartRate, sampleTime, isAbnormal); - #endregion - - #region 注册定时计算胎心数据触发器 {interval} 秒后 - //await SetIntervalTriggerAsync(key, imeiDel, 60 * 15); - #endregion - } - } - + /** + 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!); + + // 上15分钟的数据 + // 获取当前时间 + DateTime now = DateTime.Now; + + // 计算当前时间到上一刻钟的分钟数 + int minutesToSubtract = now.Minute % 15; + + // 计算上一刻钟的时间 + DateTime previousQuarter = now.AddMinutes(-minutesToSubtract).AddSeconds(-now.Second).AddMilliseconds(-now.Millisecond); + + var lastQuarterPhr = await _serviceTDengine.GetBySerialNoAsync(imeiDel, 1); + + var filteredPhr = lastQuarterPhr + .Where(i => i.LastUpdate <= previousQuarter && i.LastUpdate >= previousQuarter.AddMinutes(-15)) + .ToList(); + + var lastQuarterPhrValue = filteredPhr.Count == 1 + ? filteredPhr.First().PregnancyHeartRate + : filteredPhr.Average(i => i.PregnancyHeartRate); + + var fetalHeartRate = SafeType.SafeInt(lastQuarterPhrValue * 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 = filteredPhr.OrderByDescending(i=>i.LastUpdate).First().LastUpdate, + StatEndTime = filteredPhr.OrderByDescending(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(imeiDel, fetalHeartRate, sampleTime, isAbnormal); + #endregion + + #region 注册定时计算胎心数据触发器 {interval} 秒后 + //await SetIntervalTriggerAsync(key, imeiDel, 60 * 15); + #endregion + } + } + */ } @@ -331,11 +331,11 @@ namespace HealthMonitor.WebApi if (isFetalHeartEnable) { // 检查胎心建模 - var fchr = await _serviceTDengine.GetLastAsync(); + var fchr = await _serviceTDengine.GetLastAsync(imeiDel); if (fchr != null) { // 获取孕妇心率数据接近最近2小时的数据 - var phr = await _serviceTDengine.GetBySerialNoAsync(imeiDel, 1); + var phr = await _serviceTDengine.GetBySerialNoAsync(imeiDel, 7); var now = DateTime.Now; var ago2hrs = now.AddHours(-2); var phrRange = phr.Where(i => i.LastUpdate >= ago2hrs)