Jelajahi Sumber

1. 修复设备心跳超时掉线问题.

kindring 2 tahun lalu
induk
melakukan
aaceacd873

+ 64 - 13
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AiConfig.java

@@ -28,9 +28,71 @@ public class AiConfig {
 
     @Schema(description = "多媒体资源上传地址")
     private String uploadUrl;
-
     @Schema(description = "回调地址")
     private String pushUrl;
+    @Schema(description = "ai配置名称")
+    private String configName;
+    @Schema(description = "图形库名称")
+    private String libraryName;
+    @Schema(description = "图像块版本")
+    private String version;
+    @Schema(description = "图像id")
+    private int imgId;
+    @Schema(description = "图片的链接")
+    private String imageUrl;
+    @Schema(description = "用于匹配的值")
+    private String textValue;
+    @Schema(description = "人员名称")
+    private String personName;
+
+    @Schema(description = "工号")
+    private String workerNo;
+
+    @Schema(description = "身份证")
+    private String idCard;
+
+    @Schema(description = "子项数量")
+    private int total;
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+
+    public String getPersonName() {
+        return personName;
+    }
+
+    public void setPersonName(String personName) {
+        this.personName = personName;
+    }
+
+    public String getWorkerNo() {
+        return workerNo;
+    }
+
+    public void setWorkerNo(String workerNo) {
+        this.workerNo = workerNo;
+    }
+
+    public String getIdCard() {
+        return idCard;
+    }
+
+    public void setIdCard(String idCard) {
+        this.idCard = idCard;
+    }
+    public String getTextValue() {
+        return textValue;
+    }
+
+    public void setTextValue(String textValue) {
+        this.textValue = textValue;
+    }
 
     public String getConfigName() {
         return configName;
@@ -40,8 +102,7 @@ public class AiConfig {
         this.configName = configName;
     }
 
-    @Schema(description = "ai配置名称")
-    private String configName;
+
 
     public String getLibraryName() {
         return libraryName;
@@ -75,17 +136,7 @@ public class AiConfig {
         this.imageUrl = imageUrl;
     }
 
-    @Schema(description = "图形库名称")
-    private String libraryName;
-
-    @Schema(description = "图像块版本")
-    private String version;
 
-    @Schema(description = "图像id")
-    private int imgId;
-
-    @Schema(description = "图片的链接")
-    private String imageUrl;
 
     public int getConfigId() {
         return configId;

+ 1 - 0
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@@ -144,6 +144,7 @@ public class ZLMRTPServerFactory {
 
     public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
         boolean result = false;
+        logger.error("--------主动关闭RTP Server --------------");
         if (serverItem !=null){
             Map<String, Object> param = new HashMap<>();
             param.put("stream_id", streamId);

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java

@@ -135,7 +135,8 @@ public class DeviceServiceImpl implements IDeviceService {
         }
         // 刷新过期任务
         String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId();
-        dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000);
+//      // 设备过期时间多增加3秒
+        dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), (device.getExpires() * 1000) + 5000);
     }
 
     @Override

+ 1 - 0
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java

@@ -174,6 +174,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
 
     @Override
     public void closeRTPServer(String mediaServerId, String streamId) {
+        logger.info("[关闭rtp server], mediaServerId:", mediaServerId);
         MediaServerItem mediaServerItem = this.getOne(mediaServerId);
         closeRTPServer(mediaServerItem, streamId);
     }

+ 7 - 0
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java

@@ -55,6 +55,13 @@ public interface IVideoManagerStorage {
 	 */
 	public List<AiConfig> queryDevAiConfigList(String deviceId);
 
+	/**
+	 * 获取所有的ai配置项
+	 * @return
+	 */
+	public List<AiConfig> queryAiConfigList();
+
+	public List<AiConfig> devUseAiConfig(String deviceId,int configId);
 	/**
 	 * 获取数据库中所有的ai库
 	 * @return

+ 34 - 1
src/main/java/com/genersoft/iot/vmp/storager/dao/HfyDevAiMapper.java

@@ -12,10 +12,41 @@ import java.util.List;
 @Repository
 public interface HfyDevAiMapper {
     @Select("select c.* from ai_configs as c " +
-            "left Join devAiConfigs as dc on dc.configId = c.configId " +
+            "left Join dev_ai_config as dc on dc.configId = c.configId " +
             "where dc.deviceId = #{deviceId}")
     List<AiConfig> getDevAiConfigByDeviceId(String deviceId);
+    @Select("select * from ai_configs")
+    List<AiConfig> getAiConfigList();
 
+    @Insert("insert into ai_config(" +
+            "libraryId," +
+            "arithmetic," +
+            "triggerType," +
+            "refreshTime," +
+            "score," +
+            "resourcePath," +
+            "uploadUrl," +
+            "pushUrl" +
+            ") values(" +
+            "#{libraryId}," +
+            "#{arithmetic}," +
+            "#{triggerType}," +
+            "#{refreshTime}," +
+            "#{score}," +
+            "#{resourcePath}," +
+            "#{uploadUrl}," +
+            "#{pushUrl}" +
+            ")")
+    int createAiConfig(AiConfig aiConfig);
+
+    @Insert("insert into dev_ai_config(" +
+            "deviceId," +
+            "configId"+
+            ") values(" +
+            "#{deviceId}," +
+            "#{configId}," +
+            ")")
+    int devUseConfig(AiConfig aiConfig);
     @Select("select * from ai_library ")
     List<AiConfig> getAiLibraryList();
 
@@ -56,4 +87,6 @@ public interface HfyDevAiMapper {
             ")")
     int addImg(AiConfig aiConfig);
 
+
+
 }

+ 5 - 2
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -235,8 +235,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 	 * @return
 	 */
 	public List<AiConfig> queryDevAiConfigList(String deviceId) {
-		List<AiConfig> all = HfyDevAiMapper.getDevAiConfigByDeviceId(deviceId);
-		return all;
+		return HfyDevAiMapper.getDevAiConfigByDeviceId(deviceId);
+	}
+
+	public List<AiConfig> queryAiConfigList() {
+		return HfyDevAiMapper.getAiConfigList();
 	}
 
 	/**

+ 21 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java

@@ -35,6 +35,7 @@ import org.springframework.web.context.request.async.DeferredResult;
 import javax.servlet.http.HttpServletResponse;
 import javax.sip.InvalidArgumentException;
 import javax.sip.SipException;
+import javax.websocket.server.PathParam;
 import java.io.*;
 import java.nio.file.Files;
 import java.text.ParseException;
@@ -95,6 +96,26 @@ public class DeviceQuery {
 		return storager.queryDevAiConfigList(deviceId);
 	}
 
+	@Operation(summary = "获取所有ai配置")
+	@GetMapping("/aiConfigs")
+	public List<AiConfig> aiConfigList(){
+		if (logger.isDebugEnabled()) {
+			logger.debug("查询所有的ai配置列表");
+		}
+		return storager.queryAiConfigList();
+	}
+
+	@Operation(summary = "设备使用ai配置")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "configId", description = "配置id", required = true)
+	@GetMapping("/useAi/{deviceId}/{configId}")
+	public List<AiConfig> devUseConfig(@PathVariable String deviceId,@PathVariable int configId){
+		if (logger.isDebugEnabled()) {
+			logger.debug("设备使用ai配置");
+		}
+		return storager.devUseAiConfig(deviceId,configId);
+	}
+
 
 	@Operation(summary = "ai数据库查询")
 	@GetMapping("/aiLibrary")

+ 2 - 2
src/main/resources/application.yml

@@ -123,10 +123,10 @@ media:
     # [必须修改] zlm服务器的内网IP
     ip: 192.168.1.203
     # [可选] 返回流地址时的ip,置空使用 media.ip
-    stream-ip: 113.88.193.113
+    stream-ip: szgpay.ticp.net
     #stream-ip: 192.168.1.203
     # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
-    sdp-ip: 113.88.193.113
+    sdp-ip: szgpay.ticp.net
     #sdp-ip: 192.168.1.203
     # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
     hook-ip:

+ 40 - 11
web_src/src/components/aiConfig.vue

@@ -8,10 +8,11 @@
     </div>
     <div class="page-header-btn">
       <el-tooltip class="item" effect="dark" content="添加算法" placement="left-start">
-        <el-button icon="el-icon-plus" circle size="mini" ></el-button>
+        <el-button icon="el-icon-plus" circle size="mini" @click="showArithmeticDialog" ></el-button>
       </el-tooltip>
     </div>
   </div>
+  <add-arithmetic ref="addArithmeticDialog" ></add-arithmetic>
   <el-container v-loading="isLoading" style="min-height: 82vh;flex-direction: column;" >
     <el-card class="box-card" v-for="item in useAiList" :key="item.arithmetic">
       <div slot="header" class="card-header flex space-between align-center" >
@@ -68,9 +69,11 @@
 <script>
 import aiMap from "../map/ai"
 import {toNumber} from "../until/typeTool";
+import AddArithmetic from "./dialog/addArithmetic";
 
 export default {
   name: "aiConfig",
+  components: {AddArithmetic},
   data(){
     return {
       deviceId: this.$route.params.deviceId,
@@ -78,26 +81,23 @@ export default {
       arithmeticEnum:aiMap.arithmeticEnum,
       // ai数据库标记列表
       aiList:[
-        {
-          id: 1,
-          libraryName: "人脸库1",
-          version: "20121",
-          total: 120
-        }
       ],
       useAiList: [
       ],
     }
   },
-  mounted(){
-    this.loadDeviceAi();
+  async mounted(){
+    await this.loadAiLib();
+    await this.loadDeviceAi();
+
   },
   methods:{
     toArithmetic: aiMap.toArithmetic,
     toTriggerType: aiMap.toTriggerType,
     toAiData(num){
       num=toNumber(num);
-      let key = Object.keys(this.aiList).find(key=>this.aiList[key].id===num);
+      console.log(this.aiList);
+      let key = Object.keys(this.aiList).find(key=>toNumber(this.aiList[key].libraryId)===num);
       return key?this.aiList[key]:false;
     },
     showDevice() {
@@ -106,10 +106,36 @@ export default {
         this.beforeUrl = "/deviceList"
       }
     },
+    loadAiLib(){
+      this.isLoading = true;
+      let that = this;
+      return this.$axios({
+        method: 'get',
+        url: '/api/device/query/aiLibrary'
+      }).then((res) => {
+        // console.log("获取ai数据结果:" + JSON.stringify(res));
+        this.isLoading = false;
+        // console.log(res);
+        let data = res.data;
+        if(data.code === 0 ){
+          that.aiList = data.data;
+        }else{
+          console.log(res);
+          console.error("未知的返回结果!")
+        }
+      }).catch((e) => {
+        console.error(e)
+        that.$message({
+          showClose: true,
+          message: e,
+          type: 'error'
+        });
+      });
+    },
     loadDeviceAi(){
       this.isLoading = true;
       let that = this;
-      this.$axios({
+      return this.$axios({
         method: 'get',
         url: '/api/device/query/devAis/' + that.deviceId
       }).then((res) => {
@@ -135,6 +161,9 @@ export default {
     showEditAi(id){
       this.$router.push(`/devEditAi/${id}`);
     },
+    showArithmeticDialog(){
+      this.$refs.addArithmeticDialog.showDialog(this.deviceId);
+    }
 
   }
 

+ 84 - 0
web_src/src/components/dialog/addArithmetic.vue

@@ -0,0 +1,84 @@
+<template>
+  <div id="ptzControl " v-loading="isLoading">
+    <el-dialog title="为设备启用算法" top="0" :close-on-click-modal="false" :visible.sync="showThisDialog" @close="close()">
+
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import handle from "@/until/handle"
+export default {
+  name: "addArithmetic",
+  data(){
+    return {
+      deviceId: '',
+      isLoading: false,
+      showThisDialog: false,
+      aiConfigs: []
+    }
+  },
+  methods:{
+    showDialog(deviceId){
+      this.showThisDialog = true;
+      this.deviceId = deviceId;
+      console.log(handle);
+    },
+    async loadAiConfigs(){
+      this.isLoading = true;
+      let [err,res] = await handle(this.$axios({
+        method: 'get',
+        url: '/api/device/query/aiLibrary'
+      }))
+      this.isLoading = false;
+      if(err){
+        console.error(err)
+        this.$message({
+          showClose: true,
+          message: err,
+          type: 'error'
+        });
+        return;
+      }
+
+      let data = res.data;
+      if(data.code === 0 ){
+        this.aiConfigs = data.data;
+      }else{
+        console.log(res);
+        console.error("未知的返回结果!")
+      }
+    }
+
+  }
+}
+</script>
+
+<style >
+.el-dialog{
+  display: flex;
+  display: -ms-flex; /* 兼容IE */
+  flex-direction: column;
+  -ms-flex-direction: column; /* 兼容IE */
+  margin:0 !important;
+  position:absolute;
+  top:50%;
+  left:50%;
+  transform:translate(-50%,-50%);
+  max-height:calc(100% - 30px);
+  max-width:calc(100% - 30px);
+  transition: all 1s;
+}
+.el-dialog .el-dialog__body{
+  max-height: 100%;
+  flex: 1;
+  -ms-flex: 1 1 auto; /* 兼容IE */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.el-dialog__wrapper {
+  /*隐藏ie和edge中遮罩的滚动条*/
+  overflow: hidden;
+}
+</style>

+ 19 - 0
web_src/src/until/handle.js

@@ -0,0 +1,19 @@
+
+
+
+function handle (promise){
+    return new Promise(resolve => {
+        try{
+            promise.then(val => {
+                resolve([null, val])
+            }).catch(err => {
+                resolve([err])
+            })
+        }catch(err){
+            resolve([err])
+        }
+    })
+}
+
+
+export default handle

+ 6 - 1
参考文档/数据库扩展.md

@@ -18,7 +18,12 @@
 | libraryId | int | tk | 图像库id  |
 | itemType | int | 1,2 | 数据类型,图片,文本 |
 | imageUrl | string | url | 图片的链接 |
+| trait | string | '' | 用来匹配的图片的特征值 |
 | textValue | string | '' | 用于匹配的值 |
+| personName | string | '' | 人员名称 |
+| workerNo | string | '' | 工号 |
+| idCard | string | '' | 身份证号 |
+
 ## ai配置 aiConfigs
 | 字段    | 类型 | 可选值 | 备注  |
 |-------| -- | --- |-----|
@@ -32,7 +37,7 @@
 | uploadUrl | string | url | 多媒体资源上传地址 |
 | pushUrl | string | url | 回调地址 | 
 
-### 国标设备配置 devAiConfigs
+### 国标设备配置 dev_ai_config
 | 字段    | 类型 | 可选值 | 备注  |
 |-------| -- | --- |-----|
 | deviceId | int | tk | 设备id |