|
- using GpsCardGatewayPosition.Model.Config;
- using GpsCardGatewayPosition.Service.Cache;
- using GpsCardGatewayPosition.Service.MqProducer;
- using Microsoft.Extensions.DependencyInjection;
- 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.Sos
- {
- public class SosLogic
- {
- public enum SosStatusType : int
- {
- /// <summary>
- /// 不存在
- /// </summary>
- NotExisted = 0,
- /// <summary>
- /// 不完整,已填写内容
- /// </summary>
- FilledContent = 1,
- /// <summary>
- /// 不完整,已填写地址
- /// </summary>
- FilledAddress = 2,
- /// <summary>
- /// 信息已完整
- /// </summary>
- Complete = 3,
- /// <summary>
- ///
- /// </summary>
- Reserved
- }
-
- private const string KEY_CACHE_SOS_STATUS = "Sos_Status";
- private const int KEY_CACHE_SECONDS = 600;
-
- private const string TEMPLATE_SOS_TOPIC = "/{0}/{1}/thing/event/SOS/post";
- private const string TEMPLATE_SOS_BODY = "{{\"deviceType\":\"CustomCategory\",\"identifier\":\"SOS\",\"iotId\":\"{0}\",\"requestId\":\"666\",\"name\":\"SOS求救报警\",\"time\":{1},\"type\":\"alert\",\"productKey\":\"{2}\",\"deviceName\":\"{3}\",\"value\":{{\"SOSID\":\"{4}\",\"state\":-5,\"info\":\"求救!\"}}}}";
-
- private readonly PersonCacheManager _personCacheMgr;
- private readonly MqProcessLogic _serviceMqProcess;
- private readonly GpsLocationHistoryAccessorClient<HisGpsAlarm> _alarmApiClient;
- // private readonly EventResolverFactory _resolverFactory;
-
- private readonly IServiceProvider _services;
- private readonly IotConfig _configIot;
- private readonly ILogger<SosLogic> _logger;
-
- //private static MsgQueueManager _queueManager = null;
- //private MsgQueueManager QueueManager
- //{
- // get
- // {
- // if (_queueManager == null) _queueManager = _services.GetRequiredService<MsgQueueManager>();
- // return _queueManager;
- // }
- //}
-
- public SosLogic(PersonCacheManager personCacheMgr, MqProcessLogic serviceMqProcess,
- GpsLocationHistoryAccessorClient<HisGpsAlarm> alarmApiClient,
- //EventResolverFactory resolverFactory,
- IServiceProvider services, IOptions<IotConfig> optConfigIot, ILogger<SosLogic> logger)
- {
- _personCacheMgr = personCacheMgr;
- _serviceMqProcess = serviceMqProcess;
- _alarmApiClient = alarmApiClient;
- //_resolverFactory = resolverFactory;
-
- _services = services;
- _configIot = optConfigIot.Value;
- _logger = logger;
- }
-
- private async Task<SosStatusType> GetSosStatusAsync(string sosId)
- {
- var key = $"{KEY_CACHE_SOS_STATUS}_{sosId}";
- var result = await RedisHelper.GetAsync<SosStatusType?>(key);
- if (result == null) return SosStatusType.NotExisted;
- if (result > SosStatusType.Reserved || result < SosStatusType.NotExisted) return SosStatusType.NotExisted;
-
- return result.Value;
- }
-
- /// <summary>
- /// 处理sos事件消息
- /// </summary>
- /// <param name="messageId"></param>
- /// <param name="sosId"></param>
- /// <param name="factoryToAdd">返回告警对象用于插入数据库</param>
- /// <param name="factoryToUpdate">返回告警对象用于更新数据库</param>
- /// <param name="handleFollowup">后续处理</param>
- /// <returns></returns>
- public async Task<bool> HandleSosContent(string messageId, string sosId,
- Func<HisGpsAlarm> factoryToAdd, Func<HisGpsAlarm, HisGpsAlarm> factoryToUpdate,
- Action handleFollowup = null)
- {
- if (factoryToAdd == null || factoryToUpdate == null) throw new ArgumentNullException();
- HisGpsAlarm alarm = null;
-
- var status = await GetSosStatusAsync(sosId).ConfigureAwait(false);
- if (status == SosLogic.SosStatusType.Complete || status == SosLogic.SosStatusType.FilledContent)
- {
- _logger.LogWarning($"SOS事件[{sosId}]已处理(内容)");
- return false;
- }
-
- if (status == SosStatusType.NotExisted)
- {
- alarm = factoryToAdd.Invoke();
- await AddSosAlarmAsync(messageId, alarm).ConfigureAwait(false);
-
- SetSosStatus(sosId, SosLogic.SosStatusType.FilledContent);
- }
- else
- {
- alarm = await GetSosAlarmAsync(messageId, sosId).ConfigureAwait(false);
- if (alarm != null)
- {
- alarm = factoryToUpdate.Invoke(alarm);
- await UpdateSosAlarmAsync(messageId, alarm).ConfigureAwait(false);
-
- SetSosStatus(sosId, SosLogic.SosStatusType.Complete);
- }
- }
-
- if (alarm != null)
- {
- //推送微信公众号
- if (alarm.TypeId >= 1 && alarm.TypeId <= 5)
- {
- await _serviceMqProcess.ProcessWxAlarmAsync(alarm);
- }
- }
-
- handleFollowup?.Invoke();
- return true;
- }
-
- public async Task<bool> HandleSosAddressAsync(string messageId, string sosId, long timestamp,
- Func<HisGpsAlarm> factoryToAdd, Func<HisGpsAlarm, HisGpsAlarm> factoryToUpdate,
- Action handleFollowup = null)
- {
- if (factoryToAdd == null || factoryToUpdate == null) throw new ArgumentNullException();
- HisGpsAlarm alarm = null;
-
- var status = await GetSosStatusAsync(sosId).ConfigureAwait(false);
- if (status == SosStatusType.Complete || status == SosStatusType.FilledAddress)
- {
- _logger.LogWarning($"SOS事件[{sosId}]已处理(地址)");
- return false;
- }
-
- if (status == SosStatusType.NotExisted)
- {
- alarm = factoryToAdd.Invoke();
- await AddSosAlarmAsync(messageId, alarm).ConfigureAwait(false);
-
- SetSosStatus(sosId, SosLogic.SosStatusType.FilledAddress);
-
- //为预防sos事件丢失的情况,这里主动构建sos事件消息并入队列
- var topic = string.Format(TEMPLATE_SOS_TOPIC, _configIot.ProductKey, alarm.Serialno);
- var body = string.Format(TEMPLATE_SOS_BODY,
- Guid.NewGuid().ToString(),
- //new DateTimeOffset(alarm.DeviceUtcTime ?? DateTime.UtcNow).ToUnixTimeMilliseconds(),
- timestamp,
- _configIot.ProductKey,
- alarm.Serialno,
- sosId);
-
- //var msg = _resolverFactory.ParseAndWrap(new ReceiveMessageModel(messageId, topic, body));
- //if (msg == null) _logger.LogError("模拟sos事件消息失败");
- //else QueueManager.EnqueueMsg(msg);
- }
- else
- {
- alarm = await GetSosAlarmAsync(messageId, sosId).ConfigureAwait(false);
- if (alarm != null)
- {
- alarm = factoryToUpdate.Invoke(alarm);
- await UpdateSosAlarmAsync(messageId, alarm).ConfigureAwait(false);
-
- SetSosStatus(sosId, SosLogic.SosStatusType.Complete);
- }
- }
-
- handleFollowup?.Invoke();
- return true;
- }
-
- private void SetSosStatus(string sosId, SosStatusType status)
- {
- var key = $"{KEY_CACHE_SOS_STATUS}_{sosId}";
- RedisHelper.SetAsync(key, (int)status, KEY_CACHE_SECONDS);
- }
-
- private async Task<HisGpsAlarm> GetSosAlarmAsync(string messageId, string sosId)
- {
- try
- {
- var alarm = await _alarmApiClient.GetByIdAsync(sosId, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false);
- return alarm;
- }
- catch (Exception ex)
- {
- _logger.LogError($"根据{sosId}获取指定SOS告警信息失败, {ex.Message}, {ex.StackTrace}");
- return null;
- }
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="messageId"></param>
- /// <param name="alarm"></param>
- /// <returns></returns>
- private async Task<bool> AddSosAlarmAsync(string messageId, HisGpsAlarm alarm)
- {
- try
- {
- var person = await _personCacheMgr.GetPersonBySerialNoAsync(messageId, alarm.Serialno).ConfigureAwait(false);
- if (person == null)
- alarm.DeviceName = alarm.Serialno;
- else
- alarm.DeviceName = person.NickName;
-
- if (string.IsNullOrWhiteSpace(alarm.MessageId)) alarm.MessageId = Guid.NewGuid().ToString("D");
- await _alarmApiClient.AddAsync(alarm, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false);
-
- return true;
- }
- catch (Exception ex)
- {
- _logger.LogError($"新增SOS报警信息发生异常:{ex.Message}, {ex.StackTrace}");
- }
-
- return false;
- }
-
- private async Task<bool> UpdateSosAlarmAsync(string messageId, HisGpsAlarm alarm)
- {
- try
- {
- await _alarmApiClient.UpdateAsync(alarm, header: new RequestHeader { RequestId = messageId }).ConfigureAwait(false);
- return true;
- }
- catch (Exception ex)
- {
- _logger.LogError($"更新SOS报警信息发生异常:{ex.Message}, {ex.StackTrace}");
- }
-
- return false;
- }
- }
- }
|