diff --git a/HealthMonitor.Model/Config/ServiceConfig.cs b/HealthMonitor.Model/Config/ServiceConfig.cs
index 0febe59..ac40e72 100644
--- a/HealthMonitor.Model/Config/ServiceConfig.cs
+++ b/HealthMonitor.Model/Config/ServiceConfig.cs
@@ -10,17 +10,9 @@
public string EtcdServerAddress { get; set; } = default!;
public string IotWebApiUrl { get; set; } = default!;
- /////
- ///// Kafka服务地址
- /////
- //public string MqServerAddress { get; set; }
- /////
- ///// 服务守护消息kafka服务地址
- /////
- //public string ServiceGuardMqAddress { get; set; }
- /////
- ///// 服务守护消息主题
- /////
- //public string ServiceGuardMqTopic { get; set; }
+
+ public string IotAuth { get; set; } = default!;
+
+ public string IotCore { get; set; } = default!;
}
}
diff --git a/HealthMonitor.Model/Service/Mapper/PregnancyCommonHeartRateModel.cs b/HealthMonitor.Model/Service/Mapper/PregnancyCommonHeartRateModel.cs
new file mode 100644
index 0000000..fec844e
--- /dev/null
+++ b/HealthMonitor.Model/Service/Mapper/PregnancyCommonHeartRateModel.cs
@@ -0,0 +1,79 @@
+using Newtonsoft.Json;
+using SqlSugar;
+using SqlSugar.TDengine;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthMonitor.Model.Service.Mapper
+{
+ [STableAttribute(STableName = "stb_hm_pregnancy_common_heart_rate")]
+ public class PregnancyCommonHeartRateModel
+ {
+ [JsonProperty("ts")]
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, ColumnName = "ts", SqlParameterDbType = typeof(DateTime19))]
+ public DateTime Timestamp { get; set; }
+
+
+ [JsonProperty("person_id")]
+ [SqlSugar.SugarColumn(ColumnName = "person_id")]
+ public string PersonId { get; set; } = default!;
+
+ [JsonProperty("device_key")]
+ [SqlSugar.SugarColumn(ColumnName = "device_key")]
+ public string DeviceKey { get; set; } = default!;
+
+ [JsonProperty("serialno")]
+ [SqlSugar.SugarColumn(ColumnName = "serialno")]
+ public string SerialNumber { get; set; } = default!;
+
+
+ [JsonProperty("mode")]
+ [SqlSugar.SugarColumn(ColumnName = "mode")]
+ public float Mode { get; set; }
+
+ [JsonProperty("percentage")]
+ [SqlSugar.SugarColumn(ColumnName = "percentage")]
+ public int Percentage { get; set; }
+
+ [JsonProperty("max_value")]
+ [SqlSugar.SugarColumn(ColumnName = "max_value")]
+ public int MaxValue { get; set; }
+
+ [JsonProperty("min_value")]
+ [SqlSugar.SugarColumn(ColumnName = "min_value")]
+ public int MinValue { get; set; }
+
+
+ [JsonProperty("original_max_value")]
+ [SqlSugar.SugarColumn(ColumnName = "original_max_value")]
+ public int OriginalMaxValue { get; set; }
+
+ [JsonProperty("original_min_value")]
+ [SqlSugar.SugarColumn(ColumnName = "original_min_value")]
+ public int OriginalMinValue { get; set; }
+
+ [JsonProperty("create_time")]
+ [SqlSugar.SugarColumn(ColumnName = "create_time")]
+ public DateTime CreateTime { get; set; }
+
+ [JsonProperty("stat_start_time")]
+ [SqlSugar.SugarColumn(ColumnName = "stat_start_time")]
+ public DateTime StatStartTime { get; set; }
+
+
+ [JsonProperty("stat_end_time")]
+ [SqlSugar.SugarColumn(ColumnName = "stat_end_time")]
+ public DateTime StatEndTime { get; set; }
+
+ [JsonProperty("remark")]
+ [SqlSugar.SugarColumn(ColumnName = "remark")]
+ public string Remark { get; set; } = default!;
+
+ [JsonProperty("serial_tail_no")]
+ [SqlSugar.SugarColumn(IsIgnore = true, ColumnName = "serial_tail_no")]
+ public string SerialTailNumber { get; set; } = default!;
+ }
+}
diff --git a/HealthMonitor.Service/Biz/IotApiService.cs b/HealthMonitor.Service/Biz/IotApiService.cs
new file mode 100644
index 0000000..6803934
--- /dev/null
+++ b/HealthMonitor.Service/Biz/IotApiService.cs
@@ -0,0 +1,328 @@
+using HealthMonitor.Common.helper;
+using HealthMonitor.Model.Config;
+using HealthMonitor.Service.Resolver;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HealthMonitor.Model.Service;
+using TelpoDataService.Util.Entities.GpsCard;
+using TelpoDataService.Util;
+using TelpoDataService.Util.Clients;
+using TelpoDataService.Util.Models;
+using TelpoDataService.Util.QueryObjects;
+using HealthMonitor.Service.Cache;
+using HealthMonitor.Model.Cache;
+using Etcdserverpb;
+
+namespace HealthMonitor.Service.Biz
+{
+ public class IotApiService
+ {
+ private readonly ServiceConfig _configService;
+ private readonly ILogger _logger;
+ private readonly PersonCacheManager _personCacheMgr;
+ private readonly DeviceCacheManager _deviceCacheMgr;
+
+
+ private readonly HttpHelper _httpHelper = default!;
+
+ private readonly GpsCardAccessorClient _gpsPersonApiClient;
+
+ public IotApiService(ILogger logger, HttpHelper httpHelper, DeviceCacheManager deviceCacheMgr, GpsCardAccessorClient gpsPersonApiClient, IOptions optConfigService, PersonCacheManager personCacheMgr)
+ {
+ _configService = optConfigService.Value;
+ _httpHelper=httpHelper;
+ _logger = logger;
+ _personCacheMgr = personCacheMgr;
+ _gpsPersonApiClient = gpsPersonApiClient;
+ _deviceCacheMgr = deviceCacheMgr;
+ }
+
+ #region 平台下发血压标定参数
+ ///
+ /// 平台下发血压标定参数
+ ///
+ ///
+ ///
+ public async Task SetBloodPressCalibrationConfigAsync(BloodPressCalibrationConfigModel bpsCalibrationConfig)
+ {
+
+#if DEBUG
+ var flag = true;
+#else
+ //systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效
+ //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
+ //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
+ //diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
+
+ var flag = false;
+ try
+ {
+ var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
+ List> headers = new()
+ {
+ new KeyValuePair("AuthKey", "key1")
+ };
+ var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
+ _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
+ var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
+ flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");
+
+ }
+
+
+#endif
+
+ return flag;
+
+
+ }
+
+
+ public async Task SetBloodPressCalibrationConfig2Async(BloodPressCalibrationConfigModel bpsCalibrationConfig)
+ {
+ BloodPressCalibrationConfigModelReponse response = new BloodPressCalibrationConfigModelReponse();
+ response.Flag = false;
+ response.Message = string.Empty;
+#if DEBUG
+ //var flag = true;
+ response.Flag=true;
+#else
+ //systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效
+ //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
+ //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
+ //diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
+
+ // var flag = false;
+ try
+ {
+ var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
+ List> headers = new()
+ {
+ new KeyValuePair("AuthKey", "key1")
+ };
+ var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
+ _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
+ var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
+ //response.Flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;
+ response.Flag = Convert.ToBoolean(resJToken?["succeed"]?.ToString());
+ if (!response.Flag)
+ {
+ response.Message = resJToken?["message"]?.ToString()!;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");
+
+ }
+
+
+#endif
+
+ return response;
+ }
+
+ public async Task UpdatePersonRemarksAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicIncValue, int diastolicIncValue, string remarks = "is_blood_press")
+ {
+ var flag = false;
+ try
+ {
+
+ // 保证实时性,先更新缓存,再更新数据库
+ var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);
+
+ if (personCache == null)
+ {
+ _logger.LogInformation($"{imei} -- Person remarks数据异常,检查缓存和数据库");
+ }
+ else
+ {
+ var newRemarkData = new
+ {
+ imei,
+ time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+ commandValue = new
+ {
+ systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
+ diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
+ systolicIncValue, //收缩压显示增量,值为0 表示不生效
+ diastolicIncValue //舒张压显示增量,值为0 表示不生效
+ }
+ };
+ var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";
+
+ personCache["person"]!["remarks"] = newRemarkStr;
+ bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
+ if (cacheFlag)
+ {
+ GeneralParam condition = new()
+ {
+ Filters = new List {
+ new QueryFilterCondition {
+ Key=nameof(GpsDevice.Serialno),
+ Value=imei,
+ Operator= QueryOperatorEnum.Equal,
+ ValueType=QueryValueTypeEnum.String
+ }
+ },
+ OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
+
+ };
+ _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
+ // 读取数据库
+ var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
+ // 更新字段
+ person!.Remarks = newRemarkStr;
+ await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
+ _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
+
+ }
+ else
+ {
+ _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
+ }
+ flag = cacheFlag;
+ }
+ // else if (string.IsNullOrWhiteSpace(personCache["person"]!["remarks"]!.ToString()))
+ //else if (personCache?["person"]!["remarks"]!.ToString()!=null)
+ //{
+ // var newRemarkData = new
+ // {
+ // imei,
+ // time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+ // commandValue = new
+ // {
+ // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
+ // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
+ // systolicIncValue, //收缩压显示增量,值为0 表示不生效
+ // diastolicIncValue //舒张压显示增量,值为0 表示不生效
+ // }
+ // };
+ // var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";
+
+ // personCache["person"]!["remarks"] = newRemarkStr;
+ // bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
+ // if (cacheFlag)
+ // {
+ // GeneralParam condition = new()
+ // {
+ // Filters = new List {
+ // new QueryFilterCondition {
+ // Key=nameof(GpsDevice.Serialno),
+ // Value=imei,
+ // Operator= QueryOperatorEnum.Equal,
+ // ValueType=QueryValueTypeEnum.String
+ // }
+ // },
+ // OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
+
+ // };
+ // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
+ // // 读取数据库
+ // var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
+ // // 更新字段
+ // person!.Remarks = newRemarkStr;
+ // await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
+ // _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
+
+ // }
+ // else
+ // {
+ // _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
+ // }
+ // flag = cacheFlag;
+ //}
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} {imei}--更新个人信息异常:{ex.Message}, {ex.StackTrace}");
+ }
+ return flag;
+ }
+
+ #endregion
+
+ #region 平台下发胎心监测参数
+ public async Task SetFetalHeartRateConfig(string serialno, int modeStatus=0, int maxValue=0, int minValue = 0)
+ {
+ try
+ {
+ #region 读取缓存
+ // db7.HashGet("TELPO#GPSDEVICE_WATCH_CONFIG_HASH","861281060086083_0067")
+ var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(serialno, "0067");
+ if (watchConfig==null)
+ {
+ return false;
+ }
+
+ #endregion
+
+ #region 获取B端 Token
+ var getTokenUrl = $"{_configService.IotAuth}/getAccessToken2";
+ var tokenReq = new
+ {
+ manufactorId= "7c7c38cb-d045-41d8-b3d0-fcaaa84a8f02",
+ imei= serialno
+ };
+ var resToken = await _httpHelper.HttpToPostAsync(getTokenUrl, tokenReq).ConfigureAwait(false);
+ var tokenAuth= JsonConvert.DeserializeObject(resToken ?? string.Empty) as JToken;
+ var tokenAuthData = tokenAuth?["data"]?.ToString()??string.Empty;
+ if (tokenAuthData == null)
+ {
+ return false;
+ }
+ #endregion
+
+ #region 发送到B端
+ List> headers = new()
+ {
+ new KeyValuePair("TelpoManufactorId", tokenAuthData)
+ };
+ var data = new
+ {
+ imeis = new string[] { serialno },
+ enabled = (int)watchConfig["fetalParamters"]!["enabled"]!,
+ triggerHighFreqHigh = maxValue == 0 ? (int)watchConfig["fetalParamters"]!["triggerHighFreqHigh"]!:maxValue,
+ triggerLowFreqLow = minValue == 0 ? (int)watchConfig["fetalParamters"]!["triggerHighFreqLow"]! : minValue,
+ highFreqSampleTimes = (int)watchConfig["fetalParamters"]!["highFreqSampleTimes"]!,
+ highFreqSampleInterval = (int)watchConfig["fetalParamters"]!["highFreqSampleInterval"]!,
+ stopHighFreqSampleCount = (int)watchConfig["fetalParamters"]!["stopHighFreqSampleCount"]!,
+ mode = modeStatus,
+ edoc = watchConfig["fetalParamters"]!["EDOC"]!,
+ vibrateEnabled = (int)watchConfig["fetalParamters"]!["vibrateEnabled"]!,
+ lcdEnabled= (int)watchConfig["fetalParamters"]!["lcdEnabled"]!
+ };
+ var setUrl = $"{_configService.IotCore}/api/v1/open/OpenIot/SetFetalConfig";
+ var res = await _httpHelper.HttpToPostAsync(setUrl, data, headers).ConfigureAwait(false);
+ var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
+ return resJToken?["message"]?.ToString().Equals("ok") ?? false;
+ //response.Flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
+ //response.Flag = Convert.ToBoolean(resJToken?["succeed"]?.ToString());
+ //if (!response.Flag)
+ //{
+ // response.Message = resJToken?["message"]?.ToString()!;
+ //}
+ #endregion
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"{nameof(SetFetalHeartRateConfig)} 下发胎心检测参数异常:{ex.Message}, {ex.StackTrace}");
+ return false;
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/HealthMonitor.Service/Biz/IotWebApiService.cs b/HealthMonitor.Service/Biz/IotWebApiService.cs
deleted file mode 100644
index dbbe453..0000000
--- a/HealthMonitor.Service/Biz/IotWebApiService.cs
+++ /dev/null
@@ -1,626 +0,0 @@
-using HealthMonitor.Common.helper;
-using HealthMonitor.Model.Config;
-using HealthMonitor.Service.Resolver;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using HealthMonitor.Model.Service;
-using TelpoDataService.Util.Entities.GpsCard;
-using TelpoDataService.Util;
-using TelpoDataService.Util.Clients;
-using TelpoDataService.Util.Models;
-using TelpoDataService.Util.QueryObjects;
-using HealthMonitor.Service.Cache;
-using HealthMonitor.Model.Cache;
-
-namespace HealthMonitor.Service.Biz
-{
- public class IotWebApiService
- {
- private readonly ServiceConfig _configService;
- private readonly ILogger _logger;
- private readonly PersonCacheManager _personCacheMgr;
-
- private readonly HttpHelper _httpHelper = default!;
-
- private readonly GpsCardAccessorClient _gpsPersonApiClient;
-
- public IotWebApiService(ILogger logger, HttpHelper httpHelper, GpsCardAccessorClient gpsPersonApiClient, IOptions optConfigService, PersonCacheManager personCacheMgr)
- {
- _configService = optConfigService.Value;
- _httpHelper=httpHelper;
- _logger = logger;
- _personCacheMgr = personCacheMgr;
- _gpsPersonApiClient = gpsPersonApiClient;
- }
- ///
- /// 平台下发血压标定参数
- ///
- ///
- ///
- public async Task SetBloodPressCalibrationConfigAsync(BloodPressCalibrationConfigModel bpsCalibrationConfig)
- {
-
-#if DEBUG
- var flag = true;
-#else
- //systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效
- //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
- //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
- //diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
-
- var flag = false;
- try
- {
- var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
- List> headers = new()
- {
- new KeyValuePair("AuthKey", "key1")
- };
- var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
- _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
- var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;
-
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");
-
- }
-
-
-#endif
-
- return flag;
-
-
- }
-
-
- public async Task SetBloodPressCalibrationConfig2Async(BloodPressCalibrationConfigModel bpsCalibrationConfig)
- {
- BloodPressCalibrationConfigModelReponse response = new BloodPressCalibrationConfigModelReponse();
- response.Flag = false;
- response.Message = string.Empty;
-#if DEBUG
- //var flag = true;
- response.Flag=true;
-#else
- //systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效
- //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
- //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
- //diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
-
- // var flag = false;
- try
- {
- var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
- List> headers = new()
- {
- new KeyValuePair("AuthKey", "key1")
- };
- var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
- _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
- var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- //response.Flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;
- response.Flag = Convert.ToBoolean(resJToken?["succeed"]?.ToString());
- if (!response.Flag)
- {
- response.Message = resJToken?["message"]?.ToString()!;
- }
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");
-
- }
-
-
-#endif
-
- return response;
- }
- /** 取消
- ///
- /// 更新 gps_person remark和缓存
- ///
- ///
- ///
- ///
- ///
- public async Task UpdatePersonRemarksAsync(string imei,int systolicRefValue,int diastolicRefValue)
- {
- var flag = false;
- try
- {
- GeneralParam condition = new ()
- {
- Filters = new List {
- new QueryFilterCondition {
- Key=nameof(GpsDevice.Serialno),
- Value=imei,
- Operator= QueryOperatorEnum.Equal,
- ValueType=QueryValueTypeEnum.String
- }
- },
- OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- };
- var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- //// 若remark为空,更新person remark字段
- //if (string.IsNullOrWhiteSpace(person?.Remarks))
- //{
- // var newRemarkData = new
- // {
- // imei,
- // time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- // commandValue = new
- // {
- // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- // systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
- // diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
- // }
- // };
- // person!.Remarks = $"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
- // await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // _logger.LogInformation($"更新Person remarks字段|{person.Remarks}");
-
- // // 更新缓存
- // var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
- // List> headers = new()
- // {
- // new KeyValuePair("AuthKey", "key1")
- // };
- // var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
- // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)},响应:{res}");
- // var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- // flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
- //}
-
- var newRemarkData = new
- {
- imei,
- time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- commandValue = new
- {
- systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
- diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
- }
- };
- person!.Remarks = $"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
- await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- _logger.LogInformation($"更新Person remarks字段|{person.Remarks}");
-
- // 更新缓存
- var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
- List> headers = new()
- {
- new KeyValuePair("AuthKey", "key1")
- };
- var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
- _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)},响应:{res}");
- var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} 更新个人信息异常:{ex.Message}, {ex.StackTrace}");
- }
- return flag;
- }
- */
-
- /////
- ///// 初次开通更新 gps_person remark和对应的缓存
- /////
- /////
- /////
- /////
- /////
- /////
- /////
- //public async Task UpdatePersonRemarksAsync0(string imei, int systolicRefValue, int diastolicRefValue,int systolicIncValue,int diastolicIncValue)
- //{
- // var flag = false;
- // try
- // {
- // GeneralParam condition = new()
- // {
- // Filters = new List {
- // new QueryFilterCondition {
- // Key=nameof(GpsDevice.Serialno),
- // Value=imei,
- // Operator= QueryOperatorEnum.Equal,
- // ValueType=QueryValueTypeEnum.String
- // }
- // },
- // OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- // };
- // var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // // 若remark为空,更新person remark字段
- // if (string.IsNullOrWhiteSpace(person?.Remarks))
- // {
- // var newRemarkData = new
- // {
- // imei,
- // time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- // commandValue = new
- // {
- // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- // systolicIncValue, //收缩压显示增量,值为0 表示不生效
- // diastolicIncValue //舒张压显示增量,值为0 表示不生效
- // }
- // };
- // person!.Remarks = $"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
- // await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // _logger.LogInformation($"更新Person remarks字段|{person.Remarks}");
-
- // // 更新缓存
- // var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);
-
- // if (personCache != null)
- // {
-
- // //personCache.Person.Remarks = person!.Remarks;
- // personCache["person"]!["remarks"] = person!.Remarks;
- // bool cacheFlag= await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
-
- // // flag = true;
- // if (cacheFlag)
- // {
- // flag = true;
- // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
- // }
- // else
- // {
- // flag = false;
- // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
- // }
- // }
-
-
- // //var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
- // //List> headers = new()
- // //{
- // // new KeyValuePair("AuthKey", "key1")
- // //};
- // //var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
- // //_logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)},响应:{res}");
- // //var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- // //flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
- // }
- // }
- // catch (Exception ex)
- // {
- // _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} 更新个人信息异常:{ex.Message}, {ex.StackTrace}");
- // }
- // return flag;
- //}
- /**
- ///
- /// 更新 gps_person remark缓存和数据库
- ///
- ///
- ///
- ///
- ///
- ///
- /// 是否初始化,即清空remakers
- ///
- public async Task UpdatePersonRemarksAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicIncValue, int diastolicIncValue, bool isInitRemakers=false)
- {
- var flag = false;
- try
- {
-
- // 保证实时性,先更新缓存,再更新数据库
- var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);
-
- if (personCache == null)
- {
- _logger.LogInformation($"{imei} -- Person remarks数据异常,检查缓存和数据库");
- }
- else if (string.IsNullOrWhiteSpace(personCache["person"]!["remarks"]!.ToString()))
- {
- var newRemarkData = new
- {
- imei,
- time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- commandValue = new
- {
- systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- systolicIncValue, //收缩压显示增量,值为0 表示不生效
- diastolicIncValue //舒张压显示增量,值为0 表示不生效
- }
- };
- var newRemarkStr = isInitRemakers ? string.Empty:$"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
- personCache["person"]!["remarks"] = newRemarkStr;
- bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
- if (cacheFlag)
- {
- GeneralParam condition = new()
- {
- Filters = new List {
- new QueryFilterCondition {
- Key=nameof(GpsDevice.Serialno),
- Value=imei,
- Operator= QueryOperatorEnum.Equal,
- ValueType=QueryValueTypeEnum.String
- }
- },
- OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- };
- _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
- // 读取数据库
- var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // 更新字段
- person!.Remarks = newRemarkStr;
- await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
-
- }
- else
- {
- _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
- }
- flag = cacheFlag;
- }
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} {imei}--更新个人信息异常:{ex.Message}, {ex.StackTrace}");
- }
- return flag;
- }
- */
- ///
- ///// 更新 gps_person remark缓存和数据库
- /////
- /////
- /////
- /////
- /////
- /////
- /////
- /////
- //public async Task UpdatePersonRemarksAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicIncValue, int diastolicIncValue, string remarks= "is_blood_press")
- //{
- // var flag = false;
- // try
- // {
-
- // // 保证实时性,先更新缓存,再更新数据库
- // var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);
-
- // if (personCache == null)
- // {
- // _logger.LogInformation($"{imei} -- Person remarks数据异常,检查缓存和数据库");
- // }
- // else if (string.IsNullOrWhiteSpace(personCache["person"]!["remarks"]!.ToString()))
- // {
- // var newRemarkData = new
- // {
- // imei,
- // time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- // commandValue = new
- // {
- // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- // systolicIncValue, //收缩压显示增量,值为0 表示不生效
- // diastolicIncValue //舒张压显示增量,值为0 表示不生效
- // }
- // };
- // var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";
-
- // personCache["person"]!["remarks"] = newRemarkStr;
- // bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
- // if (cacheFlag)
- // {
- // GeneralParam condition = new()
- // {
- // Filters = new List {
- // new QueryFilterCondition {
- // Key=nameof(GpsDevice.Serialno),
- // Value=imei,
- // Operator= QueryOperatorEnum.Equal,
- // ValueType=QueryValueTypeEnum.String
- // }
- // },
- // OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- // };
- // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
- // // 读取数据库
- // var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // // 更新字段
- // person!.Remarks = newRemarkStr;
- // await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
-
- // }
- // else
- // {
- // _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
- // }
- // flag = cacheFlag;
- // }
- // }
- // catch (Exception ex)
- // {
- // _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} {imei}--更新个人信息异常:{ex.Message}, {ex.StackTrace}");
- // }
- // return flag;
- //}
-
-
-
- /// 更新 gps_person remark缓存和数据库
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public async Task UpdatePersonRemarksAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicIncValue, int diastolicIncValue, string remarks = "is_blood_press")
- {
- var flag = false;
- try
- {
-
- // 保证实时性,先更新缓存,再更新数据库
- var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);
-
- if (personCache == null)
- {
- _logger.LogInformation($"{imei} -- Person remarks数据异常,检查缓存和数据库");
- }
- else
- {
- var newRemarkData = new
- {
- imei,
- time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- commandValue = new
- {
- systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- systolicIncValue, //收缩压显示增量,值为0 表示不生效
- diastolicIncValue //舒张压显示增量,值为0 表示不生效
- }
- };
- var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";
-
- personCache["person"]!["remarks"] = newRemarkStr;
- bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
- if (cacheFlag)
- {
- GeneralParam condition = new()
- {
- Filters = new List {
- new QueryFilterCondition {
- Key=nameof(GpsDevice.Serialno),
- Value=imei,
- Operator= QueryOperatorEnum.Equal,
- ValueType=QueryValueTypeEnum.String
- }
- },
- OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- };
- _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
- // 读取数据库
- var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // 更新字段
- person!.Remarks = newRemarkStr;
- await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
-
- }
- else
- {
- _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
- }
- flag = cacheFlag;
- }
- // else if (string.IsNullOrWhiteSpace(personCache["person"]!["remarks"]!.ToString()))
- //else if (personCache?["person"]!["remarks"]!.ToString()!=null)
- //{
- // var newRemarkData = new
- // {
- // imei,
- // time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- // commandValue = new
- // {
- // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
- // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
- // systolicIncValue, //收缩压显示增量,值为0 表示不生效
- // diastolicIncValue //舒张压显示增量,值为0 表示不生效
- // }
- // };
- // var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";
-
- // personCache["person"]!["remarks"] = newRemarkStr;
- // bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
- // if (cacheFlag)
- // {
- // GeneralParam condition = new()
- // {
- // Filters = new List {
- // new QueryFilterCondition {
- // Key=nameof(GpsDevice.Serialno),
- // Value=imei,
- // Operator= QueryOperatorEnum.Equal,
- // ValueType=QueryValueTypeEnum.String
- // }
- // },
- // OrderBys = new List { new OrderByCondition { Key = "serialno", IsDesc = true } }
-
- // };
- // _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
- // // 读取数据库
- // var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // // 更新字段
- // person!.Remarks = newRemarkStr;
- // await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
- // _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");
-
- // }
- // else
- // {
- // _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
- // }
- // flag = cacheFlag;
- //}
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} {imei}--更新个人信息异常:{ex.Message}, {ex.StackTrace}");
- }
- return flag;
- }
-
- /** 取消
- public async Task UpdatePersonInfoCacheAsync(string imei)
- {
- var flag = false;
- try
- {
- var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
- List> headers = new()
- {
- new KeyValuePair("AuthKey", "key1")
- };
- var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
- _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonInfoCacheAsync)},响应:{res}");
- var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
- flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
- }
- catch (Exception ex)
- {
- _logger.LogError($"{nameof(UpdatePersonInfoCacheAsync)} 更新缓存异常:{ex.Message}, {ex.StackTrace}");
-
- }
- return flag;
-
-
- }
- */
-
- }
-}
diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs
index e39bee1..c3ffcec 100644
--- a/HealthMonitor.Service/Biz/db/TDengineService.cs
+++ b/HealthMonitor.Service/Biz/db/TDengineService.cs
@@ -637,6 +637,7 @@ namespace HealthMonitor.Service.Biz.db
}
#region SqlSugarClient
+ /**
public async Task InsertFetalHeartRateAsync()
{
var tableName = typeof(FetalHeartRateModel)
@@ -680,61 +681,9 @@ namespace HealthMonitor.Service.Biz.db
.OrderByDescending(x => x.Timestamp).FirstAsync();
return first;
}
- public void InsertFetalHeartRate2()
- {
- //var insrtSql = "";
- //_clientSqlSugar.Ado.ExecuteCommand(insrtSql);
- // 通过反射获取STableAttribute的STableName值
- var tableName = typeof(FetalHeartRateModel)
- .GetCustomAttribute()?
- .STableName;
-
- if (tableName == null)
- {
- throw new InvalidOperationException("STableAttribute not found on FetalHeartRateModel class.");
- }
-
- _clientSqlSugar.Ado.ExecuteCommand($"create table IF NOT EXISTS hm_fhr_00 using {tableName} tags('00')");
-
- //_clientSqlSugar.Ado.ExecuteCommand($"create table IF NOT EXISTS hm_fhr_00 using `stb_hm_fetal_heart_rate_test` tags('00')");
- _clientSqlSugar.Insertable(new FetalHeartRateModel()
- {
- Timestamp = DateTime.Now,
- CreateTime = DateTime.Now,
- FetalHeartRate = 90,
- FetalHeartRateId = Guid.NewGuid().ToString("D"),
- IsDisplay = false,
- Method = 1,
- PersonId = Guid.NewGuid().ToString("D"),
- MessageId = Guid.NewGuid().ToString("D"),
- SerialNumber = Guid.NewGuid().ToString("D"),
- DeviceKey = Guid.NewGuid().ToString("D"),
- SerialTailNumber = "00",
- LastUpdate = DateTime.Now,
- }).AS("hm_fhr_00").ExecuteCommand();
-
-
- //List rows = new();
-
- //rows.Add(new FetalHeartRateModel() {
- // Timestamp = new DateTime(2024, 1, 1),
- // CreateTime = DateTime.Now,
- // FetalHeartRate = 90,
- // FetalHeartRateId = Guid.NewGuid().ToString("D"),
- // IsDisplay = false,
- // Method = 1,
- // PersonId = Guid.NewGuid().ToString("D"),
- // MessageId = Guid.NewGuid().ToString("D"),
- // SerialNumber = Guid.NewGuid().ToString("D"),
- // DeviceKey = Guid.NewGuid().ToString("D"),
- // SerialTailNumber = "00",
- // LastUpdate = DateTime.Now,
-
- //});
-
- //_clientSqlSugar.Insertable(rows).AS("hm_fhr_00").ExecuteCommand();
- }
+ */
+
///
/// 插入记录
///
@@ -808,5 +757,192 @@ namespace HealthMonitor.Service.Biz.db
return res;
}
#endregion
+
+ #region 胎心算法
+ ///
+ /// 获取孕妇心率众数
+ ///
+ ///
+ ///
+ ///
+ public async Task GetPregnancyHeartRateModeAsync(string serialNo,int days=7)
+ {
+ var tableName = typeof(PregnancyHeartRateModel)
+ .GetCustomAttribute()?
+ .STableName;
+
+ var res = await _clientSqlSugar
+ .Queryable()
+ .AS(tableName)
+ .Where(i=>i.SerialNumber.Equals(serialNo))
+ .Where(i => i.Timestamp > DateTime.Now.AddDays(-days))
+ //.OrderByDescending(i => i.PregnancyHeartRate)
+ .Select(i =>i.PregnancyHeartRate)
+ .ToListAsync();
+ // 心率数据量必须30个以上才进行计算
+ if (res.Count < 30) return 0;
+
+ // 计算众数
+ var mode = res.GroupBy(n => n)
+ .OrderByDescending(g => g.Count())
+ .First()
+ .Key;
+
+ Console.WriteLine("众数是: " + mode);
+
+ // 如果有多个众数的情况
+ var maxCount = res.GroupBy(n => n)
+ .Max(g => g.Count());
+
+ var modes = res.GroupBy(n => n)
+ .Where(g => g.Count() == maxCount)
+ .Select(g => g.Key)
+ .ToList();
+ // 多个众数,选择最接近平均数或中位数的众数
+ if (modes.Count>1)
+ {
+ // 计算平均值
+ double average = res.Average();
+ Console.WriteLine("平均值是: " + average);
+
+ // 计算中位数
+ double median;
+ int count = res.Count;
+ var sortedRes = res.OrderBy(n => n).ToList();
+ if (count % 2 == 0)
+ {
+ // 偶数个元素,取中间两个数的平均值
+ median = (sortedRes[count / 2 - 1] + sortedRes[count / 2]) / 2.0;
+ }
+ else
+ {
+ // 奇数个元素,取中间的数
+ median = sortedRes[count / 2];
+ }
+ Console.WriteLine("中位数是: " + median);
+
+ // 找出最接近平均值的众数
+ //var closestToAverage = modes.OrderBy(m => Math.Abs(m - average)).First();
+ //Console.WriteLine("最接近平均值的众数是: " + closestToAverage);
+
+ // 找出最接近中位数的众数
+ var closestToMedian = modes.OrderBy(m => Math.Abs(m - median)).First();
+ Console.WriteLine("最接近中位数的众数是: " + closestToMedian);
+ mode = closestToMedian;
+ }
+
+ return mode;
+ }
+ ///
+ /// 计算个人一般心率
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task InitPregnancyCommonHeartRateModeAsync(string serialNo, int days = 7,int percentage=90)
+ {
+ var tableName = typeof(PregnancyHeartRateModel)
+ .GetCustomAttribute()?
+ .STableName;
+
+ var collection = await _clientSqlSugar
+ .Queryable()
+ .AS(tableName)
+ .Where(i => i.SerialNumber.Equals(serialNo))
+ .Where(i => i.Timestamp > DateTime.Now.AddDays(-days))
+ .OrderByDescending(i => i.Timestamp)
+ .ToArrayAsync();
+
+ var res = collection
+ .Select(i => i.PregnancyHeartRate).ToList();
+ // 心率数据量必须30个以上才进行计算
+ if (res.Count < 30)
+ {
+ _logger.LogInformation($"{serialNo} 心率数据不足,无法计算其众数");
+ return null;
+ }
+
+ #region 计算众数
+ var mode = res.GroupBy(n => n)
+ .OrderByDescending(g => g.Count())
+ .First()
+ .Key;
+
+ Console.WriteLine("众数是: " + mode);
+
+ // 如果有多个众数的情况
+ var maxCount = res.GroupBy(n => n)
+ .Max(g => g.Count());
+
+ var modes = res.GroupBy(n => n)
+ .Where(g => g.Count() == maxCount)
+ .Select(g => g.Key)
+ .ToList();
+ // 多个众数,选择最接近平均数或中位数的众数
+ if (modes.Count > 1)
+ {
+ // 计算平均值
+ double average = res.Average();
+ Console.WriteLine("平均值是: " + average);
+
+ // 计算中位数
+ double median;
+ int count = res.Count;
+ var sortedRes = res.OrderBy(n => n).ToList();
+ if (count % 2 == 0)
+ {
+ // 偶数个元素,取中间两个数的平均值
+ median = (sortedRes[count / 2 - 1] + sortedRes[count / 2]) / 2.0;
+ }
+ else
+ {
+ // 奇数个元素,取中间的数
+ median = sortedRes[count / 2];
+ }
+ Console.WriteLine("中位数是: " + median);
+
+ // 找出最接近平均值的众数
+ //var closestToAverage = modes.OrderBy(m => Math.Abs(m - average)).First();
+ //Console.WriteLine("最接近平均值的众数是: " + closestToAverage);
+
+ // 找出最接近中位数的众数
+ var closestToMedian = modes.OrderBy(m => Math.Abs(m - median)).First();
+ Console.WriteLine("最接近中位数的众数是: " + closestToMedian);
+ mode = closestToMedian;
+ }
+ #endregion
+
+ // 计算需要的数量
+ int requiredCount = (int)(res.Count * 0.8);
+
+ // 从原始数据集中获取最接近众数的元素
+ var closestToModeData = res.OrderBy(n => Math.Abs(n - mode))
+ .Take(requiredCount)
+ .ToList();
+
+ // 输出新数据集
+ Console.WriteLine("新数据集: " + string.Join(", ", closestToModeData));
+ Console.WriteLine("新数据集的数量: " + closestToModeData.Count);
+
+ return new PregnancyCommonHeartRateModel()
+ {
+ Timestamp = DateTime.Now,
+ PersonId = collection.First().DeviceKey,
+ DeviceKey = collection.First().DeviceKey,
+ SerialNumber = collection.First().SerialNumber,
+ Mode = mode,
+ Percentage= percentage,
+ MaxValue= closestToModeData.Max(),
+ MinValue= closestToModeData.Min(),
+ OriginalMaxValue=res.Max(),
+ OriginalMinValue= res.Min(),
+ CreateTime = DateTime.Now,
+ StatStartTime = collection.OrderBy(i=>i.Timestamp).Select(i=>i.Timestamp).First(),
+ StatEndTime= collection.OrderBy(i => i.Timestamp).Select(i => i.Timestamp).Last(),
+ };
+
+ }
+ #endregion
}
}
diff --git a/HealthMonitor.Service/Cache/DeviceCacheManager.cs b/HealthMonitor.Service/Cache/DeviceCacheManager.cs
new file mode 100644
index 0000000..d7b34b7
--- /dev/null
+++ b/HealthMonitor.Service/Cache/DeviceCacheManager.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthMonitor.Service.Cache
+{
+ public class DeviceCacheManager
+ {
+ private readonly ILogger _logger;
+ private const string CACHE_KEY_GPSDEVICE_WATCH_CONFIG = "#GPSDEVICE_WATCH_CONFIG_HASH";
+
+
+ public DeviceCacheManager(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 业务码
+ /// 0067 胎心启动配置
+ ///
+ ///
+ public async Task GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(string sn, string bizCode)
+ {
+ if (string.IsNullOrWhiteSpace(sn)) return null;
+
+ try
+ {
+ var config = await RedisHelperDb7.HGetAsync(CACHE_KEY_GPSDEVICE_WATCH_CONFIG, $"{sn}_{bizCode}").ConfigureAwait(false);
+
+ if (config == null) return null;
+ return (JObject)JsonConvert.DeserializeObject(config)!;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"Redis DB7发生异常:{ex.Message}, {ex.StackTrace}");
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/HealthMonitor.Service/Resolver/BloodpressResolver.cs b/HealthMonitor.Service/Resolver/BloodpressResolver.cs
index d987746..0720e16 100644
--- a/HealthMonitor.Service/Resolver/BloodpressResolver.cs
+++ b/HealthMonitor.Service/Resolver/BloodpressResolver.cs
@@ -42,7 +42,7 @@ namespace HealthMonitor.Service.Resolver
private readonly HttpHelper _httpHelper = default!;
private readonly GpsCardAccessorClient _gpsPersonApiClient;
- private readonly IotWebApiService _serviceIotWebApi;
+ private readonly IotApiService _serviceIotWebApi;
private readonly AsyncLocal _messageId = new();
private readonly AsyncLocal _msgData = new();
@@ -54,7 +54,7 @@ namespace HealthMonitor.Service.Resolver
BloodPressReferenceValueCacheManager bpRefValCacheManager,
PersonCacheManager personCacheMgr, HttpHelper httpHelper,
GpsCardAccessorClient gpsPersonApiClient,
- IotWebApiService iotWebApiService,
+ IotApiService iotWebApiService,
EtcdService serviceEtcd,
IOptions optionBoodPressResolver,
ILogger logger)
diff --git a/HealthMonitor.Service/Resolver/Factory/ResolverFactory.cs b/HealthMonitor.Service/Resolver/Factory/ResolverFactory.cs
index 50290aa..3aa2bbf 100644
--- a/HealthMonitor.Service/Resolver/Factory/ResolverFactory.cs
+++ b/HealthMonitor.Service/Resolver/Factory/ResolverFactory.cs
@@ -55,7 +55,6 @@ namespace HealthMonitor.Service.Resolver.Factory
MessageId = msg.MessageId,
Topic = msg.Topic,
DetailData = msg.Body,
-
};
}
}
diff --git a/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
new file mode 100644
index 0000000..183e5b0
--- /dev/null
+++ b/HealthMonitor.Service/Resolver/PregnancyHeartRateResolver.cs
@@ -0,0 +1,134 @@
+using HealthMonitor.Common;
+using HealthMonitor.Common.helper;
+using HealthMonitor.Service.Etcd;
+using HealthMonitor.Service.Resolver.Interface;
+using HealthMonitor.Service.Sub;
+using HealthMonitor.Service.Sub.Topic.Model;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TelpoDataService.Util.Entities.GpsLocationHistory;
+
+namespace HealthMonitor.Service.Resolver
+{
+ public class PregnancyHeartRateResolver : IResolver
+ {
+ private readonly ILogger _logger;
+ private readonly AsyncLocal _messageId = new();
+ private readonly AsyncLocal _msgData = new();
+ private readonly HttpHelper _httpHelper = default!;
+ private readonly EtcdService _serviceEtcd;
+
+
+ public PregnancyHeartRateResolver(ILogger logger, HttpHelper httpHelper, EtcdService serviceEtcd)
+ {
+ _logger = logger;
+ _httpHelper = httpHelper;
+ _serviceEtcd = serviceEtcd;
+ }
+
+ public void SetResolveInfo(PackageMsgModel msg)
+ {
+ var topicHmPregnancyHeartRate = JsonConvert.DeserializeObject(msg.DetailData.ToString()!);
+ _messageId.Value = msg.MessageId;
+ _msgData.Value = new HisGpsHeartRate()
+ {
+ HeartRateId = topicHmPregnancyHeartRate!.PregnancyHeartRateId,
+ MessageId = topicHmPregnancyHeartRate!.MessageId,
+ Serialno = topicHmPregnancyHeartRate!.Serialno,
+ HeartRate= topicHmPregnancyHeartRate.PregnancyHeartRate,
+ LastUpdate = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.LastUpdate) / 1000000),
+ CreateTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.CreateTime) / 1000000),
+ Method = topicHmPregnancyHeartRate!.Method,
+ IsDisplay = topicHmPregnancyHeartRate!.IsDisplay ? 1 : 0
+ };
+ }
+ public override string ToString()
+ {
+ return $"{nameof(PregnancyHeartRateResolver)}[{_messageId.Value}]";
+ }
+
+ public async Task ExecuteMessageAsync()
+ {
+ //throw new NotImplementedException();
+ var messageId = _messageId.Value;
+ var phr = _msgData.Value!;
+ #region 定时下发触发器
+ var key = $"health_moniter/schedule_push/pregnancy_heart_rate/imei/{phr.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;
+
+ // 如果当前时间已经超过了8点,将等待到明天后的8点
+ if (timeUntilNextRun < TimeSpan.Zero)
+ {
+ timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1));
+ nextRunTime += timeUntilNextRun;
+ }
+ var ttl = (long)timeUntilNextRun.TotalSeconds;
+ var data = new
+ {
+ imei = phr.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
+
+ var interval = 0;
+ // 获取当前时间
+ DateTime now = DateTime.Now;
+ var rand=new Random();
+ var pushSec = rand.Next(59);
+ int pushMin= int.TryParse(phr.Serialno.AsSpan(phr.Serialno.Length - 1), out pushMin) ? pushMin : 10;
+ // 计算距离下一个$interval天后的8点的时间间隔
+ DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 18, pushMin, pushSec).AddDays(interval);
+ TimeSpan timeUntilNextRun = nextRunTime - now;
+
+
+ if (timeUntilNextRun < TimeSpan.Zero)
+ {
+ timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1));
+ nextRunTime += TimeSpan.FromDays(1);
+ }
+
+ var ttl =(long)timeUntilNextRun.TotalSeconds;
+ var data = new
+ {
+ imei = phr.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);
+#endif
+
+ }
+
+ #endregion
+ }
+
+
+
+ }
+}
diff --git a/HealthMonitor.Service/Sub/MsgQueueManager.cs b/HealthMonitor.Service/Sub/MsgQueueManager.cs
index 6939450..de5ff06 100644
--- a/HealthMonitor.Service/Sub/MsgQueueManager.cs
+++ b/HealthMonitor.Service/Sub/MsgQueueManager.cs
@@ -15,15 +15,19 @@ namespace HealthMonitor.Service.Sub
{
private readonly ILogger _logger;
private readonly BloodpressResolver _resolverBloodpress;
+ private readonly PregnancyHeartRateResolver _resolverPregnacyHeartRate;
//private const string BP = nameof(TopicHmBloodPress).ToLower();
- public MsgQueueManager(ILogger logger, BloodpressResolver resolverBloodpress)
+ public MsgQueueManager(ILogger logger,
+ BloodpressResolver resolverBloodpress,
+ PregnancyHeartRateResolver pregnacyHeartRateResolver)
{
_logger = logger;
_resolverBloodpress = resolverBloodpress;
+ _resolverPregnacyHeartRate = pregnacyHeartRateResolver;
}
//public IResolver? GetMsgResolver()
@@ -55,6 +59,12 @@ namespace HealthMonitor.Service.Sub
_resolverBloodpress.SetResolveInfo(msg);
return _resolverBloodpress;
}
+
+ if (msg.Topic.Equals(nameof(TopicHmPregnancyHeartRate).ToLower()))
+ {
+ _resolverPregnacyHeartRate.SetResolveInfo(msg);
+ return _resolverPregnacyHeartRate;
+ }
return null;
diff --git a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
index c5b3db4..91c1814 100644
--- a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
+++ b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs
@@ -20,6 +20,7 @@ using System.Threading.Tasks;
using TDengineDriver;
using TDengineTMQ;
using TelpoDataService.Util.Entities.GpsLocationHistory;
+using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace HealthMonitor.Service.Sub
{
@@ -69,40 +70,80 @@ namespace HealthMonitor.Service.Sub
DoReceive(conn);
}
- public void DoReceive(IntPtr Connection)
+ public void DoReceive(IntPtr connection)
{
- #region topichmbpstats 订阅
+ #region topic 订阅
// string topic = "topichmbpstats";
- string topic = nameof(TopicHmBloodPress).ToLower();
- TopicHmBloodPress fields = new();
- PropertyInfo[] props = fields.GetType().GetProperties();
- // 获取 fields
- string attributes = "";
- foreach (PropertyInfo prop in props)
+ //string bloodPressTopic = nameof(TopicHmBloodPress).ToLower();
+ //TopicHmBloodPress fields = new();
+ //PropertyInfo[] props = fields.GetType().GetProperties();
+ //// 获取 fields
+ //string attributes = "";
+ //foreach (PropertyInfo prop in props)
+ //{
+ // JsonPropertyAttribute attr = prop.GetCustomAttribute()!;
+ // if (attr != null)
+ // {
+ // attributes += attr.PropertyName + ",";
+ // }
+ //}
+ //attributes = attributes.TrimEnd(',');
+
+ ////创建 topichmbpstats
+ //IntPtr res = TDengine.Query(Connection, $"create topic if not exists {bloodPressTopic} as select {attributes} from health_monitor.stb_hm_bloodpress");
+
+ ////创建 topichmpregnancyheartrate
+ //var pregnancyHeartRateTopic = nameof(TopicHmPregnancyHeartRate).ToLower();
+ //var pregnancyHeartateAttributes = typeof(TopicHmPregnancyHeartRate).GetType().GetProperties().Select(prop => prop.GetCustomAttribute());
+ //var pregnancyHeartateAttributesStr = string.Join(", ", pregnancyHeartateAttributes);
+ //res = TDengine.Query(Connection, $"create topic if not exists {pregnancyHeartRateTopic} as select {pregnancyHeartateAttributesStr} from {_configTDengineService.DB}.stb_hm_pregnancy_heart_rate");
+
+ //if (TDengine.ErrorNo(res) != 0)
+ //{
+ // _logger.LogError($"create topic failed, reason:{TDengine.Error(res)}");
+ // throw new Exception($"create topic failed, reason:{TDengine.Error(res)}");
+ //}
+
+ // 获取字段属性
+ string GetAttributes(Type type)
{
- JsonPropertyAttribute attr = prop.GetCustomAttribute()!;
- if (attr != null)
+ var props = type.GetProperties();
+ var attributeNames = props
+ .Select(prop => prop.GetCustomAttribute()?.PropertyName)
+ .Where(attr => !string.IsNullOrEmpty(attr));
+
+ return string.Join(",", attributeNames);
+ }
+
+ // 创建 topic
+ void CreateTopic(IntPtr conn, string topicName, string attributes, string tableName)
+ {
+ string query = $"create topic if not exists {topicName} as select {attributes} from {tableName}";
+ IntPtr res = TDengine.Query(conn, query);
+
+ if (TDengine.ErrorNo(res) != 0)
{
- attributes += attr.PropertyName + ",";
+ string error = TDengine.Error(res);
+ _logger.LogError($"Create topic {topicName} failed, reason: {error}");
+ throw new Exception($"Create topic {topicName} failed, reason: {error}");
}
}
- attributes = attributes.TrimEnd(',');
- //创建 topichmbpstats
- IntPtr res = TDengine.Query(Connection, $"create topic if not exists {topic} as select {attributes} from health_monitor.stb_hm_bloodpress");
+ // 血压 topic
+ string bloodPressTopic = nameof(TopicHmBloodPress).ToLower();
+ string bloodPressAttributes = GetAttributes(typeof(TopicHmBloodPress));
+ CreateTopic(connection, bloodPressTopic, bloodPressAttributes, $"{_configTDengineService.DB}.stb_hm_bloodpress");
+
+ // 孕期心率 topic
+ string pregnancyHeartRateTopic = nameof(TopicHmPregnancyHeartRate).ToLower();
+ string pregnancyHeartRateAttributes = GetAttributes(typeof(TopicHmPregnancyHeartRate));
+ CreateTopic(connection, pregnancyHeartRateTopic, pregnancyHeartRateAttributes, $"{_configTDengineService.DB}.stb_hm_pregnancy_heart_rate");
+
- //创建 topichmfetalheartrate
- //var fetalHeartRateTopic = "topichmfetalheartrate";
- //var fetalHeartRateFields = "ts,fetal_heart_rate_id,message_id,person_id,serialno,fetal_heart_rate,create_time,method,last_update,is_display,device_key";
- //res = TDengine.Query(Connection, $"create topic if not exists {fetalHeartRateTopic} as select {fetalHeartRateFields} from health_monitor.stb_hm_fetal_heart_rate_test");
#endregion
- if (TDengine.ErrorNo(res) != 0)
- {
- _logger.LogError($"create topic failed, reason:{TDengine.Error(res)}");
- throw new Exception($"create topic failed, reason:{TDengine.Error(res)}");
- }
+
var cfg = new ConsumerConfig
{
GourpId = "group_1",
@@ -112,12 +153,13 @@ namespace HealthMonitor.Service.Sub
TDConnectIp = _configTDengineService.Host,
};
// create consumer
- var consumer = new ConsumerBuilder(cfg)
- .Build();
+ var consumer = new ConsumerBuilder(cfg).Build();
+ var topics = new string[] { bloodPressTopic, pregnancyHeartRateTopic };
+
// subscribe
- consumer.Subscribe(topic);
-
+ consumer.Subscribe(topics);
+
while (!_tokenSource!.IsCancellationRequested)
{
var consumeRes = consumer.Consume(300);
@@ -154,14 +196,11 @@ namespace HealthMonitor.Service.Sub
}
}
consumer.Commit(consumeRes);
-
- //_logger.LogInformation("监听中....");
- // Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff},监听中....");
}
// close consumer after use.Otherwise will lead memory leak.
consumer.Close();
- TDengine.Close(Connection);
+ TDengine.Close(connection);
}
public void ParsePackage(ReceiveMessageModel model)
diff --git a/HealthMonitor.Service/Sub/Topic/Model/TopicHmPregnancyHeartRate.cs b/HealthMonitor.Service/Sub/Topic/Model/TopicHmPregnancyHeartRate.cs
new file mode 100644
index 0000000..d254425
--- /dev/null
+++ b/HealthMonitor.Service/Sub/Topic/Model/TopicHmPregnancyHeartRate.cs
@@ -0,0 +1,44 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthMonitor.Service.Sub.Topic.Model
+{
+ public class TopicHmPregnancyHeartRate
+ {
+ [JsonProperty("ts")]
+ public long Ts { get; set; } = default!;
+ [JsonProperty("pregnancy_heart_rate_id")]
+ public string PregnancyHeartRateId { get; set; } = default!;
+
+ [JsonProperty("message_id")]
+ public string MessageId { get; set; } = default!;
+
+ [JsonProperty("person_id")]
+ public string PersonId { get; set; } = default!;
+
+ [JsonProperty("serialno")]
+ public string Serialno { get; set; } = default!;
+
+ [JsonProperty("pregnancy_heart_rate")]
+ public int PregnancyHeartRate { get; set; }
+
+ [JsonProperty("last_update")]
+ public long LastUpdate { get; set; }
+
+ [JsonProperty("create_time")]
+ public long CreateTime { get; set; }
+
+ [JsonProperty("method")]
+ public int Method { get; set; }
+
+ [JsonProperty("is_display")]
+ public bool IsDisplay { get; set; }
+
+ [JsonProperty("device_key")]
+ public string DeviceKey { get; set; } = default!;
+ }
+}
diff --git a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs
index 0535a23..b94c54d 100644
--- a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs
+++ b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs
@@ -46,7 +46,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
private readonly TDengineService _serviceTDengine;
private readonly HttpHelper _httpHelper = default!;
- private readonly IotWebApiService _serviceIotWebApi;
+ private readonly IotApiService _serviceIotWebApi;
private readonly GpsCardAccessorClient _deviceApiClient;
private readonly GpsCardAccessorClient _gpsPersonApiClient;
@@ -58,7 +58,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
GpsCardAccessorClient gpsPersonApiClient,
GpsCardAccessorClient deviceApiClient,
ILogger logger,
- IotWebApiService iotWebApiService
+ IotApiService iotWebApiService
)
{
diff --git a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
index de805ee..affcb1e 100644
--- a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
+++ b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressController.cs
@@ -97,7 +97,24 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
//await _serviceTDengine.InsertAsync("hm_fhr", test);
//var first = _serviceTDengine.GetFirst();
- var first = await _serviceTDengine.GetBySerialNoAsync("864144050568123");
+ var test2 = new PregnancyHeartRateModel()
+ {
+ Timestamp = DateTime.Now,
+ CreateTime = DateTime.Now,
+ PregnancyHeartRate = 120,
+ PregnancyHeartRateId= Guid.NewGuid().ToString("D"),
+ IsDisplay = false,
+ Method = 1,
+ PersonId = Guid.NewGuid().ToString("D"),
+ MessageId = Guid.NewGuid().ToString("D"),
+ SerialNumber = "864144050568123",
+ DeviceKey = Guid.NewGuid().ToString("D"),
+ SerialTailNumber = "23",
+ LastUpdate = DateTime.Now,
+ };
+ await _serviceTDengine.InsertAsync("hm_phr", test2);
+
+ var first = await _serviceTDengine.GetBySerialNoAsync("864144050568123");
return Ok(first);
}
}
diff --git a/HealthMonitor.WebApi/Program.cs b/HealthMonitor.WebApi/Program.cs
index 27d2bf7..b7c072a 100644
--- a/HealthMonitor.WebApi/Program.cs
+++ b/HealthMonitor.WebApi/Program.cs
@@ -93,7 +93,7 @@ namespace HealthMonitor.WebApi
var serverVersion = ServerVersion.AutoDetect(mySqlCon);
options.UseMySql(mySqlCon, serverVersion)
.UseLoggerFactory(loggerFactory);
- }, poolSize: 64); ;
+ }, poolSize: 64);
builder.Services
.AddScoped(sp =>
@@ -172,6 +172,7 @@ namespace HealthMonitor.WebApi
#region Cache
builder.Services
.AddSingleton()
+ .AddSingleton()
.AddSingleton();
#endregion
@@ -189,11 +190,12 @@ namespace HealthMonitor.WebApi
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services
.AddSingleton()
- .AddSingleton()
+ .AddSingleton()
.AddSingleton()
.AddHostedService();
#endregion
diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs
index 0bfcc94..5f58ada 100644
--- a/HealthMonitor.WebApi/Worker.cs
+++ b/HealthMonitor.WebApi/Worker.cs
@@ -33,19 +33,19 @@ namespace HealthMonitor.WebApi
private readonly TDengineService _serviceTDengine;
private readonly EtcdService _serviceEtcd;
private readonly HttpHelper _httpHelper = default!;
- private readonly IotWebApiService _serviceIotWebApi;
+ private readonly IotApiService _serviceIotApi;
private readonly BoodPressResolverConfig _configBoodPressResolver;
private readonly BloodPressReferenceValueCacheManager _bpRefValCacheManager;
private readonly PersonCacheManager _personCacheMgr;
private CancellationTokenSource _tokenSource = default!;
- public Worker(ILogger logger, IServiceProvider services, PersonCacheManager personCacheMgr, BloodPressReferenceValueCacheManager bpRefValCacheManager, IotWebApiService iotWebApiService, 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, HttpHelper httpHelper, EtcdService serviceEtcd)
{
_logger = logger;
_tdEngineDataSubcribe = tdEngineDataSubcribe;
_services = services;
- _serviceIotWebApi = iotWebApiService;
+ _serviceIotApi = IotApiService;
_processor = processor;
_serviceEtcd = serviceEtcd;
_serviceTDengine = serviceDengine;
@@ -116,283 +116,382 @@ namespace HealthMonitor.WebApi
case "Delete":
// TTL到了重新计算TTL,下发
- Console.BackgroundColor = ConsoleColor.Green;
- Console.WriteLine($"--- {e.Type}--{e.Kv.Key.ToStringUtf8()}--{e.Kv.Value.ToStringUtf8()}---{DateTime.Now}");
+ //Console.BackgroundColor = ConsoleColor.Green;
+ //Console.WriteLine($"--- {e.Type}--{e.Kv.Key.ToStringUtf8()}--{e.Kv.Value.ToStringUtf8()}---{DateTime.Now}");
// var key = $"health_moniter/schedule_push/imei/{bp.Serialno}";
var key = e.Kv.Key.ToStringUtf8();
- var imeiDel = key.Split('/')[3];
+ var imeiDel = key.Split('/')[^1];
var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(schedule_push))
{
- int systolicInc;
- int diastolicInc;
+ if (key.Contains("pregnancy_heart_rate"))
+ {
+ // 处理孕妇业务,计算一般心率并下发
+ var commonPHR= await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(imeiDel);
+ // 设置胎心监测参数
- int systolicRefValue;
- int diastolicRefValue;
+ if (commonPHR == null)
+ {
+ // 建模中
+ var flag= await _serviceIotApi.SetFetalHeartRateConfig(imeiDel);
+ _logger.LogInformation($"{imeiDel} 建模建模中");
+ }
+ else
+ {
+ // 建模完成
+ var flag = await _serviceIotApi.SetFetalHeartRateConfig(imeiDel,1,commonPHR.MaxValue,commonPHR.MinValue);
+ _logger.LogInformation($"{imeiDel} 建模完成");
+ // 保存到TDengine数据库
+ await _serviceTDengine.InsertAsync("hm_pchr", commonPHR);
+ _logger.LogInformation($"保存TDengine完成");
+ }
- decimal systolicAvg;
- decimal diastolicAvg;
+ #region 注册定时下发
+ var startTime = DateTime.Now;
+ // 注册下次下推
+ var endTime = DateTime.Now;
- int systolicMax = 0;
- int diastolicMax = 0;
+#if DEBUG
- // 统计时间
- //DateTime endTime = DateTime.Now; //测试
- DateTime statStartTime = DateTime.Now;
+ //long ttl = (long)((60 * 1000-(endTime-startTime).TotalMilliseconds)/1000);
+ //await _serviceEtcd.PutValAsync(key, imeiDel,ttl, false).ConfigureAwait(false);
- // 最小值
- int systolicMin = 0;
- int diastolicMin = 0;
+ var interval = 0;
+ // 获取当前时间
+ DateTime now = DateTime.Now;
- // 偏移参数
- var avgOffset = 0.25M;
- var systolicAvgOffset = avgOffset;
- var diastolicAvgOffset = avgOffset;
+ // 计算距离下一个$interval天后的8点的时间间隔
+ DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 2, 0).AddDays(interval);
+ TimeSpan timeUntilNextRun = nextRunTime - now;
- // 最后一次下发值
- int lastPushSystolicInc = 0;
- int lastPushDiastolicInc = 0;
+ // 如果当前时间已经超过了8点,将等待到明天后的8点
+ if (timeUntilNextRun < TimeSpan.Zero)
+ {
+ timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1));
+ nextRunTime += timeUntilNextRun;
+ }
+
+ //long ttl = timeUntilNextRun.Milliseconds/1000;
+ long ttl = (long)((timeUntilNextRun.TotalMilliseconds - (endTime - startTime).TotalMilliseconds) / 1000);
+ var data = new
+ {
+ imei = imeiDel,
+ 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);
- var startTime = DateTime.Now;
- // 下发增量值
- #region 统计定时下发增量值
- //var last = await _serviceTDengine.GetLastAsync("stb_hm_bloodpress_stats_inc", $"serialno='{imeiDel}' order by last_update desc");
- //var ts = last?[0];
- // 最后一条血压数据
- var condition = $"serialno='{imeiDel}' order by last_update desc";
- var field = "last_row(*)";
- var lastHmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition, field);
- var lastHmBpParser = JsonConvert.DeserializeObject>(lastHmBpResponse!);
- var lastHmBp = lastHmBpParser?.Select().FirstOrDefault();
- //if (lastHmBpParser?.Select()?.ToList().Count < 2)
- //{
- // _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} -- 血压数据条目不足");
- // break;
- //}
+#else
+ // 每$interval天,晚上8点
+ var interval = 1;
+ // 获取当前时间
+ DateTime now = DateTime.Now;
+ var rand = new Random();
- // 7 天有效数据
- if (lastHmBp?.Timestamp.AddDays(7) > DateTime.Now)
+ 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);
+ TimeSpan timeUntilNextRun = nextRunTime - now;
+
+ // 如果当前时间已经超过了8点,将等待到明天后的8点
+ if (timeUntilNextRun < TimeSpan.Zero)
+ {
+ timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1));
+ nextRunTime += timeUntilNextRun;
+ }
+
+ // var ttl = timeUntilNextRun.TotalMilliseconds;
+ long ttl = (long)((timeUntilNextRun.TotalMilliseconds-(endTime-startTime).TotalMilliseconds)/1000);
+ var data = new
+ {
+ imei = imeiDel,
+ 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);
+#endif
+ #endregion
+ }
+ else
{
- // 计算增量值
- condition = $"serialno='{imeiDel}' order by ts desc";
- var lastPushResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bp_push_ref_inc_value", condition, field);
- if (lastPushResponse == null)
+ // 处理血压业务
+ int systolicInc;
+ int diastolicInc;
+
+ int systolicRefValue;
+ int diastolicRefValue;
+
+ decimal systolicAvg;
+ decimal diastolicAvg;
+
+ int systolicMax = 0;
+ int diastolicMax = 0;
+
+ // 统计时间
+ //DateTime endTime = DateTime.Now; //测试
+ DateTime statStartTime = DateTime.Now;
+
+
+ // 最小值
+ int systolicMin = 0;
+ int diastolicMin = 0;
+
+ // 偏移参数
+ var avgOffset = 0.25M;
+ var systolicAvgOffset = avgOffset;
+ var diastolicAvgOffset = avgOffset;
+
+ // 最后一次下发值
+ int lastPushSystolicInc = 0;
+ int lastPushDiastolicInc = 0;
+
+
+ var startTime = DateTime.Now;
+ // 下发增量值
+ #region 统计定时下发增量值
+ //var last = await _serviceTDengine.GetLastAsync("stb_hm_bloodpress_stats_inc", $"serialno='{imeiDel}' order by last_update desc");
+ //var ts = last?[0];
+
+ // 最后一条血压数据
+ var condition = $"serialno='{imeiDel}' order by last_update desc";
+ var field = "last_row(*)";
+ var lastHmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition, field);
+ var lastHmBpParser = JsonConvert.DeserializeObject>(lastHmBpResponse!);
+ var lastHmBp = lastHmBpParser?.Select().FirstOrDefault();
+ //if (lastHmBpParser?.Select()?.ToList().Count < 2)
+ //{
+ // _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} -- 血压数据条目不足");
+ // break;
+ //}
+
+ // 7 天有效数据
+ if (lastHmBp?.Timestamp.AddDays(7) > DateTime.Now)
{
- _logger.LogInformation($"{imeiDel}--没有下发记录");
- break;
- }
- var lastPushParser = JsonConvert.DeserializeObject>(lastPushResponse);
- var lastPush = lastPushParser!.Select().FirstOrDefault();
- // 有下推记录
- if (lastPush != null)
- {
- systolicRefValue = lastPush!.SystolicRefValue;
- diastolicRefValue = lastPush!.DiastolicRefValue;
- lastPushSystolicInc = lastPush!.SystolicIncValue;
- lastPushDiastolicInc = lastPush!.DiastolicIncValue;
- condition = $"ts between '{lastPush?.Timestamp:yyyy-MM-dd HH:mm:ss.fff}' and '{startTime:yyyy-MM-dd HH:mm:ss.fff}' " +
- $"and serialno='{imeiDel}' " +
- $"and is_display = true";
- // 使用最近一次的下推时间作为统计的开始时间
- statStartTime = lastPush!.Timestamp;
- }
- // 没有下推记录(历史遗留数据),没有初始的测量值产生的平均值(测量值=平均值)
- else
- {
- #region 获取个人信息
-
- var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(Guid.NewGuid().ToString(), imeiDel).ConfigureAwait(false);
- //验证这个信息是否存在
- if (person == null || person?.Person.BornDate == null)
+ // 计算增量值
+ condition = $"serialno='{imeiDel}' order by ts desc";
+ var lastPushResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bp_push_ref_inc_value", condition, field);
+ if (lastPushResponse == null)
{
- _logger.LogWarning($"{nameof(Worker)}--{imeiDel} 验证个人信息,找不到个人信息,跳过此消息");
+ _logger.LogInformation($"{imeiDel}--没有下发记录");
break;
}
- // 验证年龄是否在范围 (2 - 120)
- var age = SafeType.SafeInt(DateTime.Today.Year - person?.Person.BornDate!.Value.Year!);
- if (age < 2 || age > 120)
+ var lastPushParser = JsonConvert.DeserializeObject>(lastPushResponse);
+ var lastPush = lastPushParser!.Select().FirstOrDefault();
+ // 有下推记录
+ if (lastPush != null)
{
- _logger.LogWarning($"{nameof(Worker)}--{imeiDel} 验证年龄,不在范围 (2 - 120)岁,跳过此消息");
- break;
+ systolicRefValue = lastPush!.SystolicRefValue;
+ diastolicRefValue = lastPush!.DiastolicRefValue;
+ lastPushSystolicInc = lastPush!.SystolicIncValue;
+ lastPushDiastolicInc = lastPush!.DiastolicIncValue;
+ condition = $"ts between '{lastPush?.Timestamp:yyyy-MM-dd HH:mm:ss.fff}' and '{startTime:yyyy-MM-dd HH:mm:ss.fff}' " +
+ $"and serialno='{imeiDel}' " +
+ $"and is_display = true";
+ // 使用最近一次的下推时间作为统计的开始时间
+ statStartTime = lastPush!.Timestamp;
}
+ // 没有下推记录(历史遗留数据),没有初始的测量值产生的平均值(测量值=平均值)
+ else
+ {
+ #region 获取个人信息
- var gender = person?.Person.Gender == true ? 1 : 2;
- var isHypertension = SafeType.SafeBool(person?.Person.Ishypertension!);
- var height = SafeType.SafeDouble(person?.Person.Height!);
- var weight = SafeType.SafeDouble(person?.Person.Weight!);
-
- #endregion
-
- #region 初始化常规血压标定值标定值
- var bpRef = await _bpRefValCacheManager.GetBloodPressReferenceValueAsync(age, gender, isHypertension);
- //systolicRefValue = bpRef!.Systolic;//?
- //diastolicRefValue = bpRef!.Diastolic;//?
- #endregion
-
- systolicRefValue = bpRef!.Systolic;
- diastolicRefValue = bpRef!.Diastolic;
- lastPushSystolicInc = 0;
- lastPushDiastolicInc = 0;
- condition = $"ts <= '{startTime:yyyy-MM-dd HH:mm:ss.fff}' " +
- $"and serialno='{imeiDel}' " +
- $"and is_display = true";
- }
+ var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(Guid.NewGuid().ToString(), imeiDel).ConfigureAwait(false);
+ //验证这个信息是否存在
+ if (person == null || person?.Person.BornDate == null)
+ {
+ _logger.LogWarning($"{nameof(Worker)}--{imeiDel} 验证个人信息,找不到个人信息,跳过此消息");
+ break;
+ }
+ // 验证年龄是否在范围 (2 - 120)
+ var age = SafeType.SafeInt(DateTime.Today.Year - person?.Person.BornDate!.Value.Year!);
+ if (age < 2 || age > 120)
+ {
+ _logger.LogWarning($"{nameof(Worker)}--{imeiDel} 验证年龄,不在范围 (2 - 120)岁,跳过此消息");
+ break;
+ }
+ var gender = person?.Person.Gender == true ? 1 : 2;
+ var isHypertension = SafeType.SafeBool(person?.Person.Ishypertension!);
+ var height = SafeType.SafeDouble(person?.Person.Height!);
+ var weight = SafeType.SafeDouble(person?.Person.Weight!);
+ #endregion
- var hmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition);
- var hmBpParser = JsonConvert.DeserializeObject>(hmBpResponse!);
- var hmBp = hmBpParser?.Select();
- //if (hmBp?.ToList().Count < 2)
- // 1. 判断数据样本数量
- if (hmBpParser!.Rows < 5)
- {
- _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} -- 统计定时下发,计算增量值的数据条目不足:{hmBpParser!.Rows} < 5");
- _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} 没有足够的数据样本,不会定时下发");
- break;
- }
- // 没有下推记录重新计算统计时间
- if (lastPush == null)
- {
- var firstHmBp = hmBpParser?.Select(i => i).OrderBy(i => i.Timestamp).FirstOrDefault();
- statStartTime = firstHmBp!.Timestamp;
- }
+ #region 初始化常规血压标定值标定值
+ var bpRef = await _bpRefValCacheManager.GetBloodPressReferenceValueAsync(age, gender, isHypertension);
+ //systolicRefValue = bpRef!.Systolic;//?
+ //diastolicRefValue = bpRef!.Diastolic;//?
+ #endregion
- // NewMethod(systolicRefValue, hmBpParser);
+ systolicRefValue = bpRef!.Systolic;
+ diastolicRefValue = bpRef!.Diastolic;
+ lastPushSystolicInc = 0;
+ lastPushDiastolicInc = 0;
+ condition = $"ts <= '{startTime:yyyy-MM-dd HH:mm:ss.fff}' " +
+ $"and serialno='{imeiDel}' " +
+ $"and is_display = true";
+ }
- // 最大值
- //systolicMax = (int)hmBpParser?.Select(i => i.SystolicValue).Max()!;
- //diastolicMax = (int)hmBpParser?.Select(i => i.DiastolicValue).Max()!;
- //// 最小值
- //systolicMin = (int)hmBpParser?.Select(i => i.SystolicValue).Min()!;
- //diastolicMin = (int)hmBpParser?.Select(i => i.DiastolicValue).Min()!;
- //systolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.SystolicValue, SafeType.SafeInt(systolicRefValue!)))!;
- //diastolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.DiastolicValue, SafeType.SafeInt(diastolicRefValue!)))!;
- var avgs = _serviceTDengine.AverageAfterRemovingOneMinMaxRef(hmBpParser!);
- systolicAvg = avgs[0];
- diastolicAvg = avgs[1];
+ var hmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition);
+ var hmBpParser = JsonConvert.DeserializeObject>(hmBpResponse!);
+ var hmBp = hmBpParser?.Select();
+ //if (hmBp?.ToList().Count < 2)
+ // 1. 判断数据样本数量
+ if (hmBpParser!.Rows < 5)
+ {
+ _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} -- 统计定时下发,计算增量值的数据条目不足:{hmBpParser!.Rows} < 5");
+ _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} 没有足够的数据样本,不会定时下发");
+ break;
+ }
+ // 没有下推记录重新计算统计时间
+ if (lastPush == null)
+ {
+ var firstHmBp = hmBpParser?.Select(i => i).OrderBy(i => i.Timestamp).FirstOrDefault();
+ statStartTime = firstHmBp!.Timestamp;
+ }
+ // NewMethod(systolicRefValue, hmBpParser);
- // 2. 判断能否计算增量值
- if (systolicAvg.Equals(0))
- {
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算平均值" +
- $"\n currentSystolicAvg:{systolicAvg} -- lastPushSystolicInc:{lastPushSystolicInc}" +
- $"\n currentDiastolicInc:{diastolicAvg} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)} 没有足够的数据样本计算平均值,不会定时下发");
- break;
- }
- // 除最大值和最小值后的平均值与标定值差值少于4后(当天计算出该结果则也不产生增量调整),就不再进行增量值调整了。
- if (systolicRefValue - systolicAvg < 4)
- {
- _logger.LogInformation($"diastolic 舒张压 {imeiDel}除最大值和最小值后的平均值:{diastolicAvg}与标定值:{diastolicRefValue}\n systolic 收缩压 {imeiDel}除最大值和最小值后的平均值:{systolicAvg}与标定值:{systolicRefValue}的差值(标定值-平均值)少于4后,systolic 收缩压 不再进行增量值调整");
- break;
- }
+ // 最大值
+ //systolicMax = (int)hmBpParser?.Select(i => i.SystolicValue).Max()!;
+ //diastolicMax = (int)hmBpParser?.Select(i => i.DiastolicValue).Max()!;
+ //// 最小值
+ //systolicMin = (int)hmBpParser?.Select(i => i.SystolicValue).Min()!;
+ //diastolicMin = (int)hmBpParser?.Select(i => i.DiastolicValue).Min()!;
- if (diastolicRefValue - diastolicAvg < 4)
- {
- _logger.LogInformation($"systolic 收缩压 {imeiDel}除最大值和最小值后的平均值:{systolicAvg}与标定值:{systolicRefValue}\n diastolic 舒张压 {imeiDel}除最大值和最小值后的平均值:{diastolicAvg}与标定值:{diastolicRefValue}的差值(标定值-平均值)少于4后,diastolic 舒张压 不再进行增量值调整");
- break;
- }
+ //systolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.SystolicValue, SafeType.SafeInt(systolicRefValue!)))!;
+ //diastolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.DiastolicValue, SafeType.SafeInt(diastolicRefValue!)))!;
- // 增量值=(标定值-平均值)* 0.25
- var currentSystolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!;
- var currentDiastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!;
+ var avgs = _serviceTDengine.AverageAfterRemovingOneMinMaxRef(hmBpParser!);
+ systolicAvg = avgs[0];
+ diastolicAvg = avgs[1];
- // 累计增量
- systolicInc = currentSystolicInc + lastPushSystolicInc;
- diastolicInc = currentDiastolicInc + lastPushDiastolicInc;
+ // 2. 判断能否计算增量值
+ if (systolicAvg.Equals(0))
+ {
+ _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算平均值" +
+ $"\n currentSystolicAvg:{systolicAvg} -- lastPushSystolicInc:{lastPushSystolicInc}" +
+ $"\n currentDiastolicInc:{diastolicAvg} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
+ _logger.LogInformation($"{imeiDel}--{nameof(Worker)} 没有足够的数据样本计算平均值,不会定时下发");
+ break;
+ }
+ // 除最大值和最小值后的平均值与标定值差值少于4后(当天计算出该结果则也不产生增量调整),就不再进行增量值调整了。
+ if (systolicRefValue - systolicAvg < 4)
+ {
+ _logger.LogInformation($"diastolic 舒张压 {imeiDel}除最大值和最小值后的平均值:{diastolicAvg}与标定值:{diastolicRefValue}\n systolic 收缩压 {imeiDel}除最大值和最小值后的平均值:{systolicAvg}与标定值:{systolicRefValue}的差值(标定值-平均值)少于4后,systolic 收缩压 不再进行增量值调整");
+ break;
+ }
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算增量值" +
- $"\n {imeiDel} -- systolicAvg:{systolicAvg}-- systolicInc:{systolicInc}-- currentSystolicInc:{currentSystolicInc} -- lastPushSystolicInc:{lastPushSystolicInc}" +
- $"\n {imeiDel} -- diastolicAvg:{diastolicAvg}-- diastolicInc:{diastolicInc} --currentDiastolicInc:{currentDiastolicInc} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}-- 定时校准,发给设备的绝对增量值=(上次绝对增量值+新数据的增量值)");
+ if (diastolicRefValue - diastolicAvg < 4)
+ {
+ _logger.LogInformation($"systolic 收缩压 {imeiDel}除最大值和最小值后的平均值:{systolicAvg}与标定值:{systolicRefValue}\n diastolic 舒张压 {imeiDel}除最大值和最小值后的平均值:{diastolicAvg}与标定值:{diastolicRefValue}的差值(标定值-平均值)少于4后,diastolic 舒张压 不再进行增量值调整");
+ break;
+ }
+ // 增量值=(标定值-平均值)* 0.25
+ var currentSystolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!;
+ var currentDiastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!;
- _logger.LogInformation($"{nameof(Worker)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}");
- if (_configBoodPressResolver.EnableBPRefPush)
- // if (false) // 临时关闭
- {
- BloodPressCalibrationConfigModel bpIncData = new()
- {
- Imei = imeiDel,
- SystolicRefValue = SafeType.SafeInt(((int)systolicRefValue!)), //收缩压标定值,值为0 表示不生效
- DiastolicRefValue = SafeType.SafeInt(((int)diastolicRefValue!)), //舒张压标定值,值为0表示不生效
- SystolicIncValue = SafeType.SafeInt(((int)systolicInc!)), //收缩压显示增量,值为0 表示不生效
- DiastolicIncValue = SafeType.SafeInt(((int)diastolicInc!)) //舒张压显示增量,值为0 表示不生效
- };
- //var pushedBP = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false);
- var response = await _serviceIotWebApi.SetBloodPressCalibrationConfig2Async(bpIncData).ConfigureAwait(false);
- var pushedBP = response.Flag;
- if (pushedBP)
+ // 累计增量
+ systolicInc = currentSystolicInc + lastPushSystolicInc;
+ diastolicInc = currentDiastolicInc + lastPushDiastolicInc;
+
+ _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算增量值" +
+ $"\n {imeiDel} -- systolicAvg:{systolicAvg}-- systolicInc:{systolicInc}-- currentSystolicInc:{currentSystolicInc} -- lastPushSystolicInc:{lastPushSystolicInc}" +
+ $"\n {imeiDel} -- diastolicAvg:{diastolicAvg}-- diastolicInc:{diastolicInc} --currentDiastolicInc:{currentDiastolicInc} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
+ _logger.LogInformation($"{imeiDel}--{nameof(Worker)}-- 定时校准,发给设备的绝对增量值=(上次绝对增量值+新数据的增量值)");
+
+
+ _logger.LogInformation($"{nameof(Worker)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}");
+ if (_configBoodPressResolver.EnableBPRefPush)
+ // if (false) // 临时关闭
{
- #region 保存下推记录 stb_hm_bp_push_ref_inc_value
- var sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{imeiDel.Substring(imeiDel.Length - 2)} " +
- $"USING health_monitor.stb_hm_bp_push_ref_inc_value " +
- $"TAGS ('{imeiDel.Substring(imeiDel.Length - 2)}') " +
- $"VALUES(" +
- $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," +
- $"'{imeiDel}'," +
- $"{bpIncData.SystolicRefValue}," +
- $"{bpIncData.DiastolicRefValue}," +
- $"{bpIncData.SystolicIncValue}," +
- $"{bpIncData.DiastolicIncValue}," +
- $"{false}," +
- $"{systolicAvg}," +
- $"{diastolicAvg}," +
- $"{systolicAvgOffset}," +
- $"{diastolicAvgOffset}," +
- $"'{statStartTime:yyyy-MM-dd HH:mm:ss.fff}'," +
- $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'" +
- $")";
- _serviceTDengine.ExecuteInsertSQL(sql);
- #endregion
+ BloodPressCalibrationConfigModel bpIncData = new()
+ {
- #region 注册定时下发
- // 注册下次下推
- var endTime = DateTime.Now;
+ Imei = imeiDel,
+ SystolicRefValue = SafeType.SafeInt(((int)systolicRefValue!)), //收缩压标定值,值为0 表示不生效
+ DiastolicRefValue = SafeType.SafeInt(((int)diastolicRefValue!)), //舒张压标定值,值为0表示不生效
+ SystolicIncValue = SafeType.SafeInt(((int)systolicInc!)), //收缩压显示增量,值为0 表示不生效
+ DiastolicIncValue = SafeType.SafeInt(((int)diastolicInc!)) //舒张压显示增量,值为0 表示不生效
+ };
+ //var pushedBP = await _serviceIotApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false);
+ var response = await _serviceIotApi.SetBloodPressCalibrationConfig2Async(bpIncData).ConfigureAwait(false);
+ var pushedBP = response.Flag;
+ if (pushedBP)
+ {
+ #region 保存下推记录 stb_hm_bp_push_ref_inc_value
+ var sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{imeiDel.Substring(imeiDel.Length - 2)} " +
+ $"USING health_monitor.stb_hm_bp_push_ref_inc_value " +
+ $"TAGS ('{imeiDel.Substring(imeiDel.Length - 2)}') " +
+ $"VALUES(" +
+ $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," +
+ $"'{imeiDel}'," +
+ $"{bpIncData.SystolicRefValue}," +
+ $"{bpIncData.DiastolicRefValue}," +
+ $"{bpIncData.SystolicIncValue}," +
+ $"{bpIncData.DiastolicIncValue}," +
+ $"{false}," +
+ $"{systolicAvg}," +
+ $"{diastolicAvg}," +
+ $"{systolicAvgOffset}," +
+ $"{diastolicAvgOffset}," +
+ $"'{statStartTime:yyyy-MM-dd HH:mm:ss.fff}'," +
+ $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'" +
+ $")";
+ _serviceTDengine.ExecuteInsertSQL(sql);
+ #endregion
+
+ #region 注册定时下发
+ // 注册下次下推
+ var endTime = DateTime.Now;
#if DEBUG
- //long ttl = (long)((60 * 1000-(endTime-startTime).TotalMilliseconds)/1000);
- //await _serviceEtcd.PutValAsync(key, imeiDel,ttl, false).ConfigureAwait(false);
+ //long ttl = (long)((60 * 1000-(endTime-startTime).TotalMilliseconds)/1000);
+ //await _serviceEtcd.PutValAsync(key, imeiDel,ttl, false).ConfigureAwait(false);
- var interval = 0;
- // 获取当前时间
- DateTime now = DateTime.Now;
+ var interval = 0;
+ // 获取当前时间
+ DateTime now = DateTime.Now;
- // 计算距离下一个$interval天后的8点的时间间隔
- DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 2, 0).AddDays(interval);
- TimeSpan timeUntilNextRun = nextRunTime - now;
+ // 计算距离下一个$interval天后的8点的时间间隔
+ DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 2, 0).AddDays(interval);
+ TimeSpan timeUntilNextRun = nextRunTime - now;
- // 如果当前时间已经超过了8点,将等待到明天后的8点
- if (timeUntilNextRun < TimeSpan.Zero)
- {
- timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1));
- nextRunTime += timeUntilNextRun;
- }
+ // 如果当前时间已经超过了8点,将等待到明天后的8点
+ if (timeUntilNextRun < TimeSpan.Zero)
+ {
+ timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1));
+ nextRunTime += timeUntilNextRun;
+ }
- // var ttl = timeUntilNextRun.TotalMilliseconds;
- long ttl = (long)((timeUntilNextRun.TotalMilliseconds - (endTime - startTime).TotalMilliseconds) / 1000);
- var data = new
- {
- imei = imeiDel,
- 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);
+ // var ttl = timeUntilNextRun.TotalMilliseconds;
+ long ttl = (long)((timeUntilNextRun.TotalMilliseconds - (endTime - startTime).TotalMilliseconds) / 1000);
+ var data = new
+ {
+ imei = imeiDel,
+ 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);
+ await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false);
#else
@@ -424,24 +523,24 @@ namespace HealthMonitor.WebApi
var result = JsonConvert.SerializeObject(data);
await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false);
#endif
- #endregion
+ #endregion
- }
- else
- {
- _logger.LogInformation($"错误响应,没有下推数据:{response.Message}");
+ }
+ else
+ {
+ _logger.LogInformation($"错误响应,没有下推数据:{response.Message}");
+ }
}
}
- }
- else
- {
- _logger.LogInformation($"向{imeiDel}统计数据已经失效");
- }
- #endregion
+ else
+ {
+ _logger.LogInformation($"向{imeiDel}统计数据已经失效");
+ }
+ #endregion
+ }
}
-
break;
}
}
@@ -454,62 +553,6 @@ namespace HealthMonitor.WebApi
});
}
- /**
- protected override Task ExecuteAsync(CancellationToken stoppingToken)
- {
- TaskFactory factory = new(_tokenSource.Token);
- factory.StartNew(async () =>
- {
- if (_tokenSource.IsCancellationRequested)
- _logger.LogWarning("Worker exit");
-
- _logger.LogInformation("------ResolveAsync");
- while (!_tokenSource.IsCancellationRequested)
- {
-
- await _processor.ResolveAsync().ConfigureAwait(false);
- }
-
- }, TaskCreationOptions.LongRunning);
-
- factory.StartNew(() =>
- {
- _logger.LogInformation("------_tdEngineDataSubcribe");
- while (!_tokenSource.IsCancellationRequested)
- {
- _tdEngineDataSubcribe.BeginListen(_tokenSource.Token);
- }
- }, TaskCreationOptions.LongRunning);
-
- Task.Run(() =>
- _serviceEtcd.WacthKeysWithPrefixResponseAsync($"health_moniter/schedule_push", WatchEvents)
- , stoppingToken);
- return Task.Delay(1000, _tokenSource.Token);
-
- }
- **/
-
- /**
- private void WatchEvents(WatchEvent[] response)
- {
- foreach (WatchEvent e1 in response)
- {
- // Console.WriteLine($"{nameof(WatchEventsAsync)} --- {e1.Key}:{e1.Value}:{e1.Type}");
-
- switch (e1.Type.ToString())
- {
- //case "Put":
- // // 获取时间点计算TTL
- // break;
-
- case "Delete":
- // TTL到了重新计算TTL,下发
- Console.WriteLine($"--- {e1.Key}:{e1.Value}:{e1.Type}");
- break;
- }
- }
- }
- */
}
diff --git a/HealthMonitor.WebApi/appsettings.Development.json b/HealthMonitor.WebApi/appsettings.Development.json
index 8a14514..9bc2665 100644
--- a/HealthMonitor.WebApi/appsettings.Development.json
+++ b/HealthMonitor.WebApi/appsettings.Development.json
@@ -27,7 +27,9 @@
"ServiceConfig": {
"TelpoDataUrl": "https://id.gdssjl.com/data/",
"EtcdServerAddress": "http://192.168.2.121:2379",
- "IotWebApiUrl": "http://id.gdssjl.com/webapi/api/"
+ "IotWebApiUrl": "http://id.gdssjl.com/webapi/api/",
+ "IotAuth": "http://id.ssjlai.com/auth/identityController",
+ "IotCore": "https://id.ssjlai.com/gateway/core/api/v1/open/OpenIot"
},
"BoodPressResolverConfig": {
"EnableBPRefPush": true
diff --git a/HealthMonitor.WebApi/appsettings.production.json b/HealthMonitor.WebApi/appsettings.production.json
index b0dd66a..88c3dac 100644
--- a/HealthMonitor.WebApi/appsettings.production.json
+++ b/HealthMonitor.WebApi/appsettings.production.json
@@ -24,7 +24,9 @@
"ServiceConfig": {
"TelpoDataUrl": "https://ai.gdssjl.com/data/",
"EtcdServerAddress": "http://172.19.42.40:2379",
- "IotWebApiUrl": "http://ai.gdssjl.com/webapi/api/"
+ "IotWebApiUrl": "http://ai.gdssjl.com/webapi/api/",
+ "IotAuth": "http://ai.ssjlai.com/auth/identityController",
+ "IotCore": "https://ai.ssjlai.com/gateway/core/api/v1/open/OpenIot"
},
"BoodPressResolverConfig": {
"EnableBPRefPush": true
diff --git a/HealthMonitor.WebApi/appsettings.test.json b/HealthMonitor.WebApi/appsettings.test.json
index 9fdc349..06be6f4 100644
--- a/HealthMonitor.WebApi/appsettings.test.json
+++ b/HealthMonitor.WebApi/appsettings.test.json
@@ -32,7 +32,9 @@
"ServiceConfig": {
"TelpoDataUrl": "https://id.gdssjl.com/data/",
"EtcdServerAddress": "http://172.19.42.44:2379",
- "IotWebApiUrl": "http://id.gdssjl.com/webapi/api/"
+ "IotWebApiUrl": "http://id.gdssjl.com/webapi/api/",
+ "IotAuth": "http://id.ssjlai.com/auth/identityController",
+ "IotCore": "https://id.ssjlai.com/gateway/core/api/v1/open/OpenIot"
},
"BoodPressResolverConfig": {
"EnableBPRefPush": true