using GpsCardGatewayPosition.Model.Config; using GpsCardGatewayPosition.Model.Enum; using GpsCardGatewayPosition.Service.Cache; using GpsCardGatewayPosition.Service.MqProducer; using GpsCardGatewayPosition.Service.Resolver.Property.Dto; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TelpoDataService.Util.Clients; using TelpoDataService.Util.Entities.GpsLocationHistory; namespace GpsCardGatewayPosition.Service.Biz.Health { public class HealthLogic { public enum TemperatureStatusType : int { /// /// 不存在 /// NotExisted = 0, /// /// 不完整,已填写内容 /// FilledContent = 1, /// /// 不完整,已填写地址 /// FilledAddress = 2, /// /// 信息已完整 /// Complete = 3, /// /// /// Reserved } private const string KEY_CACHE_TEMPERATURE_STATUS = "Temperature_Status"; private const int KEY_CACHE_SECONDS = 600; private readonly ServiceConfig _configService; private readonly MqProcessLogic _serviceMqProcess; private readonly PersonCacheManager _personCacheMgr; private readonly DeviceCacheManager _deviceCacheMgr; //private readonly StepCacheManager _stepCacheMgr; private readonly GpsLocationHistoryAccessorClient _hisTemperatureApiClient; private readonly GpsLocationHistoryAccessorClient _hisStepApiClient; private readonly GpsLocationHistoryAccessorClient _hisHeartApiClient; private readonly GpsLocationHistoryAccessorClient _hisSpo2ApiClient; private readonly GpsLocationHistoryAccessorClient _hisBloodPressApiClient; private readonly GpsLocationHistoryAccessorClient _hisDrownReportApiClient; private readonly GpsLocationHistoryAccessorClient _hisWearStatusApiClient; private readonly GpsLocationHistoryAccessorClient _hisSportResultApiClient; private readonly ILogger _logger; public HealthLogic(IOptions optConfigService, MqProcessLogic serviceMqProcess, // StepCacheManager stepCacheMgr, PersonCacheManager personCacheMgr, DeviceCacheManager deviceCacheMgr, GpsLocationHistoryAccessorClient temperatureApiClient, GpsLocationHistoryAccessorClient stepApiClient, GpsLocationHistoryAccessorClient hisHeartApiClient, GpsLocationHistoryAccessorClient hisSpo2ApiClient, GpsLocationHistoryAccessorClient hisBloodPressApiClient, GpsLocationHistoryAccessorClient hisDrownReportApiClient, GpsLocationHistoryAccessorClient hisWearStatusApiClient, GpsLocationHistoryAccessorClient hisSportResultApiClient, ILogger logger) { _configService = optConfigService.Value; _serviceMqProcess = serviceMqProcess; _deviceCacheMgr = deviceCacheMgr; _personCacheMgr = personCacheMgr; //_stepCacheMgr = stepCacheMgr; _hisTemperatureApiClient = temperatureApiClient; _hisStepApiClient = stepApiClient; _logger = logger; _hisHeartApiClient = hisHeartApiClient; _hisSpo2ApiClient = hisSpo2ApiClient; _hisDrownReportApiClient = hisDrownReportApiClient; _hisWearStatusApiClient = hisWearStatusApiClient; _hisBloodPressApiClient = hisBloodPressApiClient; _hisSportResultApiClient = hisSportResultApiClient; } #region 体温相关 /// /// 处理测温事件消息(内容部分) /// /// /// 和serialno组合的tempId /// 返回测温对象用于插入数据库 /// 返回测温对象用于更新数据库 /// 后续处理 /// 定位类型 // 2022/11/10 增加 type 参数判断定位类型 /// public async Task HandleTemperatureContent(string messageId, string tempId, Func factoryToAdd, Func factoryToUpdate, Action handleFollowup = null, LocationType type = default) { if (factoryToAdd == null || factoryToUpdate == null) throw new ArgumentNullException(); HisGpsTemperature temperature = null; var status = await GetTemperatureStatusAsync(tempId).ConfigureAwait(false); if (status == TemperatureStatusType.Complete || status == TemperatureStatusType.FilledContent) { _logger.LogWarning($"TEMPERATURE事件[{tempId}]已处理(内容部分)|事件"); return false; } if (status == TemperatureStatusType.NotExisted) { temperature = factoryToAdd.Invoke(); await AddTemperatureAsync(messageId, temperature).ConfigureAwait(false); SetTemperatureStatus(tempId, TemperatureStatusType.FilledContent); // 对应无地址也要推送测温情况,创建一个线程,并让该线程休眠 60 秒 Thread thread = new Thread(async () => { _logger.LogInformation($"messageId:[{messageId}],TEMPERATURE事件[{tempId}] 无地址测温推送延时60s,判断入库后gps_temperature表中address是否为空,若为空也推送"); Task.Delay(TimeSpan.FromSeconds(60)).Wait(); var temperatureLate = await GetTemperatureAsync(messageId, tempId).ConfigureAwait(false); if (string.IsNullOrEmpty(temperatureLate.Address)) { PushWxTemperature(messageId, temperatureLate); _logger.LogInformation($"messageId:[{messageId}],TEMPERATURE事件[{tempId}]延时60s,无地址已推送"); } _logger.LogInformation($"messageId:[{messageId}],TEMPERATURE事件[{tempId}]延时60s,在HandleTemperatureAddressAsync地址已推送"); }); thread.Start(); } else { temperature = await GetTemperatureAsync(messageId, tempId).ConfigureAwait(false); if (temperature != null) { temperature = factoryToUpdate.Invoke(temperature); await UpdateTemperatureAsync(messageId, temperature).ConfigureAwait(false); SetTemperatureStatus(tempId, TemperatureStatusType.Complete); //推送微信公众号 await PushWxTemperature(messageId, temperature, type); } } handleFollowup?.Invoke(); return true; } /// /// 处理测温事件消息(地址信息部分) /// /// /// 和serialno组合的tempId /// 返回测温对象用于插入数据库 /// 返回测温对象用于更新数据库 /// 后续处理 /// 定位类型 // 2022/11/10 增加 type 参数判断定位类型 /// public async Task HandleTemperatureAddressAsync(string messageId, string tempId, Func factoryToAdd, Func factoryToUpdate, Action handleFollowup = null, LocationType type = default) { if (factoryToAdd == null || factoryToUpdate == null) throw new ArgumentNullException(); HisGpsTemperature temperature = null; var status = await GetTemperatureStatusAsync(tempId).ConfigureAwait(false); if (status == TemperatureStatusType.Complete || status == TemperatureStatusType.FilledAddress) { _logger.LogWarning($"TEMPERATURE事件[{tempId}]已处理(地址信息内容部分)"); return false; } if (status == TemperatureStatusType.NotExisted) { temperature = factoryToAdd.Invoke(); await AddTemperatureAsync(messageId, temperature).ConfigureAwait(false); SetTemperatureStatus(tempId, TemperatureStatusType.FilledAddress); // 2023/02/02 新增测温数据 没有匹配定位信息,也推送给第三方平台。 // if (temperature.Temperature != null) // { // PushWxTemperature(messageId, temperature); // } } else { temperature = await GetTemperatureAsync(messageId, tempId).ConfigureAwait(false); if (temperature != null) { temperature = factoryToUpdate.Invoke(temperature); await UpdateTemperatureAsync(messageId, temperature).ConfigureAwait(false); SetTemperatureStatus(tempId, TemperatureStatusType.Complete); //推送微信公众号 PushWxTemperature(messageId, temperature, type); } } handleFollowup?.Invoke(); return true; } // 2022/11/10 增加 type 参数判断定位类型 private async Task PushWxTemperature(string messageId, HisGpsTemperature temperature, LocationType type = default) { var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(messageId, temperature.Serialno); if (device == null) return; string deviceName = temperature.Serialno; var person = await _personCacheMgr.GetPersonBySerialNoAsync(messageId, temperature.Serialno).ConfigureAwait(false); if (person != null) deviceName = person.NickName; MethodType method = MethodType.Manual; //if (temperature.Method == 0) method = MethodType.Manual; if (temperature.Method == 1) method = MethodType.Period; await _serviceMqProcess.ProcessWxTemperatureAsync(messageId, new TemperatureInfoModel { DeviceId = device.DeviceId, DeviceName = deviceName, TempId = temperature.TempId, TempTime = temperature.LastUpdate, Imei = temperature.Serialno, Temperature = temperature.Temperature, Province = temperature.Province, City = temperature.City, District = temperature.District, Address = temperature.Address }, type, method); } private async Task GetTemperatureStatusAsync(string tempId) { var key = $"{KEY_CACHE_TEMPERATURE_STATUS}_{tempId}"; var result = await RedisHelper.GetAsync(key); if (result == null) return TemperatureStatusType.NotExisted; if (result > TemperatureStatusType.Reserved || result < TemperatureStatusType.NotExisted) return TemperatureStatusType.NotExisted; return result.Value; } private void SetTemperatureStatus(string sosId, TemperatureStatusType status) { var key = $"{KEY_CACHE_TEMPERATURE_STATUS}_{sosId}"; RedisHelper.SetAsync(key, (int)status, KEY_CACHE_SECONDS); } public async Task GetTemperatureAsync(string messageId, string temperatureId) { try { //var param = new GeneralParam //{ // Filters = new List // { // new QueryFilterCondition // { // Key=nameof(HisGpsTemperature.TempId), // Value=tempId, // ValueType=QueryValueTypeEnum.String, // Operator=QueryOperatorEnum.Equal // }, // new QueryFilterCondition // { // Key=nameof(HisGpsTemperature.Serialno), // Value=serialno, // ValueType=QueryValueTypeEnum.String, // Operator=QueryOperatorEnum.Equal // } // } //}; //var temperature = await _hisTemperatureApiClient.GetFirstAsync(param, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false); //return temperature; var temperature = await _hisTemperatureApiClient.GetByIdAsync(temperatureId, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false); return temperature; } catch (Exception ex) { _logger.LogError($"根据{temperatureId}获取指定测温信息失败, {ex.Message}, {ex.StackTrace}"); return null; } } public async Task AddTemperatureAsync(string messageId, HisGpsTemperature temperature) { try { // 体温gps_temperature,步数gps_step,血压gps_bloodpress,心率gps_heart_rate,血氧gps_spo2 五个表新增 person_id 字段 var person = await _personCacheMgr.GetDeviceGpsPersonCacheBySerialNoAsync(messageId, temperature.Serialno).ConfigureAwait(false); var persnId = string.Empty; if (person != null && person.Person != null) persnId = person.Person.PersonId; temperature.PersonId = persnId; await _hisTemperatureApiClient.AddAsync(temperature, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false); return true; } catch (Exception ex) { _logger.LogError($"新增体温信息发生异常:{ex.Message}, {ex.StackTrace}"); } return false; } public async Task UpdateTemperatureAsync(string messageId, HisGpsTemperature temperature) { try { await _hisTemperatureApiClient.UpdateAsync(temperature, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false); return true; } catch (Exception ex) { _logger.LogError($"更新体温信息发生异常:{ex.Message}, {ex.StackTrace}"); } return false; } #endregion } }