浏览代码

增加消息通道配置,可以通道redis在wvp上下级之间发送消息

648540858 2 年之前
父节点
当前提交
943f95ba8c

+ 6 - 0
sql/2.6.6-2.6.7更新.sql

@@ -0,0 +1,6 @@
+alter table device
+    add asMessageChannel int default 0;
+
+alter table parent_platform
+    add asMessageChannel int default 0;
+

+ 2 - 0
src/main/resources/db/migration/V2.6.7_20230201__初始化.sql → sql/初始化.sql

@@ -47,6 +47,7 @@ CREATE TABLE `device` (
                           `mobilePositionSubmissionInterval` int DEFAULT '5',
                           `subscribeCycleForAlarm` int DEFAULT NULL,
                           `ssrcCheck` int DEFAULT '0',
+                          `asMessageChannel` int DEFAULT '0',
                           `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
                           `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
                           `custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
@@ -329,6 +330,7 @@ CREATE TABLE `parent_platform` (
                                    `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
                                    `ptz` int DEFAULT NULL,
                                    `rtcp` int DEFAULT NULL,
+                                   `asMessageChannel` int DEFAULT '0',
                                    `status` bit(1) DEFAULT NULL,
                                    `startOfflinePush` int DEFAULT '0',
                                    `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,

+ 9 - 0
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java

@@ -48,6 +48,7 @@ public class UserSetting {
     private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
 
     private Boolean sipLog = Boolean.FALSE;
+    private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
 
     private String serverId = "000000";
 
@@ -218,4 +219,12 @@ public class UserSetting {
     public void setSipLog(Boolean sipLog) {
         this.sipLog = sipLog;
     }
+
+    public Boolean getSendToPlatformsWhenIdLost() {
+        return sendToPlatformsWhenIdLost;
+    }
+
+    public void setSendToPlatformsWhenIdLost(Boolean sendToPlatformsWhenIdLost) {
+        this.sendToPlatformsWhenIdLost = sendToPlatformsWhenIdLost;
+    }
 }

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java

@@ -188,6 +188,9 @@ public class Device {
 	@Schema(description = "SIP交互IP(设备访问平台的IP)")
 	private String localIp;
 
+	@Schema(description = "是否作为消息通道")
+	private boolean asMessageChannel;
+
 
 	public String getDeviceId() {
 		return deviceId;
@@ -428,4 +431,12 @@ public class Device {
 	public void setKeepaliveIntervalTime(int keepaliveIntervalTime) {
 		this.keepaliveIntervalTime = keepaliveIntervalTime;
 	}
+
+	public boolean isAsMessageChannel() {
+		return asMessageChannel;
+	}
+
+	public void setAsMessageChannel(boolean asMessageChannel) {
+		this.asMessageChannel = asMessageChannel;
+	}
 }

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java

@@ -189,6 +189,9 @@ public class ParentPlatform {
     @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")
     private String treeType;
 
+    @Schema(description = "是否作为消息通道")
+    private boolean asMessageChannel;
+
     public Integer getId() {
         return id;
     }
@@ -428,4 +431,12 @@ public class ParentPlatform {
     public void setTreeType(String treeType) {
         this.treeType = treeType;
     }
+
+    public boolean isAsMessageChannel() {
+        return asMessageChannel;
+    }
+
+    public void setAsMessageChannel(boolean asMessageChannel) {
+        this.asMessageChannel = asMessageChannel;
+    }
 }

+ 11 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java

@@ -1,6 +1,8 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 import java.time.Instant;
 import java.util.List;
 
@@ -9,22 +11,29 @@ import java.util.List;
  * @author: swwheihei
  * @date:   2020年5月8日 下午2:05:56     
  */
+@Schema(description = "设备录像查询结果信息")
 public class RecordInfo {
 
+	@Schema(description = "设备编号")
 	private String deviceId;
 
+	@Schema(description = "通道编号")
 	private String channelId;
 
+	@Schema(description = "命令序列号")
 	private String sn;
 
+	@Schema(description = "设备名称")
 	private String name;
-	
+
+	@Schema(description = "列表总数")
 	private int sumNum;
 
 	private int count;
 
 	private Instant lastTime;
-	
+
+	@Schema(description = "")
 	private List<RecordItem> recordList;
 
 	public String getDeviceId() {

+ 19 - 8
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java

@@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean;
 
 
 import com.genersoft.iot.vmp.utils.DateUtil;
+import io.swagger.v3.oas.annotations.media.Schema;
 import org.jetbrains.annotations.NotNull;
 
-import java.text.ParseException;
 import java.time.Instant;
 import java.time.temporal.TemporalAccessor;
 
@@ -13,26 +13,37 @@ import java.time.temporal.TemporalAccessor;
  * @author: swwheihei
  * @date:   2020年5月8日 下午2:06:54     
  */
+@Schema(description = "设备录像详情")
 public class RecordItem  implements Comparable<RecordItem>{
 
+	@Schema(description = "设备编号")
 	private String deviceId;
-	
+
+	@Schema(description = "名称")
 	private String name;
-	
+
+	@Schema(description = "文件路径名 (可选)")
 	private String filePath;
 
+	@Schema(description = "录像文件大小,单位:Byte(可选)")
 	private String fileSize;
 
+	@Schema(description = "录像地址(可选)")
 	private String address;
-	
+
+	@Schema(description = "录像开始时间(可选)")
 	private String startTime;
-	
+
+	@Schema(description = "录像结束时间(可选)")
 	private String endTime;
-	
+
+	@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
 	private int secrecy;
-	
+
+	@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
 	private String type;
-	
+
+	@Schema(description = "录像触发者ID(可选)")
 	private String recorderId;
 
 	public String getDeviceId() {

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@@ -1376,7 +1376,7 @@ public class SIPCommander implements ISIPCommander {
         if (device == null) {
             return;
         }
-        logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
+        logger.info("[发送报警通知]设备: {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
                 deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
 
         String characterSet = device.getCharset();

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java

@@ -402,7 +402,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
         if (parentPlatform == null) {
             return;
         }
-        logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
+        logger.info("[发送报警通知]平台: {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
                 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm));
         String characterSet = parentPlatform.getCharacterSet();
         StringBuffer deviceStatusXml = new StringBuffer(600);

+ 39 - 7
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java

@@ -1,6 +1,7 @@
 package com.genersoft.iot.vmp.service.redisMsg;
 
 import com.alibaba.fastjson2.JSON;
+import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@@ -44,8 +45,12 @@ public class RedisAlarmMsgListener implements MessageListener {
     @Autowired
     private ThreadPoolTaskExecutor taskExecutor;
 
+    @Autowired
+    private UserSetting userSetting;
+
     @Override
     public void onMessage(@NotNull Message message, byte[] bytes) {
+        // 消息示例:  PUBLISH alarm_receive '{ "gbId": "", "alarmSn": 1, "alarmType": "111", "alarmDescription": "222", }'
         logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody()));
         boolean isEmpty = taskQueue.isEmpty();
         taskQueue.offer(message);
@@ -74,17 +79,44 @@ public class RedisAlarmMsgListener implements MessageListener {
                         deviceAlarm.setLatitude(0);
 
                         if (ObjectUtils.isEmpty(gbId)) {
-                            // 发送给所有的上级
-                            List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
-                            if (parentPlatforms.size() > 0) {
-                                for (ParentPlatform parentPlatform : parentPlatforms) {
+                            if (userSetting.getSendToPlatformsWhenIdLost()) {
+                                // 发送给所有的上级
+                                List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
+                                if (parentPlatforms.size() > 0) {
+                                    for (ParentPlatform parentPlatform : parentPlatforms) {
+                                        try {
+                                            commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
+                                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                                            logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
+                                        }
+                                    }
+                                }
+                            }else {
+                                // 获取开启了消息推送的设备和平台
+                                List<ParentPlatform> parentPlatforms = storage.queryEnablePlatformListWithAsMessageChannel();
+                                if (parentPlatforms.size() > 0) {
+                                    for (ParentPlatform parentPlatform : parentPlatforms) {
+                                        try {
+                                            commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
+                                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                                            logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
+                                        }
+                                    }
+                                }
+
+                            }
+                            // 获取开启了消息推送的设备和平台
+                            List<Device> devices = storage.queryDeviceWithAsMessageChannel();
+                            if (devices.size() > 0) {
+                                for (Device device : devices) {
                                     try {
-                                        commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
-                                    } catch (SipException | InvalidArgumentException | ParseException e) {
-                                        logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
+                                        commander.sendAlarmMessage(device, deviceAlarm);
+                                    } catch (InvalidArgumentException | SipException | ParseException e) {
+                                        logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
                                     }
                                 }
                             }
+
                         }else {
                             Device device = storage.queryVideoDevice(gbId);
                             ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);

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

@@ -378,4 +378,7 @@ public interface IVideoManagerStorage {
 
 	List<DeviceChannelExtend> queryChannelsByDeviceId(String serial, List<String> channelIds, Boolean online);
 
+	List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel();
+
+	List<Device> queryDeviceWithAsMessageChannel();
 }

+ 12 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java

@@ -39,6 +39,7 @@ public interface DeviceMapper {
             "mobilePositionSubmissionInterval," +
             "subscribeCycleForAlarm," +
             "ssrcCheck," +
+            "asMessageChannel," +
             "geoCoordSys," +
             "treeType," +
             "online" +
@@ -70,6 +71,7 @@ public interface DeviceMapper {
                 "mobilePositionSubmissionInterval," +
                 "subscribeCycleForAlarm," +
                 "ssrcCheck," +
+                "asMessageChannel," +
                 "geoCoordSys," +
                 "treeType," +
                 "online" +
@@ -98,6 +100,7 @@ public interface DeviceMapper {
                 "#{mobilePositionSubmissionInterval}," +
                 "#{subscribeCycleForAlarm}," +
                 "#{ssrcCheck}," +
+                "#{asMessageChannel}," +
                 "#{geoCoordSys}," +
                 "#{treeType}," +
                 "#{online}" +
@@ -152,6 +155,7 @@ public interface DeviceMapper {
             "mobilePositionSubmissionInterval," +
             "subscribeCycleForAlarm," +
             "ssrcCheck," +
+            "asMessageChannel," +
             "geoCoordSys," +
             "treeType," +
             "online," +
@@ -192,6 +196,7 @@ public interface DeviceMapper {
             "mobilePositionSubmissionInterval," +
             "subscribeCycleForAlarm," +
             "ssrcCheck," +
+            "asMessageChannel," +
             "geoCoordSys," +
             "treeType," +
             "online " +
@@ -222,6 +227,7 @@ public interface DeviceMapper {
             "mobilePositionSubmissionInterval," +
             "subscribeCycleForAlarm," +
             "ssrcCheck," +
+            "asMessageChannel," +
             "geoCoordSys," +
             "treeType," +
             "online" +
@@ -243,6 +249,7 @@ public interface DeviceMapper {
             "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" +
             "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" +
             "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" +
+            "<if test=\"asMessageChannel != null\">, asMessageChannel=#{asMessageChannel}</if>" +
             "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" +
             "<if test=\"treeType != null\">, treeType=#{treeType}</if>" +
             "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" +
@@ -259,6 +266,7 @@ public interface DeviceMapper {
             "updateTime," +
             "charset," +
             "ssrcCheck," +
+            "asMessageChannel," +
             "geoCoordSys," +
             "treeType," +
             "online" +
@@ -271,6 +279,7 @@ public interface DeviceMapper {
             "#{updateTime}," +
             "#{charset}," +
             "#{ssrcCheck}," +
+            "#{asMessageChannel}," +
             "#{geoCoordSys}," +
             "#{treeType}," +
             "#{online}" +
@@ -282,4 +291,7 @@ public interface DeviceMapper {
 
     @Select("select * from device")
     List<Device> getAll();
+
+    @Select("select * from device where  asMessageChannel = 1")
+    List<Device> queryDeviceWithAsMessageChannel();
 }

+ 7 - 3
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java

@@ -15,10 +15,10 @@ import java.util.List;
 public interface ParentPlatformMapper {
 
     @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp,  " +
-            "            devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
+            "            devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, asMessageChannel, " +
             "            status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
             "            VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
-            "            #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, " +
+            "            #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " +
             "            #{status},  #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
     int addParentPlatform(ParentPlatform parentPlatform);
 
@@ -40,6 +40,7 @@ public interface ParentPlatformMapper {
             "characterSet=#{characterSet}, " +
             "ptz=#{ptz}, " +
             "rtcp=#{rtcp}, " +
+            "asMessageChannel=#{asMessageChannel}, " +
             "status=#{status}, " +
             "startOfflinePush=#{startOfflinePush}, " +
             "catalogGroup=#{catalogGroup}, " +
@@ -68,9 +69,12 @@ public interface ParentPlatformMapper {
             "FROM parent_platform pp ")
     List<ParentPlatform> getParentPlatformList();
 
-    @Select("SELECT * FROM parent_platform WHERE enable=#{enable}")
+    @Select("SELECT * FROM parent_platform WHERE enable=#{enable} ")
     List<ParentPlatform> getEnableParentPlatformList(boolean enable);
 
+    @Select("SELECT * FROM parent_platform WHERE enable=1 and asMessageChannel = 1")
+    List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel();
+
     @Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}")
     ParentPlatform getParentPlatByServerGBId(String platformGbId);
 

+ 10 - 0
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -524,6 +524,16 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 		return platformMapper.getEnableParentPlatformList(enable);
 	}
 
+	@Override
+	public List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel() {
+		return platformMapper.queryEnablePlatformListWithAsMessageChannel();
+	}
+
+	@Override
+	public List<Device> queryDeviceWithAsMessageChannel() {
+		return deviceMapper.queryDeviceWithAsMessageChannel();
+	}
+
 	@Override
 	public void outlineForAllParentPlatform() {
 		platformMapper.outlineForAllParentPlatform();

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

@@ -199,8 +199,8 @@ user-settings:
     sip-use-source-ip-as-remote-address: false
     # 是否开启sip日志
     sip-log: true
-    # 自动数据库升级,保证表结构完整
-    sync-db: true
+    # 消息通道功能-缺少国标ID是否给所有上级发送消息
+    send-to-platforms-when-id-lost: true
 
 # 关闭在线文档(生产环境建议关闭)
 springdoc:

+ 1 - 0
web_src/index.html

@@ -15,5 +15,6 @@
     <script type="text/javascript" src="./static/js/ZLMRTCClient.js"></script>
     <script type="text/javascript" src="./static/js/config.js"></script>
     <div id="app"></div>
+
   </body>
 </html>

+ 1 - 0
web_src/src/components/dialog/deviceEdit.vue

@@ -66,6 +66,7 @@
           </el-form-item>
           <el-form-item label="其他选项">
             <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
+            <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
           </el-form-item>
           <el-form-item>
             <div style="float: right;">

+ 5 - 1
web_src/src/components/dialog/platformEdit.vue

@@ -96,9 +96,10 @@
               </el-form-item>
               <el-form-item label="其他选项">
                 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
-                <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
+<!--                <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>-->
                 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
                 <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
+                <el-checkbox label="作为消息通道" v-model="platform.asMessageChannel" ></el-checkbox>
               </el-form-item>
               <el-form-item>
                 <el-button type="primary" @click="onSubmit">{{
@@ -145,6 +146,7 @@ export default {
         enable: true,
         ptz: true,
         rtcp: false,
+        asMessageChannel: false,
         name: null,
         serverGBId: null,
         serverGBDomain: null,
@@ -213,6 +215,7 @@ export default {
         this.platform.enable = platform.enable;
         this.platform.ptz = platform.ptz;
         this.platform.rtcp = platform.rtcp;
+        this.platform.rtcpasMessageChannel = platform.asMessageChannel;
         this.platform.name = platform.name;
         this.platform.serverGBId = platform.serverGBId;
         this.platform.serverGBDomain = platform.serverGBDomain;
@@ -290,6 +293,7 @@ export default {
         enable: true,
         ptz: true,
         rtcp: false,
+        asMessageChannel: false,
         name: null,
         serverGBId: null,
         administrativeDivision: null,