20260309:地图规范化
This commit is contained in:
parent
41543cc5a5
commit
2cfc9c35ea
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -1 +1,4 @@
|
|||||||
* text=auto
|
* text=auto
|
||||||
|
*.xml text eol=lf # 所有 XML 文件强制使用 LF 作为行结束符(提交和拉取都为 LF)
|
||||||
|
*.yml text eol=lf # YAML 文件同理
|
||||||
|
*.java text eol=lf # Java 文件同理
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.fastbee.common.constant;/**
|
||||||
|
* @description: 系统错误码枚举
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.fastbee.common.exception.ErrorCode;
|
||||||
|
import com.fastbee.common.utils.MessageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 系统错误码枚举
|
||||||
|
*
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
*/
|
||||||
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
|
// client error 100000
|
||||||
|
// 编码异常
|
||||||
|
ErrorCode ENCODING_EXCEPTION = new ErrorCode(100000, MessageUtils.message("encoding.exception"));
|
||||||
|
|
||||||
|
}
|
||||||
@ -371,4 +371,14 @@ public interface FastBeeConstant {
|
|||||||
String GB28181 = "GB28181";
|
String GB28181 = "GB28181";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 地图相关
|
||||||
|
interface MAP {
|
||||||
|
// 百度 BAIDU
|
||||||
|
String BAIDU_GEOCODING = "http://api.map.baidu.com/geocoding/v3/";
|
||||||
|
|
||||||
|
// 高德 GAODE
|
||||||
|
|
||||||
|
// 腾讯 TENCENT
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,20 +72,20 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendGet ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendGet SocketTimeoutException, url={},param={}", url, param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendGet IOException, url={},param={}", url, param, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
|
log.error("调用HttpsUtil.sendGet Exception, url={},param={}", url, param, e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (in != null) {
|
if (in != null) {
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
log.error("调用in.close Exception, url={},param={}", url, param, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
@ -123,13 +123,13 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost IOException, url={},param={}", url, param, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, param, e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
@ -139,7 +139,7 @@ public class HttpUtils {
|
|||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
log.error("调用in.close Exception, url={},param={}", url, param, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
@ -177,13 +177,13 @@ public class HttpUtils {
|
|||||||
conn.disconnect();
|
conn.disconnect();
|
||||||
br.close();
|
br.close();
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url={},param={}", url, param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost IOException, url={},param={}", url, param, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
|
log.error("调用HttpsUtil.sendSSLPost Exception, url={},param={}", url, param, e);
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
@ -213,13 +213,13 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost ConnectException, url={},param={}", url, json, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, json, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost IOException, url={},param={}", url, json, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + json, e);
|
log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, json, e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
@ -229,7 +229,7 @@ public class HttpUtils {
|
|||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("调用in.close Exception, url=" + url + ",param=" + json, ex);
|
log.error("调用in.close Exception, url={},param={}", url, json, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.fastbee.http.ip;/**
|
||||||
|
* @description: IP地址相关客户端调用
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.fastbee.common.constant.Constants;
|
||||||
|
import com.fastbee.common.utils.StringUtils;
|
||||||
|
import com.fastbee.common.utils.http.HttpUtils;
|
||||||
|
import com.fastbee.common.utils.ip.IpUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: IP地址相关客户端调用
|
||||||
|
*
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class IPAddressService {
|
||||||
|
|
||||||
|
// 根据IP地址获取地址信息
|
||||||
|
private static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
||||||
|
|
||||||
|
|
||||||
|
public String getAddressByIP(String ip) {
|
||||||
|
|
||||||
|
if (IpUtils.internalIp(ip)) {
|
||||||
|
return "内网IP";
|
||||||
|
}
|
||||||
|
|
||||||
|
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
|
||||||
|
if (StringUtils.isEmpty(rspStr)) {
|
||||||
|
log.info("根据IP地址获取地址失败");
|
||||||
|
return "未知地址";
|
||||||
|
}
|
||||||
|
JSONObject obj = JSONObject.parseObject(rspStr);
|
||||||
|
String addr = obj.getString("addr");
|
||||||
|
log.info("IP{}- 获取地址:{}", ip, addr);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,18 +1,24 @@
|
|||||||
package com.fastbee.http.map;
|
package com.fastbee.http.map;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.fastbee.common.constant.Constants;
|
import com.fastbee.common.constant.Constants;
|
||||||
import com.fastbee.common.exception.ServerException;
|
import com.fastbee.common.constant.ErrorCodeConstants;
|
||||||
|
import com.fastbee.common.constant.FastBeeConstant;
|
||||||
import com.fastbee.common.utils.http.HttpUtils;
|
import com.fastbee.common.utils.http.HttpUtils;
|
||||||
import com.fastbee.http.model.Coordinate;
|
import com.fastbee.http.model.Coordinate;
|
||||||
|
import com.fastbee.http.utils.CoordinateTransformUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static com.fastbee.common.exception.ServiceExceptionUtil.exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 百度地图API接口服务
|
* @description: 百度地图API接口服务
|
||||||
*
|
*
|
||||||
@ -21,17 +27,11 @@ import java.nio.charset.StandardCharsets;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service("baiduLocationService")
|
@Service("baiduLocationService")
|
||||||
public class BaiduLocationService implements LocationService {
|
public class BaiduILocationService implements ILocationService {
|
||||||
|
|
||||||
@Value("${other.baidu_ak}")
|
@Value("${other.baidu_ak}")
|
||||||
private String baiduAK;
|
private String baiduAK;
|
||||||
|
|
||||||
interface API {
|
|
||||||
String BAIDU_URL = "http://api.map.baidu.com";
|
|
||||||
|
|
||||||
String geocoding = "/geocoding/v3/";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据结构化地址获取地理编码(即经纬度)
|
* 根据结构化地址获取地理编码(即经纬度)
|
||||||
* 地理编码服务提供将结构化地址数据(如:北京市海淀区上地十街十号)转换为对应坐标点(经纬度)功能。
|
* 地理编码服务提供将结构化地址数据(如:北京市海淀区上地十街十号)转换为对应坐标点(经纬度)功能。
|
||||||
@ -41,15 +41,16 @@ public class BaiduLocationService implements LocationService {
|
|||||||
@Override
|
@Override
|
||||||
public Coordinate getCoordinateByAddress(String address) {
|
public Coordinate getCoordinateByAddress(String address) {
|
||||||
|
|
||||||
String baseUri = API.BAIDU_URL + API.geocoding;
|
log.info("结构化地址:{}", address);
|
||||||
|
String baseUrl = FastBeeConstant.MAP.BAIDU_GEOCODING;
|
||||||
address = StringUtils.isEmpty(address) ? "湖南省长沙市岳麓区" : address;
|
address = StringUtils.isEmpty(address) ? "湖南省长沙市岳麓区" : address;
|
||||||
String encodedAddress;
|
String encodedAddress;
|
||||||
try {
|
try {
|
||||||
encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
|
encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new ServerException(100001, "地理编码异常");
|
throw exception(ErrorCodeConstants.ENCODING_EXCEPTION);
|
||||||
}
|
}
|
||||||
String baiduResponse = HttpUtils.sendGet(baseUri, "address=" + encodedAddress + "&output=json&ak=" + baiduAK, Constants.UTF8);
|
String baiduResponse = HttpUtils.sendGet(baseUrl, "address=" + encodedAddress + "&output=json&ak=" + baiduAK, Constants.UTF8);
|
||||||
if (!StringUtils.isEmpty(baiduResponse)) {
|
if (!StringUtils.isEmpty(baiduResponse)) {
|
||||||
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
|
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
|
||||||
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
|
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
|
||||||
@ -59,4 +60,14 @@ public class BaiduLocationService implements LocationService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Coordinate convertToWgs84(Coordinate baiduCoordinate) {
|
||||||
|
|
||||||
|
// 将百度坐标 转化为 世界坐标
|
||||||
|
double[] doubles = CoordinateTransformUtils.bd09ToWgs84(baiduCoordinate.getLongitude().doubleValue(),
|
||||||
|
baiduCoordinate.getLatitude().doubleValue());
|
||||||
|
|
||||||
|
return new Coordinate(BigDecimal.valueOf(doubles[0]), BigDecimal.valueOf(doubles[1]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.fastbee.http.map;
|
||||||
|
|
||||||
|
import com.fastbee.http.model.Coordinate;
|
||||||
|
import com.fastbee.http.utils.CoordinateTransformUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 高德地图API实现类
|
||||||
|
*
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
*/
|
||||||
|
@Service("gaodeLocationService")
|
||||||
|
public class GaodeLocationService implements ILocationService {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Coordinate getCoordinateByAddress(String address) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Coordinate convertToWgs84(Coordinate marsCoordinate) {
|
||||||
|
// 将高德(火星)坐标 转化为 世界坐标
|
||||||
|
double[] doubles = CoordinateTransformUtils.gcj02ToWgs84(
|
||||||
|
marsCoordinate.getLongitude().doubleValue(),
|
||||||
|
marsCoordinate.getLatitude().doubleValue()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Coordinate(BigDecimal.valueOf(doubles[0]), BigDecimal.valueOf(doubles[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@ import com.fastbee.http.model.Coordinate;
|
|||||||
* @author Sumuxi
|
* @author Sumuxi
|
||||||
* @date 2026/3/7
|
* @date 2026/3/7
|
||||||
*/
|
*/
|
||||||
public interface LocationService {
|
public interface ILocationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据地址获取经纬度坐标
|
* 根据地址获取经纬度坐标
|
||||||
@ -23,4 +23,12 @@ public interface LocationService {
|
|||||||
* @return 详细地址信息
|
* @return 详细地址信息
|
||||||
*/
|
*/
|
||||||
//AddressInfo getAddressByCoordinate(Coordinate coordinate);
|
//AddressInfo getAddressByCoordinate(Coordinate coordinate);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将不同坐标转化为世界坐标
|
||||||
|
* @param coordinate 不同(BD09,GCJ02,WGS84)实现类坐标
|
||||||
|
* @return 世界坐标系
|
||||||
|
*/
|
||||||
|
Coordinate convertToWgs84(Coordinate coordinate);
|
||||||
}
|
}
|
||||||
@ -15,10 +15,10 @@ import javax.annotation.Resource;
|
|||||||
public class LocationServiceFactory {
|
public class LocationServiceFactory {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private LocationService baiduLocationService;
|
private ILocationService baiduLocationService;
|
||||||
|
|
||||||
// @Resource
|
@Resource
|
||||||
// private LocationService gaodeLocationService;
|
private ILocationService gaodeLocationService;
|
||||||
|
|
||||||
// 从配置文件读取当前使用的服务商
|
// 从配置文件读取当前使用的服务商
|
||||||
@Value("${map.provider:baidu}")
|
@Value("${map.provider:baidu}")
|
||||||
@ -28,7 +28,7 @@ public class LocationServiceFactory {
|
|||||||
* 获取当前配置的 LocationService 实例
|
* 获取当前配置的 LocationService 实例
|
||||||
* @return 具体服务实现
|
* @return 具体服务实现
|
||||||
*/
|
*/
|
||||||
public LocationService getLocationService() {
|
public ILocationService getLocationService() {
|
||||||
// if ("gaode".equalsIgnoreCase(provider)) {
|
// if ("gaode".equalsIgnoreCase(provider)) {
|
||||||
// return gaodeLocationService;
|
// return gaodeLocationService;
|
||||||
// } else if ("tencent".equalsIgnoreCase(provider)) {
|
// } else if ("tencent".equalsIgnoreCase(provider)) {
|
||||||
|
|||||||
@ -0,0 +1,222 @@
|
|||||||
|
package com.fastbee.http.utils;
|
||||||
|
/**
|
||||||
|
* 坐标系转换工具类(WGS-84 ⇄ GCJ-02 ⇄ BD-09)
|
||||||
|
* 基于 double 类型实现,适用于 LBS、地图开发等场景
|
||||||
|
* 精度:约 1~10 米级
|
||||||
|
* GPS 是 WGS-84
|
||||||
|
* 国内地图要 GCJ-02(火星坐标系)
|
||||||
|
* 百度再加一层 BD-09
|
||||||
|
* OSM 坚持用 WGS-84
|
||||||
|
* @author Sumuxi
|
||||||
|
* @date 2026/3/8
|
||||||
|
**/
|
||||||
|
public class CoordinateTransformUtils {
|
||||||
|
|
||||||
|
// ====================== 常量定义 ======================
|
||||||
|
|
||||||
|
private static final double PI = Math.PI;
|
||||||
|
private static final double A = 6378245.0; // 长半轴 (km)
|
||||||
|
private static final double EE = 0.00669342162296594323; // 扁率平方
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否在国内(粗略判断,用于避免国外偏移)
|
||||||
|
* @param lng 经度
|
||||||
|
* @param lat 纬度
|
||||||
|
* @return true:国内;false:国外
|
||||||
|
*/
|
||||||
|
private static boolean inOfChina(double lng, double lat) {
|
||||||
|
return (lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弧度转角度
|
||||||
|
private static double radToDeg(double rad) {
|
||||||
|
return rad * 180.0 / PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角度转弧度
|
||||||
|
private static double degToRad(double deg) {
|
||||||
|
return deg * PI / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 求两点间距离(简化球面距离,单位:米)
|
||||||
|
private static double distance(double lng1, double lat1, double lng2, double lat2) {
|
||||||
|
double dLat = degToRad(lat2 - lat1);
|
||||||
|
double dLng = degToRad(lng2 - lng1);
|
||||||
|
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos(degToRad(lat1)) * Math.cos(degToRad(lat2)) *
|
||||||
|
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
||||||
|
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
return A * c; // A 是地球半径(米)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== WGS-84 → GCJ-02 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WGS-84 转 GCJ-02(火星坐标系)
|
||||||
|
*/
|
||||||
|
public static double[] wgs84ToGcj02(double wgsLng, double wgsLat) {
|
||||||
|
if (!inOfChina(wgsLng, wgsLat)) {
|
||||||
|
return new double[]{wgsLng, wgsLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
double dLat = transformLat(wgsLng - 105.0, wgsLat - 35.0);
|
||||||
|
double dLng = transformLng(wgsLng - 105.0, wgsLat - 35.0);
|
||||||
|
|
||||||
|
double radLat = degToRad(wgsLat);
|
||||||
|
double magic = Math.sin(radLat);
|
||||||
|
magic = 1 - EE * magic * magic;
|
||||||
|
double sqrtMagic = Math.sqrt(magic);
|
||||||
|
|
||||||
|
dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
|
||||||
|
dLng = (dLng * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
|
||||||
|
|
||||||
|
return new double[]{wgsLng + dLng, wgsLat + dLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== GCJ-02 → WGS-84 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GCJ-02 转 WGS-84(近似还原,存在微小误差)
|
||||||
|
*/
|
||||||
|
public static double[] gcj02ToWgs84(double gcjLng, double gcjLat) {
|
||||||
|
if (!inOfChina(gcjLng, gcjLat)) {
|
||||||
|
return new double[]{gcjLng, gcjLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] gps = wgs84ToGcj02(gcjLng, gcjLat);
|
||||||
|
double dLng = gps[0] - gcjLng;
|
||||||
|
double dLat = gps[1] - gcjLat;
|
||||||
|
return new double[]{gcjLng - dLng, gcjLat - dLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== GCJ-02 → BD-09 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GCJ-02 转 BD-09(百度坐标系)
|
||||||
|
*/
|
||||||
|
public static double[] gcj02ToBd09(double gcjLng, double gcjLat) {
|
||||||
|
double z = Math.sqrt(gcjLng * gcjLng + gcjLat * gcjLat) + 0.00002 * Math.sin(gcjLat * PI);
|
||||||
|
double theta = Math.atan2(gcjLat, gcjLng) + 0.000003 * Math.cos(gcjLng * PI);
|
||||||
|
double bdLng = z * Math.cos(theta) + 0.0065;
|
||||||
|
double bdLat = z * Math.sin(theta) + 0.006;
|
||||||
|
return new double[]{bdLng, bdLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== BD-09 → GCJ-02 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BD-09 转 GCJ-02
|
||||||
|
*/
|
||||||
|
public static double[] bd09ToGcj02(double bdLng, double bdLat) {
|
||||||
|
double x = bdLng - 0.0065;
|
||||||
|
double y = bdLat - 0.006;
|
||||||
|
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
|
||||||
|
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
|
||||||
|
double gcjLng = z * Math.cos(theta);
|
||||||
|
double gcjLat = z * Math.sin(theta);
|
||||||
|
return new double[]{gcjLng, gcjLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== WGS-84 ⇄ BD-09 快捷转换 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WGS-84 转 BD-09(先转 GCJ-02,再转 BD-09)
|
||||||
|
*/
|
||||||
|
public static double[] wgs84ToBd09(double wgsLng, double wgsLat) {
|
||||||
|
double[] gcj = wgs84ToGcj02(wgsLng, wgsLat);
|
||||||
|
return gcj02ToBd09(gcj[0], gcj[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BD-09 转 WGS-84(先转 GCJ-02,再转 WGS-84)
|
||||||
|
*/
|
||||||
|
public static double[] bd09ToWgs84(double bdLng, double bdLat) {
|
||||||
|
double[] gcj = bd09ToGcj02(bdLng, bdLat);
|
||||||
|
return gcj02ToWgs84(gcj[0], gcj[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 内部辅助函数 ====================
|
||||||
|
|
||||||
|
private static double transformLat(double lng, double lat) {
|
||||||
|
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
||||||
|
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double transformLng(double lng, double lat) {
|
||||||
|
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
||||||
|
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 工具方法 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化坐标输出(保留6位小数)
|
||||||
|
*/
|
||||||
|
public static String formatCoord(double lng, double lat) {
|
||||||
|
return String.format("%.6f, %.6f", lng, lat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 四舍五入到指定位数
|
||||||
|
*/
|
||||||
|
public static double round(double value, int scale) {
|
||||||
|
double factor = Math.pow(10, scale);
|
||||||
|
return Math.round(value * factor) / factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印转换结果(调试用)
|
||||||
|
*/
|
||||||
|
public static void printConvert(String fromType, double fromLng, double fromLat,
|
||||||
|
String toType, double[] result) {
|
||||||
|
System.out.printf("%s [%.6f, %.6f] → %s [%s]%n",
|
||||||
|
fromType, fromLng, fromLat,
|
||||||
|
toType, formatCoord(result[0], result[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 北京天安门 GPS 坐标(WGS-84)116.397428,39.90923
|
||||||
|
// 长沙市政府 BD-09 112.945473,28.234889
|
||||||
|
// 岩安测控 WGS-84 112.862816,28.125462
|
||||||
|
|
||||||
|
double wgsLng = 112.862816;
|
||||||
|
double wgsLat = 28.125462;
|
||||||
|
|
||||||
|
System.out.println("是否在国内 = " + inOfChina(wgsLng, wgsLat));
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("=== 坐标系转换测试 ===");
|
||||||
|
|
||||||
|
// WGS-84 → GCJ-02 111.94760023918425,28.812219998012168
|
||||||
|
double[] gcj = CoordinateTransformUtils.wgs84ToGcj02(wgsLng, wgsLat);
|
||||||
|
CoordinateTransformUtils.printConvert("WGS-84", wgsLng, wgsLat, "GCJ-02", gcj);
|
||||||
|
|
||||||
|
// GCJ-02 → BD-09
|
||||||
|
double[] bd = CoordinateTransformUtils.gcj02ToBd09(gcj[0], gcj[1]);
|
||||||
|
CoordinateTransformUtils.printConvert("GCJ-02", gcj[0], gcj[1], "BD-09", bd);
|
||||||
|
|
||||||
|
// BD-09 → GCJ-02
|
||||||
|
double[] gcjBack = CoordinateTransformUtils.bd09ToGcj02(112.945473,28.234889);
|
||||||
|
CoordinateTransformUtils.printConvert("BD-09", bd[0], bd[1], "GCJ-02", gcjBack);
|
||||||
|
|
||||||
|
// GCJ-02 → WGS-84 111.944921,28.809167
|
||||||
|
double[] wgsBack = CoordinateTransformUtils.gcj02ToWgs84(111.944921,28.809167);
|
||||||
|
CoordinateTransformUtils.printConvert("GCJ-02", gcjBack[0], gcjBack[1], "WGS-84", wgsBack);
|
||||||
|
|
||||||
|
// 直接计算 WGS-84 → BD-09
|
||||||
|
double[] directBd = CoordinateTransformUtils.wgs84ToBd09(wgsLng, wgsLat);
|
||||||
|
CoordinateTransformUtils.printConvert("WGS-84", wgsLng, wgsLat, "BD-09(Direct)", directBd);
|
||||||
|
|
||||||
|
// 计算偏移距离
|
||||||
|
double offset = CoordinateTransformUtils.distance(wgsLng, wgsLat, gcj[0], gcj[1]);
|
||||||
|
System.out.printf("WGS-84 与 GCJ-02 偏移距离:%.2f 米%n", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,7 +6,6 @@ import com.alibaba.fastjson2.JSONArray;
|
|||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.fastbee.common.constant.Constants;
|
|
||||||
import com.fastbee.common.constant.FastBeeConstant;
|
import com.fastbee.common.constant.FastBeeConstant;
|
||||||
import com.fastbee.common.constant.ProductAuthConstant;
|
import com.fastbee.common.constant.ProductAuthConstant;
|
||||||
import com.fastbee.common.core.device.DeviceAndProtocol;
|
import com.fastbee.common.core.device.DeviceAndProtocol;
|
||||||
@ -24,10 +23,9 @@ import com.fastbee.common.utils.CaculateUtils;
|
|||||||
import com.fastbee.common.utils.DateUtils;
|
import com.fastbee.common.utils.DateUtils;
|
||||||
import com.fastbee.common.utils.SecurityUtils;
|
import com.fastbee.common.utils.SecurityUtils;
|
||||||
import com.fastbee.common.utils.StringUtils;
|
import com.fastbee.common.utils.StringUtils;
|
||||||
import com.fastbee.common.utils.http.HttpUtils;
|
|
||||||
import com.fastbee.common.utils.ip.IpUtils;
|
|
||||||
import com.fastbee.common.utils.json.JsonUtils;
|
import com.fastbee.common.utils.json.JsonUtils;
|
||||||
import com.fastbee.http.map.LocationService;
|
import com.fastbee.http.ip.IPAddressService;
|
||||||
|
import com.fastbee.http.map.ILocationService;
|
||||||
import com.fastbee.http.map.LocationServiceFactory;
|
import com.fastbee.http.map.LocationServiceFactory;
|
||||||
import com.fastbee.http.model.Coordinate;
|
import com.fastbee.http.model.Coordinate;
|
||||||
import com.fastbee.iot.cache.IDeviceCache;
|
import com.fastbee.iot.cache.IDeviceCache;
|
||||||
@ -124,9 +122,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
@Resource
|
@Resource
|
||||||
@Lazy
|
@Lazy
|
||||||
private IDataRepairService dataRepairService;
|
private IDataRepairService dataRepairService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private LocationServiceFactory locationServiceFactory;
|
private LocationServiceFactory locationServiceFactory;
|
||||||
|
@Resource
|
||||||
|
private IPAddressService ipAddressService;
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private EventLogMapper eventLogMapper;
|
private EventLogMapper eventLogMapper;
|
||||||
@ -1571,30 +1571,23 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据IP获取地址
|
* 设置地址信息(地址,经纬度)
|
||||||
*
|
*
|
||||||
* @param ip
|
* @param ip ip地址
|
||||||
* @return
|
* @param device 设备信息
|
||||||
*/
|
*/
|
||||||
private void setLocation(String ip, Device device) {
|
private void setLocation(String ip, Device device) {
|
||||||
String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
|
||||||
// String address = "未知地址";
|
|
||||||
// 内网不查询
|
|
||||||
if (IpUtils.internalIp(ip)) {
|
|
||||||
device.setNetworkAddress("内网IP");
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
|
// 根据IP获取地址
|
||||||
if (!StringUtils.isEmpty(rspStr)) {
|
String address = ipAddressService.getAddressByIP(ip);
|
||||||
JSONObject obj = JSONObject.parseObject(rspStr);
|
device.setNetworkAddress(address);
|
||||||
device.setNetworkAddress(obj.getString("addr"));
|
log.info("{}- 设置地址:{}", device.getSerialNumber(), address);
|
||||||
log.info("{}- 设置地址:{}", device.getSerialNumber(), obj.getString("addr"));
|
|
||||||
// 查询经纬度
|
// 查询经纬度
|
||||||
LocationService service = locationServiceFactory.getLocationService();
|
ILocationService service = locationServiceFactory.getLocationService();
|
||||||
Coordinate coordinate = service.getCoordinateByAddress(obj.getString("city"));
|
Coordinate coordinate = service.getCoordinateByAddress(address);
|
||||||
device.setLongitude(coordinate.getLongitude());
|
Coordinate wgs84Coordinate = service.convertToWgs84(coordinate);
|
||||||
device.setLatitude(coordinate.getLatitude());
|
device.setLongitude(wgs84Coordinate.getLongitude());
|
||||||
}
|
device.setLatitude(wgs84Coordinate.getLatitude());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.fastbee.common.exception.ServiceException;
|
import com.fastbee.common.exception.ServiceException;
|
||||||
|
import com.fastbee.common.utils.DateUtils;
|
||||||
import com.fastbee.common.utils.SecurityUtils;
|
import com.fastbee.common.utils.SecurityUtils;
|
||||||
import com.fastbee.iot.domain.ModbusParams;
|
import com.fastbee.iot.domain.ModbusParams;
|
||||||
import com.fastbee.iot.domain.ProductModbusJob;
|
import com.fastbee.iot.domain.ProductModbusJob;
|
||||||
@ -170,6 +171,9 @@ public class ProductSubGatewayServiceImpl extends ServiceImpl<ProductSubGatewayM
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int editBatch(List<ProductSubGateway> list) {
|
public int editBatch(List<ProductSubGateway> list) {
|
||||||
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
|
throw new ServiceException("修改数据不能为空");
|
||||||
|
}
|
||||||
// 同步产品轮询修改从机地址
|
// 同步产品轮询修改从机地址
|
||||||
Long gwProductId = list.get(0).getGwProductId();
|
Long gwProductId = list.get(0).getGwProductId();
|
||||||
LambdaQueryWrapper<ProductSubGateway> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<ProductSubGateway> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
@ -220,4 +224,18 @@ public class ProductSubGatewayServiceImpl extends ServiceImpl<ProductSubGatewayM
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 iot_modbus_params 记录
|
||||||
|
*/
|
||||||
|
private void createModbusParams(Long productId, Integer slaveId, String createBy) {
|
||||||
|
ModbusParams modbusParams = new ModbusParams();
|
||||||
|
modbusParams.setProductId(productId);
|
||||||
|
modbusParams.setSlaveId(slaveId);
|
||||||
|
modbusParams.setCreateBy(createBy);
|
||||||
|
modbusParams.setCreateTime(DateUtils.getNowDate());
|
||||||
|
modbusParams.setPollType(0);
|
||||||
|
modbusParams.setStatusDeter(1);
|
||||||
|
modbusParams.setDeterTimer("300");
|
||||||
|
modbusParamsMapper.insert(modbusParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user