diff --git a/HealthMonitor.Model/Service/Mapper/BloodPressureModel.cs b/HealthMonitor.Model/Service/Mapper/BloodPressureModel.cs new file mode 100644 index 0000000..84de0ac --- /dev/null +++ b/HealthMonitor.Model/Service/Mapper/BloodPressureModel.cs @@ -0,0 +1,45 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HealthMonitor.Model.Service.Mapper +{ + public class BloodPressureModel + { + [JsonProperty("ts")] + public DateTime Timestamp { get; set; } + + [JsonProperty("bloodpress_id")] + public string BloodPressureId { get; set; } = default!; + + [JsonProperty("message_id")] + public string MessageId { get; set; } = default!; + + [JsonProperty("serialno")] + public string SerialNumber { get; set; } = default!; + + [JsonProperty("systolic_value")] + public int SystolicValue { get; set; } + + [JsonProperty("diastolic_value")] + public int DiastolicValue { get; set; } + + [JsonProperty("create_time")] + public DateTime CreateTime { get; set; } + + [JsonProperty("last_update")] + public DateTime LastUpdate { get; set; } + + [JsonProperty("method")] + public byte Method { get; set; } + + [JsonProperty("is_display")] + public bool IsDisplay { get; set; } + + [JsonProperty("serial_tail_no")] + public string SerialTailNumber { get; set; } = default!; + } +} diff --git a/HealthMonitor.Model/Service/Mapper/BloodPressurePushRefIncModel.cs b/HealthMonitor.Model/Service/Mapper/BloodPressurePushRefIncModel.cs new file mode 100644 index 0000000..6b286b5 --- /dev/null +++ b/HealthMonitor.Model/Service/Mapper/BloodPressurePushRefIncModel.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HealthMonitor.Model.Service.Mapper +{ + public class BloodPressurePushRefIncModel + { + + [JsonProperty("ts")] + public DateTime Timestamp { get; set; } + + [JsonProperty("serialno")] + public string SerialNumber { get; set; } = default!; + + + [JsonProperty("systolic_ref_value")] + public int SystolicRefValue { get; set; } + + [JsonProperty("diastolic_ref_value")] + public int DiastolicRefValue { get; set; } + + + [JsonProperty("systolic_inc_value")] + public int SystolicIncValue { get; set; } + + [JsonProperty("diastolic_inc_value")] + public int DiastolicIncValue { get; set; } + + + [JsonProperty("systolic_avg_value")] + public int SystolicAvgValue { get; set; } + + [JsonProperty("diastolic_avg_value")] + public int DiastoliAvgValue { get; set; } + + + [JsonProperty("diastolic_avg_offset")] + public float DiastolicAvgOffset { get; set; } + + [JsonProperty("systolic_avg_offset")] + public float SystolicAvgOffset { get; set; } + + + [JsonProperty("stat_start_time")] + public DateTime StatStartTime { get; set; } + + [JsonProperty("stat_end_time")] + public DateTime StatEndTime { get; set; } + + + [JsonProperty("is_manual")] + public bool IsManual { get; set; } + + [JsonProperty("serial_tail_no")] + public string SerialTailNumber { get; set; } = default!; + } +} diff --git a/HealthMonitor.Model/Service/Mapper/ParseTDengineRestResponse.cs b/HealthMonitor.Model/Service/Mapper/ParseTDengineRestResponse.cs new file mode 100644 index 0000000..4a2ecf6 --- /dev/null +++ b/HealthMonitor.Model/Service/Mapper/ParseTDengineRestResponse.cs @@ -0,0 +1,176 @@ +using Newtonsoft.Json; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace HealthMonitor.Model.Service.Mapper +{ + public class ParseTDengineRestResponse + { + #region 泛化解析 + private List ParseDataList(dynamic data) + { + List result = new(); + + foreach (var row in data) + { + var model = CreateInstance(); + + for (int i = 0; i < ColumnMeta.Count; i++) + { + var columnName = ColumnMeta[i][0].ToString()!; + var columnType = ColumnMeta[i][1].ToString()!; + + string pattern = @"\((.*?)\)"; // 匹配括号内的任意字符(非贪婪模式) + + // 使用正则表达式进行匹配 + Match match = Regex.Match(columnName, pattern); + + // 检查是否有匹配项 + if (match.Success) + { + // 提取括号内的内容 + string contentInsideParentheses = match.Groups[1].Value; + columnName = contentInsideParentheses; + } + + var columnValue = ConvertValue(row[i], columnType!); + + SetProperty(model, columnName!, columnValue); + } + + result.Add(model); + } + + return result; + } + + private static T CreateInstance() + { + return Activator.CreateInstance(); + } + + private static void SetProperty(T target, string propertyName, TValue value) + { + var property = typeof(T).GetProperties() + .FirstOrDefault(p => GetJsonPropertyName(p) == propertyName); + + if (property != null) + { + property.SetValue(target, value); + } + } + + private static object ConvertValue(object value, string columnType) + { + return columnType.ToUpper() switch + { + "TIMESTAMP" => DateTime.TryParse(value.ToString(),out DateTime dateTimeValue)? dateTimeValue:DateTime.Now, + "NCHAR" or "VARCHAR" => value==null?string.Empty:value.ToString()!, + "INT" => int.TryParse(value.ToString(), out int intValue)? intValue:0, + "TINYINT" => Convert.ToByte(value), + "BOOL" => Convert.ToBoolean(value), + "FLOAT" => float.TryParse(value.ToString(), out float floatValue)? floatValue : 0f, + _ => value, + } ; + + } + + private static string GetJsonPropertyName(PropertyInfo property) + { + var attribute = (JsonPropertyAttribute)Attribute.GetCustomAttribute(property, typeof(JsonPropertyAttribute))!; + return attribute?.PropertyName ?? property.Name; + } + + private List ParseData = default!; + #endregion + + #region 响应解析 + [JsonProperty("code")] + public int Code { get; set; } + + [JsonProperty("column_meta")] + public List> ColumnMeta { get; set; } = new List>(); + + [JsonProperty("rows")] + public int Rows { get; set; } + + [JsonProperty("data")] + public dynamic Data + { + get => ParseData; + set => ParseData = ParseDataList(value); + } + + #endregion + + #region Linq + public IEnumerable Select(Func selector) + { + return ParseData.Select(selector); + } + + public IEnumerable Select() + { + return ParseData; + } + #endregion + + #region 统计算法 + /// + /// 统计算法 + /// + /// + /// + /// + /// + public float AverageAfterRemovingOneMinMaxRef(Func valueSelector, int numToRemove, out int[] collection, out int max, out int min) + { + var values = ParseData.Select(valueSelector).ToList(); + collection = values.Select(i => (int)i).ToArray(); + if (values.Count <= 2) + { + throw new ArgumentException("Not enough elements to remove."); + } + + // Remove the specified number of minimum and maximum values + //values.RemoveAll(_ => _ == values.Min()); + //values.RemoveAll(_ => _ == values.Max()); + max = (int)values.Max(); + min = (int)values.Min(); + values.Remove(max); + values.Remove(min); + + // Remove values less than the specified threshold + values.RemoveAll(_ => _ > numToRemove); + + // Calculate and return the average of the remaining values + return values.Average(); + } + + public decimal AverageAfterRemovingOneMinMaxRef(Func valueSelector, int refValue) + { + var values = ParseData.Select(valueSelector).ToList(); + + if (values.Count <= 2) + { + throw new ArgumentException("数据不够不能计算"); + } + + // Remove the specified number of minimum and maximum values + //values.RemoveAll(_ => _ == values.Min()); + //values.RemoveAll(_ => _ == values.Max()); + + values.Remove(values.Max()); + values.Remove(values.Min()); + + // Remove values less than the specified threshold + values.RemoveAll(_ => _ > refValue); + + // Calculate and return the average of the remaining values + return values.Average(); + } + + #endregion + + } +} diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs index f5c6e41..5d31d2a 100644 --- a/HealthMonitor.Service/Biz/db/TDengineService.cs +++ b/HealthMonitor.Service/Biz/db/TDengineService.cs @@ -329,6 +329,29 @@ namespace HealthMonitor.Service.Biz.db #region RestAPI + public async Task ExecuteQuerySQLRestResponse(string sql) + { + var url = $"http://{_configTDengineService.Host}:{_configTDengineService.RestPort}/rest/sql/{_configTDengineService.DB}"; + List> headers = new() + { + new KeyValuePair("Authorization", "Basic " + _configTDengineService.Token) + }; + var result = await _httpHelper.HttpToPostAsync(url, sql, headers).ConfigureAwait(false); + return result; + } + + public async Task ExecuteSelectRestResponseAsync( string tbName, string condition="1", string field = "*") + { + var url = $"http://{_configTDengineService.Host}:{_configTDengineService.RestPort}/rest/sql/{_configTDengineService.DB}"; + var sql = $"SELECT {field} FROM {_configTDengineService.DB}.{tbName} WHERE {condition}"; + + List> headers = new() + { + new KeyValuePair("Authorization", "Basic " + _configTDengineService.Token) + }; + var result = await _httpHelper.HttpToPostAsync(url, sql, headers).ConfigureAwait(false); + return result; + } public async Task GernalRestSql(string sql) { diff --git a/HealthMonitor.Service/Resolver/BloodpressResolver.cs b/HealthMonitor.Service/Resolver/BloodpressResolver.cs index 19fa25a..f31c875 100644 --- a/HealthMonitor.Service/Resolver/BloodpressResolver.cs +++ b/HealthMonitor.Service/Resolver/BloodpressResolver.cs @@ -25,6 +25,7 @@ using HealthMonitor.Service.Biz; using HealthMonitor.Model.Service; using Microsoft.Extensions.Options; using HealthMonitor.Model.Config; +using HealthMonitor.Model.Service.Mapper; namespace HealthMonitor.Service.Resolver { @@ -94,331 +95,339 @@ namespace HealthMonitor.Service.Resolver public async Task ExecuteMessageAsync() { - var messageId = _messageId.Value; - var bp = _msgData.Value!; + try + { + var messageId = _messageId.Value; + var bp = _msgData.Value!; + + int systolicRefValue; + int diastolicRefValue; + int systolicInc; + int diastolicInc; + int systolicAvg; + int diastolicAvg; + + int systolicMax = 0; + int diastolicMax = 0; + // 最小值 + int systolicMin = 0; + int diastolicMin = 0; + + // 偏移参数 + var avgOffset = 0.25M; + var systolicAvgOffset = avgOffset; + var diastolicAvgOffset = avgOffset; + // 统计时间 + DateTime endTime = DateTime.Now; //测试 + DateTime startTime = DateTime.Now; + // 最后一次下发值 + int lastPushSystolicInc = 0; + int lastPushDiastolicInc = 0; + + bool remarkFlag = false; + long duration = 7 * 24 * 3600 * 1000; + string sql = string.Empty; + + #region 获取个人信息 + + var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(bp.MessageId, bp.Serialno).ConfigureAwait(false); + //验证这个信息是否存在 + if (person == null || person?.Person.BornDate == null) + { + _logger.LogWarning("验证个人信息,找不到个人信息,跳过此消息"); + return; + } + // 验证年龄是否在范围 (2 - 120) + var age = SafeType.SafeInt(DateTime.Today.Year - person?.Person.BornDate!.Value.Year!); + if (age < 1 || age > 120) + { + _logger.LogWarning("验证年龄,不在范围 (2 - 120)岁,跳过此消息"); + return; + } - #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!); - var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(bp.MessageId, bp.Serialno).ConfigureAwait(false); - //验证这个信息是否存在 - if (person == null || person?.Person.BornDate == null) - { - _logger.LogWarning("验证个人信息,找不到个人信息,跳过此消息"); - return; - } - // 验证年龄是否在范围 (2 - 120) - var age = SafeType.SafeInt(DateTime.Today.Year - person?.Person.BornDate!.Value.Year!); - if (age < 1 || age > 120) - { - _logger.LogWarning("验证年龄,不在范围 (2 - 120)岁,跳过此消息"); - return; - } - #endregion + #endregion - 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!); - #region 计算增量值 + #region 初始化常规血压标定值标定值 + var bpRef = await _bpRefValCacheManager.GetBloodPressReferenceValueAsync(age, gender, isHypertension); + systolicRefValue = bpRef!.Systolic;//? + diastolicRefValue = bpRef!.Diastolic;//? + #endregion - var bpRef = await _bpRefValCacheManager.GetBloodPressReferenceValueAsync(age, gender, isHypertension); - var lastPush = await _serviceTDengine.GetLastAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{bp.Serialno}' order by ts desc"); - //var ts = last?[0]; - var systolicRefValue = bpRef?.Systolic;//? - var diastolicRefValue = bpRef?.Diastolic;//? - long duration = 7 * 24 * 3600 * 1000; + if (string.IsNullOrWhiteSpace(person?.Person.Remarks)) + { + #region 初始化计算增量值(个人血压信息) + // 测量值当作平均值 + systolicAvg = bp.SystolicValue; + diastolicAvg = bp.DiastolicValue; + systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; + diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + + #region 更新 gps_persoon remarks 下发增量值到iot + // 更新 + remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); + if (remarkFlag) + { + Console.WriteLine($"{nameof(BloodpressResolver)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}"); + // 启血压标定值下发开关 + if (_configBoodPressResolver.EnableBPRefPush) + { + // 下推 + BloodPressCalibrationConfigModel bpIncData = new() + { + Imei = bp.Serialno, + SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 + DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 + SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 + DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 + }; + // 下发 IOT 增量值 + var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); + if (flagIot) + { + startTime = (DateTime)bp.LastUpdate!; + endTime = DateTime.Now; + #region 保存下推记录 stb_hm_bp_push_ref_inc_value + sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + + $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + + $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + + $"VALUES(" + + $"'{endTime:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{bp.Serialno}'," + + $"{systolicRefValue}," + + $"{diastolicRefValue}," + + $"{systolicInc}," + + $"{diastolicInc}," + + $"{true}," + + $"{systolicAvg}," + + $"{diastolicAvg}," + + $"{systolicAvgOffset}," + + $"{diastolicAvgOffset}," + + $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{endTime:yyyy-MM-dd HH:mm:ss.fff}'," + + $")"; + + _serviceTDengine.ExecuteInsertSQL(sql); + #endregion + } + } - int systolicInc; - int diastolicInc; - string sql = string.Empty; + } - var remarkFlag = false; + #endregion - // 曾经有下发记录 - if (lastPush?.Count!=0) - { - // 重置设备,取正常值标定值 - if ( - (int)lastPush![2] == 0 - && (int)lastPush![3] == 0 - && (int)lastPush![4] == 0 - && (int)lastPush![5] == 0 - ) - { - systolicRefValue = bpRef?.Systolic;//? - diastolicRefValue = bpRef?.Diastolic;//? + #endregion } - // 取最后一条下推的标定值 else { - systolicRefValue = (int)lastPush?[2]!; - diastolicRefValue = (int)lastPush?[3]!; - } + #region 正常计算增量值 + // var lastPush = await _serviceTDengine.GetLastAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{bp.Serialno}' order by ts desc"); - if (DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs)) - { - duration = SafeType.SafeInt64(((DateTime)bp.LastUpdate! - newTs).TotalMilliseconds); - } + var lastPushResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{bp.Serialno}' order by ts desc", "last_row(*)"); + if (lastPushResponse == null) + { + return; + } + var lastPushParser = JsonConvert.DeserializeObject>(lastPushResponse); + var lastPush = lastPushParser!.Select().FirstOrDefault(); + //var ts = last?[0]; - } + // 曾经有下发记录 + if (lastPushParser?.Rows != 0) + { + // 重置设备,取正常值标定值 + if ( + lastPush!.SystolicRefValue == 0 + && lastPush!.DiastolicRefValue == 0 + && lastPush!.SystolicIncValue == 0 + && lastPush!.DiastolicIncValue == 0 + ) + { + systolicRefValue = bpRef!.Systolic;//? + diastolicRefValue = bpRef!.Diastolic;//? + + } + // 取最后一条下推的标定值 + else + { + systolicRefValue = lastPush!.SystolicRefValue; + diastolicRefValue = lastPush!.DiastolicRefValue; + } + duration = SafeType.SafeInt64(((DateTime)bp.LastUpdate! - lastPush!.Timestamp).TotalMilliseconds); + lastPushSystolicInc = lastPush!.SystolicIncValue; + lastPushDiastolicInc = lastPush!.DiastolicIncValue; + } - - TimeSpan ts= TimeSpan.FromMilliseconds(duration); - // 获取历史数据 - ////DateTime now = DateTime.Now; - //DateTime now = (DateTime)bp.LastUpdate!; //测试 - //DateTime startTime = now.AddDays(-duration); - //DateTime endTime = now; - - DateTime endTime = (DateTime)bp.LastUpdate!; //测试 - DateTime startTime = endTime-ts; - - - // 如果hm_bp_config_manual_calibration存在数据,使用最新数据 - - // - var systolicAggregate = await _serviceTDengine.GetAggregateValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - var diastolicAggregate = await _serviceTDengine.GetAggregateValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - //var systolicAggregate = _serviceTDengine.GetAggregateValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - //var diastolicAggregate = _serviceTDengine.GetAggregateValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - - // 最大值 - var systolicMax = systolicAggregate.Max; - var diastolicMax = diastolicAggregate.Max; - // 最小值 - var systolicMin = systolicAggregate.Min; - var diastolicMin = diastolicAggregate.Min; - // 偏移参数 - var avgOffset = 0.25M; - var systolicAvgOffset = avgOffset; - var diastolicAvgOffset = avgOffset; - - - // 计算去除最大值和最小值和异常值的平均值 - var systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); - var diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); - - // - if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) - { - _logger.LogWarning($"{bp.Serialno} 历史数据{startTime}---{endTime}除最大值和最小值和异常值的平均值为0,使用测试量当做平均值"); - systolicAvg = bp.SystolicValue; - diastolicAvg = bp.DiastolicValue; - //systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! > 0? (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!:0; - //diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! >0? (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!:0; - - //// 初始化 remark - //remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); - //if (remarkFlag) - //{ - // // 下推 - // BloodPressCalibrationConfigModel bpIncData = new() - // { - // Imei = bp.Serialno, - // SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 - // DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 - // SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 - // DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 - // }; - // // 下发 IOT 增量值 - // var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); - // if (flagIot) - // { - // #region 保存下推记录 stb_hm_bp_push_ref_inc_value - // sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + - // $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + - // $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + - // $"VALUES(" + - // $"'{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}'," + - // $"'{bp.Serialno}'," + - // $"{systolicRefValue}," + - // $"{diastolicRefValue}," + - // $"{systolicInc}," + - // $"{diastolicInc}," + - // $"{true})"; - - // _serviceTDengine.ExecuteInsertSQL(sql); - // #endregion - // } - //} - //return; - } - //var systolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); - //var diastolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); - - // 增量值=(标定值-平均值)* 0.25 - systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; - diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; - - #endregion - - #region 插入BP增量值 hm_bloodpress_stats_inc - // 自动建表 - sql = $"INSERT INTO health_monitor.hm_bp_stats_inc_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + - $"USING health_monitor.stb_hm_bloodpress_stats_inc " + - $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + - $"VALUES(" + - $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + - $"'{bp.BloodPressId}'," + - $"'{bp.MessageId}'," + - $"'{bp.Serialno}'," + - $"{bp.SystolicValue}," + - $"{systolicRefValue}," + - $"{systolicAvg}," + - $"{systolicMax}," + - $"{systolicMin}," + - $"{systolicAvgOffset}," + - $"{systolicInc}," + - $"{bp.DiastolicValue}," + - $"{diastolicRefValue}," + - $"{diastolicAvg}," + - $"{diastolicMax}," + - $"{diastolicMin}," + - $"{diastolicAvgOffset}," + - $"{diastolicInc}," + - $"{gender}," + - $"{age}," + - $"{height}," + - $"{weight}," + - $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + - $"{duration}," + - $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," + - $"'{endTime:yyyy-MM-dd HH:mm:ss.fff}'," + - $"'{string.Empty}'," + - $"{isHypertension})"; - - _serviceTDengine.ExecuteInsertSQL(sql); - // 发送到 设置设备血压标定参数 - - #endregion - - - #region 更新 gps_persoon remarks - // 更新 - remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); - if (remarkFlag) - { - Console.WriteLine($"{nameof(BloodpressResolver)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}"); - // 启血压标定值下发开关 - if (_configBoodPressResolver.EnableBPRefPush) - { - // 下推 - BloodPressCalibrationConfigModel bpIncData = new() - { + TimeSpan ts = TimeSpan.FromMilliseconds(duration); + // 获取历史数据 + ////DateTime now = DateTime.Now; + //DateTime now = (DateTime)bp.LastUpdate!; //测试 + //DateTime startTime = now.AddDays(-duration); + //DateTime endTime = now; + + endTime = (DateTime)bp.LastUpdate!; //测试 + startTime = endTime - ts; + + var condition = $"ts between '{startTime:yyyy-MM-dd HH:mm:ss.fff}' and '{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"; + var hmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition); + var hmBpParser = JsonConvert.DeserializeObject>(hmBpResponse!); + var hmBp = hmBpParser?.Select(); + + // 最大值 + 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()!; + - Imei = bp.Serialno, - SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 - DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 - SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 - DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 - }; - // 下发 IOT 增量值 - var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); - if (flagIot) + // 计算去除最大值和最小值和异常值的平均值 + //var systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); + //var diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); + systolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.SystolicValue, SafeType.SafeInt(systolicRefValue!)))!; + diastolicAvg = (int)(hmBpParser?.AverageAfterRemovingOneMinMaxRef(i => i.DiastolicValue, SafeType.SafeInt(diastolicRefValue!)))!; + if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) { - #region 保存下推记录 stb_hm_bp_push_ref_inc_value - sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + - $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + - $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + - $"VALUES(" + - $"'{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}'," + - $"'{bp.Serialno}'," + - $"{systolicRefValue}," + - $"{diastolicRefValue}," + - $"{systolicInc}," + - $"{diastolicInc}," + - $"{true})"; - - _serviceTDengine.ExecuteInsertSQL(sql); - #endregion + _logger.LogWarning($"{bp.Serialno} 历史数据{startTime}---{endTime}除最大值和最小值和异常值的平均值为0,使用测试量当做平均值"); + + systolicAvg = bp.SystolicValue; + diastolicAvg = bp.DiastolicValue; + /* + systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; + diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + + // 初始化 remark + remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); + if (remarkFlag) + { + // 下推 + BloodPressCalibrationConfigModel bpIncData = new() + { + Imei = bp.Serialno, + SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 + DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 + SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 + DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 + }; + // 下发 IOT 增量值 + var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); + if (flagIot) + { + #region 保存下推记录 stb_hm_bp_push_ref_inc_value + sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + + $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + + $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + + $"VALUES(" + + $"'{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{bp.Serialno}'," + + $"{systolicRefValue}," + + $"{diastolicRefValue}," + + $"{systolicInc}," + + $"{diastolicInc}," + + $"{true})"; + + _serviceTDengine.ExecuteInsertSQL(sql); + #endregion + } + } + + return; + */ } + //var systolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); + //var diastolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); + + // 增量值=(标定值-平均值)* 0.25 + var currentSystolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; + var currentDiastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + + // 累计增量 + systolicInc = currentSystolicInc + lastPushSystolicInc; + diastolicInc = currentDiastolicInc + lastPushDiastolicInc; + #endregion } - - } - #endregion - - - /** 取消 - - // 注册定时下发事件 - // 获取当前时间 - //DateTime sNow = DateTime.Now; - - //// 计算距离明天12点的时间间隔 - //TimeSpan timeUntil = new DateTime(sNow.Year, sNow.Month, sNow.Day, 12, 0, 0) - sNow; - - //// 如果当前时间已经超过了12点,将等待到明天 - //if (timeUntil < TimeSpan.Zero) - //{ - // timeUntil = timeUntil.Add(TimeSpan.FromHours(24)); - //} - //var data = new - //{ - // imei = bp.Serialno, - // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 - // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 - // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 - // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 - //}; - - //var url = $"http://id.ssjlai.com/webapi/api/Command/SetBloodPressCalibrationConfig"; - //List> headers = new() - //{ - // new KeyValuePair("AuthKey", "key1") - //}; - - //var data = new - //{ - // imei = bp.Serialno, - // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 - // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 - // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 - // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 - //}; - - - //var result = JsonConvert.SerializeObject(data); - //var result = bp.Serialno; - */ - - #region 定时下发触发器 - var key = $"health_moniter/schedule_push/imei/{bp.Serialno}"; - var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false); - if (string.IsNullOrWhiteSpace(schedule_push)) - { - // 注册首次下推 + #region 插入BP增量值 hm_bloodpress_stats_inc + // 自动建表 + sql = $"INSERT INTO health_monitor.hm_bp_stats_inc_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + + $"USING health_monitor.stb_hm_bloodpress_stats_inc " + + $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + + $"VALUES(" + + $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{bp.BloodPressId}'," + + $"'{bp.MessageId}'," + + $"'{bp.Serialno}'," + + $"{bp.SystolicValue}," + + $"{systolicRefValue}," + + $"{systolicAvg}," + + $"{systolicMax}," + + $"{systolicMin}," + + $"{systolicAvgOffset}," + + $"{systolicInc}," + + $"{bp.DiastolicValue}," + + $"{diastolicRefValue}," + + $"{diastolicAvg}," + + $"{diastolicMax}," + + $"{diastolicMin}," + + $"{diastolicAvgOffset}," + + $"{diastolicInc}," + + $"{gender}," + + $"{age}," + + $"{height}," + + $"{weight}," + + $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + + $"{duration}," + + $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{endTime:yyyy-MM-dd HH:mm:ss.fff}'," + + $"'{string.Empty}'," + + $"{isHypertension})"; + + _serviceTDengine.ExecuteInsertSQL(sql); + // 发送到 设置设备血压标定参数 + + #endregion + + #region 定时下发触发器 + var key = $"health_moniter/schedule_push/imei/{bp.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); + // await _serviceEtcd.PutValAsync(key, result, 60*1, 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+1, 58).AddDays(interval); - TimeSpan timeUntilNextRun = nextRunTime - 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 = bp.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); + // 如果当前时间已经超过了8点,将等待到明天后的8点 + if (timeUntilNextRun < TimeSpan.Zero) + { + timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1)); + nextRunTime += timeUntilNextRun; + } + var ttl = (long)timeUntilNextRun.TotalSeconds; + var data = new + { + imei = bp.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 //DateTime sNow = DateTime.Now; @@ -461,44 +470,426 @@ namespace HealthMonitor.Service.Resolver await _serviceEtcd.PutValAsync(key, result,ttl, false).ConfigureAwait(false); #endif + } + + #endregion } + catch (Exception ex) + { - #endregion - + _logger.LogError($"解析血压出错, {ex.Message}\n{ex.StackTrace}"); + } - /** 取消 - //// 生效 - //if (DateTime.Now.Hour == 1) - //{ - // var data = new - // { - // imei = bp.Serialno, - // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 - // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 - // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 - // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 - // }; - // var result = await _httpHelper.HttpToPostAsync(url, data, headers).ConfigureAwait(false); - // _logger.LogInformation($"将 {JsonConvert.SerializeObject(data)}发送到 {url} 并且返回 {JsonConvert.SerializeObject(result)}"); - //} - //// 不生效 - //else if (DateTime.Now.Hour == 3) - //{ - // var data = new - // { - // imei = bp.Serialno, - // systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效 - // diastolicCalibrationValue = 0, //舒张压标定值,值为0表示不生效 - // systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效 - // diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效 - // }; - // var result = await _httpHelper.HttpToPostAsync(url, data, headers).ConfigureAwait(false); - // _logger.LogInformation($"将 {JsonConvert.SerializeObject(data)}发送到 {url} 并且返回 {JsonConvert.SerializeObject(result)}"); - //} - - */ } +// public async Task ExecuteMessageAsync0() +// { +// var messageId = _messageId.Value; +// var bp = _msgData.Value!; + +// #region 获取个人信息 + +// var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(bp.MessageId, bp.Serialno).ConfigureAwait(false); +// //验证这个信息是否存在 +// if (person == null || person?.Person.BornDate == null) +// { +// _logger.LogWarning("验证个人信息,找不到个人信息,跳过此消息"); +// return; +// } +// // 验证年龄是否在范围 (2 - 120) +// var age = SafeType.SafeInt(DateTime.Today.Year - person?.Person.BornDate!.Value.Year!); +// if (age < 1 || age > 120) +// { +// _logger.LogWarning("验证年龄,不在范围 (2 - 120)岁,跳过此消息"); +// return; +// } +// #endregion + +// 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!); + +// #region 计算增量值 + +// var bpRef = await _bpRefValCacheManager.GetBloodPressReferenceValueAsync(age, gender, isHypertension); + +// var lastPush = await _serviceTDengine.GetLastAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{bp.Serialno}' order by ts desc"); +// //var ts = last?[0]; +// var systolicRefValue = bpRef?.Systolic;//? +// var diastolicRefValue = bpRef?.Diastolic;//? +// long duration = 7 * 24 * 3600 * 1000; + +// int systolicInc; +// int diastolicInc; +// string sql = string.Empty; + +// var remarkFlag = false; + +// // 曾经有下发记录 +// if (lastPush?.Count != 0) +// { +// // 重置设备,取正常值标定值 +// if ( +// (int)lastPush![2] == 0 +// && (int)lastPush![3] == 0 +// && (int)lastPush![4] == 0 +// && (int)lastPush![5] == 0 +// ) +// { +// systolicRefValue = bpRef?.Systolic;//? +// diastolicRefValue = bpRef?.Diastolic;//? +// } +// // 取最后一条下推的标定值 +// else +// { +// systolicRefValue = (int)lastPush?[2]!; +// diastolicRefValue = (int)lastPush?[3]!; +// } + +// if (DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs)) +// { +// duration = SafeType.SafeInt64(((DateTime)bp.LastUpdate! - newTs).TotalMilliseconds); +// } + +// } + + +// TimeSpan ts = TimeSpan.FromMilliseconds(duration); +// // 获取历史数据 +// ////DateTime now = DateTime.Now; +// //DateTime now = (DateTime)bp.LastUpdate!; //测试 +// //DateTime startTime = now.AddDays(-duration); +// //DateTime endTime = now; + +// DateTime endTime = (DateTime)bp.LastUpdate!; //测试 +// DateTime startTime = endTime - ts; + + +// // 如果hm_bp_config_manual_calibration存在数据,使用最新数据 + +// // +// var systolicAggregate = await _serviceTDengine.GetAggregateValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); +// var diastolicAggregate = await _serviceTDengine.GetAggregateValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); +// //var systolicAggregate = _serviceTDengine.GetAggregateValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); +// //var diastolicAggregate = _serviceTDengine.GetAggregateValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); + +// // 最大值 +// var systolicMax = systolicAggregate.Max; +// var diastolicMax = diastolicAggregate.Max; +// // 最小值 +// var systolicMin = systolicAggregate.Min; +// var diastolicMin = diastolicAggregate.Min; +// // 偏移参数 +// var avgOffset = 0.25M; +// var systolicAvgOffset = avgOffset; +// var diastolicAvgOffset = avgOffset; + + +// // 计算去除最大值和最小值和异常值的平均值 +// var systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); +// var diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); + +// // +// if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) +// { +// _logger.LogWarning($"{bp.Serialno} 历史数据{startTime}---{endTime}除最大值和最小值和异常值的平均值为0,使用测试量当做平均值"); +// systolicAvg = bp.SystolicValue; +// diastolicAvg = bp.DiastolicValue; +// //systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! > 0? (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!:0; +// //diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! >0? (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!:0; + +// //// 初始化 remark +// //remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); +// //if (remarkFlag) +// //{ +// // // 下推 +// // BloodPressCalibrationConfigModel bpIncData = new() +// // { +// // Imei = bp.Serialno, +// // SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 +// // DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 +// // SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 +// // DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 +// // }; +// // // 下发 IOT 增量值 +// // var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); +// // if (flagIot) +// // { +// // #region 保存下推记录 stb_hm_bp_push_ref_inc_value +// // sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + +// // $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + +// // $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + +// // $"VALUES(" + +// // $"'{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}'," + +// // $"'{bp.Serialno}'," + +// // $"{systolicRefValue}," + +// // $"{diastolicRefValue}," + +// // $"{systolicInc}," + +// // $"{diastolicInc}," + +// // $"{true})"; + +// // _serviceTDengine.ExecuteInsertSQL(sql); +// // #endregion +// // } +// //} + +// //return; +// } +// //var systolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and systolic_value < {systolicRefValue} "); +// //var diastolicAvg = _serviceTDengine.GetAvgExceptMaxMinValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}' and diastolic_value < {diastolicRefValue}"); + +// // 增量值=(标定值-平均值)* 0.25 +// systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; +// diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + +// #endregion + +// #region 插入BP增量值 hm_bloodpress_stats_inc +// // 自动建表 +// sql = $"INSERT INTO health_monitor.hm_bp_stats_inc_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + +// $"USING health_monitor.stb_hm_bloodpress_stats_inc " + +// $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + +// $"VALUES(" + +// $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + +// $"'{bp.BloodPressId}'," + +// $"'{bp.MessageId}'," + +// $"'{bp.Serialno}'," + +// $"{bp.SystolicValue}," + +// $"{systolicRefValue}," + +// $"{systolicAvg}," + +// $"{systolicMax}," + +// $"{systolicMin}," + +// $"{systolicAvgOffset}," + +// $"{systolicInc}," + +// $"{bp.DiastolicValue}," + +// $"{diastolicRefValue}," + +// $"{diastolicAvg}," + +// $"{diastolicMax}," + +// $"{diastolicMin}," + +// $"{diastolicAvgOffset}," + +// $"{diastolicInc}," + +// $"{gender}," + +// $"{age}," + +// $"{height}," + +// $"{weight}," + +// $"'{bp.LastUpdate:yyyy-MM-dd HH:mm:ss.fff}'," + +// $"{duration}," + +// $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," + +// $"'{endTime:yyyy-MM-dd HH:mm:ss.fff}'," + +// $"'{string.Empty}'," + +// $"{isHypertension})"; + +// _serviceTDengine.ExecuteInsertSQL(sql); +// // 发送到 设置设备血压标定参数 + +// #endregion + + +// #region 更新 gps_persoon remarks +// // 更新 +// remarkFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(bp.Serialno, (int)systolicRefValue!, (int)diastolicRefValue!, systolicInc, diastolicInc).ConfigureAwait(false); +// if (remarkFlag) +// { +// Console.WriteLine($"{nameof(BloodpressResolver)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}"); +// // 启血压标定值下发开关 +// if (_configBoodPressResolver.EnableBPRefPush) +// { +// // 下推 +// BloodPressCalibrationConfigModel bpIncData = new() +// { + +// Imei = bp.Serialno, +// SystolicRefValue = (int)systolicRefValue!, //收缩压标定值,值为0 表示不生效 +// DiastolicRefValue = (int)diastolicRefValue!, //舒张压标定值,值为0表示不生效 +// SystolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 +// DiastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 +// }; +// // 下发 IOT 增量值 +// var flagIot = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); + +// if (flagIot) +// { +// #region 保存下推记录 stb_hm_bp_push_ref_inc_value +// sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{bp.Serialno.Substring(bp.Serialno.Length - 2)} " + +// $"USING health_monitor.stb_hm_bp_push_ref_inc_value " + +// $"TAGS ('{bp.Serialno.Substring(bp.Serialno.Length - 2)}') " + +// $"VALUES(" + +// $"'{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}'," + +// $"'{bp.Serialno}'," + +// $"{systolicRefValue}," + +// $"{diastolicRefValue}," + +// $"{systolicInc}," + +// $"{diastolicInc}," + +// $"{true})"; + +// _serviceTDengine.ExecuteInsertSQL(sql); +// #endregion +// } +// } + +// } + +// #endregion + + + +// /** 取消 + +// // 注册定时下发事件 +// // 获取当前时间 +// //DateTime sNow = DateTime.Now; + +// //// 计算距离明天12点的时间间隔 +// //TimeSpan timeUntil = new DateTime(sNow.Year, sNow.Month, sNow.Day, 12, 0, 0) - sNow; + +// //// 如果当前时间已经超过了12点,将等待到明天 +// //if (timeUntil < TimeSpan.Zero) +// //{ +// // timeUntil = timeUntil.Add(TimeSpan.FromHours(24)); +// //} +// //var data = new +// //{ +// // imei = bp.Serialno, +// // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 +// // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 +// // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 +// // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 +// //}; + +// //var url = $"http://id.ssjlai.com/webapi/api/Command/SetBloodPressCalibrationConfig"; +// //List> headers = new() +// //{ +// // new KeyValuePair("AuthKey", "key1") +// //}; + +// //var data = new +// //{ +// // imei = bp.Serialno, +// // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 +// // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 +// // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 +// // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 +// //}; + + +// //var result = JsonConvert.SerializeObject(data); +// //var result = bp.Serialno; +// */ + +// #region 定时下发触发器 +// var key = $"health_moniter/schedule_push/imei/{bp.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 = bp.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 +// //DateTime sNow = DateTime.Now; + +// //// 计算距离19:59:55点的时间间隔 +// //TimeSpan timeUntil = new DateTime(sNow.Year, sNow.Month, sNow.Day, 19, 59, 55) - sNow; + +// //// 如果当前时间已经超过了12点,将等待到明天 +// //if (timeUntil < TimeSpan.Zero) +// //{ +// // timeUntil = timeUntil.Add(TimeSpan.FromHours(24)); +// //} +// //var ttl = (long)timeUntil.TotalSeconds; + + +// var interval = 0; +// // 获取当前时间 +// DateTime now = DateTime.Now; + +// // 计算距离下一个$interval天后的8点的时间间隔 +// DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 19, 59, 58).AddDays(interval); +// TimeSpan timeUntilNextRun = nextRunTime - now; + +// // 如果当前时间已经超过了8点,将等待到明天后的8点 +// if (timeUntilNextRun < TimeSpan.Zero) +// { +// timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1)); +// nextRunTime += timeUntilNextRun; +// } + +// var ttl =(long)timeUntilNextRun.TotalSeconds; +// var data = new +// { +// imei = bp.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 + + +// /** 取消 +// //// 生效 +// //if (DateTime.Now.Hour == 1) +// //{ +// // var data = new +// // { +// // imei = bp.Serialno, +// // systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效 +// // diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效 +// // systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效 +// // diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效 +// // }; +// // var result = await _httpHelper.HttpToPostAsync(url, data, headers).ConfigureAwait(false); +// // _logger.LogInformation($"将 {JsonConvert.SerializeObject(data)}发送到 {url} 并且返回 {JsonConvert.SerializeObject(result)}"); +// //} +// //// 不生效 +// //else if (DateTime.Now.Hour == 3) +// //{ +// // var data = new +// // { +// // imei = bp.Serialno, +// // systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效 +// // diastolicCalibrationValue = 0, //舒张压标定值,值为0表示不生效 +// // systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效 +// // diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效 +// // }; +// // var result = await _httpHelper.HttpToPostAsync(url, data, headers).ConfigureAwait(false); +// // _logger.LogInformation($"将 {JsonConvert.SerializeObject(data)}发送到 {url} 并且返回 {JsonConvert.SerializeObject(result)}"); +// //} + +// */ +// } + } } diff --git a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs index 269f0f7..afcd65d 100644 --- a/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs +++ b/HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs @@ -30,6 +30,8 @@ using TelpoDataService.Util.QueryObjects; using HealthMonitor.WebApi.Controllers.Api; using HealthMonitor.Service.Biz; using HealthMonitor.Model.Service; +using HealthMonitor.Model.Service.Mapper; +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; namespace HealthMonitor.WebApi.Controllers.HealthMonitor { @@ -73,6 +75,331 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor } [HttpPost] public async Task> Put([FromBody] BloodPressManualCalibration model, [FromHeader] string requestId) + { + try + { + var imei = model.Imei; + + #region 设备合法性 + +#if DEBUG + +#else + var param = new GeneralParam + { + Filters = new List + { + new QueryFilterCondition + { + Key=nameof(GpsDevice.Serialno), + Value=model.Imei, + ValueType=QueryValueTypeEnum.String, + Operator=QueryOperatorEnum.Equal + } + } + }; + + var device = await _deviceApiClient.GetFirstAsync(param, new RequestHeader { RequestId = requestId }).ConfigureAwait(false); + + if (device == null) + { + + _logger.LogError($"非法设备:{model.Imei}"); + return ApiResponse.Fail(500, $"非法设备:{model.Imei}"); + } +#endif + + #endregion + + #region 重置设备 + if (model.ManualSystolicRefValue.Equals(0) && model.ManualDiastolicRefValue.Equals(0)) + { + //return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, 0, 0, 0, 0).ConfigureAwait(false); + var statNow = DateTime.Now; + return await IotSetBloodPressCalibrationConfigResponseAsync(imei, 0, 0, 0, 0, 0, 0, 0, 0, statNow, statNow).ConfigureAwait(false); + + //return ApiResponse.Success(new + //{ + // imei = model.Imei, + // systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效 + // diastolicCalibrationValue = 0, //舒张压标定值,值为0表示不生效 + // systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效 + // diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效 + //}); + } + + #endregion + + #region 数据合法性 + if (model.ManualSystolicRefValue.Equals(0) || model.ManualDiastolicRefValue.Equals(0)) + { + return ApiResponse.Fail(501, $"数据非法,{JsonConvert.SerializeObject(model)}"); + } + #endregion + + #region 计算增量值 + + // 计算增量值 + int systolicRefValue = model.ManualSystolicRefValue;//? + int diastolicRefValue = model.ManualDiastolicRefValue;//? + // 没有血压数据时增量值为0 + int systolicInc; + int diastolicInc; + int systolicAvg; + int diastolicAvg; + + // 最后一次下发值 + int lastPushSystolicInc = 0; + int lastPushDiastolicInc = 0; + + // 偏移参数 + var avgOffset = 0.25M; + var systolicAvgOffset = avgOffset; + var diastolicAvgOffset = avgOffset; + + //int duration = 7; + long duration = 7 * 24 * 3600 * 1000; + TimeSpan ts = TimeSpan.FromMilliseconds(duration); + DateTime endTime = DateTime.Now; //测试 + DateTime startTime = endTime - ts; + + var lastPushResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{imei}' order by ts desc", "last_row(*)"); + var lastPushParser = JsonConvert.DeserializeObject>(lastPushResponse!); + var lastPush = lastPushParser!.Select().FirstOrDefault(); + + // 上次下推增量 + lastPushSystolicInc = lastPush!.SystolicIncValue; + lastPushDiastolicInc = lastPush!.DiastolicIncValue; + startTime = lastPush!.Timestamp; + + var condition = $"ts between '{startTime:yyyy-MM-dd HH:mm:ss.fff}' and '{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}'"; + var hmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition); + var hmBpParser = JsonConvert.DeserializeObject>(hmBpResponse!); + + 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)!; + + // 累计增量 + systolicInc = currentSystolicInc + lastPushSystolicInc; + diastolicInc = currentDiastolicInc + lastPushDiastolicInc; + + return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + + + /** 取消 + //// A.没有下推记录 + //if (lastPush?.Count == 0 || lastPush == null) + //{ + // //#region 初始化remarks + // //// 读数据库,remarks为空就写commandValue,更新缓存 + // //var resFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(imei, systolicRefValue, diastolicRefValue).ConfigureAwait(false); + // //if (resFlag) + // //{ + // // _logger.LogInformation($"更新gps_person remarks和缓存"); + // //} + // //else + // //{ + // // _logger.LogInformation($"更新gps_person remarks和缓存失败"); + // //} + // //#endregion + + // int count = await _serviceTDengine.GetCount("stb_hm_bloodpress", $"serialno='{imei}' "); + // // A.1 没有下推记录,没有测量记录,下推增量值 0 + // if (count.Equals(0)) + // { + // _logger.LogInformation("A.1 没有下推记录,没有测量记录,下推增量值 0"); + // // return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false); + // systolicInc = 0; + // diastolicInc = 0; + // systolicAvg = 0; + // diastolicAvg = 0; + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + + // } + // // A.2 没有下推记录,测量记录,正常计算增量值 + // else + // { + // // 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值 + // systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and systolic_value < {systolicRefValue} "); + // diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}"); + + // // 数据异常,不修改增量值 + // if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) + // { + // _logger.LogInformation(" A.2 没有下推记录,有测量记录,正常计算增量值 ,平均值为0, 增量值将按0下发"); + // systolicInc = 0; + // diastolicInc = 0; + // //return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + + // } + // // 数据正常 + // else + // { + // //// 偏移参数 + // //var avgOffset = 0.25M; + // //var systolicAvgOffset = avgOffset; + // //var diastolicAvgOffset = avgOffset; + + + // // 增量值=(标定值-平均值)* 0.25 + // systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; + // diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + // _logger.LogInformation(" A.2 没有下推记录,有测量记录,正常计算增量值 ,增量值将正常下发"); + // // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + + // } + // } + //} + //// B.有下推记录(更改过个人信息) + //else + //{ + // // B.1. 设备已经被重新设置 + // if ( + // (int)lastPush![2] == 0 + // && (int)lastPush![3] == 0 + // && (int)lastPush![4] == 0 + // && (int)lastPush![5] == 0 + // ) + // { + + // // 转换时间 + // _ = DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs); + // endTime = DateTime.Now;//newTs; + // startTime = newTs;//DateTime.Now; + + // int count = await _serviceTDengine.GetCount("stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' "); + // // B.1.1 设备已经被重新设置, 从重置的ts 到 now 没有测量数据,inc=0 + // if (count.Equals(0)) + // { + // _logger.LogWarning("B.1.1 设备已经被重新设置, 从重置的ts 到 now 没有测量数据,inc=0"); + // systolicInc = 0; + // diastolicInc = 0; + // systolicAvg = 0; + // diastolicAvg = 0; + // // return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + + // } + // // B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据 + // else + // { + // // 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值 + // systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and systolic_value < {systolicRefValue} "); + // diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}"); + + // // 数据异常,不修改增量值 + // if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) + // { + // _logger.LogWarning("B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据,平均值为0,增量值将按0下发"); + // systolicInc = 0; + // diastolicInc = 0; + // //return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + // } + // // 数据正常 + // else + // { + // //// 偏移参数 + // //var avgOffset = 0.25M; + // //var systolicAvgOffset = avgOffset; + // //var diastolicAvgOffset = avgOffset; + // // 增量值=(标定值-平均值)* 0.25 + // systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! + SafeType.SafeInt(lastPush![4]); ; + // diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! + SafeType.SafeInt(lastPush![5]); ; + // _logger.LogInformation("B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据 ,增量值将正常下发"); + // //return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + // } + + // } + + // } + // // B.2. 曾经下推过断言有测量记录 + // else + // { + // // 转换时间 + // _ = DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs); + // endTime = DateTime.Now; + // startTime = newTs; + + // // 最大值,最小值 + // var systolicAggregate = await _serviceTDengine.GetAggregateValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}'"); + // var diastolicAggregate = await _serviceTDengine.GetAggregateValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}'"); + + // // 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值 + // systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and systolic_value < {systolicRefValue} "); + // diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}"); + // // 偏移参数 + // //var avgOffset = 0.25M; + // //var systolicAvgOffset = avgOffset; + // //var diastolicAvgOffset = avgOffset; + + + // // 增量值=(标定值-平均值)* 0.25 + // //systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; + // //diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; + + // systolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! + SafeType.SafeInt(lastPush![4]); ; + // diastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! + SafeType.SafeInt(lastPush![5]); ; + + // // B.2.1 数据异常,将按最后一次测量值的offeset下发 + // if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) + // { + // _logger.LogInformation("B.2.1 曾经下推过断言有测量记录,数据异常,平均值为0"); + // _logger.LogInformation($"{imei}本次计算结果\n{startTime:yyyy-MM-dd HH:mm:ss.fff}--{endTime:yyyy-MM-dd HH:mm:ss.fff}" + + // $"\n systolic:REF:{systolicRefValue} - Inc:{systolicInc} - AVG:{systolicAvg} - MAX:{systolicAggregate.Max} - MIN: {systolicAggregate.Min} " + + // $"\n diastolic:REF:{diastolicRefValue} - Inc:{diastolicInc} - AVG:{diastolicAvg} - MAX:{diastolicAggregate.Max} - MIN: {diastolicAggregate.Min}"); + // _logger.LogInformation($"上次下发的增量值:systolic:{(int)lastPush![4]}--diastolic:{(int)lastPush![5]}"); + + // //if (systolicAvg.Equals(0)) + // //{ + // // systolicInc = (int)lastPush[4]; + // //} + + // //if (diastolicAvg.Equals(0)) + // //{ + // // diastolicInc = (int)lastPush[5]; + // //} + + // //return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + // } + // // B.2.2 数据正常,按正常计算 + // else + // { + + // // 增量值=(标定值-平均值)* 0.25 + // systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! + SafeType.SafeInt(lastPush![4]); + // diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! + SafeType.SafeInt(lastPush![5]); + // _logger.LogInformation("B.2.2 曾经下推过断言有测量记录,数据正常,按正常计算 ,增量值将正常下发"); + // return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); + // } + // } + //} + */ + + #endregion + + } + catch + ( Exception ex ) + { + + return ApiResponse.Fail(500, $" 接口出错:{ex.Message}\n{ex.StackTrace}"); + } + + + } + + /** + [HttpPost] + public async Task> Put([FromBody] BloodPressManualCalibration model, [FromHeader] string requestId) { var imei = model.Imei; @@ -111,7 +438,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor if (model.ManualSystolicRefValue.Equals(0) && model.ManualDiastolicRefValue.Equals(0)) { //return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, 0, 0, 0, 0).ConfigureAwait(false); - var statNow= DateTime.Now; + var statNow = DateTime.Now; return await IotSetBloodPressCalibrationConfigResponseAsync(imei, 0, 0, 0, 0, 0, 0, 0, 0, statNow, statNow).ConfigureAwait(false); //return ApiResponse.Success(new @@ -134,7 +461,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor #endregion #region 计算增量值 - + // 计算增量值 int systolicRefValue = model.ManualSystolicRefValue;//? int diastolicRefValue = model.ManualDiastolicRefValue;//? @@ -156,7 +483,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor DateTime startTime = endTime - ts; var lastPush = await _serviceTDengine.GetLastAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{imei}' order by ts desc"); - + // A.没有下推记录 if (lastPush?.Count == 0 || lastPush == null) { @@ -258,7 +585,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor // 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值 systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and systolic_value < {systolicRefValue} "); diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}"); - + // 数据异常,不修改增量值 if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) { @@ -339,83 +666,17 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor // B.2.2 数据正常,按正常计算 else { - + // 增量值=(标定值-平均值)* 0.25 systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)! + SafeType.SafeInt(lastPush![4]); diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)! + SafeType.SafeInt(lastPush![5]); _logger.LogInformation("B.2.2 曾经下推过断言有测量记录,数据正常,按正常计算 ,增量值将正常下发"); - return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc,systolicAvg, diastolicAvg,systolicAvgOffset,diastolicAvgOffset,startTime,endTime).ConfigureAwait(false); + return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc, systolicAvg, diastolicAvg, systolicAvgOffset, diastolicAvgOffset, startTime, endTime).ConfigureAwait(false); } } } - - - - - /**if (lastPush?.Count == 0) - { - #region 初始化remarks - var resFlag = await _serviceIotWebApi.UpdatePersonRemarksAsync(imei, systolicRefValue, diastolicRefValue).ConfigureAwait(false); - if (resFlag) - { - _logger.LogInformation($"更新gps_person remarks和缓存"); - } - #endregion - } - else - { - if (DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs)) - { - startTime = newTs; - } - } - - - var lastBP = await _serviceTDengine.GetLastAsync("stb_hm_bloodpress", $"serialno='{imei}' order by ts desc"); - - //var total = await _serviceTDengine.GetCount("stb_hm_bloodpress", $"serialno='{imei}' order by ts desc"); - //if (total >= 4) - if (lastBP?.Count != 0) - { - //var systolicAggregate = await _serviceTDengine.GetAggregateValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}'"); - //var diastolicAggregate = await _serviceTDengine.GetAggregateValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}'"); - //var systolicAggregate = _serviceTDengine.GetAggregateValue("systolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - //var diastolicAggregate = _serviceTDengine.GetAggregateValue("diastolic_value", "hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{bp.Serialno}'"); - - //// 最大值 - //var systolicMax = systolicAggregate.Max; - //var diastolicMax = diastolicAggregate.Max; - //// 最小值 - //var systolicMin = systolicAggregate.Min; - //var diastolicMin = diastolicAggregate.Min; - - - // 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值 - var systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and systolic_value < {systolicRefValue} "); - var diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-dd HH:mm:ss.fff}' and ts <='{endTime:yyyy-MM-dd HH:mm:ss.fff}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}"); - - if (systolicAvg.Equals(0) || diastolicAvg.Equals(0)) - { - _logger.LogWarning("平均值为0,下发增量值按0处理"); - //return ApiResponse.Fail(501, "平均值为0不处理"); - return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false); - } - // 偏移参数 - var avgOffset = 0.25M; - var systolicAvgOffset = avgOffset; - var diastolicAvgOffset = avgOffset; - - - // 增量值=(标定值-平均值)* 0.25 - systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!; - diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!; - - } - - return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false); - */ #endregion - } + }*/ private async Task> IotSetBloodPressCalibrationConfigResponseAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicInc, int diastolicInc) { diff --git a/HealthMonitor.WebApi/Worker.cs b/HealthMonitor.WebApi/Worker.cs index 46afcbc..51fcd02 100644 --- a/HealthMonitor.WebApi/Worker.cs +++ b/HealthMonitor.WebApi/Worker.cs @@ -265,17 +265,18 @@ namespace HealthMonitor.WebApi //if (resJToken!["message"]!.ToString().Equals("ok")) Console.WriteLine($"{nameof(Worker)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}"); - if (_configBoodPressResolver.EnableBPRefPush) + // if (_configBoodPressResolver.EnableBPRefPush) + if (false) // 临时关闭 { BloodPressCalibrationConfigModel bpIncData = new() - { + { - Imei = imeiDel, - SystolicRefValue = SafeType.SafeInt(((int)systolic_ref_value!)), //收缩压标定值,值为0 表示不生效 - DiastolicRefValue = SafeType.SafeInt(((int)diastolic_ref_value!)), //舒张压标定值,值为0表示不生效 - SystolicIncValue = SafeType.SafeInt(((int)systolic_inc_value!)), //收缩压显示增量,值为0 表示不生效 - DiastolicIncValue = SafeType.SafeInt(((int)diastolic_inc_value!)) //舒张压显示增量,值为0 表示不生效 - }; + Imei = imeiDel, + SystolicRefValue = SafeType.SafeInt(((int)systolic_ref_value!)), //收缩压标定值,值为0 表示不生效 + DiastolicRefValue = SafeType.SafeInt(((int)diastolic_ref_value!)), //舒张压标定值,值为0表示不生效 + SystolicIncValue = SafeType.SafeInt(((int)systolic_inc_value!)), //收缩压显示增量,值为0 表示不生效 + DiastolicIncValue = SafeType.SafeInt(((int)diastolic_inc_value!)) //舒张压显示增量,值为0 表示不生效 + }; var pushedBP = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false); if (pushedBP) {