Ver código fonte

调整手动设置血压增量值

datasub12_previous
H Vs 1 ano atrás
pai
commit
5bee6f681f
9 arquivos alterados com 537 adições e 135 exclusões
  1. +2
    -0
      HealthMonitor.Model/Config/ServiceConfig.cs
  2. +26
    -0
      HealthMonitor.Model/Service/BloodPressCalibrationConfigModel.cs
  3. +170
    -0
      HealthMonitor.Service/Biz/IotWebApiService.cs
  4. +74
    -0
      HealthMonitor.WebApi/Controllers/Api/ApiResponse.cs
  5. +256
    -132
      HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs
  6. +2
    -0
      HealthMonitor.WebApi/Program.cs
  7. +2
    -1
      HealthMonitor.WebApi/appsettings.Development.json
  8. +3
    -1
      HealthMonitor.WebApi/appsettings.production.json
  9. +2
    -1
      HealthMonitor.WebApi/appsettings.test.json

+ 2
- 0
HealthMonitor.Model/Config/ServiceConfig.cs Ver arquivo

@@ -8,6 +8,8 @@
public string TelpoDataUrl { get; set; } = default!;

public string EtcdServerAddress { get; set; } = default!;

public string IotWebApiUrl { get; set; } = default!;
///// <summary>
///// Kafka服务地址
///// </summary>


+ 26
- 0
HealthMonitor.Model/Service/BloodPressCalibrationConfigModel.cs Ver arquivo

@@ -0,0 +1,26 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HealthMonitor.Model.Service
{
public class BloodPressCalibrationConfigModel
{
[JsonProperty("imei")]
public string Imei { get; set; } = default!;
[JsonProperty("systolicCalibrationValue")]
public int SystolicRefValue { get; set; }

[JsonProperty("diastolicCalibrationValue")]
public int DiastolicRefValue { get; set; }

[JsonProperty("systolicIncValue")]
public int SystolicIncValue { get; set; }

[JsonProperty("diastolicIncValue")]
public int DiastolicIncValue { get; set; }
}
}

+ 170
- 0
HealthMonitor.Service/Biz/IotWebApiService.cs Ver arquivo

@@ -0,0 +1,170 @@
using HealthMonitor.Common.helper;
using HealthMonitor.Model.Config;
using HealthMonitor.Service.Resolver;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HealthMonitor.Model.Service;
using TelpoDataService.Util.Entities.GpsCard;
using TelpoDataService.Util;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;

namespace HealthMonitor.Service.Biz
{
public class IotWebApiService
{
private readonly ServiceConfig _configService;
private readonly ILogger<IotWebApiService> _logger;


private readonly HttpHelper _httpHelper = default!;

private readonly GpsCardAccessorClient<GpsPerson> _gpsPersonApiClient;

public IotWebApiService(ILogger<IotWebApiService> logger, HttpHelper httpHelper, GpsCardAccessorClient<GpsPerson> gpsPersonApiClient, IOptions<ServiceConfig> optConfigService)
{
_configService = optConfigService.Value;
_httpHelper=httpHelper;
_logger = logger;
_gpsPersonApiClient = gpsPersonApiClient;
}

public async Task<bool> SetBloodPressCalibrationConfigAsync(BloodPressCalibrationConfigModel bpsCalibrationConfig)
{

#if DEBUG
var flag = true;
#else
//systolicCalibrationValue = 0, //收缩压标定值,值为0 表示不生效
//diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
//systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
//diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效

var flag = false;
try
{
var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
List<KeyValuePair<string, string>> headers = new()
{
new KeyValuePair<string, string>("AuthKey", "key1")
};
var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
_logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;

}
catch (Exception ex)
{
_logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");

}

#endif

return flag;


}

public async Task<bool> UpdatePersonInfoCacheAsync(string imei)
{
var flag = false;
try
{
var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
List<KeyValuePair<string, string>> headers = new()
{
new KeyValuePair<string, string>("AuthKey", "key1")
};
var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
_logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonInfoCacheAsync)},响应:{res}");
var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
}
catch (Exception ex)
{
_logger.LogError($"{nameof(UpdatePersonInfoCacheAsync)} 更新缓存异常:{ex.Message}, {ex.StackTrace}");

}
return flag;


}

/// <summary>
/// 更新 gps_person remark和缓存
/// </summary>
/// <param name="imei"></param>
/// <param name="systolicRefValue"></param>
/// <param name="diastolicRefValue"></param>
/// <returns></returns>
public async Task<bool> UpdatePersonRemarksAsync(string imei,int systolicRefValue,int diastolicRefValue)
{
var flag = false;
try
{
GeneralParam condition = new ()
{
Filters = new List<QueryFilterCondition> {
new QueryFilterCondition {
Key=nameof(GpsDevice.Serialno),
Value=imei,
Operator= QueryOperatorEnum.Equal,
ValueType=QueryValueTypeEnum.String
}
},
OrderBys = new List<OrderByCondition> { new OrderByCondition { Key = "serialno", IsDesc = true } }

};
var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
// 若remark为空,更新person remark字段
if (string.IsNullOrWhiteSpace(person?.Remarks))
{
var newRemarkData = new
{
imei,
time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
commandValue = new
{
systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
}
};
person!.Remarks = $"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
_logger.LogInformation($"更新Person remarks字段|{person.Remarks}");
// 更新缓存
var url = $"{_configService.IotWebApiUrl}Device/UpdatePersonInfoCache?imei={imei}";
List<KeyValuePair<string, string>> headers = new()
{
new KeyValuePair<string, string>("AuthKey", "key1")
};
var res = await _httpHelper.HttpToGetAsync(url, headers).ConfigureAwait(false);
_logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonInfoCacheAsync)},响应:{res}");
var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
}
}
catch (Exception ex)
{
_logger.LogError($"{nameof(UpdatePersonRemarksAsync)} 更新个人信息异常:{ex.Message}, {ex.StackTrace}");
}
return flag;


}
}
}

+ 74
- 0
HealthMonitor.WebApi/Controllers/Api/ApiResponse.cs Ver arquivo

@@ -0,0 +1,74 @@
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

namespace HealthMonitor.WebApi.Controllers.Api
{
public class ApiResponse<T>
{
public string Timestamp { get; set; } = default!;

public T Data { get; set; } = default!;

public Result Result { get; set; } = default!;

//public bool Succeeded { get; set; }
// public string Message { get; set; } = String.Empty;


public static ApiResponse<T> Fail(int code, string errorMessage) => new()
{
//MsgType = msgType,
//Signature = signature,
Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
Result = new()
{
Status = "failed",
Code = code,
Message = errorMessage,
},

};

//public static ApiResponse<T> Success(string msgType,string signature,T data) => new()
//{
// MsgType= msgType,
// Signature = signature,
// Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
// Data = data,
// Result = new()
// {
// Status = "succeed",
// Code = 200,
// Message = "请求成功!",
// },
//};
public static ApiResponse<T> Success(T data) => new()
{
Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
Data = data,
Result = new()
{
Status = "succeed",
Code = 200,
Message = "请求成功!",
},
};
public string ToJsonString()
{
var settings = new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd HH:mm:ss.fff", // 设置日期格式
ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }
};
return JsonConvert.SerializeObject(this, settings);
}
}


public class Result
{
public string Status { get; set; } = default!;
public int Code { get; set; }
public string Message { get; set; } = default!;
}
}

+ 256
- 132
HealthMonitor.WebApi/Controllers/HealthMonitor/HmBloodPressConfigManualCalibrationController.cs Ver arquivo

@@ -19,9 +19,17 @@ using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TelpoDataService.Util.Entities.GpsCard;
using TelpoDataService.Util.Clients;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using TelpoDataService.Util;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;
using HealthMonitor.WebApi.Controllers.Api;
using HealthMonitor.Service.Biz;
using HealthMonitor.Model.Service;

namespace HealthMonitor.WebApi.Controllers.HealthMonitor
{
@@ -36,113 +44,275 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
private readonly TDengineService _serviceTDengine;
private readonly HttpHelper _httpHelper = default!;

private readonly IotWebApiService _serviceIotWebApi;

private readonly GpsCardAccessorClient<GpsDevice> _deviceApiClient;
private readonly GpsCardAccessorClient<GpsPerson> _gpsPersonApiClient;

public HmBloodPressConfigManualCalibrationController
(
TDengineService serviceDengine,
PersonCacheManager personCacheMgr, HttpHelper httpHelper,

ILogger<HmBloodPressConfigManualCalibrationController> logger
GpsCardAccessorClient<GpsPerson> gpsPersonApiClient,
GpsCardAccessorClient<GpsDevice> deviceApiClient,
ILogger<HmBloodPressConfigManualCalibrationController> logger,
IotWebApiService iotWebApiService
)
{


_serviceTDengine = serviceDengine;
_logger = logger;

_httpHelper = httpHelper;
_gpsPersonApiClient = gpsPersonApiClient;
_deviceApiClient = deviceApiClient;
_personCacheMgr = personCacheMgr;
_serviceIotWebApi = iotWebApiService;
}
[HttpPost]
public async Task<IActionResult> Put([FromBody] BloodPressManualCalibration model, [FromHeader] string requestId)
public async Task<ApiResponse<object>> Put([FromBody] BloodPressManualCalibration model, [FromHeader] string requestId)
{
/**
没有血压数据时增量值为0
*/

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

//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 计算增量值
var imei = model.Imei;
// 计算增量值
var systolicRefValue = model.ManualSystolicRefValue;//?
var diastolicRefValue = model.ManualDiastolicRefValue;//?
// 没有血压数据时增量值为0
var systolicInc = 0;
var diastolicInc = 0;
int systolicRefValue = model.ManualSystolicRefValue;//?
int diastolicRefValue = model.ManualDiastolicRefValue;//?
// 没有血压数据时增量值为0
int systolicInc;
int diastolicInc;
int systolicAvg;
int diastolicAvg;
//int duration = 7;
long duration = 7 * 24 * 3600 * 1000;
TimeSpan ts = TimeSpan.FromMilliseconds(duration);
DateTime endTime = DateTime.Now; //测试
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)
{
#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);
}
// A.2 没有下推记录,测量记录,正常计算增量值
else
{
// 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值
systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and systolic_value < {systolicRefValue} ");
diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}");

// 数据异常,不修改增量值
if (systolicAvg.Equals(0) || diastolicAvg.Equals(0))
{
_logger.LogInformation(" A.2 没有下推记录,有测量记录,正常计算增量值 ,平均值为0, 增量值将按0下发");
return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false);

}
// 数据正常
else
{
// 偏移参数
var avgOffset = 0.25M;
var systolicAvgOffset = avgOffset;
var diastolicAvgOffset = avgOffset;

var last = await _serviceTDengine.GetLastAsync("stb_hm_bp_push_ref_inc_value", $"serialno='{imei}' order by ts desc");
if (last?.Count != 0)
{
if (DateTime.TryParse(last?[0]!.ToString(), out DateTime newTs))
{
startTime = newTs;

// 增量值=(标定值-平均值)* 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);
}
}
}
// 读数据库,remark为空就写commandValue,更新缓存
// B.有下推记录(更改过个人信息)
else
{
#region 初始化remark
var dataServiceBaseUrl = $"https://id.ssjlai.com/data";
var DataServicePersionGet = $"{dataServiceBaseUrl}/api/GpsCard/GpsPerson/GetFirst";
List<KeyValuePair<string, string>> Dataheaders = new()
{
new KeyValuePair<string, string>("requestId", $"{imei}")
};
var dataPersion = new
// B.1. 设备已经被重新设置
if (
(int)lastPush![2] == 0
&& (int)lastPush![3] == 0
&& (int)lastPush![4] == 0
&& (int)lastPush![5] == 0
)
{
filters = new List<object>() { new { key = "serialno", value = $"{imei}", valueType = "string", @operator = "Equal" } },
orderBys = new List<object>() { new { key = "serialno", isDesc = true } }
};
var resPersion = await _httpHelper.HttpToPostAsync(DataServicePersionGet, dataPersion, Dataheaders).ConfigureAwait(false);
var resObj = JsonConvert.DeserializeObject(resPersion!) as JToken;
var remark = resObj?["remarks"]?.ToString();
// 修改数据库
if (string.IsNullOrWhiteSpace(remark))
{
var newRemarkData = new

// 转换时间
_ = 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-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' ");
// B.1.1 设备已经被重新设置, 从重置的ts 到 now 没有测量数据,inc=0
if (count.Equals(0))
{
imei,
time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
commandValue = new
_logger.LogWarning("B.1.1 设备已经被重新设置, 从重置的ts 到 now 没有测量数据,inc=0");
return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false);
}
// B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据
else
{
// 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值
systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and systolic_value < {systolicRefValue} ");
diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}");
// 数据异常,不修改增量值
if (systolicAvg.Equals(0) || diastolicAvg.Equals(0))
{
systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
diastolicIncValue = 0 //舒张压显示增量,值为0 表示不生效
_logger.LogWarning("B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据,平均值为0,增量值将按0下发");
return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false);

}
};
resObj!["remarks"] = $"is_blood_press:{JsonConvert.SerializeObject(newRemarkData)}|";
var DataServicePersionUpdate = $"{dataServiceBaseUrl}/api/GpsCard/GpsPerson/Update";
var resUpdate = await _httpHelper.HttpToPostAsync(DataServicePersionUpdate, resObj, Dataheaders).ConfigureAwait(false);
_logger.LogInformation($"更新Person数据库|{resUpdate}");

//更新缓存
List<KeyValuePair<string, string>> headersCache = new()
// 数据正常
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("B.1.2 设备已经被重新设置, 从重置的ts 到 now 有测量数据 ,增量值将正常下发");
return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false);
}

}

}
// B.2. 曾经下推过断言有测量记录
else
{
// 转换时间
_ = DateTime.TryParse(lastPush?[0]!.ToString(), out DateTime newTs);
endTime = DateTime.Now;
startTime = newTs;

// 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值
systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and systolic_value < {systolicRefValue} ");
diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}");

// B.2.1 数据异常,将按最后一次测量值的offeset下发
if (systolicAvg.Equals(0) || diastolicAvg.Equals(0))
{
_logger.LogInformation("B.2.1 曾经下推过断言有测量记录,数据异常,平均值为0,增量值将按0下发");
return await IotSetBloodPressCalibrationConfigResponseAsync(model.Imei, systolicRefValue, diastolicRefValue, 0, 0).ConfigureAwait(false);

}
// B.2.2 数据正常,按正常计算
else
{
new KeyValuePair<string, string>("AuthKey", "key1")
};
// 偏移参数
var avgOffset = 0.25M;
var systolicAvgOffset = avgOffset;
var diastolicAvgOffset = avgOffset;

var cacheUrl = $"http://id.ssjlai.com/webapi/api/Device/UpdatePersonInfoCache?imei={imei}";
var updateCache = await _httpHelper.HttpToGetAsync(cacheUrl, headersCache);
_logger.LogInformation($"更新Person缓存|{updateCache}");

// 增量值=(标定值-平均值)* 0.25
systolicInc = systolicAvg.Equals(0M) ? 0 : (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!;
diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!;
_logger.LogInformation("B.2.2 曾经下推过断言有测量记录,数据正常,按正常计算 ,增量值将正常下发");
return await IotSetBloodPressCalibrationConfigResponseAsync(imei, systolicRefValue, diastolicRefValue, systolicInc, diastolicInc).ConfigureAwait(false);
}
}
}

#endregion



/**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;
}
}


@@ -150,7 +320,7 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor

//var total = await _serviceTDengine.GetCount("stb_hm_bloodpress", $"serialno='{imei}' order by ts desc");
//if (total >= 4)
if(lastBP?.Count !=0 )
if (lastBP?.Count != 0)
{
//var systolicAggregate = await _serviceTDengine.GetAggregateValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}'");
//var diastolicAggregate = await _serviceTDengine.GetAggregateValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}'");
@@ -165,17 +335,18 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
//var diastolicMin = diastolicAggregate.Min;


// 计算去除最大值和最小值和异常值的平均值
// 平均值: 计算去除最大值 MAX和最小值 MIN 和异常值 ABN 的平均值
var systolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("systolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and systolic_value < {systolicRefValue} ");
var diastolicAvg = await _serviceTDengine.GetAvgExceptMaxMinValueAsync("diastolic_value", "stb_hm_bloodpress", $"ts>='{startTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and ts <='{endTime:yyyy-MM-ddTHH:mm:ss.fffZ}' and serialno='{imei}' and diastolic_value < {diastolicRefValue}");

if (systolicAvg.Equals(0) || diastolicAvg.Equals(0))
{
_logger.LogWarning("平均值为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;

@@ -185,37 +356,26 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
diastolicInc = diastolicAvg.Equals(0M) ? 0 : (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!;

}
var bpData = new
{
imei = imei,
//systolicCalibrationValue = last?[5], //收缩压标定值,值为0 表示不生效
//diastolicCalibrationValue = last?[12], //舒张压标定值,值为0表示不生效
//systolicIncValue = last?[10], //收缩压显示增量,值为0 表示不生效
//diastolicIncValue = last?[17] //舒张压显示增量,值为0 表示不生效

systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效
diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效
};
var str = JsonConvert.SerializeObject(bpData);
var url = $"http://id.ssjlai.com/webapi/api/Command/SetBloodPressCalibrationConfig";
List<KeyValuePair<string, string>> headers = new()

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)
{
BloodPressCalibrationConfigModel bpIncData = new()
{
new KeyValuePair<string, string>("AuthKey", "key1")
};
#if DEBUG
var flag = true;
#else
var res = await _httpHelper.HttpToPostAsync(url, bpData, headers).ConfigureAwait(false);
_logger.LogInformation($"向{imei}下发增量值数据:{str},响应:{res}");
var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
var flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
#endif

object? response;
if (flag)
Imei = imei,
SystolicRefValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
DiastolicRefValue = 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
var sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{imei.Substring(imei.Length - 2)} " +
@@ -234,48 +394,12 @@ namespace HealthMonitor.WebApi.Controllers.HealthMonitor
#endregion

// 返回结果
response = new
{
//Timestamp= DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
data = new
{
imei = model.Imei,
systolicCalibrationValue = systolicRefValue, //收缩压标定值,值为0 表示不生效
diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
systolicIncValue = systolicInc, //收缩压显示增量,值为0 表示不生效
diastolicIncValue = diastolicInc //舒张压显示增量,值为0 表示不生效
},
result = new
{
status = "succeed",
code = 200,
message = "请求成功!"
}
};
return ApiResponse<object>.Success(bpIncData);
}
else
{
// 返回结果
response = new
{
//Timestamp= DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
data = new
{
imei = model.Imei,
systolicCalibrationValue = -1, //收缩压标定值,值为0 表示不生效
diastolicCalibrationValue = -1, //舒张压标定值,值为0表示不生效
systolicIncValue = -1, //收缩压显示增量,值为0 表示不生效
diastolicIncValue = -1 //舒张压显示增量,值为0 表示不生效
},
result = new
{
status = "failed",
code = 500,
message = "业务出错!下发指令失败"
}
};
return ApiResponse<object>.Fail(500, "业务出错!下发指令失败");
}
return Ok(response);
}
}
}

+ 2
- 0
HealthMonitor.WebApi/Program.cs Ver arquivo

@@ -33,6 +33,7 @@ using Microsoft.Extensions.Http;
using Microsoft.Extensions.DependencyInjection.Extensions;
using HealthMonitor.Service.Etcd;
using HealthMonitor.WebApi.Middleware;
using HealthMonitor.Service.Biz;

namespace HealthMonitor.WebApi
{
@@ -191,6 +192,7 @@ namespace HealthMonitor.WebApi

builder.Services
.AddSingleton<TDengineDataSubcribe>()
.AddSingleton<IotWebApiService>()
.AddSingleton<EtcdService>()
.AddHostedService<Worker>();
#endregion


+ 2
- 1
HealthMonitor.WebApi/appsettings.Development.json Ver arquivo

@@ -26,7 +26,8 @@
},
"ServiceConfig": {
"TelpoDataUrl": "https://id.ssjlai.com/data/",
"EtcdServerAddress": "http://192.168.2.121:2379"
"EtcdServerAddress": "http://192.168.2.121:2379",
"IotWebApiUrl": "http://id.ssjlai.com/webapi/api/"
},
"ConnectionStrings": {
//"GpsCard_Connection_String": "server=172.16.192.26;port=3304;database=user_operation_platform;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",


+ 3
- 1
HealthMonitor.WebApi/appsettings.production.json Ver arquivo

@@ -22,7 +22,9 @@
"IdleTimeout": 20000
},
"ServiceConfig": {
"TelpoDataUrl": "https://ai.ssjlai.com/data/"
"TelpoDataUrl": "https://ai.ssjlai.com/data/",
"EtcdServerAddress": "http://172.19.42.44:2379",
"IotWebApiUrl": "http://ai.ssjlai.com/webapi/api/"
},
"ConnectionStrings": {
"GpsCard_Connection_String": "server=rm-uf6j529mu0v6g0btp.mysql.rds.aliyuncs.com;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",


+ 2
- 1
HealthMonitor.WebApi/appsettings.test.json Ver arquivo

@@ -31,7 +31,8 @@
},
"ServiceConfig": {
"TelpoDataUrl": "https://id.ssjlai.com/data/",
"EtcdServerAddress": "http://172.19.42.44:2379"
"EtcdServerAddress": "http://172.19.42.44:2379",
"IotWebApiUrl": "http://id.ssjlai.com/webapi/api/"
},
"ConnectionStrings": {
// 测试环境内网


Carregando…
Cancelar
Salvar