定位推送服务
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

347 lines
17KB

  1. using Confluent.Kafka;
  2. using Microsoft.Extensions.Options;
  3. using Newtonsoft.Json;
  4. using TelpoPush.Position.Worker.Common;
  5. using TelpoPush.Position.Worker.Models.Config;
  6. using TelpoPush.Position.Worker.Models.Enum;
  7. using TelpoPush.Position.Worker.Models.MqTemplates;
  8. using TelpoPush.Position.Worker.Models.PushTemplates;
  9. using TelpoPush.Position.Worker.Service.Cache;
  10. using TelpoPush.Position.Worker.Service.Mq;
  11. namespace TelpoPush.Position.Worker.Handlers
  12. {
  13. public class PositionProcess
  14. {
  15. private readonly static object _syncLocker = new object();
  16. private readonly IHostEnvironment _env;
  17. private readonly ILogger<PositionProcess> _logger;
  18. private readonly HttpHelperAsync _httpHelper;
  19. private readonly RedisUtil _redis;
  20. private readonly MqProcessMessage _serviceMqProcess;
  21. private readonly PositionConfig _positionConfig;
  22. public PositionProcess(
  23. IHostEnvironment env,
  24. ILogger<PositionProcess> logger,
  25. HttpHelperAsync httpHelper,
  26. RedisUtil redis,
  27. MqProcessMessage serviceMqProcess,
  28. IOptions<PositionConfig> positionConfig
  29. )
  30. {
  31. _env = env;
  32. _logger = logger;
  33. _httpHelper = httpHelper;
  34. _redis = redis;
  35. _positionConfig = positionConfig.Value;
  36. _serviceMqProcess = serviceMqProcess;
  37. }
  38. public async Task SendPosition(string? message, string topic, Headers headers)
  39. {
  40. #region 数据初始验证
  41. bool isHandle = true;
  42. BaseModel model = null;
  43. string imei = "";
  44. if (!string.IsNullOrEmpty(message))
  45. {
  46. model = JsonConvert.DeserializeObject<BaseModel>(message);
  47. if (model != null)
  48. {
  49. var Jo = JsonConvert.DeserializeObject<Dictionary<string, object>>(model.data.ToString());
  50. if (Jo.ContainsKey("imei"))
  51. imei = Jo["imei"].ToString();
  52. if (Jo.ContainsKey("Imei"))
  53. imei = Jo["Imei"].ToString();
  54. else if (Jo.ContainsKey("nickname"))
  55. imei = Jo["nickname"].ToString();
  56. if (string.IsNullOrEmpty(imei))
  57. {
  58. _logger.LogInformation($"[数据信息不完整] imei信息不存在:{message}");
  59. isHandle = false;
  60. }
  61. else
  62. await _redis.GetGpsDevice(imei);
  63. }
  64. else
  65. {
  66. _logger.LogInformation($"[数据信息不完整] 数据解析异常:{message}");
  67. isHandle = false;
  68. }
  69. }
  70. else
  71. {
  72. _logger.LogInformation($"[数据信息不完整] message数据异常:{message}");
  73. isHandle = false;
  74. }
  75. #endregion
  76. if (isHandle)
  77. {
  78. lock (_syncLocker)
  79. {
  80. //Headers 解析
  81. HeadersDto headersDto = new HeadersDto();
  82. try
  83. {
  84. foreach (var item in headers)
  85. {
  86. if (item.Key == KafkaHeader.DataType)
  87. headersDto.DataType = BitConverter.ToInt32(item.GetValueBytes(), 0);
  88. else if (item.Key == KafkaHeader.AlarmType)
  89. headersDto.AlarmType = BitConverter.ToInt32(item.GetValueBytes(), 0);
  90. else if (item.Key == KafkaHeader.OperType)
  91. headersDto.OperType = BitConverter.ToInt32(item.GetValueBytes(), 0);
  92. }
  93. }
  94. catch (Exception ex)
  95. {
  96. _logger.LogError($"当前工作线程Headers异常,{ex.Message}|{ex.Source}|{ex.StackTrace}");
  97. }
  98. try
  99. {
  100. #region 注释
  101. //string dataType = headersDto.DataType != null ? "_" + headersDto.DataType : "";
  102. //string alarmType = headersDto.AlarmType != null ? "_" + headersDto.AlarmType : "";
  103. //string operType = headersDto.OperType != null ? "_" + headersDto.OperType : "";
  104. //string key = dataType + alarmType + operType;
  105. //var dataStatus = _redis.IsDateStatus(model, imei, key).Result;
  106. //过滤
  107. //if (headersDto.DataType == (int)MqDataType.TemperatureInfo
  108. // || headersDto.DataType == (int)MqDataType.Temperature1Info
  109. // || headersDto.DataType == (int)MqDataType.BindDevice
  110. // || headersDto.DataType == (int)MqDataType.PositionInfo
  111. // || headersDto.DataType == (int)MqDataType.HeartRateInfo
  112. // || headersDto.DataType == (int)MqDataType.HeartRate1Info
  113. // || headersDto.DataType == (int)MqDataType.Spo2Info
  114. // || headersDto.DataType == (int)MqDataType.Spo21Info
  115. // || headersDto.DataType == (int)MqDataType.BloodPressInfo
  116. // || headersDto.DataType == (int)MqDataType.BloodPress1Info
  117. // || headersDto.DataType == (int)MqDataType.SportResult
  118. // || headersDto.DataType == (int)MqDataType.BloodSugar
  119. // )
  120. // dataStatus.isPush = true;
  121. //dataStatus.isPush = true;
  122. //if (dataStatus.isPush)
  123. //{
  124. //switch (topic)
  125. //{
  126. // case "topic.push.third":
  127. // switch (headersDto.DataType)
  128. // {
  129. // case (int)MqDataType.AlarmInfo: //报警消息
  130. // break;
  131. // case (int)MqDataType.TemperatureInfo: //体温消息
  132. // break;
  133. // case (int)MqDataType.PositionInfo: //定位消息
  134. // // DataServicePusPosition(model, imei);
  135. // break;
  136. // case (int)MqDataType.StepInfo: //步数消息
  137. // break;
  138. // case (int)MqDataType.BatteryLevelInfo: //电量消息
  139. // break;
  140. // case (int)MqDataType.DeviceCallLog: //设备通话记录
  141. // break;
  142. // case (int)MqDataType.DeviceSmsLog: //设备短信记录
  143. // break;
  144. // case (int)MqDataType.DeviceConfigInfo: //设备配置信息
  145. // break;
  146. // case (int)MqDataType.Status: //设备状态(offline,online)
  147. // break;
  148. // case (int)MqDataType.Active: //设备激活状态
  149. // break;
  150. // case (int)MqDataType.reply: //指令回调
  151. // break;
  152. // case (int)MqDataType.Weather: //天气查询
  153. // break;
  154. // case (int)MqDataType.ReadMsg: //短消息阅读
  155. // break;
  156. // case (int)MqDataType.StudyAINotifyStatusUpload: //学习能力状态
  157. // break;
  158. // case (int)MqDataType.HeartRateInfo: //心率
  159. // break;
  160. // case (int)MqDataType.HeartRate1Info: //周期性心率
  161. // break;
  162. // case (int)MqDataType.Spo2Info: //血氧
  163. // break;
  164. // case (int)MqDataType.Spo21Info: //周期性血氧
  165. // break;
  166. // case (int)MqDataType.Temperature1Info: //周期性报体温数据
  167. // break;
  168. // case (int)MqDataType.DrownReportInfo: //防溺水告警
  169. // break;
  170. // case (int)MqDataType.WearStatusInfo: //手表未佩戴告警
  171. // break;
  172. // case (int)MqDataType.BloodPressInfo: //血压
  173. // break;
  174. // case (int)MqDataType.BloodPress1Info: //周期性血压
  175. // break;
  176. // case (int)MqDataType.PsychInfo: //心理监测
  177. // break;
  178. // case (int)MqDataType.AiCallResult: //AI呼叫结果回调
  179. // case (int)MqDataType.CrossBorder: //越界上报(围栏进出告警)
  180. // break;
  181. // case (int)MqDataType.SportResult: //运动数据上报
  182. // break;
  183. // case (int)MqDataType.BindDevice: //绑定业务
  184. // break;
  185. // case (int)MqDataType.BloodSugar: //血糖业务
  186. // break;
  187. // default:
  188. // break;
  189. // }
  190. // break;
  191. // default:
  192. // break;
  193. //}
  194. //}
  195. //else
  196. // _logger.LogInformation($"数据未处理(历史数据):{JsonConvert.SerializeObject(dataStatus)}");
  197. #endregion
  198. switch (topic)
  199. {
  200. case "topic.push.position":
  201. switch (headersDto.DataType)
  202. {
  203. case (int)MqDataType.PositionInfo: //定位消息
  204. DataServicePusPosition(model, imei);
  205. break;
  206. default:
  207. break;
  208. }
  209. break;
  210. default:
  211. break;
  212. }
  213. }
  214. catch (Exception ex)
  215. {
  216. _logger.LogError($"当前工作线程异常: {ex.Message}|{ex.Source}|{ex.StackTrace}");
  217. }
  218. }
  219. }
  220. }
  221. //位置
  222. public async Task DataServicePusPosition(BaseModel model, string imei)
  223. {
  224. var device = await _redis.GetGpsDevice(imei);
  225. if (device != null)
  226. {
  227. await _redis.SetPersonInfoHash(imei); //更行设备用户详情缓存
  228. var position = JsonConvert.DeserializeObject<MqPositionTemplate>(model.data.ToString());
  229. if ((int)position.locationType != 2) // 限制条件:locationType=2 LBS定位不推送
  230. {
  231. Dictionary<string, int> dicHeader = new Dictionary<string, int>();
  232. dicHeader.Add(MqHeader.DataType, (int)MqDataType.PositionInfo);
  233. #region 定位-围栏推送服务
  234. var fenceObj = new
  235. {
  236. messageId = model.messageId,
  237. topic = "topic.push.position",
  238. time = model.time,
  239. data = new
  240. {
  241. DeviceId = device.deviceId,
  242. imei = position.imei,
  243. wifiInfo = position.wifiMacs,
  244. address = position.address,
  245. baiduLatitude = position.baiduLatitude,
  246. baiduLongitude = position.baiduLongitude,
  247. gaodeLatitude = position.gaodeLatitude,
  248. gaodeLongitude = position.gaodeLongitude,
  249. originalLatitude = position.originalLatitude,
  250. originalLongitude = position.originalLongitude,
  251. locationType = position.locationType,
  252. LastUpdate = model.time,
  253. UtcDate = DateTime.Parse(model.time).AddHours(-8).ToString("yyyy-MM-dd HH:mm:ss"),
  254. Radius = position.radius,
  255. }
  256. };
  257. await _serviceMqProcess.ProcessFenceServer(imei, fenceObj, dicHeader, "定位-围栏");
  258. #endregion
  259. #region 定位-JAVA数据推送服务
  260. var settingInfos = await _redis.GetManufactorPushSettingHash(imei, _positionConfig.RzlManufactorId, (int)MqDataType.PositionInfo);
  261. settingInfos = null;
  262. if (settingInfos != null)
  263. {
  264. Dictionary<string, object> dic = new Dictionary<string, object>();
  265. dic.Add("imei", imei);
  266. dic.Add("locationType", (int)position.locationType);
  267. dic.Add("altitude", position.radius);
  268. dic.Add("gaodeLongitude", position.gaodeLongitude);
  269. dic.Add("gaodeLatitude", position.gaodeLatitude);
  270. dic.Add("originalLongitude", position.originalLongitude);
  271. dic.Add("originalLatitude", position.originalLatitude);
  272. dic.Add("baiduLongitude", position.baiduLongitude);
  273. dic.Add("baiduLatitude", position.baiduLatitude);
  274. dic.Add("address", position.address);
  275. if (!string.IsNullOrEmpty(position.wifiMacs))
  276. {
  277. position.wifiMacs = position.wifiMacs.Replace(",|", "|").Trim(',');
  278. dic.Add("wifiMacs", position.wifiMacs);
  279. }
  280. dic.Add("dataTime", model.time);
  281. MultipartFormDataContent mfdc = Utils.GetMultipartFormDataContent(dic, _positionConfig.RzlManufactorId, ref dic);
  282. var result = await _httpHelper.PostFormAsync(settingInfos.pushUrl, mfdc);
  283. _logger.LogInformation($"[定位-RZL数据-替换JAVA推送服务<{imei}>] url:{settingInfos.pushUrl},参数:{JsonConvert.SerializeObject(dic)},结果:{result}");
  284. }
  285. else
  286. {
  287. if (!string.IsNullOrEmpty(position.wifiMacs))
  288. position.wifiMacs = position.wifiMacs.Replace(",|", "|").Trim(',');
  289. PushPositionTemplate positionInfo = new PushPositionTemplate //上报存储位置信息
  290. {
  291. MessageId = model.messageId,
  292. Imei = imei,
  293. Altitude = position.radius,
  294. BaiduLatitude = position.baiduLatitude,
  295. BaiduLongitude = position.baiduLongitude,
  296. GaodeLatitude = position.gaodeLatitude,
  297. GaodeLongitude = position.gaodeLongitude,
  298. LocationType = (int)position.locationType,
  299. OriginalLatitude = position.originalLatitude,
  300. OriginalLongitude = position.originalLongitude,
  301. Address = position.address,
  302. wifiMacs = position.wifiMacs,
  303. Time = model.time
  304. };
  305. await _serviceMqProcess.ProcessDataPushServer(imei, positionInfo, dicHeader, "定位");
  306. }
  307. #endregion
  308. }
  309. }
  310. }
  311. }
  312. }