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
{
///
/// 不存在
///
NotExisted = 0,
///
/// 不完整,已填写内容
///
FilledContent = 1,
///
/// 不完整,已填写地址
///
FilledAddress = 2,
///
/// 信息已完整
///
Complete = 3,
///
///
///
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 _alarmApiClient;
// private readonly EventResolverFactory _resolverFactory;
private readonly IServiceProvider _services;
private readonly IotConfig _configIot;
private readonly ILogger _logger;
//private static MsgQueueManager _queueManager = null;
//private MsgQueueManager QueueManager
//{
// get
// {
// if (_queueManager == null) _queueManager = _services.GetRequiredService();
// return _queueManager;
// }
//}
public SosLogic(PersonCacheManager personCacheMgr, MqProcessLogic serviceMqProcess,
GpsLocationHistoryAccessorClient alarmApiClient,
//EventResolverFactory resolverFactory,
IServiceProvider services, IOptions optConfigIot, ILogger logger)
{
_personCacheMgr = personCacheMgr;
_serviceMqProcess = serviceMqProcess;
_alarmApiClient = alarmApiClient;
//_resolverFactory = resolverFactory;
_services = services;
_configIot = optConfigIot.Value;
_logger = logger;
}
private async Task GetSosStatusAsync(string sosId)
{
var key = $"{KEY_CACHE_SOS_STATUS}_{sosId}";
var result = await RedisHelper.GetAsync(key);
if (result == null) return SosStatusType.NotExisted;
if (result > SosStatusType.Reserved || result < SosStatusType.NotExisted) return SosStatusType.NotExisted;
return result.Value;
}
///
/// 处理sos事件消息
///
///
///
/// 返回告警对象用于插入数据库
/// 返回告警对象用于更新数据库
/// 后续处理
///
public async Task HandleSosContent(string messageId, string sosId,
Func factoryToAdd, Func 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 HandleSosAddressAsync(string messageId, string sosId, long timestamp,
Func factoryToAdd, Func 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 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;
}
}
///
///
///
///
///
///
private async Task 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 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;
}
}
}