| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package com.qingjian.common.utils;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.util.StrUtil;
- import com.qingjian.common.constants.PathConst;
- import com.sun.jna.ptr.DoubleByReference;
- import lombok.extern.slf4j.Slf4j;
- import java.nio.charset.StandardCharsets;
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.util.concurrent.atomic.AtomicBoolean;
- /**
- * 基站定位工具类
- * <p>
- * 通过调用动态链接库实现基站信息查询和逆地理编码功能
- * 支持将WGS84坐标转换为百度BD09坐标
- * </p>
- *
- * @author cc
- */
- @Slf4j
- public class TowerUtils {
- private static final int ADDRESS_BUFFER_SIZE = 2048;
- private static final AtomicBoolean FLAG = new AtomicBoolean(false);
- /**
- * 根据操作系统类型返回对应的动态链接库路径
- * Windows系统使用DLL,Linux系统使用SO
- *
- * @return 动态链接库路径字符串
- */
- public static String dll() {
- return LicenseUtil.isWin() ? PathConst.CELL_TOWER_PATH.toString() : PathConst.CELL_TOWER_PATH_SO.toString();
- }
- /**
- * 初始化基站数据库
- * <p>
- * 在首次使用前必须调用此方法进行初始化
- * 加载基站数据文件到内存中
- * </p>
- */
- public static void init() {
- if (FLAG.get()) {
- log.info("基站数据库路径已经加载,无需再次初始化!");
- return;
- }
- String cellLocal = SystemConfManager.INSTANCE.getCellLocal();
- if (StrUtil.isEmpty(cellLocal)) {
- log.info("请先设置基站数据库路径!");
- return;
- }
- Path path = Paths.get(cellLocal);
- if (Files.exists(path)) {
- String name = FileUtil.getName(path);
- if (StrUtil.endWith(name, ".bin")) {
- log.info("基站数据库文件名不正确!");
- return;
- }
- CellDll.INSTANCE_DLL.cell_init(cellLocal);
- FLAG.set(true);
- log.info("基站数据库路径已经加载!");
- return;
- }
- log.info("基站数据库路径不存在!");
- }
- /**
- * 根据基站信息查询位置和地址
- * <p>
- * 查询流程:
- * 1. 调用cell_query获取基站的经纬度信息(WGS84坐标系)
- * 2. 将WGS84坐标转换为百度BD09坐标
- * 3. 调用regeo_simple进行逆地理编码获取详细地址
- * </p>
- *
- * @param mcc 移动国家代码(Mobile Country Code),中国代码为460
- * @param mnc 移动网络代码(Mobile Network Code),0-移动,1-联通,电信对应sid(十进制)
- * @param lac 位置区码(Location Area Code),电信对应nid(十进制)
- * @param ci 小区标识(Cell Identity),电信对应bid(十进制)
- * @return 包含位置信息的数组,格式为:[纬度, 经度, 覆盖半径, 详细地址]
- * - obj[0]: 百度纬度(BD09)
- * - obj[1]: 百度经度(BD09)
- * - obj[2]: 覆盖半径(米)
- * - obj[3]: 详细地址描述
- * 示例调用:CellUtils.getCells(460, 0, 1, 2)
- * getCells(460, 0, 32796, 64265);
- * <p>
- * 返回示例:[35.994564, 12.468795, 123, "北京市朝阳xxx4号楼;望京街xx163米"]
- * </p>
- */
- public static Object[] getCells(int mcc, int mnc, int lac, int ci) {
- Object[] result = new Object[4];
- if (!FLAG.get()) {
- return result;
- }
- // 创建用于接收查询结果的引用对象
- DoubleByReference latitude = new DoubleByReference(0.0); // WGS84 纬度
- DoubleByReference longitude = new DoubleByReference(0.0); // WGS84 经度
- byte[] combined = new byte[ADDRESS_BUFFER_SIZE];
- // 调用本地库查询基站信息
- int queryResult = CellDll.INSTANCE_DLL.cell_query_combined(mcc, mnc, lac, ci,
- CellDll.COORD_WGS84, latitude, longitude, combined, combined.length);
- // 如果查询失败,返回空数组
- if (queryResult != 0) {
- return result;
- }
- double sourceLatitude = latitude.getValue();
- double sourceLongitude = longitude.getValue();
- // 查询结果的原始坐标来自 WGS84,需要先转换为 BD09 再返回给上层。
- //double[] bd09 = CoordinateTransform.transformWGS84ToBD09(sourceLongitude, sourceLatitude);
- result[0] = sourceLatitude;
- result[1] = sourceLongitude;
- result[2] = 0;
- // 逆地理编码依旧使用原始 WGS84 坐标,保持与现有 native 接口行为一致。
- result[3] = StrUtil.str(combined, StandardCharsets.UTF_8);
- return result;
- }
- }
|