Browse Source

调整

datasub12_fetal_heart_rate_0
H Vs 3 months ago
parent
commit
26dce9ea5d
8 changed files with 595 additions and 186 deletions
  1. +1
    -1
      HealthMonitor.Service/Biz/db/TDengineService.cs
  2. +12
    -10
      HealthMonitor.Service/Cache/DeviceCacheManager.cs
  3. +94
    -0
      HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs
  4. +8
    -6
      HealthMonitor.Service/Cache/FetalMovementCacheManager.cs
  5. +11
    -0
      HealthMonitor.Service/Cache/RedisHelperDb10.cs
  6. +459
    -167
      HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
  7. +8
    -0
      HealthMonitor.WebApi/Program.cs
  8. +2
    -2
      HealthMonitor.WebApi/Worker.cs

+ 1
- 1
HealthMonitor.Service/Biz/db/TDengineService.cs View File

@@ -825,7 +825,7 @@ namespace HealthMonitor.Service.Biz.db
#region 胎心算法

/// <summary>
/// 计算个人一般心率
/// 计算个人一般心率(最大值,最大值,最小值)
/// </summary>
/// <param name="serialNo"></param>
/// <param name="days"></param>


+ 12
- 10
HealthMonitor.Service/Cache/DeviceCacheManager.cs View File

@@ -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<DeviceCacheManager> _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<GpsDevice?> GetDeviceBySerialNoAsync(string sn)
{
string key = CACHE_KEY_DEVICE + sn;
var device = await RedisHelperDb10.GetAsync<GpsDevice>(key).ConfigureAwait(false);
return device;
}

/// <summary>
///
/// </summary>


+ 94
- 0
HealthMonitor.Service/Cache/FetalHeartRateCacheManager.cs View File

@@ -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<FetalHeartRateCacheManager> _logger;

private readonly GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> _hisFetalHeartRateApiClient;

private const string CACHE_KEY_FETALHEARTRATE = "FHR_";

public FetalHeartRateCacheManager(ILogger<FetalHeartRateCacheManager> logger, GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> 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<bool> 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<QueryFilterCondition>
{
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;
}
}
}

+ 8
- 6
HealthMonitor.Service/Cache/FetalMovementCacheManager.cs View File

@@ -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<bool> 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;
}
}


+ 11
- 0
HealthMonitor.Service/Cache/RedisHelperDb10.cs View File

@@ -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<RedisHelperDb10> { }
}

+ 459
- 167
HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs View File

@@ -45,13 +45,14 @@ namespace HealthMonitor.Service.Resolver
private readonly FetalMovementNormalValueRangeCacheManager _mgrFetalMovementNormalValueRangeCache;

private readonly FetalMovementCacheManager _mgrFetalMovement;
private readonly FetalHeartRateCacheManager _mgrFetalHeartRateCache;


public PregnancyHeartRateResolver(ILogger<PregnancyHeartRateResolver> logger,
HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr,
IotApiService iotApiService, TDengineService serviceDengine, FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr,
GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> hisFetalHeartApiClient,
FetalMovementCacheManager fetalMovementCacheManager,
FetalMovementCacheManager fetalMovementCacheManager, FetalHeartRateCacheManager fetalHeartRateCacheManager,
GpsLocationHistoryAccessorClient<HisGpsFetalMovement> 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<PregnancyHeartRateModel>(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<PregnancyCommonHeartRateModel>(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<PregnancyCommonHeartRateModel>(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<PregnancyHeartRateModel>(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<PregnancyHeartRateModel>(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;


+ 8
- 0
HealthMonitor.WebApi/Program.cs View File

@@ -174,6 +174,7 @@ namespace HealthMonitor.WebApi
.AddSingleton<PersonCacheManager>()
.AddSingleton<DeviceCacheManager>()
.AddSingleton<FetalMovementCacheManager>()
.AddSingleton<FetalHeartRateCacheManager>()
.AddSingleton<FhrPhrMapCacheManager>()
.AddSingleton<FetalMovementNormalValueRangeCacheManager>()
.AddSingleton<BloodPressReferenceValueCacheManager>();
@@ -286,6 +287,13 @@ namespace HealthMonitor.WebApi
var csredisDb7 = new CSRedis.CSRedisClient(csredisDb7Con.ToString());
RedisHelperDb7.Initialization(csredisDb7);

// redis db10
var csredisDb10Con = app.Services.GetService<IOptions<RedisConfig>>()!.Value;
csredisDb10Con.DefaultDatabase = 10;
csredisDb10Con.Prefix = "_GW_";
var csredisDb10 = new CSRedis.CSRedisClient(csredisDb10Con.ToString());
RedisHelperDb10.Initialization(csredisDb10);


app.UseHttpsRedirection();



+ 2
- 2
HealthMonitor.WebApi/Worker.cs View File

@@ -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点


Loading…
Cancel
Save