瀏覽代碼

优化BDLocation项目配置和功能- 修改应用端口和访问路径
- 更新Druid和MQTT配置
- 添加设备定位消息推送功能
- 新增围栏闯禁事件通知页面
- 重构点位融合和围栏闯禁引擎,支持MQTT
- 更新依赖和调整项目结构

chen.cheng 9 月之前
父節點
當前提交
0bab24168c

+ 2 - 2
bd-location/build.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project name="tfc-minapp-be" basedir=".">
+<project name="bd-location" basedir=".">
     <property environment="SystemVariable"/>
-    <property name="buildName" value="ruoyi-admin"/>
+    <property name="buildName" value="bd-location"/>
     <!--默认目标-->
     <target name="Build" depends="copy-out"/>
     <!--所有的打包最终需要文件copy到特定目录,方便jenkins上取包-->

+ 3 - 0
bd-location/src/main/java/com/ruoyi/bd/service/engine/impl/FenceBreakInEngine.java

@@ -15,10 +15,12 @@ import com.ruoyi.common.enums.EvtStatus;
 import com.ruoyi.common.enums.EvtType;
 import com.ruoyi.common.utils.DateTimeUtil;
 import com.ruoyi.common.utils.geo.GeoUtils;
+import com.ruoyi.web.core.config.MqttCfg;
 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate;
 import org.apache.commons.lang3.ObjectUtils;
 import org.locationtech.jts.geom.Polygon;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -27,6 +29,7 @@ import javax.annotation.Resource;
 import java.util.List;
 
 @Service
+@ConditionalOnBean(MqttCfg.class)
 public class FenceBreakInEngine extends EvtFusionEngine {
 
     @Autowired

+ 7 - 0
bd-location/src/main/java/com/ruoyi/bd/service/engine/impl/PointFusionEngine.java

@@ -7,7 +7,9 @@ import com.ruoyi.bd.service.engine.LocationInfo;
 import com.ruoyi.bd.socket.PointWebSocketServer;
 import com.ruoyi.common.BDConst;
 import com.ruoyi.common.utils.DateTimeUtil;
+import com.ruoyi.web.core.config.MqttCfg;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
@@ -18,6 +20,7 @@ import javax.annotation.PostConstruct;
  * @author chen.cheng
  */
 @Service
+@ConditionalOnBean(MqttCfg.class)
 public class PointFusionEngine extends EvtFusionEngine {
 
     @Autowired
@@ -80,4 +83,8 @@ public class PointFusionEngine extends EvtFusionEngine {
     public void newEvtCallback(LocationInfo msg) {
         webSocketServer.sendInfo(msg.getMsg().getString("deviceId"), msg.getMsg().toJSONString());
     }
+
+    public void  pushDevcLocation(LocationInfo msg) {
+        webSocketServer.sendInfo(msg.getMsg().getString("deviceId"), msg.getMsg().toJSONString());
+    }
 }

+ 2 - 0
bd-location/src/main/java/com/ruoyi/common/BDConst.java

@@ -11,5 +11,7 @@ public interface BDConst {
         String POINT_LOCATION_TOPIC = "/uwb/point/#";
         String EVT_LOCATION_TOPIC = "/uwb/evt";
 
+        String DEVICE_LOCATION_TOPIC = "/uwb/point/%s";
+
     }
 }

+ 4 - 0
bd-location/src/main/java/com/ruoyi/mqtt/UWBLocationSubscribeListener.java

@@ -5,17 +5,21 @@ import com.alibaba.fastjson2.JSONObject;
 import com.ruoyi.bd.service.engine.impl.FenceBreakInEngine;
 import com.ruoyi.bd.service.engine.impl.PointFusionEngine;
 import com.ruoyi.common.BDConst;
+import com.ruoyi.web.core.config.MqttCfg;
 import net.dreamlu.iot.mqtt.codec.MqttQoS;
 import net.dreamlu.iot.mqtt.spring.client.MqttClientSubscribe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
 import java.nio.charset.StandardCharsets;
 
 @Service
+@ConditionalOnBean(MqttCfg.class)
 public class UWBLocationSubscribeListener {
     private static final Logger logger = LoggerFactory.getLogger(UWBLocationSubscribeListener.class);
 

+ 50 - 34
bd-location/src/main/java/com/ruoyi/web/controller/bd/BdDevcTrailUwbController.java

@@ -1,25 +1,33 @@
 package com.ruoyi.web.controller.bd;
 
-import java.util.List;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.security.access.prepost.PreAuthorize;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.bd.domain.BdDevcTrailUwb;
+import com.ruoyi.bd.service.IBdDevcTrailUwbService;
+import com.ruoyi.common.BDConst;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.DateTimeUtil;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.bd.domain.BdDevcTrailUwb;
-import com.ruoyi.bd.service.IBdDevcTrailUwbService;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.common.core.page.TableDataInfo;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 室内坐标定位Controller
@@ -28,19 +36,20 @@ import com.ruoyi.common.core.page.TableDataInfo;
  * @date 2024-10-16
  */
 @RestController
+@CrossOrigin
 @RequestMapping("/bd/devcTrailUwb")
-public class BdDevcTrailUwbController extends BaseController
-{
+public class BdDevcTrailUwbController extends BaseController {
     @Autowired
     private IBdDevcTrailUwbService bdDevcTrailUwbService;
 
+    @Autowired
+    private MqttClientTemplate client;
+
     /**
      * 查询室内坐标定位列表
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:list')")
     @GetMapping("/list")
-    public TableDataInfo list(BdDevcTrailUwb bdDevcTrailUwb)
-    {
+    public TableDataInfo list(BdDevcTrailUwb bdDevcTrailUwb) {
         startPage();
         List<BdDevcTrailUwb> list = bdDevcTrailUwbService.selectBdDevcTrailUwbList(bdDevcTrailUwb);
         return getDataTable(list);
@@ -49,56 +58,63 @@ public class BdDevcTrailUwbController extends BaseController
     /**
      * 导出室内坐标定位列表
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:export')")
     @Log(title = "室内坐标定位", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    public void export(HttpServletResponse response, BdDevcTrailUwb bdDevcTrailUwb)
-    {
+    public void export(HttpServletResponse response, BdDevcTrailUwb bdDevcTrailUwb) {
         List<BdDevcTrailUwb> list = bdDevcTrailUwbService.selectBdDevcTrailUwbList(bdDevcTrailUwb);
         ExcelUtil<BdDevcTrailUwb> util = new ExcelUtil<BdDevcTrailUwb>(BdDevcTrailUwb.class);
         util.exportExcel(response, list, "室内坐标定位数据");
     }
 
+    @PostMapping("/point")
+    @Anonymous
+    public void pushPoint(@RequestBody BdDevcTrailUwb bdDevcTrailUwb) {
+        Map<String, Object> map = new HashMap() {
+            {
+                put("latitude", bdDevcTrailUwb.getLat());
+                put("longitude", bdDevcTrailUwb.getLng());
+                put("srcTimestamp", DateTimeUtil.timestampMillis());
+                put("key", bdDevcTrailUwb.getDevcKey());
+                put("deviceId", bdDevcTrailUwb.getDevcKey());
+            }
+        };
+        client.publish(String.format(BDConst.MQTT_TOPIC.DEVICE_LOCATION_TOPIC, bdDevcTrailUwb.getDevcKey()), JSON.toJSONBytes(map));
+    }
+
+
     /**
      * 获取室内坐标定位详细信息
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:query')")
     @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
         return success(bdDevcTrailUwbService.selectBdDevcTrailUwbById(id));
     }
 
     /**
      * 新增室内坐标定位
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:add')")
     @Log(title = "室内坐标定位", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody BdDevcTrailUwb bdDevcTrailUwb)
-    {
+    @Anonymous
+    public AjaxResult add(@RequestBody BdDevcTrailUwb bdDevcTrailUwb) {
         return toAjax(bdDevcTrailUwbService.insertBdDevcTrailUwb(bdDevcTrailUwb));
     }
 
     /**
      * 修改室内坐标定位
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:edit')")
     @Log(title = "室内坐标定位", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@RequestBody BdDevcTrailUwb bdDevcTrailUwb)
-    {
+    public AjaxResult edit(@RequestBody BdDevcTrailUwb bdDevcTrailUwb) {
         return toAjax(bdDevcTrailUwbService.updateBdDevcTrailUwb(bdDevcTrailUwb));
     }
 
     /**
      * 删除室内坐标定位
      */
-    @PreAuthorize("@ss.hasPermi('bd:devcTrailUwb:remove')")
     @Log(title = "室内坐标定位", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
         return toAjax(bdDevcTrailUwbService.deleteBdDevcTrailUwbByIds(ids));
     }
 }

+ 20 - 0
bd-location/src/main/java/com/ruoyi/web/core/config/MqttCfg.java

@@ -0,0 +1,20 @@
+package com.ruoyi.web.core.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "bd.mqtt")
+@ConditionalOnProperty(name = "bd.mqtt.enabled", havingValue = "true")
+public class MqttCfg {
+    private boolean enabled;
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+}

+ 3 - 0
bd-location/src/main/resources/application-druid.yml

@@ -99,3 +99,6 @@ mqtt:
     clean-session: true
     ssl:
       enabled: false
+bd:
+  mqtt:
+    enabled: false

+ 3 - 0
bd-location/src/main/resources/application-hm.yml

@@ -100,3 +100,6 @@ mqtt:
     clean-session: true
     ssl:
       enabled: false
+bd:
+  mqtt:
+    enabled: true

+ 104 - 0
bd-location/src/main/resources/application-prod.yml

@@ -0,0 +1,104 @@
+# 数据源配置
+spring:
+  # redis 配置
+  redis:
+    # 地址
+    host: 127.0.0.1
+    # 端口,默认为6379
+    port: 6379
+    # 数据库索引
+    database: 1
+    # 密码
+    password:
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: 3s
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:mysql://127.0.0.1:3306/hs_cps?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: hscps
+        password: hscps2024
+      # 从库数据源
+      slave:
+        # 从数据源开关/默认关闭
+        enabled: false
+        url:
+        username:
+        password:
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置连接超时时间
+      connectTimeout: 30000
+      # 配置网络超时时间
+      socketTimeout: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+mqtt:
+  client:
+    enabled: true
+    ip: xt.wenhq.top
+    port: 8581
+    name: uwb-location-client
+    client-id: uwb-000001
+    global-subscribe:
+    timeout: 5
+    reconnect: true
+    re-interval: 5000
+    version: mqtt_3_1_1
+    read-buffer-size: 8KB
+    max-bytes-in-message: 10MB
+    keep-alive-secs: 60
+    clean-session: true
+    ssl:
+      enabled: false
+bd:
+  mqtt:
+    enabled: false

+ 3 - 3
bd-location/src/main/resources/application.yml

@@ -16,10 +16,10 @@ ruoyi:
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为8080
-  port: 18080
+  port: 28080
   servlet:
     # 应用的访问路径
-    context-path: /tfc
+    context-path: /bd-api
   tomcat:
     # tomcat的URI编码
     uri-encoding: UTF-8
@@ -52,7 +52,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: hm
+    active: druid
   # 文件上传
   servlet:
     multipart:

+ 0 - 4
ruoyi-admin/pom.xml

@@ -64,10 +64,6 @@
             <groupId>com.dtflys.forest</groupId>
             <artifactId>forest-spring-boot-starter</artifactId>
         </dependency>
-        <dependency>
-            <groupId>net.dreamlu</groupId>
-            <artifactId>mica-mqtt-client-spring-boot-starter</artifactId>
-        </dependency>
     </dependencies>
 
     <build>

+ 2 - 0
ruoyi-ui/src/views/bd/mobile/index.scss

@@ -0,0 +1,2 @@
+.fence-location-container {
+}

+ 102 - 0
ruoyi-ui/src/views/bd/mobile/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <pannel class="fence-location-container">
+    <template v-slot:title>
+      围栏闯禁事件
+    </template>
+    <template v-slot:action>
+
+    </template>
+    <template v-slot:content>
+       <div>
+        <socket-message :onMessage="onMessage" :ws="ws"></socket-message>
+      </div>
+    </template>
+  </pannel>
+</template>
+
+<script>
+
+import { listFenceVioEvt } from '@/api/bd/fenceVioEvt';
+import SocketMessage from '@/components/WebsocketMessage/index.vue';
+import Pannel from '@/views/bd/pannel/index.vue';
+import FingerprintJS from '@fingerprintjs/fingerprintjs';
+import dayjs from 'dayjs';
+
+export default {
+  name: 'fenceVioEvt',
+  components: {
+    SocketMessage,
+    Pannel,
+  },
+  data() {
+    return {
+      evtList: [],
+      fp: null,
+      ws: null,
+    };
+  },
+  // 组件卸载前清空图层信息
+  beforeDestroy() {
+  },
+  created() {
+
+  },
+  mounted() {
+    this.getFenceVioEvtList();
+    this.getFingerprint();
+  },
+  methods: {
+    dayjs,
+    async getFenceVioEvtList() {
+      const { rows } = await listFenceVioEvt({
+        pageNum: 1,
+        pageSize: 10,
+      });
+      this.evtList = rows;
+      debugger
+    },
+    async getFingerprint() {
+      // 初始化FingerprintJS
+      const fp = await FingerprintJS.load();
+      // 获取访问者的指纹
+      const result = await fp.get();
+      // 配置
+      const {
+        osCpu,
+        webGlBasics,
+        languages,
+        audioBaseLatency,
+        reducedTransparency,
+        vendor,
+        vendorFlavors,
+        fonts,
+        fontPreferences,
+        plugins,
+        forcedColors,
+        domBlockers,
+        pdfViewerEnabled,
+        audio,
+        canvas,
+        webGlExtensions,
+        math,
+        ...components
+      } = result.components;
+      const extendedComponents = {
+        ...components,
+      };
+      const fingerprintId = FingerprintJS.hashComponents(extendedComponents);
+      this.ws = `/ws/evt/${fingerprintId}`;
+    },
+    onMessage(a) {
+      const data = JSON.parse(a.data);
+      this.$notify({
+        title: '警告',
+        message: `${data.msg.fenceName}发生闯禁事件。`,
+        type: 'warning',
+      });
+      this.getFenceVioEvtList();
+    },
+  },
+};
+</script>
+<style lang="scss" src="./index.scss" />