diff --git a/.gitattributes b/.gitattributes index 21256661..3c9caca8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,4 @@ -* text=auto \ No newline at end of file +* text=auto +*.xml text eol=lf # 所有 XML 文件强制使用 LF 作为行结束符(提交和拉取都为 LF) +*.yml text eol=lf # YAML 文件同理 +*.java text eol=lf # Java 文件同理 \ No newline at end of file diff --git a/fastbee-common/src/main/java/com/fastbee/common/constant/ErrorCodeConstants.java b/fastbee-common/src/main/java/com/fastbee/common/constant/ErrorCodeConstants.java new file mode 100644 index 00000000..f98ae2e8 --- /dev/null +++ b/fastbee-common/src/main/java/com/fastbee/common/constant/ErrorCodeConstants.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")); + +} diff --git a/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java b/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java index ea44ca72..026cda53 100644 --- a/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java +++ b/fastbee-common/src/main/java/com/fastbee/common/constant/FastBeeConstant.java @@ -371,4 +371,14 @@ public interface FastBeeConstant { String GB28181 = "GB28181"; } + // 地图相关 + interface MAP { + // 百度 BAIDU + String BAIDU_GEOCODING = "http://api.map.baidu.com/geocoding/v3/"; + + // 高德 GAODE + + // 腾讯 TENCENT + } + } diff --git a/fastbee-common/src/main/java/com/fastbee/common/utils/http/HttpUtils.java b/fastbee-common/src/main/java/com/fastbee/common/utils/http/HttpUtils.java index 087596d0..517a0681 100644 --- a/fastbee-common/src/main/java/com/fastbee/common/utils/http/HttpUtils.java +++ b/fastbee-common/src/main/java/com/fastbee/common/utils/http/HttpUtils.java @@ -72,20 +72,20 @@ public class HttpUtils { } log.info("recv - {}", result); } 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) { - log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + log.error("调用HttpUtils.sendGet SocketTimeoutException, url={},param={}", url, param, 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) { - log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + log.error("调用HttpsUtil.sendGet Exception, url={},param={}", url, param, e); } finally { try { if (in != null) { in.close(); } } 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(); @@ -123,13 +123,13 @@ public class HttpUtils { } log.info("recv - {}", result); } 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) { - log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, param, 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) { - log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, param, e); } finally { try { if (out != null) { @@ -139,7 +139,7 @@ public class HttpUtils { in.close(); } } 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(); @@ -177,13 +177,13 @@ public class HttpUtils { conn.disconnect(); br.close(); } 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) { - log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url={},param={}", url, param, 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) { - log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + log.error("调用HttpsUtil.sendSSLPost Exception, url={},param={}", url, param, e); } return result.toString(); } @@ -213,13 +213,13 @@ public class HttpUtils { } log.info("recv - {}", result); } 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) { - log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + json, e); + log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, json, 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) { - log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + json, e); + log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, json, e); } finally { try { if (out != null) { @@ -229,7 +229,7 @@ public class HttpUtils { in.close(); } } 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(); diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/ip/IPAddressService.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/ip/IPAddressService.java new file mode 100644 index 00000000..8a032ac7 --- /dev/null +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/ip/IPAddressService.java @@ -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; + } + +} diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduLocationService.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduILocationService.java similarity index 66% rename from fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduLocationService.java rename to fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduILocationService.java index dfb28e0a..fcf27f02 100644 --- a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduLocationService.java +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/BaiduILocationService.java @@ -1,18 +1,24 @@ package com.fastbee.http.map; + import com.alibaba.fastjson2.JSONObject; 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.http.model.Coordinate; +import com.fastbee.http.utils.CoordinateTransformUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import static com.fastbee.common.exception.ServiceExceptionUtil.exception; + /** * @description: 百度地图API接口服务 * @@ -21,17 +27,11 @@ import java.nio.charset.StandardCharsets; */ @Slf4j @Service("baiduLocationService") -public class BaiduLocationService implements LocationService { +public class BaiduILocationService implements ILocationService { @Value("${other.baidu_ak}") 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 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; String encodedAddress; try { encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8.toString()); } 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)) { JSONObject baiduObject = JSONObject.parseObject(baiduResponse); JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location"); @@ -59,4 +60,14 @@ public class BaiduLocationService implements LocationService { 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])); + } + } diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/GaodeLocationService.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/GaodeLocationService.java new file mode 100644 index 00000000..c7ac5324 --- /dev/null +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/GaodeLocationService.java @@ -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])); + } +} diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationService.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/ILocationService.java similarity index 68% rename from fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationService.java rename to fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/ILocationService.java index d6726ad4..737fe321 100644 --- a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationService.java +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/ILocationService.java @@ -8,7 +8,7 @@ import com.fastbee.http.model.Coordinate; * @author Sumuxi * @date 2026/3/7 */ -public interface LocationService { +public interface ILocationService { /** * 根据地址获取经纬度坐标 @@ -23,4 +23,12 @@ public interface LocationService { * @return 详细地址信息 */ //AddressInfo getAddressByCoordinate(Coordinate coordinate); + + + /** + * 将不同坐标转化为世界坐标 + * @param coordinate 不同(BD09,GCJ02,WGS84)实现类坐标 + * @return 世界坐标系 + */ + Coordinate convertToWgs84(Coordinate coordinate); } diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationServiceFactory.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationServiceFactory.java index 9e1df41f..31aa8e1c 100644 --- a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationServiceFactory.java +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/map/LocationServiceFactory.java @@ -15,10 +15,10 @@ import javax.annotation.Resource; public class LocationServiceFactory { @Resource - private LocationService baiduLocationService; + private ILocationService baiduLocationService; -// @Resource -// private LocationService gaodeLocationService; + @Resource + private ILocationService gaodeLocationService; // 从配置文件读取当前使用的服务商 @Value("${map.provider:baidu}") @@ -28,7 +28,7 @@ public class LocationServiceFactory { * 获取当前配置的 LocationService 实例 * @return 具体服务实现 */ - public LocationService getLocationService() { + public ILocationService getLocationService() { // if ("gaode".equalsIgnoreCase(provider)) { // return gaodeLocationService; // } else if ("tencent".equalsIgnoreCase(provider)) { diff --git a/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/utils/CoordinateTransformUtils.java b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/utils/CoordinateTransformUtils.java new file mode 100644 index 00000000..4f6ed84d --- /dev/null +++ b/fastbee-plugs/fastbee-http/src/main/java/com/fastbee/http/utils/CoordinateTransformUtils.java @@ -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); + } + +} diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java index be63ec99..54f73518 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java @@ -6,7 +6,6 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DSTransactional; 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.ProductAuthConstant; 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.SecurityUtils; 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.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.model.Coordinate; import com.fastbee.iot.cache.IDeviceCache; @@ -124,9 +122,11 @@ public class DeviceServiceImpl implements IDeviceService { @Resource @Lazy private IDataRepairService dataRepairService; - @Resource private LocationServiceFactory locationServiceFactory; + @Resource + private IPAddressService ipAddressService; + @Resource private EventLogMapper eventLogMapper; @@ -1571,30 +1571,23 @@ public class DeviceServiceImpl implements IDeviceService { } /** - * 根据IP获取地址 + * 设置地址信息(地址,经纬度) * - * @param ip - * @return + * @param ip ip地址 + * @param 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 { - String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); - if (!StringUtils.isEmpty(rspStr)) { - JSONObject obj = JSONObject.parseObject(rspStr); - device.setNetworkAddress(obj.getString("addr")); - log.info("{}- 设置地址:{}", device.getSerialNumber(), obj.getString("addr")); - // 查询经纬度 - LocationService service = locationServiceFactory.getLocationService(); - Coordinate coordinate = service.getCoordinateByAddress(obj.getString("city")); - device.setLongitude(coordinate.getLongitude()); - device.setLatitude(coordinate.getLatitude()); - } + // 根据IP获取地址 + String address = ipAddressService.getAddressByIP(ip); + device.setNetworkAddress(address); + log.info("{}- 设置地址:{}", device.getSerialNumber(), address); + // 查询经纬度 + ILocationService service = locationServiceFactory.getLocationService(); + Coordinate coordinate = service.getCoordinateByAddress(address); + Coordinate wgs84Coordinate = service.convertToWgs84(coordinate); + device.setLongitude(wgs84Coordinate.getLongitude()); + device.setLatitude(wgs84Coordinate.getLatitude()); } catch (Exception e) { log.error(e.getMessage()); } diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ProductSubGatewayServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ProductSubGatewayServiceImpl.java index be52cb0d..ceea5f4a 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ProductSubGatewayServiceImpl.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/ProductSubGatewayServiceImpl.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fastbee.common.exception.ServiceException; +import com.fastbee.common.utils.DateUtils; import com.fastbee.common.utils.SecurityUtils; import com.fastbee.iot.domain.ModbusParams; import com.fastbee.iot.domain.ProductModbusJob; @@ -170,6 +171,9 @@ public class ProductSubGatewayServiceImpl extends ServiceImpl list) { + if (CollectionUtils.isEmpty(list)) { + throw new ServiceException("修改数据不能为空"); + } // 同步产品轮询修改从机地址 Long gwProductId = list.get(0).getGwProductId(); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); @@ -220,4 +224,18 @@ public class ProductSubGatewayServiceImpl extends ServiceImpl