Browse Source

调整计算查询

datasub12_previous
H Vs 11 months ago
parent
commit
3d117f6be1
7 changed files with 1371 additions and 413 deletions
  1. +45
    -0
      HealthMonitor.Model/Service/Mapper/BloodPressureModel.cs
  2. +61
    -0
      HealthMonitor.Model/Service/Mapper/BloodPressurePushRefIncModel.cs
  3. +176
    -0
      HealthMonitor.Model/Service/Mapper/ParseTDengineRestResponse.cs
  4. +23
    -0
      HealthMonitor.Service/Biz/db/TDengineService.cs
  5. +723
    -332
      HealthMonitor.Service/Resolver/BloodpressResolver.cs
  6. +334
    -73
      HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs
  7. +9
    -8
      HealthMonitor.WebApi/Worker.cs

+ 45
- 0
HealthMonitor.Model/Service/Mapper/BloodPressureModel.cs View File

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

+ 61
- 0
HealthMonitor.Model/Service/Mapper/BloodPressurePushRefIncModel.cs View File

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

+ 176
- 0
HealthMonitor.Model/Service/Mapper/ParseTDengineRestResponse.cs View File

@@ -0,0 +1,176 @@
using Newtonsoft.Json;
using System.Reflection;
using System.Text.RegularExpressions;

namespace HealthMonitor.Model.Service.Mapper
{
public class ParseTDengineRestResponse<T>
{
#region 泛化解析
private List<T> ParseDataList(dynamic data)
{
List<T> result = new();

foreach (var row in data)
{
var model = CreateInstance<T>();

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<U>()
{
return Activator.CreateInstance<T>();
}

private static void SetProperty<TValue>(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<T> ParseData = default!;
#endregion

#region 响应解析
[JsonProperty("code")]
public int Code { get; set; }

[JsonProperty("column_meta")]
public List<List<object>> ColumnMeta { get; set; } = new List<List<object>>();

[JsonProperty("rows")]
public int Rows { get; set; }

[JsonProperty("data")]
public dynamic Data
{
get => ParseData;
set => ParseData = ParseDataList(value);
}

#endregion

#region Linq
public IEnumerable<TResult> Select<TResult>(Func<T, TResult> selector)
{
return ParseData.Select(selector);
}

public IEnumerable<T> Select()
{
return ParseData;
}
#endregion

#region 统计算法
/// <summary>
/// 统计算法
/// </summary>
/// <param name="valueSelector"></param>
/// <param name="numToRemove"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public float AverageAfterRemovingOneMinMaxRef(Func<T, float> 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<T, decimal> 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

}
}

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

@@ -329,6 +329,29 @@ namespace HealthMonitor.Service.Biz.db

#region RestAPI

public async Task<string?> ExecuteQuerySQLRestResponse(string sql)
{
var url = $"http://{_configTDengineService.Host}:{_configTDengineService.RestPort}/rest/sql/{_configTDengineService.DB}";
List<KeyValuePair<string, string>> headers = new()
{
new KeyValuePair<string, string>("Authorization", "Basic " + _configTDengineService.Token)
};
var result = await _httpHelper.HttpToPostAsync(url, sql, headers).ConfigureAwait(false);
return result;
}

public async Task<string?> 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<KeyValuePair<string, string>> headers = new()
{
new KeyValuePair<string, string>("Authorization", "Basic " + _configTDengineService.Token)
};
var result = await _httpHelper.HttpToPostAsync(url, sql, headers).ConfigureAwait(false);
return result;
}
public async Task<bool> GernalRestSql(string sql)
{



+ 723
- 332
HealthMonitor.Service/Resolver/BloodpressResolver.cs
File diff suppressed because it is too large
View File


+ 334
- 73
HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs View File

@@ -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<ApiResponse<object>> Put([FromBody] BloodPressManualCalibration model, [FromHeader] string requestId)
{
try
{
var imei = model.Imei;

#region 设备合法性

#if DEBUG

#else
var param = new GeneralParam
{
Filters = new List<QueryFilterCondition>
{
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<object>.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<object>.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<object>.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<ParseTDengineRestResponse<BloodPressurePushRefIncModel>>(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<ParseTDengineRestResponse<BloodPressureModel>>(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<object>.Fail(500, $" 接口出错:{ex.Message}\n{ex.StackTrace}");
}

}

/**
[HttpPost]
public async Task<ApiResponse<object>> 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<object>.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<object>.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<ApiResponse<object>> IotSetBloodPressCalibrationConfigResponseAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicInc, int diastolicInc)
{


+ 9
- 8
HealthMonitor.WebApi/Worker.cs View File

@@ -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)
{


Loading…
Cancel
Save