cc hai 4 meses
pai
achega
f8d2290b74

+ 1 - 1
QingJian/conf/c5e503ad.json

@@ -1 +1 @@
-{"init":"N","forceData":"N","version":"2","mapLocal": ""}
+{"init":"N","forceData":"N","version":"2","mapLocal": "","cellLocal":""}

+ 2 - 2
src/main/java/com/qingjian/common/constants/PathConst.java

@@ -61,8 +61,8 @@ public class PathConst {
     /**
      * 基站库路径
      */
-    public static final Path CELL_TOWER_PATH = RUN_QINGJIAN_PATH.resolve("w6df89sk").resolve("liblbsrepo.dll");
-    public static final Path CELL_TOWER_PATH_SO = RUN_QINGJIAN_PATH.resolve("w6df89sk").resolve("liblbsrepo.so");
+    public static final Path CELL_TOWER_PATH = RUN_QINGJIAN_PATH.resolve("w6df89sk").resolve("libCell.dll");
+    public static final Path CELL_TOWER_PATH_SO = RUN_QINGJIAN_PATH.resolve("w6df89sk").resolve("libCell.so");
     public static final Path CELL_TOWER_PATH_BIN = RUN_QINGJIAN_PATH.resolve("w6df89sk").resolve("cellinfo.bin");
 
     /**

+ 2 - 0
src/main/java/com/qingjian/common/event/AppStopEndEventListener.java

@@ -1,6 +1,7 @@
 package com.qingjian.common.event;
 
 import com.qingjian.common.rocksdb.RocksDBHelper;
+import com.qingjian.common.utils.CellDll;
 import com.qingjian.common.utils.LuceneManager;
 import org.noear.solon.annotation.Component;
 import org.noear.solon.core.event.AppStopEndEvent;
@@ -13,5 +14,6 @@ public class  AppStopEndEventListener implements EventListener<AppStopEndEvent>{
         //event.app(); //获取应用对象
         RocksDBHelper.INSTANCE.remove();
         LuceneManager.close();
+        CellDll.INSTANCE_DLL.cell_fini();
     }
 }

+ 22 - 41
src/main/java/com/qingjian/common/utils/CellDll.java

@@ -2,9 +2,7 @@ package com.qingjian.common.utils;
 
 import com.sun.jna.Library;
 import com.sun.jna.Native;
-import com.sun.jna.Pointer;
 import com.sun.jna.ptr.DoubleByReference;
-import com.sun.jna.ptr.IntByReference;
 
 /**
  * 基站定位动态链接库接口
@@ -18,7 +16,9 @@ import com.sun.jna.ptr.IntByReference;
  * @author aa
  */
 public interface CellDll extends Library {
-
+    int COORD_WGS84 = 0;
+    int COORD_GCJ02 = 1;
+    int COORD_BD09 = 2;
     /**
      * 动态链接库实例
      * 通过Native.load加载本地库,单例模式
@@ -38,51 +38,32 @@ public interface CellDll extends Library {
     int cell_init(String fileName);
 
     /**
-     * 根据基站参数查询位置信息
-     * <p>
-     * 查询指定基站的经纬度、覆盖范围等信息
-     * 返回的坐标为WGS84坐标系
-     * </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,十进制
-     * @param lat      输出参数,WGS84纬度值引用
-     * @param lon      输出参数,WGS84经度值引用
-     * @param radius   输出参数,覆盖半径(米)引用
-     * @param date     输出参数,日期信息引用
-     * @param validity 输出参数,数据有效性标识引用
-     * @return 查询结果状态码,0表示成功,非0表示失败
+     * 释放所有资源。
+     * @return
      */
-    int cell_query(int mcc, int mnc, int lac, int ci, DoubleByReference lat, DoubleByReference lon,
-                   IntByReference radius, IntByReference date, DoubleByReference validity);
+    int cell_fini();
 
-    /**
-     * 完整逆地理编码
-     * <p>
-     * 根据经纬度获取详细的地址信息
-     * 返回完整的地址描述,包括省市区街道等详细信息
-     * </p>
-     *
-     * @param addr 输出参数,用于接收地址信息的Pointer缓冲区
-     * @param lat  WGS84纬度值
-     * @param lon  WGS84经度值
-     * @return 查询结果状态码,0表示成功,非0表示失败
-     */
-    int regeo_full(Pointer addr, double lat, double lon);
 
     /**
-     * 简化逆地理编码
+     * 合并查询基站位置与逆地理编码地址
      * <p>
-     * 根据经纬度获取简化的地址信息
-     * 返回简洁的地址描述,适用于快速查询场景
+     * 一次调用同时完成基站定位和逆地理编码,返回指定坐标系的经纬度及合并地址字符串。
+     * 地址格式示例:"四川省成都市武侯区石羊场街道锦城湖立交;剑南大道北段与锦城湖立交路口东260米"
      * </p>
      *
-     * @param p   输出参数,用于接收地址信息的Pointer缓冲区
-     * @param lat WGS84纬度值
-     * @param lon WGS84经度值
+     * @param mcc          移动国家代码(Mobile Country Code),中国大陆固定填460
+     * @param mnc          移动网络代码,0=移动,1=联通,11=LTE,10000~19999=CDMA SID
+     * @param lac          位置区码(0~65535),LTE填TAC,CDMA填NID
+     * @param ci           小区标识(0~268435455),CDMA填BID
+     * @param coordSys     输出坐标系:0=WGS84,1=GCJ02(高德/腾讯),2=BD09(百度)
+     * @param lat          输出参数,纬度值引用
+     * @param lon          输出参数,经度值引用
+     * @param combined     输出参数,用于接收合并地址字符串的字节缓冲区
+     * @param combinedLen  地址缓冲区长度
      * @return 查询结果状态码,0表示成功,非0表示失败
      */
-    int regeo_simple(Pointer p, double lat, double lon);
+    int cell_query_combined(int mcc, int mnc, int lac, int ci, int coordSys,
+                            DoubleByReference lat, DoubleByReference lon,
+                            byte[] combined, int combinedLen);
+
 }

+ 4 - 0
src/main/java/com/qingjian/common/utils/SystemConfManager.java

@@ -63,6 +63,10 @@ public class SystemConfManager {
         FileUtil.writeUtf8String(Json.toStr(systemConf), PathConst.SYSTEM_CONF_PATH.toFile());
     }
 
+    public String getCellLocal() {
+        return systemConf.get("cellLocal");
+    }
+
     public String getVersion() {
         return systemConf.get("version");
     }

+ 33 - 31
src/main/java/com/qingjian/common/utils/TowerUtils.java

@@ -1,12 +1,15 @@
 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.Memory;
-import com.sun.jna.Pointer;
 import com.sun.jna.ptr.DoubleByReference;
-import com.sun.jna.ptr.IntByReference;
+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;
 
 /**
@@ -18,9 +21,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
  *
  * @author cc
  */
+@Slf4j
 public class TowerUtils {
 
-    private static final int ADDRESS_BUFFER_SIZE = 1024;
+    private static final int ADDRESS_BUFFER_SIZE = 2048;
     private static final AtomicBoolean FLAG = new AtomicBoolean(false);
 
     /**
@@ -41,10 +45,25 @@ public class TowerUtils {
      * </p>
      */
     public static void init() {
-        if (Files.exists(PathConst.CELL_TOWER_PATH_BIN)) {
-            CellDll.INSTANCE_DLL.cell_init(PathConst.CELL_TOWER_PATH_BIN.toString());
+        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(!name.equalsIgnoreCase("cellinfo.bin")){
+                log.info("基站数据库文件名不正确!");
+                return;
+            }
+            Path parent = path.getParent();
+            CellDll.INSTANCE_DLL.cell_init(parent.toString());
             FLAG.set(true);
+            log.info("基站数据库路径已经加载!");
+            return;
         }
+        log.info("基站数据库路径不存在!");
     }
 
     /**
@@ -66,6 +85,7 @@ public class TowerUtils {
      * - obj[2]: 覆盖半径(米)
      * - obj[3]: 详细地址描述
      * 示例调用:CellUtils.getCells(460, 0, 1, 2)
+     *  getCells(460, 0, 32796, 64265);
      * <p>
      * 返回示例:[35.994564, 12.468795, 123, "北京市朝阳xxx4号楼;望京街xx163米"]
      * </p>
@@ -79,15 +99,15 @@ public class TowerUtils {
         // 创建用于接收查询结果的引用对象
         DoubleByReference latitude = new DoubleByReference(0.0);   // WGS84 纬度
         DoubleByReference longitude = new DoubleByReference(0.0);  // WGS84 经度
-        DoubleByReference valid = new DoubleByReference(0.0);      // 原生库要求的有效性输出参数
-        IntByReference radius = new IntByReference(0);             // 覆盖半径
-        IntByReference date = new IntByReference(0);               // 原生库要求的日期输出参数
+        byte[] combined = new byte[ADDRESS_BUFFER_SIZE];
+
 
         // 调用本地库查询基站信息
-        int queryResult = CellDll.INSTANCE_DLL.cell_query(mcc, mnc, lac, ci, latitude, longitude, radius, date, valid);
+        int queryResult = CellDll.INSTANCE_DLL.cell_query_combined(mcc, mnc, lac, ci,
+                CellDll.COORD_WGS84, latitude, longitude, combined, combined.length);
 
         // 如果查询失败,返回空数组
-        if (queryResult == 0) {
+        if (queryResult != 0) {
             return result;
         }
 
@@ -97,28 +117,10 @@ public class TowerUtils {
         //double[] bd09 = CoordinateTransform.transformWGS84ToBD09(sourceLongitude, sourceLatitude);
         result[0] = sourceLatitude;
         result[1] = sourceLongitude;
-        result[2] = radius.getValue();
+        result[2] = 0;
 
         // 逆地理编码依旧使用原始 WGS84 坐标,保持与现有 native 接口行为一致。
-        result[3] = reverseGeocode(sourceLatitude, sourceLongitude);
-
+        result[3] = StrUtil.str(combined, StandardCharsets.UTF_8);
         return result;
     }
-
-    /**
-     * 调用原生库根据 WGS84 坐标获取地址描述。
-     *
-     * @param latitude  WGS84 纬度
-     * @param longitude WGS84 经度
-     * @return 地址描述
-     */
-    private static String reverseGeocode(double latitude, double longitude) {
-        Pointer addressBuffer = new Memory(ADDRESS_BUFFER_SIZE);
-        try {
-            CellDll.INSTANCE_DLL.regeo_simple(addressBuffer, latitude, longitude);
-            return addressBuffer.getString(0, "utf-8");
-        } finally {
-            addressBuffer.clear(ADDRESS_BUFFER_SIZE);
-        }
-    }
 }

+ 22 - 0
src/main/java/com/qingjian/module/plat/controller/SystemController.java

@@ -151,4 +151,26 @@ public class SystemController {
         systemService.mapLocal(path);
     }
 
+    /**
+     * 获取基站本地路径
+     *
+     * @return 基站本地路径
+     */
+    @Get
+    @Mapping("/getCellLocal")
+    public String getCellLocal() {
+        return systemService.getCellLocal();
+    }
+
+    /**
+     * 设置基站本地路径
+     *
+     * @param path 基站本地路径
+     */
+    @Get
+    @Mapping("/cellLocal")
+    public void cellLocal(String path) {
+        systemService.cellLocal(path);
+    }
+
 }

+ 15 - 0
src/main/java/com/qingjian/module/plat/service/SystemService.java

@@ -354,4 +354,19 @@ public class SystemService extends ServiceImpl<SystemInfoMapper, SystemInfo> {
             throw new ServerException("升级文件不存在!");
         }
     }
+
+    public String getCellLocal() {
+        return SystemConfManager.INSTANCE.get("cellLocal");
+    }
+
+    public void cellLocal(String path) {
+        Path file = Path.of(path);
+        if (Files.notExists(file)) {
+            throw new ServerException("基站文件不存在!");
+        }
+        if (Files.isDirectory(file)) {
+            throw new ServerException("当前不支持文件夹!");
+        }
+        SystemConfManager.INSTANCE.set("cellLocal", path);
+    }
 }