Przeglądaj źródła

调整胎动计算

datasub12_fetal_heart_rate_0
H Vs 7 miesięcy temu
rodzic
commit
aa5c68bb74
2 zmienionych plików z 234 dodań i 29 usunięć
  1. +37
    -26
      HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
  2. +197
    -3
      HealthMonitor.WebApi/Worker.cs

+ 37
- 26
HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs Wyświetl plik

@@ -50,6 +50,8 @@ namespace HealthMonitor.Service.Resolver

private readonly MqProcessLogic _serviceMqProcess;

private static int[] SCHEDULE_HOUR = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 };




@@ -323,10 +325,10 @@ namespace HealthMonitor.Service.Resolver
#endregion
}
*/
#region 高频心率计算
//// 获取最近的两个记录,并计算它们的 LastUpdate 时间差
//var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList();
//var timeDiff = firstTwoPhr[0] - firstTwoPhr[1];
@@ -337,7 +339,7 @@ namespace HealthMonitor.Service.Resolver
//// 高频心率启动
//if (timeDiffInSeconds<=highFreqSampleInterval)
//{
// var phrFreqstatus =await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
// if (phrFreqstatus == null)
// {
@@ -418,7 +420,7 @@ namespace HealthMonitor.Service.Resolver
// _logger.LogInformation($"结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}");
// }
//}
#endregion

#region 计算胎心和胎动数据
@@ -513,7 +515,7 @@ namespace HealthMonitor.Service.Resolver
// 正常心率
else
{
// 上15分钟的数据
// 获取当前时间
DateTime nowInterval = (DateTime)heartRate.LastUpdate!;
@@ -587,7 +589,7 @@ namespace HealthMonitor.Service.Resolver
await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTimeFHR, fetalHeartRateIsAbnormal);

// 推送送微信
if (fetalHeartRateIsAbnormal!=0)
if (fetalHeartRateIsAbnormal != 0)
{
var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
var fhrMsgId = $"{heartRate.Serialno}-{sampleTimeFHR}-{Guid.NewGuid().ToString("D")[^3..]}";
@@ -610,14 +612,15 @@ namespace HealthMonitor.Service.Resolver
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);
}

}
}

#endregion

#region 计算胎动数据
#region 计算胎动数据(按心率时间LastUpdate)
/**
_logger.LogInformation($"{heartRate.Serialno} 计算胎动数据 ");

var fetalMovementNow = (DateTime)heartRate.LastUpdate!;
@@ -751,10 +754,11 @@ namespace HealthMonitor.Service.Resolver
}

}
*/
#endregion
}
#endregion


#region 定时计算胎心数据触发器 {interval} 秒后
@@ -784,23 +788,30 @@ namespace HealthMonitor.Service.Resolver
//await SetIntervalTriggerAsync(fetalKey, heartRate.Serialno, (long)timeDifference.TotalSeconds);
#endregion

#region 定时计算胎动数据触发器 0 点开始
//var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
#region 定时计算胎动数据触发器两小时间隔开始
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
///// 计算 0 点秒数
//DateTime now = DateTime.Now;
//var rand = new Random();
//var pushSec = rand.Next(59);
//int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10;
//DateTime nextRunTime = new (now.Year, now.Month, now.Day, 0, pushMin, pushSec);
//TimeSpan timeUntilNextRun = nextRunTime - now;
//if (timeUntilNextRun < TimeSpan.Zero)
//{
// timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1));
// nextRunTime += timeUntilNextRun;
//}
//var ttl = (long)timeUntilNextRun.TotalSeconds;

//await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl);
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
}



+ 197
- 3
HealthMonitor.WebApi/Worker.cs Wyświetl plik

@@ -12,6 +12,7 @@ using HealthMonitor.Service.Biz;
using HealthMonitor.Service.Biz.db;
using HealthMonitor.Service.Cache;
using HealthMonitor.Service.Etcd;
using HealthMonitor.Service.MessageQueue;
using HealthMonitor.Service.Sub;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
@@ -48,6 +49,9 @@ namespace HealthMonitor.WebApi
private readonly FetalMovementNormalValueRangeCacheManager _mgrFetalMovementNormalValueRangeCache;

private readonly GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> _hisFetalHeartApiClient;
private readonly GpsLocationHistoryAccessorClient<HisGpsFetalMovement> _hisFetalMovementApiClient;

private readonly MqProcessLogic _serviceMqProcess;

private CancellationTokenSource _tokenSource = default!;

@@ -56,7 +60,8 @@ namespace HealthMonitor.WebApi
IOptions<BoodPressResolverConfig> optionBoodPressResolver, PackageProcess processor,
TDengineDataSubcribe tdEngineDataSubcribe, TDengineService serviceDengine,
GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> hisFetalHeartApiClient,
FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr,
GpsLocationHistoryAccessorClient<HisGpsFetalMovement> hisFetalMovementApiClient,
FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr, MqProcessLogic serviceMqProcess,
HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr)
{
_logger = logger;
@@ -72,6 +77,8 @@ namespace HealthMonitor.WebApi
_personCacheMgr = personCacheMgr;
_deviceCacheMgr = deviceCacheMgr;
_hisFetalHeartApiClient = hisFetalHeartApiClient;
_hisFetalMovementApiClient = hisFetalMovementApiClient;
_serviceMqProcess = serviceMqProcess;
_mgrFetalMovementNormalValueRangeCache = fetalMovementNormalValueRangeCacheMgr;
}

@@ -371,7 +378,7 @@ namespace HealthMonitor.WebApi
// .Select(i => i.InitialMovement)
// .FirstOrDefault()
// ;
// var fetalMovementValue = fetalMovementMapValue * duringMins * 2 / 120;
// // 四舍五入
// var fetalMovement= (int)Math.Round(fetalMovementValue, 0, MidpointRounding.AwayFromZero);
@@ -388,7 +395,7 @@ namespace HealthMonitor.WebApi
// {
// new ()
// {
// Key=nameof(HisGpsFetalHeartRate.Serialno),
// Key=nameof(HisGpsFetalimeiDel),
// Value=imeiDel,
// ValueType=QueryValueTypeEnum.String,
// Operator=QueryOperatorEnum.Equal
@@ -422,7 +429,177 @@ namespace HealthMonitor.WebApi
// #endregion
//}

#region 胎动延时计算
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067");
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1;
if (isFetalHeartEnable)
{

var edoc = DateTimeUtil.ToDateTime(watchConfig!["EDOC"]!.ToString());
// 已经建模
var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(imeiDel);
if (commonPHR != null)
{
var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(imeiDel, 7);
_logger.LogInformation($"{imeiDel} 计算胎动数据 ");

var fmNow = DateTime.Now;
// 两小时前
var fmNowSubtract = fmNow.AddMinutes(-fmNow.Minute).AddSeconds(-fmNow.Second).AddMilliseconds(-fmNow.Millisecond);
var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(fmNowSubtract).ToString()[..10];

// 统计开始时间
var statStartTime = fmNowSubtract.AddHours(-2);
// 统计结束时间
var statEndTime = fmNowSubtract;

var isFetalMovementExisted = await _deviceCacheMgr.FetalMovementIsExistedAsync(imeiDel, fetalMovementSampleTime);
_logger.LogInformation($"{imeiDel} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{fmNowSubtract.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(statEndTime);

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($"{imeiDel} segmentCountFMIndex: {i} -- fetalMovementSampleTime:{fetalMovementSampleTime}|{midNight.AddHours(2 * i).ToString("yyyy-MM-dd HH:mm:ss")} -- statStartTime: {statStartTime} -- statEndTime: {statEndTime}-- isFetalMovementExisted: {isFetalMovementExisted} ");

_logger.LogInformation($"{imeiDel} 胎动数据采样时间:{fetalMovementSampleTime}|{fmNowSubtract.ToString("yyyy-MM-dd HH:mm:ss")}, 采样周期:{statStartTime}-{statEndTime}, 原始胎动值:{fetalMovementMapValue}, 佩戴时间 :{duringMins}|{statStartTime}-{phrRange.First()}, 胎动计算值:{fetalMovementValue}, 胎动最终值:{fetalMovement} 已完成.");

// 读取胎心数据
GeneralParam param = new()
{
Filters = new List<QueryFilterCondition>
{
new ()
{
Key=nameof(HisGpsFetalHeartRate.Serialno),
Value=imeiDel,
ValueType=QueryValueTypeEnum.String,
Operator=QueryOperatorEnum.Equal
},
//new ()
//{
// Key=nameof(HisGpsFetalHeartRate.SampleTime),
// Value=sampleTime,
// ValueType=QueryValueTypeEnum.String,
// Operator=QueryOperatorEnum.GreaterEqual
//},
},
OrderBys=new List<OrderByCondition>
{
new (){
IsDesc=true,
Key=nameof(HisGpsFetalHeartRate.SampleTime)
}
}
};
var fetalHeartRateIsAbnormal = 0;
var fhr = await _hisFetalHeartApiClient.GetFirstAsync(param, imeiDel[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") });
// 获取胎心数据状态与胎动数据状态一致
var feltalMovementIsAbnormal = fetalHeartRateIsAbnormal;
//var feltalMovementIsAbnormal = 0;
// 推送到api/v1/open/OpenIot/SetFetalMovementConfig

await _serviceIotApi.SetFetalMovementConfig(imeiDel, fetalMovement, fetalMovementSampleTime, feltalMovementIsAbnormal);

// 保存到MySQL数据库
HisGpsFetalMovement fm = new()
{
FetalMovementId = Guid.NewGuid().ToString("D"),
PersonId = commonPHR!.PersonId,
Serialno = imeiDel,
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(imeiDel).ConfigureAwait(false);
var fmMsgId = $"{imeiDel}-{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 = imeiDel,
alarmTypeId = 12,
alarmDeviceName = imeiDel,
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(imeiDel, fetalMovementSampleTime, fm);

}
else
{
_logger.LogWarning($"{imeiDel} 孕周 {pregnancyWeeks},超出胎动计算范围");
}
}
else
{
_logger.LogInformation($"{imeiDel} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{fmNowSubtract.ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 不足两条,不能判断是否持续佩戴");

}
}
else
{
_logger.LogInformation($"{imeiDel} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{fmNowSubtract.ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 已处理");
}
}

}
#endregion
}
else
{
@@ -794,5 +971,22 @@ namespace HealthMonitor.WebApi

return timeRanges.Any(range => now >= range.Start && now <= range.End);
}
public static bool IsLastUpdateInTimeRanges(DateTime lastUpdate)
{
var now = lastUpdate.TimeOfDay;

var timeRanges = new List<(TimeSpan Start, TimeSpan End)>
{
// 8:00~10:00,12:00~14:00,18:00~20:00,22:00~24:00
(new TimeSpan(8, 0, 0), new TimeSpan(10, 0, 0)),
(new TimeSpan(12, 0, 0), new TimeSpan(14, 0, 0)),
(new TimeSpan(18, 0, 0), new TimeSpan(20, 0, 0)),
(new TimeSpan(22, 0, 0), new TimeSpan(24, 0, 0))
};

return timeRanges.Any(range => now >= range.Start && now <= range.End);
}


}
}

Ładowanie…
Anuluj
Zapisz