From 15c1342cf2c576a83950c8f16e6867b070ad03c3 Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Wed, 3 Feb 2021 11:00:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=9A=E7=A7=8D=E4=BF=A1?= =?UTF-8?q?=E4=BB=A4=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../callback/DeferredResultHolder.java | 12 + .../gb28181/transmit/cmd/ISIPCommander.java | 83 +++- .../transmit/cmd/impl/SIPCommander.java | 437 ++++++++++++++++-- .../request/impl/MessageRequestProcessor.java | 298 +++++++++--- 4 files changed, 721 insertions(+), 109 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java index 574e94c7..edf86797 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -17,8 +17,16 @@ import org.springframework.web.context.request.async.DeferredResult; @Component public class DeferredResultHolder { + public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS"; + public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO"; + public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL"; + + public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG"; + + public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD"; + public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG"; public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO"; @@ -29,6 +37,10 @@ public class DeferredResultHolder { public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION"; + public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; + + public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM"; + private Map map = new ConcurrentHashMap(); public void put(String key, DeferredResult result) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index 7e63af75..30fbfe94 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -115,24 +115,35 @@ public interface ISIPCommander { /** * 音视频录像控制 * - * @param device 视频设备 - * @param channelId 预览通道 + * @param device 视频设备 + * @param channelId 预览通道 + * @param recordCmdStr 录像命令:Record / StopRecord */ - boolean recordCmd(Device device,String channelId); + boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent); + /** + * 远程启动控制命令 + * + * @param device 视频设备 + */ + boolean teleBootCmd(Device device); + /** * 报警布防/撤防命令 * - * @param device 视频设备 + * @param device 视频设备 + * @param setGuard true: SetGuard, false: ResetGuard */ - boolean guardCmd(Device device); + boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent); /** * 报警复位命令 * - * @param device 视频设备 + * @param device 视频设备 + * @param alarmMethod 报警方式(可选) + * @param alarmType 报警类型(可选) */ - boolean alarmCmd(Device device); + boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent); /** * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 @@ -140,14 +151,17 @@ public interface ISIPCommander { * @param device 视频设备 * @param channelId 预览通道 */ - boolean iFameCmd(Device device,String channelId); + boolean iFrameCmd(Device device, String channelId); /** * 看守位控制命令 * - * @param device 视频设备 + * @param device 视频设备 + * @param enabled 看守位使能:1 = 开启,0 = 关闭 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 */ - boolean homePositionCmd(Device device); + boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent); /** * 设备配置命令 @@ -156,13 +170,24 @@ public interface ISIPCommander { */ boolean deviceConfigCmd(Device device); + /** + * 设备配置命令:basicParam + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param name 设备/通道名称(可选) + * @param expiration 注册过期时间(可选) + * @param heartBeatInterval 心跳间隔时间(可选) + * @param heartBeatCount 心跳超时次数(可选) + */ + boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent); /** * 查询设备状态 * * @param device 视频设备 */ - boolean deviceStatusQuery(Device device); + boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent); /** * 查询设备信息 @@ -191,23 +216,33 @@ public interface ISIPCommander { /** * 查询报警信息 * - * @param device 视频设备 + * @param device 视频设备 + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 */ - boolean alarmInfoQuery(Device device); + boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); /** * 查询设备配置 * - * @param device 视频设备 + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param configType 配置类型: */ - boolean configQuery(Device device); + boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent); /** * 查询设备预置位置 * * @param device 视频设备 */ - boolean presetQuery(Device device); + boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent); /** * 查询移动设备位置数据 @@ -222,9 +257,25 @@ public interface ISIPCommander { * @param device 视频设备 * @param expires 订阅超时时间(值=0时为取消订阅) * @param interval 上报时间间隔 + * @return true = 命令发送成功 */ boolean mobilePositionSubscribe(Device device, int expires, int interval); + /** + * 订阅、取消订阅报警信息 + * @param device 视频设备 + * @param expires 订阅过期时间(0 = 取消订阅) + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethods 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); + + /** * 释放rtpserver * @param device diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index b661c5e6..c174455f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -34,6 +34,8 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; /** * @Description:设备能力接口,用于定义设备的控制、查询能力 @@ -577,24 +579,89 @@ public class SIPCommander implements ISIPCommander { /** * 音视频录像控制 * - * @param device 视频设备 - * @param channelId 预览通道 + * @param device 视频设备 + * @param channelId 预览通道 + * @param recordCmdStr 录像命令:Record / StopRecord */ @Override - public boolean recordCmd(Device device, String channelId) { - // TODO Auto-generated method stub - return false; + public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("" + recordCmdStr + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } + /** + * 远程启动控制命令 + * + * @param device 视频设备 + */ + @Override + public boolean teleBootCmd(Device device) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("Boot\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null); + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + /** * 报警布防/撤防命令 * - * @param device 视频设备 - */ + * @param device 视频设备 + * @param guardCmdStr "SetGuard"/"ResetGuard" + */ @Override - public boolean guardCmd(Device device) { - // TODO Auto-generated method stub - return false; + public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("" + guardCmdStr + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -603,9 +670,37 @@ public class SIPCommander implements ISIPCommander { * @param device 视频设备 */ @Override - public boolean alarmCmd(Device device) { - // TODO Auto-generated method stub - return false; + public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + cmdXml.append("ResetAlarm\r\n"); + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + cmdXml.append("\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod)) { + cmdXml.append("" + alarmMethod + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmType)) { + cmdXml.append("" + alarmType + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + cmdXml.append("\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -615,20 +710,79 @@ public class SIPCommander implements ISIPCommander { * @param channelId 预览通道 */ @Override - public boolean iFameCmd(Device device, String channelId) { - // TODO Auto-generated method stub - return false; + public boolean iFrameCmd(Device device, String channelId) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("Send\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null); + transmitRequest(device, request); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** * 看守位控制命令 * - * @param device 视频设备 + * @param device 视频设备 + * @param enabled 看守位使能:1 = 开启,0 = 关闭 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 */ @Override - public boolean homePositionCmd(Device device) { - // TODO Auto-generated method stub - return false; + public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceControl\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { + cmdXml.append("1\r\n"); + if (NumericUtil.isInteger(resetTime)) { + cmdXml.append("" + resetTime + "\r\n"); + } else { + cmdXml.append("0\r\n"); + } + if (NumericUtil.isInteger(presetIndex)) { + cmdXml.append("" + presetIndex + "\r\n"); + } else { + cmdXml.append("0\r\n"); + } + } else { + cmdXml.append("0\r\n"); + } + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -642,15 +796,88 @@ public class SIPCommander implements ISIPCommander { return false; } + /** + * 设备配置命令:basicParam + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param name 设备/通道名称(可选) + * @param expiration 注册过期时间(可选) + * @param heartBeatInterval 心跳间隔时间(可选) + * @param heartBeatCount 心跳超时次数(可选) + */ + @Override + public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("DeviceConfig\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + if (!XmlUtil.isEmpty(name)) { + cmdXml.append("" + name + "\r\n"); + } + if (NumericUtil.isInteger(expiration)) { + if (Integer.valueOf(expiration) > 0) { + cmdXml.append("" + expiration + "\r\n"); + } + } + if (NumericUtil.isInteger(heartBeatInterval)) { + if (Integer.valueOf(heartBeatInterval) > 0) { + cmdXml.append("" + heartBeatInterval + "\r\n"); + } + } + if (NumericUtil.isInteger(heartBeatCount)) { + if (Integer.valueOf(heartBeatCount) > 0) { + cmdXml.append("" + heartBeatCount + "\r\n"); + } + } + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } + } + /** * 查询设备状态 * * @param device 视频设备 */ @Override - public boolean deviceStatusQuery(Device device) { - // TODO Auto-generated method stub - return false; + public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) { + try { + StringBuffer catalogXml = new StringBuffer(200); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("DeviceStatus\r\n"); + catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + catalogXml.append("" + device.getDeviceId() + "\r\n"); + catalogXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null); + + transmitRequest(device, request, errorEvent); + return true; + + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -748,23 +975,86 @@ public class SIPCommander implements ISIPCommander { /** * 查询报警信息 * - * @param device 视频设备 - */ + * @param device 视频设备 + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethods 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ @Override - public boolean alarmInfoQuery(Device device) { - // TODO Auto-generated method stub - return false; + public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, + String startTime, String endTime, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("Alarm\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + if (!XmlUtil.isEmpty(startPriority)) { + cmdXml.append("" + startPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(endPriority)) { + cmdXml.append("" + endPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod)) { + cmdXml.append("" + alarmMethod + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmType)) { + cmdXml.append("" + alarmType + "\r\n"); + } + if (!XmlUtil.isEmpty(startTime)) { + cmdXml.append("" + startTime + "\r\n"); + } + if (!XmlUtil.isEmpty(endTime)) { + cmdXml.append("" + endTime + "\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** * 查询设备配置 * - * @param device 视频设备 - */ + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param configType 配置类型: + */ @Override - public boolean configQuery(Device device) { - // TODO Auto-generated method stub - return false; + public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("ConfigDownload\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("" + configType + "\r\n"); + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -773,9 +1063,28 @@ public class SIPCommander implements ISIPCommander { * @param device 视频设备 */ @Override - public boolean presetQuery(Device device) { - // TODO Auto-generated method stub - return false; + public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("PresetQuery\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + if (XmlUtil.isEmpty(channelId)) { + cmdXml.append("" + device.getDeviceId() + "\r\n"); + } else { + cmdXml.append("" + channelId + "\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); + transmitRequest(device, request, errorEvent); + return true; + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; + } } /** @@ -813,6 +1122,7 @@ public class SIPCommander implements ISIPCommander { * @param device 视频设备 * @param expires 订阅超时时间 * @param interval 上报时间间隔 + * @return true = 命令发送成功 */ public boolean mobilePositionSubscribe(Device device, int expires, int interval) { try { @@ -828,7 +1138,60 @@ public class SIPCommander implements ISIPCommander { subscribePostitionXml.append("\r\n"); String tm = Long.toString(System.currentTimeMillis()); - Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "Position;id=" + tm.substring(tm.length() - 4)); + Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4)); + transmitRequest(device, request); + + return true; + + } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { + e.printStackTrace(); + return false; + } + } + + /** + * 订阅、取消订阅报警信息 + * + * @param device 视频设备 + * @param expires 订阅过期时间(0 = 取消订阅) + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) { + try { + StringBuffer cmdXml = new StringBuffer(200); + cmdXml.append("\r\n"); + cmdXml.append("\r\n"); + cmdXml.append("Alarm\r\n"); + cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); + cmdXml.append("" + device.getDeviceId() + "\r\n"); + if (!XmlUtil.isEmpty(startPriority)) { + cmdXml.append("" + startPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(endPriority)) { + cmdXml.append("" + endPriority + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmMethod)) { + cmdXml.append("" + alarmMethod + "\r\n"); + } + if (!XmlUtil.isEmpty(alarmType)) { + cmdXml.append("" + alarmType + "\r\n"); + } + if (!XmlUtil.isEmpty(startTime)) { + cmdXml.append("" + startTime + "\r\n"); + } + if (!XmlUtil.isEmpty(endTime)) { + cmdXml.append("" + endTime + "\r\n"); + } + cmdXml.append("\r\n"); + + String tm = Long.toString(System.currentTimeMillis()); + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); transmitRequest(device, request); return true; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index 1c7c775b..c865ad39 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -10,6 +10,7 @@ import javax.sip.SipException; import javax.sip.message.Request; import javax.sip.message.Response; +import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.UserSetup; @@ -78,9 +79,12 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { private static final String MESSAGE_RECORD_INFO = "RecordInfo"; private static final String MESSAGE_MEDIA_STATUS = "MediaStatus"; // private static final String MESSAGE_BROADCAST = "Broadcast"; - // private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus"; + private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus"; + private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl"; + private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig"; private static final String MESSAGE_MOBILE_POSITION = "MobilePosition"; // private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval"; + private static final String MESSAGE_PRESET_QUERY = "PresetQuery"; /** * 处理MESSAGE请求 @@ -99,12 +103,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { processMessageKeepAlive(evt); } else if (MESSAGE_CONFIG_DOWNLOAD.equals(cmd)) { logger.info("接收到ConfigDownload消息"); + processMessageConfigDownload(evt); } else if (MESSAGE_CATALOG.equals(cmd)) { logger.info("接收到Catalog消息"); processMessageCatalogList(evt); } else if (MESSAGE_DEVICE_INFO.equals(cmd)) { logger.info("接收到DeviceInfo消息"); processMessageDeviceInfo(evt); + } else if (MESSAGE_DEVICE_STATUS.equals(cmd)) { + logger.info("接收到DeviceStatus消息"); + processMessageDeviceStatus(evt); + } else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) { + logger.info("接收到DeviceControl消息"); + processMessageDeviceControl(evt); + } else if (MESSAGE_DEVICE_CONFIG.equals(cmd)) { + logger.info("接收到DeviceConfig消息"); + processMessageDeviceConfig(evt); } else if (MESSAGE_ALARM.equals(cmd)) { logger.info("接收到Alarm消息"); processMessageAlarm(evt); @@ -117,6 +131,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } else if (MESSAGE_MOBILE_POSITION.equals(cmd)) { logger.info("接收到MobilePosition消息"); processMessageMobilePosition(evt); + } else if (MESSAGE_PRESET_QUERY.equals(cmd)) { + logger.info("接收到PresetQuery消息"); + processMessagePresetQuery(evt); } else { logger.info("接收到消息:" + cmd); responseAck(evt); @@ -133,7 +150,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { */ private void processMessageMobilePosition(RequestEvent evt) { try { - //回复 200 OK Element rootElement = getRootElement(evt); MobilePosition mobilePosition = new MobilePosition(); Element deviceIdElement = rootElement.element("DeviceID"); @@ -174,12 +190,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { storager.clearMobilePositionsByDeviceId(deviceId); } storager.insertMobilePosition(mobilePosition); - // List all= storager.queryMobilePositions(deviceId, "2021-01-23T00:00:00", "2021-02-28T23:59:59"); - // all= storager.queryMobilePositions(deviceId, null, "2021-01-24T23:59:59"); - // all= storager.queryMobilePositions(deviceId, "2021-01-24T00:00:00", null); - // //logger.debug(all.toString()); - // MobilePosition mp = storager.queryLatestPosition(deviceId); - // logger.debug("最新位置:" + mp.getLongitude() + ", " + mp.getLatitude()); + //回复 200 OK responseAck(evt); } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); @@ -187,7 +198,169 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } /** - * 收到deviceInfo设备信息请求 处理 + * 处理DeviceStatus设备状态Message + * + * @param evt + */ + private void processMessageDeviceStatus(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + // 检查设备是否存在, 不存在则不回复 + if (storager.exists(deviceId)) { + // 回复200 OK + responseAck(evt); + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + } else { + } + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 处理DeviceControl设备状态Message + * + * @param evt + */ + private void processMessageDeviceControl(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + String result = XmlUtil.getText(rootElement, "Result"); + // 回复200 OK + responseAck(evt); + if (!XmlUtil.isEmpty(result)) { + // 此处是对本平台发出DeviceControl指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + } else { + // 此处是上级发出的DeviceControl指令 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 处理DeviceConfig设备状态Message + * + * @param evt + */ + private void processMessageDeviceConfig(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + String result = XmlUtil.getText(rootElement, "Result"); + // 回复200 OK + responseAck(evt); + //if (!XmlUtil.isEmpty(result)) { + // 此处是对本平台发出DeviceControl指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + // } else { + // // 此处是上级发出的DeviceConfig指令 + //} + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 处理ConfigDownload设备状态Message + * + * @param evt + */ + private void processMessageConfigDownload(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + String result = XmlUtil.getText(rootElement, "Result"); + // 回复200 OK + responseAck(evt); + //if (!XmlUtil.isEmpty(result)) { + // 此处是对本平台发出DeviceControl指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + // } else { + // // 此处是上级发出的DeviceConfig指令 + //} + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 处理PresetQuery预置位列表Message + * + * @param evt + */ + private void processMessagePresetQuery(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); + String result = XmlUtil.getText(rootElement, "Result"); + // 回复200 OK + responseAck(evt); + if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) { + // 此处是对本平台发出DeviceControl指令的应答 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY); + msg.setData(json); + deferredResultHolder.invokeResult(msg); + } else { + // 此处是上级发出的DeviceControl指令 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 处理DeviceInfo设备信息Message * * @param evt */ @@ -354,56 +527,72 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { Element rootElement = getRootElement(evt); Element deviceIdElement = rootElement.element("DeviceID"); String deviceId = deviceIdElement.getText().toString(); + // 回复200 OK + responseAck(evt); Device device = storager.queryVideoDevice(deviceId); if (device == null) { return; } - DeviceAlarm deviceAlarm = new DeviceAlarm(); - deviceAlarm.setDeviceId(deviceId); - deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); - deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); - deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); - if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { - deviceAlarm.setAlarmDescription(""); - } else { - deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); - } - if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) { - deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); - } else { - deviceAlarm.setLongitude(0.00); - } - if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) { - deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); - } else { - deviceAlarm.setLatitude(0.00); - } - if ( deviceAlarm.getAlarmMethod().equals("4")) { - MobilePosition mobilePosition = new MobilePosition(); - mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); - mobilePosition.setTime(deviceAlarm.getAlarmTime()); - mobilePosition.setLongitude(deviceAlarm.getLongitude()); - mobilePosition.setLatitude(deviceAlarm.getLatitude()); - mobilePosition.setReportSource("GPS Alarm"); - BaiduPoint bp = new BaiduPoint(); - bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); - logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); - mobilePosition.setGeodeticSystem("BD-09"); - mobilePosition.setCnLng(bp.getBdLng()); - mobilePosition.setCnLat(bp.getBdLat()); - if (!userSetup.getSavePositionHistory()) { - storager.clearMobilePositionsByDeviceId(deviceId); + if (rootElement.getName().equals("Notify")) { // 处理报警通知 + DeviceAlarm deviceAlarm = new DeviceAlarm(); + deviceAlarm.setDeviceId(deviceId); + deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); + deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); + deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); + if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { + deviceAlarm.setAlarmDescription(""); + } else { + deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); } - storager.insertMobilePosition(mobilePosition); - } - // TODO: 需要实现存储报警信息、报警分类 - - // 回复200 OK - responseAck(evt); - if (offLineDetector.isOnline(deviceId)) { - publisher.deviceAlarmEventPublish(deviceAlarm); + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) { + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); + } else { + deviceAlarm.setLongitude(0.00); + } + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) { + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); + } else { + deviceAlarm.setLatitude(0.00); + } + + if (!XmlUtil.isEmpty(deviceAlarm.getAlarmMethod())) { + if ( deviceAlarm.getAlarmMethod().equals("4")) { + MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); + mobilePosition.setTime(deviceAlarm.getAlarmTime()); + mobilePosition.setLongitude(deviceAlarm.getLongitude()); + mobilePosition.setLatitude(deviceAlarm.getLatitude()); + mobilePosition.setReportSource("GPS Alarm"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + } + } + // TODO: 需要实现存储报警信息、报警分类 + + if (offLineDetector.isOnline(deviceId)) { + publisher.deviceAlarmEventPublish(deviceAlarm); + } + } else if (rootElement.getName().equals("Response")) { // 处理报警查询响应 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_ALARM); + msg.setData(json); + deferredResultHolder.invokeResult(msg); } } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { // } catch (DocumentException e) { @@ -435,7 +624,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { } /*** - * 收到catalog设备目录列表请求 处理 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致 + * 处理RecordInfo设备录像列表Message请求 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致 * * @param evt */ @@ -522,12 +711,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作 // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据 - // 对记录进行排序 RequestMessage msg = new RequestMessage(); msg.setDeviceId(deviceId); msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); - // // 自然顺序排序, 元素进行升序排列 - // recordInfo.getRecordList().sort(Comparator.naturalOrder()); msg.setData(recordInfo); deferredResultHolder.invokeResult(msg); logger.info("处理完成,返回结果");