Explorar el Código

调整胎动奇数才计算之前lastupdate的数据

master
H Vs hace 2 meses
padre
commit
04dfdedd98
Se han modificado 2 ficheros con 461 adiciones y 1 borrados
  1. +50
    -0
      HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
  2. +411
    -1
      HealthMonitor.WebApi/Worker.cs

+ 50
- 0
HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs Ver fichero

@@ -52,6 +52,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 };

private static int[] ODD_SCHEDULE_HOUR = new int[] { 1, 3, 5, 7, 9, 11,13, 15, 17, 19, 21, 23 };
// 延时胎心计算间隔周期
private static int INTERVAL_FHR=15;

@@ -181,6 +183,8 @@ namespace HealthMonitor.Service.Resolver
if (nonFreqPhr.Count >= 30)
{
#region 定时计算胎动数据触发器两小时间隔开始

/**
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
///// 计算 0 点秒数
var fetalMovementLastUpdate = (DateTime)heartRate.LastUpdate!;
@@ -204,8 +208,54 @@ namespace HealthMonitor.Service.Resolver

await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl, heartRate);
}
*/
#endregion

#region 定时计算胎动数据触发器两小时间隔开始(奇数小时计算)
var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
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 fmScheduleNow = DateTime.Now;
int hour = fmScheduleNow.Hour;
int selectedScheduleHour;

// 使用模运算来获取相应的ODD_SCHEDULE_HOUR
if (hour % 2 == 0)
{
selectedScheduleHour = ODD_SCHEDULE_HOUR[hour / 2 % ODD_SCHEDULE_HOUR.Length];
}
else
{
selectedScheduleHour = ODD_SCHEDULE_HOUR[(hour + 1) / 2 % ODD_SCHEDULE_HOUR.Length];
}

DateTime scheduledDateTime = new DateTime(
fmScheduleNow.Year,
fmScheduleNow.Month,
fmScheduleNow.Day,
selectedScheduleHour,
0, // 分钟设为 0
0 // 秒设为 0
);

// 如果生成的时间在当前时间之前
// 或者 fmScheduleNow 在 23 点之后并且 selectedScheduleHour 在 1 点(即次日)
if (scheduledDateTime < fmScheduleNow || (fmScheduleNow.Hour >= 23 && selectedScheduleHour <= 1))
{
scheduledDateTime = scheduledDateTime.AddDays(1);
}

TimeSpan timeUntilNextRun = scheduledDateTime - fmScheduleNow;
var ttl = (long)timeUntilNextRun.TotalSeconds;

await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl, heartRate);
#endregion



#region 计算胎心数据(按心率时间LastUpdate)
var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(heartRate.Serialno);
if (commonPHR == null)


+ 411
- 1
HealthMonitor.WebApi/Worker.cs Ver fichero

@@ -546,7 +546,7 @@ namespace HealthMonitor.WebApi
{

#region 胎动延时计算
/**
/**
using (_logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = $"FM-{imeiDel}-{DateTime.Now.ToString("yyyyMMddHHmmss")}" }))
{
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067");
@@ -925,6 +925,7 @@ namespace HealthMonitor.WebApi
#endregion

#region 胎动延时计算(使用线程再延时)
/**
using (_logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = $"FM-{imeiDel}-{DateTime.Now.ToString("yyyyMMddHHmmss")}" }))
{
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067");
@@ -1343,6 +1344,415 @@ namespace HealthMonitor.WebApi

}
}
*/
#endregion

#region 胎动延时计算(实时now是3小时,计算 lastupdate 0~2范围的数据,)
///实时now的hour是3小时,计算 lastupdate 0~2范围的数据,
///只在 HOUR = new int[] { 1, 3, 5, 7, 9, 11,13, 15, 17, 19, 21, 23 };是奇数

using (_logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = $"FM-{imeiDel}-{DateTime.Now.ToString("yyyyMMddHHmmss")}" }))
{
try
{
var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(imeiDel, "0067");
_logger.LogInformation($"触发胎动计算,设备配置{JsonConvert.SerializeObject(watchConfig)}");
var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1;
var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! >= 60 ? (int)watchConfig!["highFreqSampleInterval"]! : 60;

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} 计算胎动数据 ");

DateTime fmNow = DateTime.Now;
int fmNowHour = fmNow.Hour;
DateTime statStartTime;
DateTime statEndTime;

if (fmNowHour == 1)
{
// last_update 22~0
statStartTime = fmNow.Date.AddDays(-1).AddHours(22);
statEndTime = fmNow.Date;
}
else
{
statStartTime = fmNow.Date.AddHours(fmNowHour - 3);
statEndTime = fmNow.Date.AddHours(fmNowHour - 1);
}

_logger.LogInformation($"{imeiDel} 胎动统计周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}-{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");


var fetalMovementSampleTime = DateTimeUtil.ConvertToTimeStamp(statStartTime).ToString()[..10];
var isFetalMovementExisted = await _deviceCacheMgr.FetalMovementIsExistedAsync(imeiDel, fetalMovementSampleTime);

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)
{
// 读取胎心数据
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 time = long.Parse(fhr.SampleTime.Length < 13 ? fhr.SampleTime.PadRight(13, '0') : fhr.SampleTime);
var fhrSampleTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(time);

// 胎心数据时间与胎动时间一致,最后一条胎心数据与胎动数据的小时差不大于3
if ((DateTime.Now.Hour - fhrSampleTime.Hour) <= 3)
{
var duringMins = Math.Abs((phrRange.First() - phrRange.Last()).TotalMinutes);
//在餐后时间段(8:00~10:00,12:00~14:00,18:00~20:00,22:00~24:00)取中间值。其他时间段取正常起始值
bool isInTimeRanges = IsLastUpdateInTimeRanges(phrRange.First());

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} ");

#region 生理健康与胎动的关系
/// (步数)运动步数超过1500步则加1;
/// (体温)低烧则胎动减1,高烧胎动减2;低烧是37.3~38.5,38.6以上是高烧。
/// (血压)血压收缩压大于160则加1。
/// (心理)心理压力高加2,压力中加1;

var fetalMovementStepVar = 0;
var fetalMovementTempVar = 0;
var fetalMovementBpVar = 0;
var fetalMovementPpVar = 0;
var fetalMovementFhrVar = 0;
// 步数
if (true)
{
var step = await _personCacheMgr.GetStepPeriodicityAsync(imeiDel);
if (step != null)
{
if (DateTime.Now.Hour - ((DateTime)step?.LastUpdate!).Hour <= 2)
{
if (step.Steps > 1500) fetalMovementStepVar = 1;
}
else
{
_logger.LogWarning($"{imeiDel} 周期步数 时间无效");
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期步数无数据");
}

}

// 体温
if (true)
{
var temp = await _personCacheMgr.GetTemperaturePeriodicityAsync(imeiDel);
if (temp != null)
{
if (DateTime.Now.Hour - ((DateTime)temp?.LastUpdate!).Hour <= 2)
{
// 中烧
if (temp.Temperature >= 37.3M && temp.Temperature <= 38.5M)
{
fetalMovementTempVar = -1;
}
// 高烧
if (temp.Temperature >= 38.6M)
{
fetalMovementTempVar = -2;
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期体温 时间无效");
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期体温无数据");
}

}

// 血压
if (true)
{
var bp = await _personCacheMgr.GetBloodPressPeriodicityAsync(imeiDel);
if (bp != null)
{
if (DateTime.Now.Hour - ((DateTime)bp?.LastUpdate!).Hour <= 2)
{
if (bp.SystolicValue > 160)
{
fetalMovementBpVar = 1;
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期血压 时间无效");
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期血压无数据");
}

}
// 心理
if (true)
{
//-1 不处理,
//0 正常,
//1 轻度,
//2 中度;
//3 重度;
GeneralParam psychResultParam = new()
{
Filters = new List<QueryFilterCondition>
{
new ()
{
Key=nameof(HisGpsPsychResult.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(HisGpsPsychResult.Serialno)
}
}
};
var psych = await _hisPsychResultApiClient.GetFirstAsync(psychResultParam, imeiDel[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") });
if (psych != null)
{
if (psych?.StressScore == 2)
{
fetalMovementPpVar = 1;
}

if (psych?.StressScore == 3)
{
fetalMovementPpVar = 2;
}
}
else
{
_logger.LogWarning($"{imeiDel} 周期心理压力无数据");
}

}

#endregion

#region 胎心与胎动的关系
/// 胎心值过缓时,则胎动数量减1;胎心值过速时,则胎动也加1。
/// 此值允许在上限值上继续增加,在下限值上继续减少,最小值为0。
/// 告警上限阀值

//1表示偏高;2表示偏低
if (true)
{
if (fhr.IsAbnormal == 2)
{
fetalMovementPpVar = -1;
}

if (fhr.IsAbnormal == 1)
{
fetalMovementPpVar = 1;
}
}

#endregion

_logger.LogInformation($"{imeiDel} 原始胎动值:{fetalMovementValue}, 步数参数变动值:{fetalMovementStepVar},体温参数变动值:{fetalMovementTempVar},血压参数变动值:{fetalMovementBpVar},心理压力参数变动值:{fetalMovementPpVar},胎心参数变动值:{fetalMovementFhrVar}");


fetalMovementValue = fetalMovementValue + fetalMovementStepVar + fetalMovementTempVar + fetalMovementBpVar + fetalMovementPpVar + fetalMovementFhrVar;


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

// 获取胎心数据状态与胎动数据状态一致
//etalHeartRateIsAbnormal= fhr.IsAbnormal;
var feltalMovementIsAbnormal = fetalHeartRateIsAbnormal;

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);

var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(imeiDel).ConfigureAwait(false);
var fmMsgId = $"{imeiDel}-{fetalMovementSampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
var fmMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(fetalMovementSampleTime.Length < 13 ? fetalMovementSampleTime.PadRight(13, '0') : fetalMovementSampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
// 胎动数据推送到第三方
var topic = "topic.push.third";
var fmThridMsg = new
{
messageId = fmMsgId,
topic = topic,
time = fmMsgTime,
data = new
{
imei = imeiDel,
value = fetalMovement,
isAbnormal = feltalMovementIsAbnormal,
type = "fetalMovement"
}
};
await _serviceMqProcess.ProcessIMEIEventMessageAsync(fmMsgId, topic, 31, fmThridMsg).ConfigureAwait(false);

// 胎动数据推送到微信
if (feltalMovementIsAbnormal != 0)
{
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.LogWarning($"{imeiDel} 最后一条胎心数据与胎动数据的小时差大于2,不计算胎动数据");
}
}
else
{
_logger.LogInformation($"{imeiDel} 胎动记录{isFetalMovementExisted},数据采样时间:{fetalMovementSampleTime}|{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}, 周期:{statStartTime}-{statEndTime} 不足两条,不能判断是否持续佩戴");

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

}
else
{
_logger.LogWarning($"{imeiDel} 胎心监测功能没有开启");
}
}
catch (Exception ex )
{

_logger.LogError($"{imeiDel} 计算胎动数据异常 {ex.Message}\n {ex.StackTrace}");
}

}

#endregion
}


Cargando…
Cancelar
Guardar