using GpsCardGatewayPosition.Common.Helper;
using GpsCardGatewayPosition.Common;
using GpsCardGatewayPosition.Model.Enum;
using GpsCardGatewayPosition.Model.IoT;
using GpsCardGatewayPosition.Service.Biz.Location;
using GpsCardGatewayPosition.Service.Biz.Location.Dto.Gaode;
using GpsCardGatewayPosition.Service.Biz.Location.Dto.Wayz;
using GpsCardGatewayPosition.Service.Cache;
using GpsCardGatewayPosition.Service.MqProducer;
using GpsCardGatewayPosition.Service.Resolver.Interface;
using GpsCardGatewayPosition.Service.Resolver.Property.Dto;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoDataService.Util.Entities.GpsCard;
using GpsCardGatewayPosition.Service.Biz.Location.Dto;
using GpsCardGatewayPosition.Model.Context;
using GpsCardGatewayPosition.Service.MqProducer.Model;
using GpsCardGatewayPosition.Service.Biz.Sos;
using GpsCardGatewayPosition.Service.Biz.Pay;
using GpsCardGatewayPosition.Service.Biz.Health;
using GpsCardGatewayPosition.Service.Biz;
using TelpoDataService.Util.Entities.GpsLocationHistory;
using GpsCardGatewayPosition.Model.Templates;
namespace GpsCardGatewayPosition.Service.Resolver.Property
{
///
/// Lbs Gsm方式定位消息
///
public class LbsGsmPositionResolver : IPropertyResolver
{
private readonly ILogger _logger;
private readonly WayzService _serviceWayz;
private readonly GaodeService _serviceGaode;
private readonly LocationLogic _serviceLocation;
private readonly MqProcessLogic _serviceMqProcess;
private readonly SosLogic _serviceSos;
private readonly PayLogic _servicePay;
private readonly HealthLogic _serviceHealth;
private readonly GlobalService _serviceGlobal;
private readonly DeviceCacheManager _deviceCacheMgr;
private AsyncLocal _messageId = new AsyncLocal();
private AsyncLocal _package = new AsyncLocal();
private AsyncLocal> _propertyValue = new AsyncLocal>();
public LbsGsmPositionResolver(ILogger logger,
GaodeService serviceGaode,
WayzService serviceWayz, LocationLogic serviceLocation, MqProcessLogic serviceMqProcess,
SosLogic serviceSos, PayLogic servicePay, HealthLogic serviceHealth, GlobalService serviceGlobal,
DeviceCacheManager deviceCacheMgr)
{
_logger = logger;
_serviceGaode = serviceGaode;
_serviceWayz = serviceWayz;
_serviceLocation = serviceLocation;
_serviceMqProcess = serviceMqProcess;
_serviceSos = serviceSos;
_servicePay = servicePay;
_serviceHealth = serviceHealth;
_serviceGlobal = serviceGlobal;
_deviceCacheMgr = deviceCacheMgr;
}
public void SetResolveInfo(PackageMsgModel msg)
{
_messageId.Value = msg.MessageId;
_package.Value = ((JToken)msg.TopicInfo).ToObject()!;
_propertyValue.Value = ((JToken)msg.DetailData).ToObject>()!;
}
public override string ToString()
{
return $"{nameof(LbsGsmPositionResolver)}[{_messageId.Value}]";
}
public async Task ExecuteMessageAsync()
{
var package = _package.Value;
var serialno = package.DeviceName; //设备序列号
var messageId = _messageId.Value;
var propertyValue = _propertyValue.Value;
//var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(messageId!, serialno!).ConfigureAwait(false);
//if (device == null)
//{
// _logger.LogError($"非法设备:{serialno}");
// return;
//}
var device = new GpsDevice()
{
DeviceId = serialno,
};
#region 定位解析
var bts = propertyValue.Value.Bts.Split(',');
WayzLbsRequest wayzLbsRequest = new WayzLbsRequest
{
Location = new WayzRequest.LocationDetail
{
Cellulars = new List
{
new WayzRequest.CellularItem {
CellId = int.Parse(bts[3]),
//RadioType = "lte",
MobileCountryCode = int.Parse(bts[0]),
MobileNetworkCode = int.Parse(bts[1]),
LocationAreaCode = int.Parse(bts[2]),
}
}
},
Asset = new WayzRequest.AssetDevice
{
Id = serialno,
ImeiMd5 = serialno,
UniqueId = device.DeviceId
}
};
var wayzServiceResult = await _serviceWayz.GetWayzLbsAddressAsync(serialno, wayzLbsRequest).ConfigureAwait(false);
// if (!wayzServiceResult.Flag)
//{
// if (wayzServiceResult.CanRetry) _serviceWayz.SendRealtimeLocationAsync(serialno, Utils.ConvertToLocalDateTime(propertyValue.Time), RealtimeLocationTypeFlag.All);
// return;
//}
var province = string.Empty;
var city = string.Empty;
var district = string.Empty;
var address = string.Empty;
var cityCode = string.Empty;
var hashParam = string.Empty;
var fullAddress = string.Empty;
decimal olat = 0M;
decimal olng = 0M;
int radius = 0;
if (wayzServiceResult.Flag)
{
province = wayzServiceResult.Province;
city = wayzServiceResult.City;
district = wayzServiceResult.District;
address = wayzServiceResult.Address;
cityCode = wayzServiceResult.CityCode;
hashParam = wayzServiceResult.HashParam;
fullAddress = wayzServiceResult.FullAddress;
olat = wayzServiceResult.Lat;
olng = wayzServiceResult.Lon;
radius = wayzServiceResult.Accuracy;
}
else
{
_logger.LogInformation($"维智服务不能解析LBS地址数据,将采用高德服务解析");
var lbsGaodeRequest = new GaodeLbsRequest()
{
Bts = propertyValue.Value.Bts,
Cdma = 0,
//Imei = serialno,
Imsi = propertyValue.Value.IMSI,
NearBts = propertyValue.Value.Nearbts,
Smac = propertyValue.Value.SMAC
};
var gaodeServiceResult = await _serviceGaode.GetGaodeLbsAddressAsync(serialno, lbsGaodeRequest);
if (gaodeServiceResult.Flag)
{
province = gaodeServiceResult.Province;
city = gaodeServiceResult.City;
district = gaodeServiceResult.District;
address = gaodeServiceResult.Address;
cityCode = gaodeServiceResult.AdCode;
hashParam = gaodeServiceResult.HashParam;
olat = gaodeServiceResult.Lat;
olng = gaodeServiceResult.Lon;
radius = gaodeServiceResult.Accuracy;
fullAddress = string.Format("{0}|{1}", "_Gaode", gaodeServiceResult.Address);
}
else
{
await _serviceWayz.SendRealtimeLocationAsync(serialno, Utils.ConvertToLocalDateTime(propertyValue.Time), RealtimeLocationTypeFlag.All);
_logger.LogInformation($"维智服务和高德服务解析都不能解析LBS地址定位数据");
return;
}
}
decimal[] latLng = GeoConvert.ConvertGoogleBaiduLatLng(olat, olng);
#endregion
#region 保存历史轨迹
var loc = new LocationInfo
{
LocationId = Guid.NewGuid().ToString("D"),
Address = address,
BaiduLat = latLng[2],
BaiduLng = latLng[3],
OLat = olat,
OLng = olng,
GLat = latLng[0],
GLng = latLng[1],
Course = 0,
DeviceId = device.DeviceId,
DeviceStatus = radius.ToString(),
IsStop = false,
LastUpdate = Utils.ConvertToLocalDateTime(propertyValue.Time),
UtcDate = Utils.ConvertToUtcDateTime(propertyValue.Time),
LocationType = Convert.ToInt32(LocationType.LBS),
Remarks = cityCode,
SerialNo = serialno,
Speed = 0,
IDNumber = propertyValue.Value.IDNumber,
IDType = propertyValue.Value.IDType,
Postcode = cityCode,
IsRedressed = false,
HashParam = hashParam,
Province = province,
City = city,
District = district
};
loc.Remarks = string.Format("Wayz_LbsGms|{0}", fullAddress);
var positionStatus = await _deviceCacheMgr.GetPositionStatusCacheAsync(serialno).ConfigureAwait(false);
var requestPositionData = new RequestLocationInfo
{
MapSource = 2,
RequestLocationType = loc.LocationType,
RequestData = wayzLbsRequest
};
var hisResult = await _serviceLocation.AddLocationAsync(messageId, loc, positionStatus, propertyValue.Time, cityCode, null, requestPositionData).ConfigureAwait(false);
if (!hisResult.IsSuccess)
{
_logger.LogError($"{hisResult.Message}");
return;
}
#endregion
#region 保存最后位置信息
var context = "online=1";
var deviceStatus = await _deviceCacheMgr.GetDeviceStatusBySerialNoAsync(messageId, serialno).ConfigureAwait(false);
var statusContext = new DeviceStatus();
if (deviceStatus != null)
{
statusContext.Deserlize(deviceStatus.DeviceStatus);
}
statusContext.Deserlize(context);
deviceStatus = new GpsDeviceStatus
{
Address = loc.Address,
IsStop = (bool)loc.IsStop,
BaiduLat = loc.BaiduLat,
BaiduLng = loc.BaiduLng,
Olat = loc.OLat,
Olng = loc.OLng,
Glat = loc.GLat,
Glng = loc.GLng,
Course = loc.Course,
DeviceId = loc.DeviceId,
DeviceStatus = statusContext.ToString(),
DeviceUtcTime = loc.UtcDate,
LastUpdate = loc.LastUpdate,
LocationType = loc.LocationType,
Remarks = loc.LocationId,
Serialno = loc.SerialNo,
//Speed = loc.Speed,
Speed = SafeType.SafeInt(loc.DeviceStatus)
};
var result = await _serviceLocation.UpdateDeviceStatusAsync(messageId, deviceStatus).ConfigureAwait(false);
if (!result.IsSuccess)
{
_logger.LogError($"{result.Message}");
return;
}
//THOMAS
var positionData = new LocationDatas()
{
imei = loc.SerialNo,
altitude = 0,
address = loc.Address,
baiduLatitude = loc.BaiduLat,
baiduLongitude = loc.BaiduLng,
gaodeLatitude = loc.GLat,
gaodeLongitude = loc.GLng,
originalLatitude = loc.OLat,
originalLongitude = loc.OLng,
locationType = loc.LocationType,
postcode = loc.Postcode,
hashParam = loc.HashParam,
radius = radius,
province = province,
city = city,
district = district
};
await _serviceMqProcess.ProcessPositionAsync(messageId, positionData, loc.LastUpdate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
#endregion
#region 更新Alarm
if (loc.IDType == (int)IdType.Sos && loc.IDNumber != "")
{
// THOMAS Kafka
//var SOSAlarm = new SoSTemplates()
//{
// imei = serialno,
// sosId = loc.IDNumber,
// address = loc.Address,
// info = "您的宝贝在求救",
// baiduLatitude = loc.BaiduLat,
// baiduLongitude = loc.BaiduLng,
// gaodeLatitude = loc.GLat,
// gaodeLongitude = loc.GLng,
// originalLatitude = loc.OLat,
// originalLongitude = loc.OLng,
//};
//_serviceMqProcess.ProcessAlarmSos(messageId, SOSAlarm, loc.LastUpdate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
var sosId = loc.IDNumber;
await _serviceSos.HandleSosAddressAsync(messageId, sosId, propertyValue.Time, () => new HisGpsAlarm
{
DeviceId = device.DeviceId,
MessageId = sosId,
Serialno = serialno,
CreateTime = DateTime.Now,
DeviceUtcTime = Utils.ConvertToUtcDateTime(propertyValue.Time),
Olat = loc.OLat,
Olng = loc.OLng,
BaiduLat = loc.BaiduLat,
BaiduLng = loc.BaiduLng,
Glat = loc.GLat,
Glng = loc.GLng
},
a =>
{
a.Olat = loc.OLat;
a.Olng = loc.OLng;
a.BaiduLat = loc.BaiduLat;
a.BaiduLng = loc.BaiduLng;
a.Glat = loc.GLat;
a.Glng = loc.GLng;
return a;
},
async () => {
var SOSAlarm = new SoSTemplates()
{
imei = serialno,
sosId = loc.IDNumber,
address = loc.Address,
info = "您的宝贝在求救",
baiduLatitude = loc.BaiduLat,
baiduLongitude = loc.BaiduLng,
gaodeLatitude = loc.GLat,
gaodeLongitude = loc.GLng,
originalLatitude = loc.OLat,
originalLongitude = loc.OLng,
};
await _serviceMqProcess.ProcessAlarmSosAsync(messageId, SOSAlarm, loc.LastUpdate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
});
}
else if (loc.IDType == (int)IdType.PayLog && loc.IDNumber != "")
{
var payId = loc.IDNumber;
var pay = await _servicePay.GetPayLogAsync(messageId, $"{serialno}-{payId}").ConfigureAwait(false);
if (pay == null)
{
pay = new GpsPayLog
{
Serialno = serialno,
Payid = $"{serialno}-{payId}",
DeviceId = device.DeviceId,
Olat = loc.OLat,
Olng = loc.OLng,
BaiduLat = loc.BaiduLat,
BaiduLng = loc.BaiduLng,
Glat = loc.GLat,
Glng = loc.GLng
};
await _servicePay.AddPayLogAsync(messageId, pay).ConfigureAwait(false);
}
else
{
pay.Olat = loc.OLat;
pay.Olng = loc.OLng;
pay.BaiduLat = loc.BaiduLat;
pay.BaiduLng = loc.BaiduLng;
pay.Glat = loc.GLat;
pay.Glng = loc.GLng;
await _servicePay.UpdatePayLogAsync(messageId, pay).ConfigureAwait(false);
}
}
else if (loc.IDType == (int)IdType.Temperature && loc.IDNumber != "") //温度上报(带地址)
{
var tempId = loc.IDNumber;
await _serviceHealth.HandleTemperatureAddressAsync(messageId, $"{serialno}-{tempId}", () => new HisGpsTemperature
{
TemperatureId = $"{serialno}-{tempId}",
Serialno = serialno,
Address = address,
Province = province,
City = city,
District = district,
LastUpdate = Utils.ConvertToLocalDateTime(propertyValue.Time),
TempId = tempId
},
a =>
{
a.Address = address;
a.Province = province;
a.City = city;
a.District = district;
return a;
});
}
#endregion
}
}
}