|
- using dotnet_etcd;
- using Etcdserverpb;
- using Google.Protobuf.WellKnownTypes;
- using HealthMonitor.Common;
- using HealthMonitor.Common.helper;
- using HealthMonitor.Core.Common.Extensions;
- using HealthMonitor.Model.Config;
- using HealthMonitor.Model.Service;
- using HealthMonitor.Model.Service.Mapper;
- using HealthMonitor.Service.Biz;
- using HealthMonitor.Service.Biz.db;
- using HealthMonitor.Service.Etcd;
- using HealthMonitor.Service.Sub;
- using Microsoft.AspNetCore.Mvc.RazorPages;
- using Microsoft.EntityFrameworkCore.Metadata.Internal;
- using Microsoft.Extensions.Options;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using System.Reflection;
- using System.Threading.Channels;
- using TDengineDriver;
- using TDengineTMQ;
-
- namespace HealthMonitor.WebApi
- {
- public class Worker : BackgroundService
- {
- private readonly ILogger<Worker> _logger;
- private readonly IServiceProvider _services;
- private readonly TDengineDataSubcribe _tdEngineDataSubcribe;
- private readonly PackageProcess _processor;
- private readonly TDengineService _serviceTDengine;
- private readonly EtcdService _serviceEtcd;
- private readonly HttpHelper _httpHelper = default!;
- private readonly IotWebApiService _serviceIotWebApi;
- private readonly BoodPressResolverConfig _configBoodPressResolver;
-
- private CancellationTokenSource _tokenSource=default!;
-
- public Worker(ILogger<Worker> logger, IServiceProvider services, IotWebApiService iotWebApiService, IOptions<BoodPressResolverConfig> optionBoodPressResolver, PackageProcess processor,TDengineDataSubcribe tdEngineDataSubcribe, TDengineService serviceDengine, HttpHelper httpHelper, EtcdService serviceEtcd)
- {
- _logger = logger;
- _tdEngineDataSubcribe = tdEngineDataSubcribe;
- _services = services;
- _serviceIotWebApi = iotWebApiService;
- _processor = processor;
- _serviceEtcd = serviceEtcd;
- _serviceTDengine = serviceDengine;
- _httpHelper = httpHelper;
- _configBoodPressResolver = optionBoodPressResolver.Value;
- }
-
- public override Task StartAsync(CancellationToken cancellationToken)
- {
- _logger.LogInformation("------StartAsync");
- _tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
-
-
- return base.StartAsync(cancellationToken);
- }
-
- public override Task StopAsync(CancellationToken cancellationToken)
- {
- _logger.LogInformation("------StopAsync");
- _tokenSource.Cancel();
-
-
- return base.StopAsync(cancellationToken);
- }
-
- protected override Task ExecuteAsync(CancellationToken stoppingToken)
- {
-
- TaskFactory factory = new(_tokenSource.Token);
- factory.StartNew(async () =>
- {
- if (_tokenSource.IsCancellationRequested)
- _logger.LogWarning("Worker exit");
-
- _logger.LogInformation("------ResolveAsync");
- while (!_tokenSource.IsCancellationRequested)
- {
-
- await _processor.ResolveAsync().ConfigureAwait(false);
-
- }
-
- }, TaskCreationOptions.LongRunning);
-
- factory.StartNew(() =>
- {
- _logger.LogInformation("------_tdEngineDataSubcribe");
- while (!_tokenSource.IsCancellationRequested)
- {
-
- _tdEngineDataSubcribe.BeginListen(_tokenSource.Token);
- }
- }, TaskCreationOptions.LongRunning);
-
- Task.Run(() =>
- _serviceEtcd.WacthKeysWithPrefixResponseAsync($"health_moniter/schedule_push", WatchEvents)
- , stoppingToken);
-
-
-
-
-
-
-
-
-
-
-
-
- return Task.Delay(1000, _tokenSource.Token);
-
- }
-
- private void WatchEvents(WatchEvent[] response)
- {
- foreach (WatchEvent e1 in response)
- {
-
-
- switch (e1.Type.ToString())
- {
-
-
-
-
- case "Delete":
-
- Console.WriteLine($"--- {e1.Key}:{e1.Value}:{e1.Type}");
- break;
- }
- }
- }
-
-
- private void WatchEvents(WatchResponse response)
- {
-
- response.Events.ToList<Mvccpb.Event>().ForEach(async e =>
- {
-
- switch (e.Type.ToString())
- {
- case "Put":
-
- Console.BackgroundColor = ConsoleColor.Blue;
- Console.WriteLine($"--- {e.Type}--{e.Kv.Key.ToStringUtf8()}--{e.Kv.Value.ToStringUtf8()}---{DateTime.Now}");
- Console.BackgroundColor = ConsoleColor.Black;
- break;
-
- case "Delete":
-
- Console.BackgroundColor = ConsoleColor.Green;
- Console.WriteLine($"--- {e.Type}--{e.Kv.Key.ToStringUtf8()}--{e.Kv.Value.ToStringUtf8()}---{DateTime.Now}");
-
-
- var key = e.Kv.Key.ToStringUtf8();
- var imeiDel = key.Split('/')[3];
- var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false);
- if (string.IsNullOrWhiteSpace(schedule_push))
- {
- int systolicInc;
- int diastolicInc;
-
- int systolicRefValue;
- int diastolicRefValue;
-
- decimal systolicAvg;
- decimal diastolicAvg;
-
- int systolicMax = 0;
- int diastolicMax = 0;
-
- int systolicMin = 0;
- int diastolicMin = 0;
-
-
- var avgOffset = 0.25M;
- var systolicAvgOffset = avgOffset;
- var diastolicAvgOffset = avgOffset;
-
-
- int lastPushSystolicInc = 0;
- int lastPushDiastolicInc = 0;
-
-
- var startTime = DateTime.Now;
-
- #region 统计定时下发增量值
-
-
-
-
- var condition = $"serialno='{imeiDel}' order by last_update desc";
- var field = "last_row(*)";
- var lastHmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition, field);
- var lastHmBpParser = JsonConvert.DeserializeObject<ParseTDengineRestResponse<BloodPressureModel>>(lastHmBpResponse!);
- var lastHmBp = lastHmBpParser?.Select().FirstOrDefault();
-
-
-
-
-
-
-
- if (lastHmBp?.Timestamp.AddDays(7) > DateTime.Now)
- {
-
- condition = $"serialno='{imeiDel}' order by ts desc";
- var lastPushResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bp_push_ref_inc_value", condition, field);
- if (lastPushResponse == null)
- {
- _logger.LogInformation($"{imeiDel}--没有下发记录");
- break;
- }
- var lastPushParser = JsonConvert.DeserializeObject<ParseTDengineRestResponse<BloodPressurePushRefIncModel>>(lastPushResponse);
- var lastPush = lastPushParser!.Select().FirstOrDefault();
-
- systolicRefValue = lastPush!.SystolicRefValue;
- diastolicRefValue = lastPush!.DiastolicRefValue;
- lastPushSystolicInc = lastPush!.SystolicIncValue;
- lastPushDiastolicInc = lastPush!.DiastolicIncValue;
-
- condition = $"ts between '{lastPush?.Timestamp:yyyy-MM-dd HH:mm:ss.fff}' and '{startTime:yyyy-MM-dd HH:mm:ss.fff}' " +
- $"and serialno='{imeiDel}' " +
- $"and is_display = true";
- var hmBpResponse = await _serviceTDengine.ExecuteSelectRestResponseAsync("stb_hm_bloodpress", condition);
- var hmBpParser = JsonConvert.DeserializeObject<ParseTDengineRestResponse<BloodPressureModel>>(hmBpResponse!);
- var hmBp = hmBpParser?.Select();
-
-
- if (hmBpParser!.Rows < 5)
- {
- _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} -- 统计定时下发,计算增量值的数据条目不足:{hmBpParser!.Rows} < 5");
- _logger.LogInformation($"{imeiDel} -- {nameof(Worker)} --{nameof(WatchEvents)} 没有足够的数据样本,不会定时下发");
- break;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- var avgs = _serviceTDengine.AverageAfterRemovingOneMinMaxRef(SafeType.SafeInt(systolicRefValue!), hmBpParser!);
- systolicAvg = avgs[0];
- diastolicAvg = avgs[1];
-
-
-
- if (systolicAvg.Equals(0))
- {
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算平均值" +
- $"\n currentSystolicAvg:{systolicAvg} -- lastPushSystolicInc:{lastPushSystolicInc}" +
- $"\n currentDiastolicInc:{diastolicAvg} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)} 没有足够的数据样本计算平均值,不会定时下发");
- break;
- }
-
-
- var currentSystolicInc = (int)((systolicRefValue - systolicAvg) * systolicAvgOffset)!;
- var currentDiastolicInc = (int)((diastolicRefValue - diastolicAvg) * diastolicAvgOffset)!;
-
-
-
- systolicInc = currentSystolicInc + lastPushSystolicInc;
- diastolicInc = currentDiastolicInc + lastPushDiastolicInc;
-
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}--计算增量值" +
- $"\n {imeiDel} -- systolicAvg:{systolicAvg}-- systolicInc:{systolicInc}-- currentSystolicInc:{currentSystolicInc} -- lastPushSystolicInc:{lastPushSystolicInc}" +
- $"\n {imeiDel} -- diastolicAvg:{diastolicAvg}-- diastolicInc:{diastolicInc} --currentDiastolicInc:{currentDiastolicInc} -- lastPushDiastolicInc:{lastPushDiastolicInc}");
- _logger.LogInformation($"{imeiDel}--{nameof(Worker)}-- 定时校准,发给设备的绝对增量值=(上次绝对增量值+新数据的增量值)");
-
-
- _logger.LogInformation($"{nameof(Worker)} 开启血压标定值下发: {_configBoodPressResolver.EnableBPRefPush}");
- if (_configBoodPressResolver.EnableBPRefPush)
-
- {
- BloodPressCalibrationConfigModel bpIncData = new()
- {
-
- Imei = imeiDel,
- SystolicRefValue = SafeType.SafeInt(((int)systolicRefValue!)),
- DiastolicRefValue = SafeType.SafeInt(((int)diastolicRefValue!)),
- SystolicIncValue = SafeType.SafeInt(((int)systolicInc!)),
- DiastolicIncValue = SafeType.SafeInt(((int)diastolicInc!))
- };
- var pushedBP = await _serviceIotWebApi.SetBloodPressCalibrationConfigAsync(bpIncData).ConfigureAwait(false);
- if (pushedBP)
- {
-
- #region 保存下推记录 stb_hm_bp_push_ref_inc_value
- var sql = $"INSERT INTO health_monitor.hm_bp_push_ref_inc_value_{imeiDel.Substring(imeiDel.Length - 2)} " +
- $"USING health_monitor.stb_hm_bp_push_ref_inc_value " +
- $"TAGS ('{imeiDel.Substring(imeiDel.Length - 2)}') " +
- $"VALUES(" +
- $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'," +
- $"'{imeiDel}'," +
- $"{bpIncData.SystolicRefValue}," +
- $"{bpIncData.DiastolicRefValue}," +
- $"{bpIncData.SystolicIncValue}," +
- $"{bpIncData.DiastolicIncValue}," +
- $"{false}," +
- $"{systolicAvg}," +
- $"{diastolicAvg}," +
- $"{systolicAvgOffset}," +
- $"{diastolicAvgOffset}," +
- $"'{lastPush?.Timestamp:yyyy-MM-dd HH:mm:ss.fff}'," +
- $"'{startTime:yyyy-MM-dd HH:mm:ss.fff}'" +
- $")";
- _serviceTDengine.ExecuteInsertSQL(sql);
- #endregion
-
- #region 注册定时下发
-
- var endTime = DateTime.Now;
-
- #if DEBUG
-
-
-
-
-
- var interval = 0;
-
- DateTime now = DateTime.Now;
-
-
- DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 2, 0).AddDays(interval);
- TimeSpan timeUntilNextRun = nextRunTime - now;
-
-
- if (timeUntilNextRun < TimeSpan.Zero)
- {
- timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromMinutes(1));
- nextRunTime += timeUntilNextRun;
- }
-
-
- long ttl = (long)((timeUntilNextRun.TotalMilliseconds - (endTime - startTime).TotalMilliseconds) / 1000);
- var data = new
- {
- imei = imeiDel,
- create_time = now.ToString("yyyy-MM-dd HH:mm:ss"),
- ttl,
- next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss")
- };
- var result = JsonConvert.SerializeObject(data);
-
- await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false);
-
-
- #else
-
- var interval = 1;
-
- DateTime now = DateTime.Now;
-
-
- DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 20, 0, 0).AddDays(interval);
- TimeSpan timeUntilNextRun = nextRunTime - now;
-
-
- if (timeUntilNextRun < TimeSpan.Zero)
- {
- timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1));
- nextRunTime += timeUntilNextRun;
- }
-
-
- long ttl = (long)((timeUntilNextRun.TotalMilliseconds-(endTime-startTime).TotalMilliseconds)/1000);
- var data = new
- {
- imei = imeiDel,
- create_time = now.ToString("yyyy-MM-dd HH:mm:ss"),
- ttl,
- next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss")
- };
- var result = JsonConvert.SerializeObject(data);
- await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false);
- #endif
- #endregion
-
- }
- else
- {
- _logger.LogInformation($"错误响应,没有下推数据");
- }
- }
- }
- else
- {
- _logger.LogInformation($"向{imeiDel}统计数据已经失效");
- }
- #endregion
-
-
- }
-
- break;
- }
-
- });
- }
-
- private static void NewMethod(int systolicRefValue, ParseTDengineRestResponse<BloodPressureModel>? hmBpParser)
- {
- var sortedList = hmBpParser?.Select(i => i)
- .Where(i => i.IsDisplay.Equals(true))
- .OrderByDescending(i => i.SystolicValue)
- .ThenByDescending(i => i.DiastolicValue)
- .ToList();
-
- var trimmedList = sortedList?
- .Skip(1)
- .Take(sortedList.Count - 2)
- .ToList();
-
-
- var filteredList = trimmedList?.Where(bp => bp.SystolicValue < SafeType.SafeInt(systolicRefValue!)).ToList();
-
- var systolicAvg1 = filteredList?.Select(bp => bp.SystolicValue).Average();
- var diastolicAvg1 = filteredList?.Select(bp => bp.DiastolicValue).Average();
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- }
|