using GpsCardGatewayPosition.Common; using GpsCardGatewayPosition.Common.Extract; using GpsCardGatewayPosition.Common.Helper; using GpsCardGatewayPosition.Model.Enum; using GpsCardGatewayPosition.Model.IoT; using GpsCardGatewayPosition.Service.Biz.Health; using GpsCardGatewayPosition.Service.Biz; using GpsCardGatewayPosition.Service.Biz.Location; using GpsCardGatewayPosition.Service.Biz.Location.Dto; using GpsCardGatewayPosition.Service.Biz.Location.Dto.Gaode; using GpsCardGatewayPosition.Service.Biz.Location.Dto.Wayz; using GpsCardGatewayPosition.Service.Biz.Pay; using GpsCardGatewayPosition.Service.Biz.Sos; 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.Model.Context; using GpsCardGatewayPosition.Model.Templates; using GpsCardGatewayPosition.Service.MqProducer.Model; using TelpoDataService.Util.Entities.GpsLocationHistory; namespace GpsCardGatewayPosition.Service.Resolver.Property { public class GpsPositionResolver : IPropertyResolver { private readonly ILogger _logger; private readonly GaodeService _serviceGaode; private readonly WayzService _serviceWayz; private readonly DeviceCacheManager _deviceCacheMgr; private readonly MqProcessLogic _serviceMqProcess; private readonly GlobalService _serviceGlobal; private readonly PayLogic _servicePay; private readonly SosLogic _serviceSos; private readonly HealthLogic _serviceHealth; private readonly LocationLogic _serviceLocation; private AsyncLocal _messageId = new AsyncLocal(); private AsyncLocal _package = new AsyncLocal(); private AsyncLocal> _propertyValue = new AsyncLocal>(); public GpsPositionResolver(ILogger logger, GaodeService serviceGaode, WayzService serviceWayz, LocationLogic serviceLocation, MqProcessLogic serviceMqProcess, GlobalService serviceGlobal, SosLogic serviceSos, PayLogic servicePay, HealthLogic serviceHealth, DeviceCacheManager deviceCacheMgr) { _logger = logger; _serviceGaode = serviceGaode; _serviceWayz = serviceWayz; _serviceLocation = serviceLocation; _serviceMqProcess = serviceMqProcess; _serviceSos = serviceSos; _servicePay = servicePay; _serviceHealth = serviceHealth; _serviceLocation = serviceLocation; _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(GpsPositionResolver)}[{_messageId.Value}]"; } public async Task ExecuteMessageAsync() { var package = _package.Value; var serialno = package.DeviceName; //设备序列号 var messageId = _messageId.Value; var propertyValue = _propertyValue.Value; if (propertyValue == null) return; if (propertyValue.Value.Latitude == 0 || propertyValue.Value.Longitude == 0) return; //var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(messageId!, serialno!).ConfigureAwait(false); //if (device == null) //{ // _logger.LogError($"非法设备:{serialno}"); // return; //} var device = new GpsDevice() { DeviceId = serialno, }; #region 定位解析 decimal[] latLng = GeoConvert.ConvertGoogleBaiduLatLng(propertyValue.Value.Latitude, propertyValue.Value.Longitude); //var serviceResult = await _serviceGaode.GetGaodeReGeoAddressAsync(serialno, new GaodeGpsRequest(latLng[1], latLng[0])).ConfigureAwait(false); WayzGpsRequest wayzGpsRequest = new WayzGpsRequest { Location = new WayzRequest.LocationDetail { //Gnss = new WayzRequest.Gnss //{ // Point = new WayzRequest.Point // { // Longitude = propertyValue.Value.Longitude, // Latitude = propertyValue.Value.Latitude, // //Longitude = latLng[1], // //Latitude = latLng[0], // } //} // 使用维智火星系坐标请求 Position = new WayzRequest.Postion { Point = new WayzRequest.Point { //Longitude = propertyValue.Value.Longitude, //Latitude = propertyValue.Value.Latitude, Longitude = latLng[1], Latitude = latLng[0], } } }, Asset = new WayzRequest.AssetDevice { Id = serialno, ImeiMd5 = serialno, UniqueId = device.DeviceId } }; var wayzServiceResult = await _serviceWayz.GetWayzReGeoAddressAsync(serialno, wayzGpsRequest).ConfigureAwait(false); //if (!wayzServiceResult.Flag) 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; if (wayzServiceResult.Flag) { province = wayzServiceResult.Province; city = wayzServiceResult.City; district = wayzServiceResult.District; address = wayzServiceResult.Address; cityCode = wayzServiceResult.CityCode; hashParam = wayzServiceResult.HashParam; fullAddress = wayzServiceResult.FullAddress; } else { _logger.LogInformation($"维智服务不能解析GPS逆地址数据,将采用高德服务解析"); var gpsGaodeRequest = new GaodeGpsRequest(latLng[1], latLng[0]); var gaodeServiceResult = await _serviceGaode.GetGaodeReGeoAddressAsync(serialno, gpsGaodeRequest); if (gaodeServiceResult.Flag) { province = gaodeServiceResult.Province; city = gaodeServiceResult.City; district = gaodeServiceResult.District; address = gaodeServiceResult.Address; cityCode = gaodeServiceResult.CityCode; hashParam = gaodeServiceResult.HashParam; fullAddress = string.Format("{0}|{1}", "_Gaode", gaodeServiceResult.Address); } else { _logger.LogInformation($"维智服务和高德服务解析都不能解析GPS逆地址定位数据"); return; } } #endregion #region 保存历史轨迹 int radius = 50; var loc = new LocationInfo { LocationId = Guid.NewGuid().ToString("D"), Address = address,//保存实际位置地址 "", BaiduLat = latLng[2], BaiduLng = latLng[3], OLat = propertyValue.Value.Latitude, OLng = propertyValue.Value.Longitude, GLat = latLng[0], GLng = latLng[1], Course = Convert.ToInt32(propertyValue.Value.Altitude), DeviceId = device.DeviceId, DeviceStatus = radius.ToString(), IsStop = false, LastUpdate = Utils.ConvertToLocalDateTime(propertyValue.Time), UtcDate = Utils.ConvertToUtcDateTime(propertyValue.Time), LocationType = (int)LocationType.GPS, Remarks = cityCode, SerialNo = serialno, Speed = 0, Postcode = cityCode, IsRedressed = false, HashParam = hashParam, Province = province, City = city, District = district }; loc.Remarks = string.Format("Wayz_Gps|{0}", fullAddress); //如果经纬度解析出来的地址包含特定内容,则替换为指定内容 for (int i = 0; i < Backups.Addresses.Count; i++) { if (address.Contains(Backups.Addresses[i].Address) && city.Contains(Backups.Addresses[i].City)) { string index = i.ToString(); loc.Address = Backups.LonLatDict[index].Address; loc.GLat = Backups.LonLatDict[index].GaodeLat; loc.GLng = Backups.LonLatDict[index].GaodeLon; break; } } var positionStatus = await _deviceCacheMgr.GetPositionStatusCacheAsync(serialno).ConfigureAwait(false); var requestPositionData = new RequestLocationInfo { MapSource = 2, RequestLocationType = loc.LocationType, RequestData = wayzGpsRequest }; var hisResult = await _serviceLocation.AddLocationAsync(messageId, loc, positionStatus, propertyValue.Time, wayzServiceResult.CityCode, null, requestPositionData).ConfigureAwait(false); if (!hisResult.IsSuccess) { _logger.LogError($"{hisResult.Message}"); return; } #endregion #region 处理围栏 //过滤历史定位消息 if (!hisResult.IsHistoryLocation) { _serviceLocation.ProcessGeofence(loc, messageId); } else { _logger.LogInformation($"设备{serialno},收到历史定位"); } #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 Kafka 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 (propertyValue.Value.IDType == (int)IdType.Sos && !string.IsNullOrWhiteSpace(propertyValue.Value.IDNumber)) //SOS { // THOMAS Kafka //var SOSAlarm = new SoSTemplates() //{ // imei = serialno, // sosId = propertyValue.Value.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 = propertyValue.Value.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 = propertyValue.Value.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 (propertyValue.Value.IDType == (int)IdType.PayLog && !string.IsNullOrWhiteSpace(propertyValue.Value.IDNumber)) { var payId = propertyValue.Value.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 (propertyValue.Value.IDType == (int)IdType.Temperature && !string.IsNullOrWhiteSpace(propertyValue.Value.IDNumber)) //温度上报(带地址) { var tempId = propertyValue.Value.IDNumber; await _serviceHealth.HandleTemperatureAddressAsync(messageId, $"{serialno}-{tempId}", () => new HisGpsTemperature { TemperatureId = $"{serialno}-{tempId}", Serialno = serialno, Address = loc.Address, Province = province, City = city, District = district, LastUpdate = Utils.ConvertToLocalDateTime(propertyValue.Time), TempId = tempId }, a => { a.Address = loc.Address; a.Province = province; a.City = city; a.District = district; return a; }); } #endregion } } }