|
- package com.telpo.beidouast.service.impl;
-
- import com.alibaba.fastjson.JSONObject;
- import com.google.common.base.Joiner;
- import com.telpo.dipperposition.common.*;
- import com.telpo.beidouast.entity.mongo.IPProvinceEntity;
- import com.telpo.beidouast.mapper.IPProvinceMapper;
- import com.telpo.beidouast.service.IDipperAstPosAsyncTaskService;
- import com.telpo.beidouast.service.IPProvinceService;
- import com.telpo.beidouast.vo.IPProvinceVo;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.ObjectUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
-
- import java.io.UnsupportedEncodingException;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.List;
-
- /**
- * @program: DipperAstPosAsyncTaskServiceImpl
- * @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
- * * 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
- * * 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
- * * 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
- * * 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
- * @author: king
- * @create: 2021-01-10 14:01
- */
- @Service
- @Slf4j
- public class DipperAstPosAsyncTaskServiceImpl implements IDipperAstPosAsyncTaskService {
-
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private OkHttpUtil okHttpUtil;
- @Autowired
- private IPProvinceService iPProvinceService;
-
- private String centerProvince;
- private String centerProvinceFilePath;
- private String ipPositionRequestPath;
- private String ipPositionRequestKey;
- // private String getAstPos(String ipAddress) throws UnsupportedEncodingException {
- //
- // String centerAddress = getIpPositionProvince(ipAddress);
- // if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
- // log.warn("IP地址非法,无法获取辅助位置信息!");
- // // 返回武汉的定位数据
- // centerAddress = centerProvince;
- // } else {
- // // 保存到mongoDB
- // createIPProvince(ipAddress, centerAddress);
- // }
- //
- // String lonAndAlt;
- // if (redisUtil.hasKey(centerAddress)) {
- // // 获取省会城市定位信息
- // lonAndAlt= (String) redisUtil.get(centerAddress);
- // } else {
- // // 请求高德IP定位服务
- // this.getPosFromFile(centerAddress);
- // lonAndAlt = (String) redisUtil.get(centerAddress);
- // }
- //
- // return lonAndAlt;
- // }
-
- // 从CSV文件读取省会城市中心点位置信息
- private void getPosFromFile(String centerAddress) {
- // 不存在说明token是已过期了
- String centerProvinceName = "";
- String centerProvinceLonAndAlt = "";
- List<String> centerAddressSets = CSVUtil.readCSV(this.centerProvinceFilePath);
- for (String centerAddressSet:centerAddressSets) {
- String[] centerAddressSetArray = centerAddressSet.split(",");
- if (centerAddressSetArray.length < 3) {
- log.warn("CSV数据格式错误");
- } else {
- centerProvinceName = centerAddressSetArray[3];
- centerProvinceLonAndAlt = centerAddressSetArray[1]+","+centerAddressSetArray[2];
- redisUtil.set(centerProvinceName, centerProvinceLonAndAlt, 0);
- }
- }
- }
-
- // 根据IP获取省会信息
- private String getIpPositionProvince(String ipAddress) {
-
- // 关于IP与省份的关系保存到缓存中
- // 使用时,先在缓存中获取匹配信息
- // 用mongodb实现
- IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress);
- if (ipProvinceEntity == null) {
- // 匹配不到,再请求高德IP定位服务。
- JSONObject userObj = new JSONObject();
- userObj.put("ip", ipAddress);
- userObj.put("key", ipPositionRequestKey);
-
- JSONObject json = okHttpUtil.postRequestWithJson(ipPositionRequestPath, null, userObj);
- if (ObjectUtils.isNotEmpty(json)) {
- String province = (String) json.get("province");
- if (ObjectUtils.isEmpty(province)) {
- log.debug("json is :" + json.toString());
- return null;
- }
- return province;
- } else {
- // 意外错误
- log.debug("ip address is null");
- return null;
- }
- } else {
- return ipProvinceEntity.getProvince();
- }
- }
-
- // 将IP对应的省会保存到mongoDB
- @Async("asyncServiceExecutor")
- public void createIPProvince(String ipAddress, String province) {
- log.debug("异步创建推送失败任务记录!");
- try {
- IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress);
- if (ipProvinceEntity == null) {
- //DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- ipProvinceEntity.setIp(ipAddress);
- ipProvinceEntity.setProvince(province);
- iPProvinceService.saveIPProvince(ipProvinceEntity);
- // } else {
- //
- // ipProvinceEntity.setProvince(province);
- // iPProvinceService.updateIPProvince(ipProvinceEntity, ipProvinceEntity);
- }
- } catch (Exception e) {
- log.error("创建推送失败记录异常:", e);
- }
- }
-
- /*
- * 获取定位辅助信息
- * @param ipAddress
- */
- @Override
- @Async("asyncServiceExecutor")
- public String pushAstPos(String ipAddress,
- String centerProvinceFilePath,
- String centerProvince,
- String ipPositionRequestPath,
- String ipPositionRequestKey) throws UnsupportedEncodingException {
- this.ipPositionRequestKey = ipPositionRequestKey;
- this.ipPositionRequestPath = ipPositionRequestPath;
- this.centerProvince = centerProvince;
- this.centerProvinceFilePath = centerProvinceFilePath;
- // (1) 获取省会城市信息
- String centerAddress = getIpPositionProvince(ipAddress);
- if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
- log.warn("IP地址非法,无法获取辅助位置信息!");
- // 返回武汉的定位数据
- centerAddress = this.centerProvince;
- } else {
- // 保存到mongoDB
- createIPProvince(ipAddress, centerAddress);
- }
-
- String lonAndAlt;
- if (redisUtil.hasKey(centerAddress)) {
- // 获取省会城市定位信息
- lonAndAlt= (String) redisUtil.get(centerAddress);
- } else {
- // 请求高德IP定位服务
- this.getPosFromFile(centerAddress);
- lonAndAlt = (String) redisUtil.get(centerAddress);
- }
-
- // (2) 处理返回结果
- if (lonAndAlt == null) {
- // null处理
- log.error("系统错误,请联系系统管理员。");
- return null;
- //return;
- }
-
- // push to GNNS Server
- String pushResult = getCmdOfPos(lonAndAlt);
- return pushResult;
- }
-
- // 组装命令发送给设备
- private String getCmdOfPos(String astPos) {
-
- // 创建Socket客户端实例;
- // SocketClient client = new SocketClient(astServer, posAstPort, astTimeout);
-
- // 时间和位置不是从服务器获取,而是本地生成
- String[] astPosArray = astPos.split(",");
- String lan = astPosArray[0].trim();
- String alt = astPosArray[1].trim();
- double lanValue = Double.parseDouble(lan) * 10000000;
- long lanLongValue = Double.doubleToLongBits(lanValue);
- if (lanLongValue < 0) {
- lanLongValue = lanLongValue + 4294967295L + 1;
- }
- double altValue = Double.parseDouble(alt) * 10000000;
- long altLongValue = Double.doubleToLongBits(altValue);
- if (altLongValue < 0) {
- altLongValue = altLongValue + 4294967295L + 1;
- }
- // 数值换算举例(以经度举例。纬度、高度、位置精度换算方法一致):
- // (1)经度数值为 113.431,则换算方法如下:
- // 113.431/比例因子 = 1134310000(十进制)
- // 439C3270(十六进制)
- // 经度数据填入 70 32 9C 43(小端模式)
- // (2)经度数值为-113.431,则换算方法如下:
- // 113.431/比例因子 = 1134310000(十进制)
- // 439C3270(十六进制)
- // FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
- // 经度数据填入 90 CD 63 BC(小端模式)
- // 指令(十六进制)
- // 举例: 23 3E 04 01 10 00 70 32 9C 43 D0 B2 CE 0D 70 17 00 00 40 0D 03 00 CA 95
- // 其中
- // 23 3E 为同步头
- // 04 01 为识别码
- // 10 00 表示长度为 16
- // 70 32 9C 43 表示注入的辅助经度为 113.431 度
- // D0 B2 CE 0D 表示注入的辅助纬度为 23.165 度
- // 00 2F 为校验和
-
- // astTimeCmd 组装
- String astTimeCmd = "233E0401";
- astTimeCmd += "1000";
- astTimeCmd += HexConvert.encodeHEX(lanLongValue);
- astTimeCmd += HexConvert.encodeHEX(altLongValue);
-
- String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd);
-
- //String sendResult = client.sendCmd(hexIn, ackAckCheckRef);
- //client.closeConnection();
-
- //return sendResult;
- return hexIn;
- }
- }
|