北斗定位
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

254 行
10KB

  1. package com.telpo.dipperposition.service.impl;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.google.common.base.Joiner;
  4. import com.telpo.dipperposition.common.*;
  5. import com.telpo.dipperposition.entity.mongo.IPProvinceEntity;
  6. import com.telpo.dipperposition.mapper.IPProvinceMapper;
  7. import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService;
  8. import com.telpo.dipperposition.service.IPProvinceService;
  9. import com.telpo.dipperposition.vo.IPProvinceVo;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.apache.commons.lang3.ObjectUtils;
  12. import org.apache.commons.lang3.StringUtils;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.beans.factory.annotation.Value;
  15. import org.springframework.scheduling.annotation.Async;
  16. import org.springframework.stereotype.Service;
  17. import java.io.UnsupportedEncodingException;
  18. import java.time.LocalDateTime;
  19. import java.time.format.DateTimeFormatter;
  20. import java.util.List;
  21. /**
  22. * @program: DipperAstPosAsyncTaskServiceImpl
  23. * @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
  24. * * 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
  25. * * 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
  26. * * 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
  27. * * 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
  28. * @author: king
  29. * @create: 2021-01-10 14:01
  30. */
  31. @Service
  32. @Slf4j
  33. public class DipperAstPosAsyncTaskServiceImpl implements IDipperAstPosAsyncTaskService {
  34. @Autowired
  35. private RedisUtil redisUtil;
  36. @Autowired
  37. private OkHttpUtil okHttpUtil;
  38. @Autowired
  39. private IPProvinceService iPProvinceService;
  40. private String centerProvince;
  41. private String centerProvinceFilePath;
  42. private String ipPositionRequestPath;
  43. private String ipPositionRequestKey;
  44. // private String getAstPos(String ipAddress) throws UnsupportedEncodingException {
  45. //
  46. // String centerAddress = getIpPositionProvince(ipAddress);
  47. // if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
  48. // log.warn("IP地址非法,无法获取辅助位置信息!");
  49. // // 返回武汉的定位数据
  50. // centerAddress = centerProvince;
  51. // } else {
  52. // // 保存到mongoDB
  53. // createIPProvince(ipAddress, centerAddress);
  54. // }
  55. //
  56. // String lonAndAlt;
  57. // if (redisUtil.hasKey(centerAddress)) {
  58. // // 获取省会城市定位信息
  59. // lonAndAlt= (String) redisUtil.get(centerAddress);
  60. // } else {
  61. // // 请求高德IP定位服务
  62. // this.getPosFromFile(centerAddress);
  63. // lonAndAlt = (String) redisUtil.get(centerAddress);
  64. // }
  65. //
  66. // return lonAndAlt;
  67. // }
  68. // 从CSV文件读取省会城市中心点位置信息
  69. private void getPosFromFile(String centerAddress) {
  70. // 不存在说明token是已过期了
  71. String centerProvinceName = "";
  72. String centerProvinceLonAndAlt = "";
  73. List<String> centerAddressSets = CSVUtil.readCSV(this.centerProvinceFilePath);
  74. for (String centerAddressSet:centerAddressSets) {
  75. String[] centerAddressSetArray = centerAddressSet.split(",");
  76. if (centerAddressSetArray.length < 3) {
  77. log.warn("CSV数据格式错误");
  78. } else {
  79. centerProvinceName = centerAddressSetArray[3];
  80. centerProvinceLonAndAlt = centerAddressSetArray[1]+","+centerAddressSetArray[2];
  81. redisUtil.set(centerProvinceName, centerProvinceLonAndAlt, 0);
  82. }
  83. }
  84. }
  85. // 根据IP获取省会信息
  86. private String getIpPositionProvince(String ipAddress) {
  87. // 关于IP与省份的关系保存到缓存中
  88. // 使用时,先在缓存中获取匹配信息
  89. // 用mongodb实现
  90. if(iPProvinceService == null) {
  91. iPProvinceService = new IPProvinceServiceImpl();
  92. }
  93. IPProvinceEntity ipProvinceEntity = iPProvinceService.getIpProvince(ipAddress);
  94. if (ipProvinceEntity == null) {
  95. // 匹配不到,再请求高德IP定位服务。
  96. JSONObject userObj = new JSONObject();
  97. userObj.put("ip", ipAddress);
  98. userObj.put("key", ipPositionRequestKey);
  99. JSONObject json = okHttpUtil.postRequestWithJson(ipPositionRequestPath, null, userObj);
  100. if (ObjectUtils.isNotEmpty(json)) {
  101. String province = (String) json.get("province");
  102. if (ObjectUtils.isEmpty(province)) {
  103. log.debug("json is :" + json.toString());
  104. return null;
  105. }
  106. return province;
  107. } else {
  108. // 意外错误
  109. log.debug("ip address is null");
  110. return null;
  111. }
  112. } else {
  113. return ipProvinceEntity.getProvince();
  114. }
  115. }
  116. // 将IP对应的省会保存到mongoDB
  117. @Async("asyncServiceExecutor")
  118. public void createIPProvince(String ipAddress, String province) {
  119. log.debug("异步创建推送失败任务记录!");
  120. try {
  121. if(iPProvinceService == null) {
  122. iPProvinceService = new IPProvinceServiceImpl();
  123. }
  124. IPProvinceEntity ipProvinceEntity = iPProvinceService.getIpProvince(ipAddress);
  125. if (ipProvinceEntity == null) {
  126. //DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  127. ipProvinceEntity.setIp(ipAddress);
  128. ipProvinceEntity.setProvince(province);
  129. iPProvinceService.saveIpProvince(ipProvinceEntity);
  130. // } else {
  131. //
  132. // ipProvinceEntity.setProvince(province);
  133. // iPProvinceService.updateIPProvince(ipProvinceEntity, ipProvinceEntity);
  134. }
  135. } catch (Exception e) {
  136. log.error("创建推送失败记录异常:", e);
  137. }
  138. }
  139. /*
  140. * 获取定位辅助信息
  141. * @param ipAddress
  142. */
  143. @Override
  144. @Async("asyncServiceExecutor")
  145. public String pushAstPos(String ipAddress,
  146. String centerProvinceFilePath,
  147. String centerProvince,
  148. String ipPositionRequestPath,
  149. String ipPositionRequestKey) throws UnsupportedEncodingException {
  150. this.ipPositionRequestKey = ipPositionRequestKey;
  151. this.ipPositionRequestPath = ipPositionRequestPath;
  152. this.centerProvince = centerProvince;
  153. this.centerProvinceFilePath = centerProvinceFilePath;
  154. // (1) 获取省会城市信息
  155. String centerAddress = getIpPositionProvince(ipAddress);
  156. if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
  157. log.warn("IP地址非法,无法获取辅助位置信息!");
  158. // 返回武汉的定位数据
  159. centerAddress = this.centerProvince;
  160. } else {
  161. // 保存到mongoDB
  162. createIPProvince(ipAddress, centerAddress);
  163. }
  164. String lonAndAlt;
  165. if (redisUtil.hasKey(centerAddress)) {
  166. // 获取省会城市定位信息
  167. lonAndAlt= (String) redisUtil.get(centerAddress);
  168. } else {
  169. // 请求高德IP定位服务
  170. this.getPosFromFile(centerAddress);
  171. lonAndAlt = (String) redisUtil.get(centerAddress);
  172. }
  173. // (2) 处理返回结果
  174. if (lonAndAlt == null) {
  175. // null处理
  176. log.error("系统错误,请联系系统管理员。");
  177. return null;
  178. //return;
  179. }
  180. // push to GNNS Server
  181. String pushResult = getCmdOfPos(lonAndAlt);
  182. return pushResult;
  183. }
  184. // 组装命令发送给设备
  185. private String getCmdOfPos(String astPos) {
  186. // 创建Socket客户端实例;
  187. // SocketClient client = new SocketClient(astServer, posAstPort, astTimeout);
  188. // 时间和位置不是从服务器获取,而是本地生成
  189. String[] astPosArray = astPos.split(",");
  190. String lan = astPosArray[0].trim();
  191. String alt = astPosArray[1].trim();
  192. double lanValue = Double.parseDouble(lan) * 10000000;
  193. long lanLongValue = Double.doubleToLongBits(lanValue);
  194. if (lanLongValue < 0) {
  195. lanLongValue = lanLongValue + 4294967295L + 1;
  196. }
  197. double altValue = Double.parseDouble(alt) * 10000000;
  198. long altLongValue = Double.doubleToLongBits(altValue);
  199. if (altLongValue < 0) {
  200. altLongValue = altLongValue + 4294967295L + 1;
  201. }
  202. // 数值换算举例(以经度举例。纬度、高度、位置精度换算方法一致):
  203. // (1)经度数值为 113.431,则换算方法如下:
  204. // 113.431/比例因子 = 1134310000(十进制)
  205. //  439C3270(十六进制)
  206. //  经度数据填入 70 32 9C 43(小端模式)
  207. // (2)经度数值为-113.431,则换算方法如下:
  208. // 113.431/比例因子 = 1134310000(十进制)
  209. //  439C3270(十六进制)
  210. //  FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
  211. // 经度数据填入 90 CD 63 BC(小端模式)
  212. // 指令(十六进制)
  213. // 举例: 23 3E 04 01 10 00 70 32 9C 43 D0 B2 CE 0D 70 17 00 00 40 0D 03 00 CA 95
  214. // 其中
  215. // 23 3E 为同步头
  216. // 04 01 为识别码
  217. // 10 00 表示长度为 16
  218. // 70 32 9C 43 表示注入的辅助经度为 113.431 度
  219. // D0 B2 CE 0D 表示注入的辅助纬度为 23.165 度
  220. // 00 2F 为校验和
  221. // astTimeCmd 组装
  222. String astTimeCmd = "233E0401";
  223. astTimeCmd += "1000";
  224. astTimeCmd += HexConvert.encodeHEX(lanLongValue);
  225. astTimeCmd += HexConvert.encodeHEX(altLongValue);
  226. //String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd);
  227. String hexIn = astTimeCmd + HexConvert.makeChecksum(astTimeCmd);
  228. //return sendResult;
  229. return hexIn;
  230. }
  231. }