From 9a30a0f23afa6baa92eb840c933a7a5f386c1e7e Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: Wed, 20 Jan 2021 09:53:25 +0800 Subject: [PATCH 01/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BD=E6=A0=87?= =?UTF-8?q?=E6=A0=A1=E6=97=B6=E7=9A=84=E6=97=B6=E5=8C=BA=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=AF=BC=E8=87=B4=E6=97=B6=E9=97=B4=E5=B7=AE=E5=85=AB?= =?UTF-8?q?=E4=B8=AA=E5=B0=8F=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/WvpSipDate.java | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java index ba1a1c7a..50d1f26b 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java @@ -1,14 +1,95 @@ package com.genersoft.iot.vmp.gb28181.bean; +import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.header.SIPDate; +import java.util.*; + /** * 重写jain sip的SIPDate解决与国标时间格式不一致的问题 */ public class WvpSipDate extends SIPDate { + private Calendar javaCal; + public WvpSipDate(long timeMillis) { - super(timeMillis); + this.javaCal = new GregorianCalendar(TimeZone.getDefault(), Locale.getDefault()); + Date date = new Date(timeMillis); + this.javaCal.setTime(date); + this.wkday = this.javaCal.get(7); + switch(this.wkday) { + case 1: + this.sipWkDay = "Sun"; + break; + case 2: + this.sipWkDay = "Mon"; + break; + case 3: + this.sipWkDay = "Tue"; + break; + case 4: + this.sipWkDay = "Wed"; + break; + case 5: + this.sipWkDay = "Thu"; + break; + case 6: + this.sipWkDay = "Fri"; + break; + case 7: + this.sipWkDay = "Sat"; + break; + default: + InternalErrorHandler.handleException("No date map for wkday " + this.wkday); + } + + this.day = this.javaCal.get(5); + this.month = this.javaCal.get(2); + switch(this.month) { + case 0: + this.sipMonth = "Jan"; + break; + case 1: + this.sipMonth = "Feb"; + break; + case 2: + this.sipMonth = "Mar"; + break; + case 3: + this.sipMonth = "Apr"; + break; + case 4: + this.sipMonth = "May"; + break; + case 5: + this.sipMonth = "Jun"; + break; + case 6: + this.sipMonth = "Jul"; + break; + case 7: + this.sipMonth = "Aug"; + break; + case 8: + this.sipMonth = "Sep"; + break; + case 9: + this.sipMonth = "Oct"; + break; + case 10: + this.sipMonth = "Nov"; + break; + case 11: + this.sipMonth = "Dec"; + break; + default: + InternalErrorHandler.handleException("No date map for month " + this.month); + } + + this.year = this.javaCal.get(1); + this.hour = this.javaCal.get(11); + this.minute = this.javaCal.get(12); + this.second = this.javaCal.get(13); } @Override From 41c1127f6c744d8b0449584bed7da551502a2d43 Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: Wed, 20 Jan 2021 10:04:52 +0800 Subject: [PATCH 02/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BD=E6=A0=87?= =?UTF-8?q?=E6=A0=A1=E6=97=B6=E7=9A=84=E6=97=B6=E5=8C=BA=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=AF=BC=E8=87=B4=E6=97=B6=E9=97=B4=E5=B7=AE=E5=85=AB?= =?UTF-8?q?=E4=B8=AA=E5=B0=8F=E6=97=B6=E7=9A=84=E4=B8=80=E4=B8=AA=E9=94=99?= =?UTF-8?q?=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java index 50d1f26b..42ad6edd 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java @@ -129,7 +129,7 @@ public class WvpSipDate extends SIPDate { var6 = "" + this.second; } - int var8 = this.getJavaCal().get(14); + int var8 = this.javaCal.get(14); String var7; if (var8 < 10) { var7 = "00" + var8; From a6ed1268e37248c5c0a2566abbf40793101fa30a Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Wed, 20 Jan 2021 23:31:00 +0800 Subject: [PATCH 03/26] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8A=A5=E8=AD=A6?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E3=80=81=E5=8F=91=E5=B8=83=E5=92=8CSSE?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../iot/vmp/gb28181/bean/DeviceAlarm.java | 10 ++-- .../iot/vmp/gb28181/event/EventPublisher.java | 12 ++++ .../vmp/gb28181/event/alarm/AlarmEvent.java | 26 +++++++++ .../event/alarm/AlarmEventListener.java | 47 ++++++++++++++++ .../request/impl/MessageRequestProcessor.java | 39 ++++++++++--- .../vmp/storager/dao/DeviceChannelMapper.java | 1 + .../vmanager/SEEController/SEEController.java | 32 +++++++++++ web_src/src/components/UiHeader.vue | 56 ++++++++++++++++++- web_src/src/main.js | 3 + 10 files changed, 211 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java diff --git a/README.md b/README.md index 19bcd515..724cfef7 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ https://gitee.com/18010473990/wvp-GB28181.git 11. 支持公网部署, 支持wvp与zlm分开部署 12. 支持播放h265, g.711格式的流 13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)) +14. 报警信息处理,支持向前端推送报警信息 # 待实现: 上级级联 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java index d91a1c7f..35cb6bf4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java @@ -11,7 +11,7 @@ public class DeviceAlarm { /** * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情- */ - private String alarmPriorit; + private String alarmPriority; /** * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警, @@ -53,12 +53,12 @@ public class DeviceAlarm { this.deviceId = deviceId; } - public String getAlarmPriorit() { - return alarmPriorit; + public String getAlarmPriority() { + return alarmPriority; } - public void setAlarmPriorit(String alarmPriorit) { - this.alarmPriorit = alarmPriorit; + public void setAlarmPriority(String alarmPriority) { + this.alarmPriority = alarmPriority; } public String getAlarmMethod() { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java index ebf04305..50f6bc0c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; +import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent; import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; @@ -31,4 +33,14 @@ public class EventPublisher { outEvent.setFrom(from); applicationEventPublisher.publishEvent(outEvent); } + + /** + * 设备报警事件 + * @param deviceAlarm + */ + public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) { + AlarmEvent alarmEvent = new AlarmEvent(this); + alarmEvent.setAlarmInfo(deviceAlarm); + applicationEventPublisher.publishEvent(alarmEvent); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java new file mode 100644 index 00000000..fecc8b1b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java @@ -0,0 +1,26 @@ +package com.genersoft.iot.vmp.gb28181.event.alarm; + +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; +import org.springframework.context.ApplicationEvent; + +/** + * @description: 报警事件 + * @author: lawrencehj + * @data: 2021-01-20 + */ + +public class AlarmEvent extends ApplicationEvent { + public AlarmEvent(Object source) { + super(source); + } + + private DeviceAlarm deviceAlarm; + + public DeviceAlarm getAlarmInfo() { + return deviceAlarm; + } + + public void setAlarmInfo(DeviceAlarm deviceAlarm) { + this.deviceAlarm = deviceAlarm; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java new file mode 100644 index 00000000..1b2f6723 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java @@ -0,0 +1,47 @@ +package com.genersoft.iot.vmp.gb28181.event.alarm; + +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @description: 报警事件监听 + * @author: lawrencehj + * @data: 2021-01-20 + */ + +@Component +public class AlarmEventListener implements ApplicationListener { + + private final static Logger logger = LoggerFactory.getLogger(AlarmEventListener.class); + + private static SseEmitter emitter = new SseEmitter(); + + public void addSseEmitters(SseEmitter sseEmitter) { + emitter = sseEmitter; + } + + @Override + public void onApplicationEvent(AlarmEvent event) { + if (logger.isDebugEnabled()) { + logger.debug("设备报警事件触发,deviceId:" + event.getAlarmInfo().getDeviceId() + ", " + + event.getAlarmInfo().getAlarmDescription()); + } + try { + String msg = "设备编码: " + event.getAlarmInfo().getDeviceId() + "" + + "
报警描述: " + event.getAlarmInfo().getAlarmDescription() + "" + + "
报警时间: " + event.getAlarmInfo().getAlarmTime() + "" + + "
定位经度: " + event.getAlarmInfo().getLongitude() + "" + + "
定位纬度: " + event.getAlarmInfo().getLatitude() + ""; + emitter.send(msg); + } catch (IOException e) { + if (logger.isDebugEnabled()) { + logger.debug("SSE 通道已关闭"); + } + // e.printStackTrace(); + } + } +} 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 fbdc7e26..73e67e58 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 @@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.bean.RecordItem; @@ -289,19 +290,41 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { // storager.queryChannel(deviceId) return; } - device.setName(XmlUtil.getText(rootElement, "DeviceName")); - device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer")); - device.setModel(XmlUtil.getText(rootElement, "Model")); - device.setFirmware(XmlUtil.getText(rootElement, "Firmware")); - if (StringUtils.isEmpty(device.getStreamMode())) { - device.setStreamMode("UDP"); + + 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.updateDevice(device); + if (XmlUtil.getText(rootElement, "Longitude") == null || XmlUtil.getText(rootElement, "Longitude") == "") { + deviceAlarm.setLongitude(0.00); + } else { + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); + } + if (XmlUtil.getText(rootElement, "Latitude") == null || XmlUtil.getText(rootElement, "Latitude") =="") { + deviceAlarm.setLatitude(0.00); + } else { + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); + } + + // device.setName(XmlUtil.getText(rootElement, "DeviceName")); + // device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer")); + // device.setModel(XmlUtil.getText(rootElement, "Model")); + // device.setFirmware(XmlUtil.getText(rootElement, "Firmware")); + // if (StringUtils.isEmpty(device.getStreamMode())) { + // device.setStreamMode("UDP"); + // } + // storager.updateDevice(device); //cmder.catalogQuery(device, null); // 回复200 OK responseAck(evt); if (offLineDetector.isOnline(deviceId)) { - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + publisher.deviceAlarmEventPublish(deviceAlarm); } } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { // } catch (DocumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java index 57dc96d6..11b728a8 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -59,6 +59,7 @@ public interface DeviceChannelMapper { " WHERE 1=1 " + " AND subCount >0" + " AND subCount=0" + + " ORDER BY channelId ASC" + " "}) List queryChannelsByDeviceId(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java new file mode 100644 index 00000000..689b967b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java @@ -0,0 +1,32 @@ +package com.genersoft.iot.vmp.vmanager.SEEController; + +import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +/** + * @description: SSE推送 + * @author: lawrencehj + * @data: 2021-01-20 + */ + +@Controller +@RequestMapping("/api") +public class SEEController { + @Autowired + AlarmEventListener alarmEventListener; + + //设置响应 + @RequestMapping("/emit") + public SseEmitter emit() { + SseEmitter sseEmitter = new SseEmitter(0L); + try { + alarmEventListener.addSseEmitters(sseEmitter); + }catch (Exception e){ + sseEmitter.completeWithError(e); + } + return sseEmitter; + } +} diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index 832d69ef..f16beba8 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -4,7 +4,7 @@ 控制台 设备列表 - + 退出 @@ -13,14 +13,64 @@ diff --git a/web_src/src/main.js b/web_src/src/main.js index 6f88c2a9..ae2baeef 100644 --- a/web_src/src/main.js +++ b/web_src/src/main.js @@ -9,10 +9,13 @@ import VueCookies from 'vue-cookies'; import echarts from 'echarts'; import VueClipboard from 'vue-clipboard2' +import { Notification } from 'element-ui'; + Vue.use(VueClipboard) Vue.use(ElementUI); Vue.use(VueCookies); Vue.prototype.$axios = axios; +Vue.prototype.$notify = Notification; axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : ""; From 5f379e2610a9b23403dea06c1ab248f32c2e55de Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Thu, 21 Jan 2021 19:51:23 +0800 Subject: [PATCH 04/26] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E8=B0=83=E6=95=B4=EF=BC=8C=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/.postcssrc.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web_src/.postcssrc.js b/web_src/.postcssrc.js index eee3e92d..b04dd5a9 100644 --- a/web_src/.postcssrc.js +++ b/web_src/.postcssrc.js @@ -5,6 +5,13 @@ module.exports = { "postcss-import": {}, "postcss-url": {}, // to edit target browsers: use "browserslist" field in package.json - "autoprefixer": {} + "autoprefixer": {}, + 'postcss-pxtorem': { + rootValue: 24, + propList: ['font-size'] // 只转化font-size + // propList: ['*'], // 转化全部 + // propList: ['*','!border'], //转化全部,除了border属性 + // selectorBlackList: ['body'] // 过滤掉.am-开头的class,不进行rem转换 + } } } From 74460e7c9553be8670946062a8c0372ee6fd6d33 Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Thu, 21 Jan 2021 19:57:57 +0800 Subject: [PATCH 05/26] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8ID=EF=BC=8C=E7=A1=AE=E4=BF=9DSSE=E5=8F=AF=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=8E=A8=E9=80=81=E5=88=B0=E4=B8=8D=E5=90=8C=E7=9A=84?= =?UTF-8?q?=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/alarm/AlarmEventListener.java | 39 +++++++++------ .../SseController.java} | 11 +++-- web_src/package-lock.json | 49 ++++++++++++++----- web_src/package.json | 2 + web_src/src/components/UiHeader.vue | 3 +- web_src/src/main.js | 22 ++++++++- 6 files changed, 92 insertions(+), 34 deletions(-) rename src/main/java/com/genersoft/iot/vmp/vmanager/{SEEController/SEEController.java => SseController/SseController.java} (67%) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java index 1b2f6723..2b563269 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java @@ -4,6 +4,10 @@ import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,10 +22,10 @@ public class AlarmEventListener implements ApplicationListener { private final static Logger logger = LoggerFactory.getLogger(AlarmEventListener.class); - private static SseEmitter emitter = new SseEmitter(); + private static Map sseEmitters = new Hashtable<>(); - public void addSseEmitters(SseEmitter sseEmitter) { - emitter = sseEmitter; + public void addSseEmitters(String browserId, SseEmitter sseEmitter) { + sseEmitters.put(browserId, sseEmitter); } @Override @@ -30,18 +34,25 @@ public class AlarmEventListener implements ApplicationListener { logger.debug("设备报警事件触发,deviceId:" + event.getAlarmInfo().getDeviceId() + ", " + event.getAlarmInfo().getAlarmDescription()); } - try { - String msg = "设备编码: " + event.getAlarmInfo().getDeviceId() + "" - + "
报警描述: " + event.getAlarmInfo().getAlarmDescription() + "" - + "
报警时间: " + event.getAlarmInfo().getAlarmTime() + "" - + "
定位经度: " + event.getAlarmInfo().getLongitude() + "" - + "
定位纬度: " + event.getAlarmInfo().getLatitude() + ""; - emitter.send(msg); - } catch (IOException e) { - if (logger.isDebugEnabled()) { - logger.debug("SSE 通道已关闭"); + String msg = "设备编码: " + event.getAlarmInfo().getDeviceId() + "" + + "
报警描述: " + event.getAlarmInfo().getAlarmDescription() + "" + + "
报警时间: " + event.getAlarmInfo().getAlarmTime() + "" + + "
报警位置: " + event.getAlarmInfo().getLongitude() + "" + + ", " + event.getAlarmInfo().getLatitude() + ""; + + for (Iterator> it = sseEmitters.entrySet().iterator(); it.hasNext();) { + Map.Entry emitter = it.next(); + logger.info("推送到SSE连接,浏览器ID: " + emitter.getKey()); + try { + emitter.getValue().send(msg); + } catch (IOException | IllegalStateException e) { + if (logger.isDebugEnabled()) { + logger.debug("SSE连接已关闭"); + } + // 移除已关闭的连接 + it.remove(); + // e.printStackTrace(); } - // e.printStackTrace(); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java similarity index 67% rename from src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java rename to src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java index 689b967b..01af4a0d 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/SEEController/SEEController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java @@ -1,9 +1,10 @@ -package com.genersoft.iot.vmp.vmanager.SEEController; +package com.genersoft.iot.vmp.vmanager.SseController; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; /** @@ -14,16 +15,16 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @Controller @RequestMapping("/api") -public class SEEController { +public class SseController { @Autowired AlarmEventListener alarmEventListener; //设置响应 @RequestMapping("/emit") - public SseEmitter emit() { - SseEmitter sseEmitter = new SseEmitter(0L); + public SseEmitter emit(@RequestParam String browserId) { + final SseEmitter sseEmitter = new SseEmitter(0L); try { - alarmEventListener.addSseEmitters(sseEmitter); + alarmEventListener.addSseEmitters(browserId, sseEmitter); }catch (Exception e){ sseEmitter.completeWithError(e); } diff --git a/web_src/package-lock.json b/web_src/package-lock.json index 334f488a..fb6278de 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -99,7 +99,6 @@ "version": "3.2.1", "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz", "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -1645,7 +1644,6 @@ "version": "2.4.2", "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz", "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1847,7 +1845,6 @@ "version": "1.9.3", "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1855,8 +1852,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { "version": "0.3.0", @@ -3713,8 +3709,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escope": { "version": "3.6.0", @@ -4150,6 +4145,11 @@ "locate-path": "^2.0.0" } }, + "fingerprintjs2": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fingerprintjs2/-/fingerprintjs2-2.1.2.tgz", + "integrity": "sha512-ZPsLgjziFRbUb5tXWpEMtWp4XFnzSah8SiNfl3aoURDZ+2zi2tuIOYUULqDBV+Cb6paN+raWT+Q2qpOaCbX/Yw==" + }, "flatten": { "version": "1.0.3", "resolved": "https://registry.npm.taobao.org/flatten/download/flatten-1.0.3.tgz", @@ -4403,8 +4403,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.1", @@ -8437,6 +8436,34 @@ } } }, + "postcss-pxtorem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-pxtorem/-/postcss-pxtorem-5.1.1.tgz", + "integrity": "sha512-uvgIujL/pn0GbZ+rczESD2orHsbXrrCqi+q9wJO8PCk3ZGCoVVtu5hZTbtk+tbZHZP5UkTfCvqOrTZs9Ncqfsg==", + "requires": { + "postcss": "^7.0.27" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "postcss-reduce-idents": { "version": "2.4.0", "resolved": "https://registry.npm.taobao.org/postcss-reduce-idents/download/postcss-reduce-idents-2.4.0.tgz?cache=0&sync_timestamp=1599672339373&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-reduce-idents%2Fdownload%2Fpostcss-reduce-idents-2.4.0.tgz", @@ -9893,8 +9920,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" }, "source-map-resolve": { "version": "0.5.3", @@ -10290,7 +10316,6 @@ "version": "5.5.0", "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1598611719015&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz", "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", - "dev": true, "requires": { "has-flag": "^3.0.0" } diff --git a/web_src/package.json b/web_src/package.json index c949393a..d99d7bcd 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -15,7 +15,9 @@ "core-js": "^2.6.5", "echarts": "^4.7.0", "element-ui": "2.10.1", + "fingerprintjs2": "^2.1.2", "moment": "^2.29.1", + "postcss-pxtorem": "^5.1.1", "vue": "^2.6.11", "vue-clipboard2": "^0.3.1", "vue-cookies": "^1.7.4", diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index f16beba8..282a89d1 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -34,7 +34,8 @@ export default { sseControl() { let that = this; if (this.alarmNotify) { - this.sseSource = new EventSource('/api/emit'); + console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId); + this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId); this.sseSource.addEventListener('message', function(evt) { that.$notify({ title: '收到报警信息', diff --git a/web_src/src/main.js b/web_src/src/main.js index ae2baeef..03bb4a48 100644 --- a/web_src/src/main.js +++ b/web_src/src/main.js @@ -8,10 +8,28 @@ import axios from 'axios'; import VueCookies from 'vue-cookies'; import echarts from 'echarts'; -import VueClipboard from 'vue-clipboard2' +import VueClipboard from 'vue-clipboard2'; import { Notification } from 'element-ui'; +import Fingerprint2 from 'fingerprintjs2'; -Vue.use(VueClipboard) +// ΨһID +Fingerprint2.get(function(components) { + const values = components.map(function(component,index) { + if (index === 0) { //΢UAwifi4G滻ɿ,ȻлIDһ + return component.value.replace(/\bNetType\/\w+\b/, ''); + } + return component.value; + }) + //console.log(values) //ʹõϢnpm + // id + let port = window.location.port; + console.log(port); + const fingerPrint = Fingerprint2.x64hash128(values.join(port), 31) + Vue.prototype.$browserId = fingerPrint; + console.log("Ψһʶ룺" + fingerPrint); +}); + +Vue.use(VueClipboard); Vue.use(ElementUI); Vue.use(VueCookies); Vue.prototype.$axios = axios; From eb04412ae948b05a1a15e035fe6fc738ac0cec19 Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Thu, 21 Jan 2021 20:02:33 +0800 Subject: [PATCH 06/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E5=A4=A7=E5=B0=8F=E8=AE=BE=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E6=96=B9=E4=BE=BF=E5=A2=9E=E5=8A=A0=E5=8A=9F=E8=83=BD=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/.postcssrc.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web_src/.postcssrc.js b/web_src/.postcssrc.js index b04dd5a9..406b4d24 100644 --- a/web_src/.postcssrc.js +++ b/web_src/.postcssrc.js @@ -9,9 +9,6 @@ module.exports = { 'postcss-pxtorem': { rootValue: 24, propList: ['font-size'] // 只转化font-size - // propList: ['*'], // 转化全部 - // propList: ['*','!border'], //转化全部,除了border属性 - // selectorBlackList: ['body'] // 过滤掉.am-开头的class,不进行rem转换 } } } From 5c45808348306c5741bef5ca5af3abd69fbd3c6d Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Fri, 22 Jan 2021 15:36:23 +0800 Subject: [PATCH 07/26] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=9A=84method=E5=A4=84=E7=90=86=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/transmit/SIPProcessorFactory.java | 6 +++--- .../transmit/request/impl/OtherRequestProcessor.java | 2 +- web_src/src/components/UiHeader.vue | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java index b50cc957..13866e87 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java @@ -132,7 +132,6 @@ public class SIPProcessorFactory { processor.setRequestEvent(evt); return processor; } else if (Request.MESSAGE.equals(method)) { - MessageRequestProcessor processor = new MessageRequestProcessor(); processor.setRequestEvent(evt); processor.setTcpSipProvider(getTcpSipProvider()); @@ -146,12 +145,13 @@ public class SIPProcessorFactory { processor.setRedisCatchStorage(redisCatchStorage); return processor; } else { - return new OtherRequestProcessor(); + OtherRequestProcessor processor = new OtherRequestProcessor(); + processor.setRequestEvent(evt); + return processor; } } public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { - Response response = evt.getResponse(); CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); String method = cseqHeader.getMethod(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java index 63da9914..028835b3 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java @@ -21,7 +21,7 @@ public class OtherRequestProcessor extends SIPRequestAbstractProcessor { */ @Override public void process(RequestEvent evt) { - System.out.println("no support the method! Method:" + evt.getRequest().getMethod()); + System.out.println("Unsupported the method: " + evt.getRequest().getMethod()); } } diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index 282a89d1..8b84ef24 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -21,7 +21,6 @@ export default { }; }, methods:{ - loginout(){ // 删除cookie,回到登录页面 this.$cookies.remove("session"); From 5e7c3ed971a6f0af5b98341399a1e4edf9a26daf Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Wed, 27 Jan 2021 15:24:28 +0800 Subject: [PATCH 08/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E6=98=BE=E7=A4=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 + web_src/index.html | 1 + web_src/package-lock.json | 80 ++++- web_src/package.json | 1 + web_src/src/components/GeoConvertTools.js | 250 +++++++++++++++ web_src/src/components/devicePosition.vue | 374 ++++++++++++++++++++++ web_src/src/components/videoList.vue | 38 ++- web_src/src/main.js | 10 +- web_src/src/router/index.js | 6 + 9 files changed, 744 insertions(+), 24 deletions(-) create mode 100644 web_src/src/components/GeoConvertTools.js create mode 100644 web_src/src/components/devicePosition.vue diff --git a/README.md b/README.md index 724cfef7..40a522ce 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,14 @@ https://gitee.com/18010473990/wvp-GB28181.git 12. 支持播放h265, g.711格式的流 13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)) 14. 报警信息处理,支持向前端推送报警信息 +15. 支持订阅与通知方法 + [X] 移动位置订阅 + [X] 移动位置通知处理 + [ ] 报警事件订阅 + [X] 报警事件通知处理 + [ ] 设备目录订阅 + [X] 设备奴鲁通知处理 +16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 # 待实现: 上级级联 diff --git a/web_src/index.html b/web_src/index.html index 12241251..8b26e729 100644 --- a/web_src/index.html +++ b/web_src/index.html @@ -7,6 +7,7 @@ +
diff --git a/web_src/package-lock.json b/web_src/package-lock.json index fb6278de..54840f6c 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -1269,6 +1269,34 @@ "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", "dev": true }, + "bmaplib.curveline": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz", + "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q==" + }, + "bmaplib.heatmap": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz", + "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q==" + }, + "bmaplib.lushu": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz", + "integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w==" + }, + "bmaplib.markerclusterer": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz", + "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==", + "requires": { + "bmaplib.texticonoverlay": "^1.0.2" + } + }, + "bmaplib.texticonoverlay": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz", + "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg==" + }, "bn.js": { "version": "5.1.3", "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.3.tgz", @@ -5266,6 +5294,14 @@ "invert-kv": "^1.0.0" } }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", @@ -5443,6 +5479,25 @@ "object-visit": "^1.0.0" } }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + } + } + }, "math-expression-evaluator": { "version": "1.2.22", "resolved": "https://registry.npm.taobao.org/math-expression-evaluator/download/math-expression-evaluator-1.2.22.tgz", @@ -5466,6 +5521,11 @@ "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=", "dev": true }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", @@ -10074,8 +10134,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "ssri": { "version": "5.3.0", @@ -10489,6 +10548,11 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1601823880483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz", @@ -10841,6 +10905,18 @@ "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600441238751&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz", "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM=" }, + "vue-baidu-map": { + "version": "0.21.22", + "resolved": "https://registry.npmjs.org/vue-baidu-map/-/vue-baidu-map-0.21.22.tgz", + "integrity": "sha512-WQMPCih4UTh0AZCKKH/OVOYnyAWjfRNeK6BIeoLmscyY5aF8zzlJhz/NOHLb3mdztIpB0Z6aohn4Jd9mfCSjQw==", + "requires": { + "bmaplib.curveline": "^1.0.0", + "bmaplib.heatmap": "^1.0.4", + "bmaplib.lushu": "^1.0.7", + "bmaplib.markerclusterer": "^1.0.13", + "markdown-it": "^8.4.0" + } + }, "vue-clipboard2": { "version": "0.3.1", "resolved": "https://registry.npm.taobao.org/vue-clipboard2/download/vue-clipboard2-0.3.1.tgz", diff --git a/web_src/package.json b/web_src/package.json index d99d7bcd..4a9f7660 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -19,6 +19,7 @@ "moment": "^2.29.1", "postcss-pxtorem": "^5.1.1", "vue": "^2.6.11", + "vue-baidu-map": "^0.21.22", "vue-clipboard2": "^0.3.1", "vue-cookies": "^1.7.4", "vue-router": "^3.1.6" diff --git a/web_src/src/components/GeoConvertTools.js b/web_src/src/components/GeoConvertTools.js new file mode 100644 index 00000000..6866249d --- /dev/null +++ b/web_src/src/components/GeoConvertTools.js @@ -0,0 +1,250 @@ +/** + * 经纬度转换 + */ +export default { + PI: 3.1415926535897932384626, + //PI: 3.14159265358979324, + x_pi: (3.1415926535897932384626 * 3000.0) / 180.0, + delta: function (lat, lng) { + // Krasovsky 1940 + // + // a = 6378245.0, 1/f = 298.3 + // b = a * (1 - f) + // ee = (a^2 - b^2) / a^2; + var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 + var ee = 0.00669342162296594323; // ee: 椭球的偏心率。 + var dLat = this.transformLat(lng - 105.0, lat - 35.0); + var dLng = this.transformLng(lng - 105.0, lat - 35.0); + var radLat = (lat / 180.0) * this.PI; + var magic = Math.sin(radLat); + magic = 1 - ee * magic * magic; + var sqrtMagic = Math.sqrt(magic); + dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * this.PI); + dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * this.PI); + return { + lat: dLat, + lng: dLng + }; + }, + /** + * WGS-84 to GCJ-02 GPS坐标转中国坐标 + * @param {number} wgsLat GPS纬度 + * @param {number} wgsLng GPS经度 + * @return {object} 返回中国坐标经纬度对象 + */ + GPSToChina: function (wgsLat, wgsLng) { + if (this.outOfChina(wgsLat, wgsLng)) return { + lat: wgsLat, + lng: wgsLng + }; + var d = this.delta(wgsLat, wgsLng); + return { + lat: Number(wgsLat) + Number(d.lat), + lng: Number(wgsLng) + Number(d.lng) + }; + }, + /** + * GCJ-02 to WGS-84 中国标准坐标转GPS坐标 + * @param {number} gcjLat 中国标准坐标纬度 + * @param {number} gcjLng 中国标准坐标经度 + * @return {object} 返回GPS经纬度对象 + */ + chinaToGPS: function (gcjLat, gcjLng) { + if (this.outOfChina(gcjLat, gcjLng)) return { + lat: gcjLat, + lng: gcjLng + }; + var d = this.delta(gcjLat, gcjLng); + return { + lat: Number(gcjLat) - Number(d.lat), + lng: Number(gcjLng) - Number(d.lng) + }; + }, + /** + * GCJ-02 to WGS-84 exactly 中国标准坐标转GPS坐标(精确) + * @param {number} gcjLat 中国标准坐标纬度 + * @param {number} gcjLng 中国标准坐标经度 + * @return {object} 返回GPS经纬度对象(精确) + */ + chinaToGPSExact: function (gcjLat, gcjLng) { + var initDelta = 0.01; + var threshold = 0.000000001; + var dLat = initDelta, + dLng = initDelta; + var mLat = gcjLat - dLat, + mLng = gcjLng - dLng; + var pLat = gcjLat + dLat, + pLng = gcjLng + dLng; + var wgsLat, + wgsLng, + i = 0; + while (1) { + wgsLat = (mLat + pLat) / 2; + wgsLng = (mLng + pLng) / 2; + var tmp = this.gcj_encrypt(wgsLat, wgsLng); + dLat = tmp.lat - gcjLat; + dLng = tmp.lng - gcjLng; + if (Math.abs(dLat) < threshold && Math.abs(dLng) < threshold) break; + + if (dLat > 0) pLat = wgsLat; + else mLat = wgsLat; + if (dLng > 0) pLng = wgsLng; + else mLng = wgsLng; + + if (++i > 10000) break; + } + //console.log(i); + return { + lat: wgsLat, + lng: wgsLng + }; + }, + /** + * GCJ-02 to BD-09 中国标准坐标转百度坐标(精确) + * @param {number} gcjLat 中国标准坐标纬度 + * @param {number} gcjLng 中国标准坐标经度 + * @return {object} 返回百度经纬度对象 + */ + chinaToBaidu: function (gcjLat, gcjLng) { + var x = gcjLng, + y = gcjLat; + var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi); + var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi); + var bdLng = z * Math.cos(theta) + 0.0065; + var bdLat = z * Math.sin(theta) + 0.006; + return { + lat: bdLat, + lng: bdLng + }; + }, + /** + * BD-09 to GCJ-02 百度坐标转中国标准坐标 + * @param {number} bdLat 百度坐标纬度 + * @param {number} bdLng 百度坐标经度 + * @return {object} 返回中国标准经纬度对象 + */ + baiduToChina: function (bdLat, bdLng) { + var x = bdLng - 0.0065, + y = bdLat - 0.006; + var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi); + var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi); + var gcjLng = z * Math.cos(theta); + var gcjLat = z * Math.sin(theta); + return { + lat: gcjLat, + lng: gcjLng + }; + }, + /** + * BD-09 to GCJ-02 百度坐标转gps坐标 + * @param {number} bdLat 百度坐标纬度 + * @param {number} bdLng 百度坐标经度 + * @return {object} 返回gps经纬度对象 + */ + baiduToGPS: function (bdLat, bdLng) { + let china = this.baiduToChina(bdLat, bdLng); + return this.chinaToGPS(china.lat, china.lng); + }, + /** + * WGS-84 to to BD-09 GPS坐标转Baidu坐标 + * @param {number} gpsLat GPS纬度 + * @param {number} gpsLng GPS经度 + * @return {object} 返回百度经纬度对象 + */ + GPSToBaidu: function (gpsLat, gpsLng) { + var china = this.GPSToChina(gpsLat, gpsLng); + return this.chinaToBaidu(china.lat, china.lng); + }, + /** + * WGS-84 to Web mercator GPS坐标转墨卡托坐标 + * @param {number} wgsLat GPS纬度 + * @param {number} wgsLng GPS经度 + * @return {object} 返回墨卡托经纬度对象 + */ + GPSToMercator: function (wgsLat, wgsLng) { + var x = (wgsLng * 20037508.34) / 180; + var y = Math.log(Math.tan(((90 + wgsLat) * this.PI) / 360)) / (this.PI / 180); + y = (y * 20037508.34) / 180; + return { + lat: y, + lng: x + }; + /* + if ((Math.abs(wgsLng) > 180 || Math.abs(wgsLat) > 90)) + return null; + var x = 6378137.0 * wgsLng * 0.017453292519943295; + var a = wgsLat * 0.017453292519943295; + var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))); + return {'lat' : y, 'lng' : x}; + //*/ + }, + /** + * Web mercator to WGS-84 墨卡托坐标转GPS坐标 + * @param {number} mercatorLat 墨卡托纬度 + * @param {number} mercatorLng 墨卡托经度 + * @return {object} 返回GPS经纬度对象 + */ + mercatorToGPS: function (mercatorLat, mercatorLng) { + var x = (mercatorLng / 20037508.34) * 180; + var y = (mercatorLat / 20037508.34) * 180; + y = (180 / this.PI) * (2 * Math.atan(Math.exp((y * this.PI) / 180)) - this.PI / 2); + return { + lat: y, + lng: x + }; + /* + if (Math.abs(mercatorLng) < 180 && Math.abs(mercatorLat) < 90) + return null; + if ((Math.abs(mercatorLng) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892)) + return null; + var a = mercatorLng / 6378137.0 * 57.295779513082323; + var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0); + var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323; + return {'lat' : y, 'lng' : x}; + //*/ + }, + /** + * 两点之间的距离 + * @param {number} latA 起点纬度 + * @param {number} lngA 起点经度 + * @param {number} latB 终点纬度 + * @param {number} lngB 终点经度 + * @return {number} 返回距离(米) + */ + distance: function (latA, lngA, latB, lngB) { + var earthR = 6371000; + var x = Math.cos((latA * this.PI) / 180) * Math.cos((latB * this.PI) / 180) * Math.cos(((lngA - lngB) * this.PI) / 180); + var y = Math.sin((latA * this.PI) / 180) * Math.sin((latB * this.PI) / 180); + var s = x + y; + if (s > 1) s = 1; + if (s < -1) s = -1; + var alpha = Math.acos(s); + var distance = alpha * earthR; + return distance; + }, + /** + * 是否在中国之外 + * @param {number} lat 纬度 + * @param {number} lng 经度 + * @return {boolean]} 返回结果真或假 + */ + outOfChina: function (lat, lng) { + if (lat < 72.004 || lat > 137.8347) return true; + if (lng < 0.8293 || lng > 55.8271) return true; + return false; + }, + transformLat: function (x, y) { + var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); + ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0; + ret += ((20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin((y / 3.0) * this.PI)) * 2.0) / 3.0; + ret += ((160.0 * Math.sin((y / 12.0) * this.PI) + 320 * Math.sin((y * this.PI) / 30.0)) * 2.0) / 3.0; + return ret; + }, + transformLng: function (x, y) { + var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); + ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0; + ret += ((20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin((x / 3.0) * this.PI)) * 2.0) / 3.0; + ret += ((150.0 * Math.sin((x / 12.0) * this.PI) + 300.0 * Math.sin((x / 30.0) * this.PI)) * 2.0) / 3.0; + return ret; + } +}; diff --git a/web_src/src/components/devicePosition.vue b/web_src/src/components/devicePosition.vue new file mode 100644 index 00000000..29106234 --- /dev/null +++ b/web_src/src/components/devicePosition.vue @@ -0,0 +1,374 @@ + + + + + diff --git a/web_src/src/components/videoList.vue b/web_src/src/components/videoList.vue index 01dae2c3..450d736f 100644 --- a/web_src/src/components/videoList.vue +++ b/web_src/src/components/videoList.vue @@ -11,7 +11,7 @@ - + @@ -40,7 +40,7 @@ - + - + @@ -73,7 +74,7 @@ "}) + List queryPositionByDeviceIdAndTime(String deviceId, String startTime, String endTime); + + @Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" + + " ORDER BY time DESC LIMIT 1") + MobilePosition queryLatestPositionByDevice(String deviceId); + + @Delete("DELETE FROM device_mobile_position WHERE deviceId = #{deviceId}") + int clearMobilePositionsByDeviceId(String deviceId); + +} diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index e11c1416..cc8320cf 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -3,8 +3,10 @@ package com.genersoft.iot.vmp.storager.impl; import java.util.*; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; +import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import io.swagger.models.auth.In; @@ -27,7 +29,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { private DeviceMapper deviceMapper; @Autowired - private DeviceChannelMapper deviceChannelMapper; + private DeviceChannelMapper deviceChannelMapper; + + @Autowired + private DeviceMobilePositionMapper deviceMobilePositionMapper; /** @@ -200,11 +205,49 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { return deviceMapper.update(device) > 0; } - + /** + * 清空通道 + * @param deviceId + */ @Override public void cleanChannelsForDevice(String deviceId) { int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId); } + /** + * 添加Mobile Position设备移动位置 + * @param MobilePosition + */ + @Override + public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { + return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; + } + /** + * 查询移动位置轨迹 + * @param deviceId + * @param startTime + * @param endTime + */ + @Override + public synchronized List queryMobilePositions(String deviceId, String startTime, String endTime) { + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); + } + + /** + * 查询最新移动位置 + * @param deviceId + */ + @Override + public MobilePosition queryLatestPosition(String deviceId) { + return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId); + } + + /** + * 删除指定设备的所有移动位置 + * @param deviceId + */ + public int clearMobilePositionsByDeviceId(String deviceId) { + return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java new file mode 100644 index 00000000..16724410 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java @@ -0,0 +1,68 @@ +package com.genersoft.iot.vmp.utils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Socket; +import java.util.Base64; + +import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint; + +public class GpsUtil { + public static BaiduPoint Wgs84ToBd09(String xx, String yy) { + try { + Socket s = new Socket("api.map.baidu.com", 80); + BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); + OutputStream out = s.getOutputStream(); + StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4"); + sb.append("&x=" + xx + "&y=" + yy); + sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n"); + sb.append("User-Agent: Java/1.6.0_20\r\n"); + sb.append("Host: api.map.baidu.com:80\r\n"); + sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"); + sb.append("Connection: Close\r\n"); + sb.append("\r\n"); + out.write(sb.toString().getBytes()); + String json = ""; + String tmp = ""; + while ((tmp = br.readLine()) != null) { + // System.out.println(tmp); + json += tmp; + } + + s.close(); + int start = json.indexOf("cbk_3976"); + int end = json.lastIndexOf("}"); + if (start != -1 && end != -1 && json.contains("\"x\":\"")) { + json = json.substring(start, end); + String[] point = json.split(","); + String x = point[1].split(":")[1].replace("\"", ""); + String y = point[2].split(":")[1].replace("\"", ""); + BaiduPoint bdPoint= new BaiduPoint(); + bdPoint.setBdLng(new String(decode(x))); + bdPoint.setBdLat(new String(decode(y))); + return bdPoint; + //return (new String(decode(x)) + "," + new String(decode(y))); + } else { + System.out.println("gps坐标无效!!"); + } + out.close(); + br.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * BASE64解码 + * @param str + * @return string + */ + public static byte[] decode(String str) { + byte[] bt = null; + final Base64.Decoder decoder = Base64.getDecoder(); + bt = decoder.decode(str); // .decodeBuffer(str); + return bt; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/MobilePosition/MobilePositionController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/MobilePosition/MobilePositionController.java new file mode 100644 index 00000000..92806b17 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/MobilePosition/MobilePositionController.java @@ -0,0 +1,118 @@ +package com.genersoft.iot.vmp.vmanager.MobilePosition; + +import java.util.List; + +import javax.sip.message.Response; + +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.github.pagehelper.util.StringUtil; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.async.DeferredResult; + +@CrossOrigin +@RestController +@RequestMapping("/api") +public class MobilePositionController { + + private final static Logger logger = LoggerFactory.getLogger(MobilePositionController.class); + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private SIPCommander cmder; + + @Autowired + private DeferredResultHolder resultHolder; + + @GetMapping("/positions/{deviceId}/history") + public ResponseEntity> positions(@PathVariable String deviceId, + @RequestParam(required = false) String start, + @RequestParam(required = false) String end) { + if (logger.isDebugEnabled()) { + logger.debug("查询设备" + deviceId + "的历史轨迹"); + } + + if (StringUtil.isEmpty(start)) { + start = null; + } + if (StringUtil.isEmpty(end)) { + end = null; + } + + List result = storager.queryMobilePositions(deviceId, start, end); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @GetMapping("/positions/{deviceId}/latest") + public ResponseEntity latestPosition(@PathVariable String deviceId) { + if (logger.isDebugEnabled()) { + logger.debug("查询设备" + deviceId + "的最新位置"); + } + MobilePosition result = storager.queryLatestPosition(deviceId); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @GetMapping("/positions/{deviceId}/realtime") + public DeferredResult> realTimePosition(@PathVariable String deviceId) { + Device device = storager.queryVideoDevice(deviceId); + cmder.mobilePostitionQuery(device, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId); + msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(5*1000L); + result.onTimeout(()->{ + logger.warn(String.format("获取移动位置信息超时")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId); + msg.setData("Timeout"); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result); + return result; + } + + @GetMapping("/positions/{deviceId}/subscribe") + public ResponseEntity positionSubscribe(@PathVariable String deviceId, + @RequestParam String expires, + @RequestParam String interval) { + String msg = ((expires.equals("0")) ? "取消" : "") + "订阅设备" + deviceId + "的移动位置"; + if (logger.isDebugEnabled()) { + logger.debug(msg); + } + + if (StringUtil.isEmpty(interval)) { + interval = "5"; + } + Device device = storager.queryVideoDevice(deviceId); + + String result = msg; + if (cmder.mobilePositionSubscribe(device, Integer.parseInt(expires), Integer.parseInt(interval))) { + result += ",成功"; + } else { + result += ",失败"; + } + + return new ResponseEntity<>(result, HttpStatus.OK); + } +} From 3b44b038ffae560d27659cfdb2f25c5512546e07 Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Wed, 27 Jan 2021 15:54:14 +0800 Subject: [PATCH 18/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SSE=E8=B7=A8=E5=9F=9F?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/vmanager/SseController/SseController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java index 01af4a0d..1e55c326 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.SseController; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @@ -13,6 +14,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; * @data: 2021-01-20 */ +@CrossOrigin @Controller @RequestMapping("/api") public class SseController { From a4afadd7d60dca520f3f98335d4a8dd573dbae2a Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Wed, 27 Jan 2021 16:05:08 +0800 Subject: [PATCH 19/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 40a522ce..03ee2764 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,12 @@ https://gitee.com/18010473990/wvp-GB28181.git 13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)) 14. 报警信息处理,支持向前端推送报警信息 15. 支持订阅与通知方法 - [X] 移动位置订阅 - [X] 移动位置通知处理 - [ ] 报警事件订阅 - [X] 报警事件通知处理 - [ ] 设备目录订阅 - [X] 设备奴鲁通知处理 + - [X] 移动位置订阅 + - [X] 移动位置通知处理 + - [ ] 报警事件订阅 + - [X] 报警事件通知处理 + - [ ] 设备目录订阅 + - [X] 设备目录通知处理 16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 # 待实现: From 40020cc5a901d01838aff43dd6e333a2a563926a Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: Thu, 28 Jan 2021 14:26:48 +0800 Subject: [PATCH 20/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=84=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=8C=89=E4=B8=8B=E5=9B=9E=E8=BD=A6=E9=94=AE=E9=83=BD?= =?UTF-8?q?=E4=BC=9A=E9=80=80=E5=9B=9EContral=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/Login.vue | 41 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/web_src/src/components/Login.vue b/web_src/src/components/Login.vue index 160197a4..2a918865 100644 --- a/web_src/src/components/Login.vue +++ b/web_src/src/components/Login.vue @@ -29,14 +29,13 @@ export default { } }, created(){ - var that = this; - document.onkeydown = function(e) { - var key = window.event.keyCode; - if (key == 13) { - that.login(); + var that = this; + document.onkeydown = function(e) { + var key = window.event.keyCode; + if (key == 13) { + that.login(); + } } - } - }, methods:{ @@ -70,6 +69,7 @@ export default { if (res.data == "success") { that.$cookies.set("session", {"username": that.username}) ; //登录成功后 + that.cancelEnterkeyDefaultAction(); that.$router.push('/'); }else{ that.isLoging = false; @@ -84,18 +84,23 @@ export default { that.$message.error(error.response.statusText); that.isLoging = false; }); - - - }, - setCookie: function (cname, cvalue, exdays) { - var d = new Date(); - d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); - var expires = "expires=" + d.toUTCString(); - console.info(cname + "=" + cvalue + "; " + expires); - document.cookie = cname + "=" + cvalue + "; " + expires; - console.info(document.cookie); - }, + setCookie: function (cname, cvalue, exdays) { + var d = new Date(); + d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); + var expires = "expires=" + d.toUTCString(); + console.info(cname + "=" + cvalue + "; " + expires); + document.cookie = cname + "=" + cvalue + "; " + expires; + console.info(document.cookie); + }, + cancelEnterkeyDefaultAction: function() { + document.onkeydown = function(e) { + var key = window.event.keyCode; + if (key == 13) { + return false; + } + } + } } } From e15842c53ce332eafb2f83daa9abe68a4a1575e7 Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Wed, 3 Feb 2021 10:54:41 +0800 Subject: [PATCH 21/26] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/devicePosition.vue | 30 +++++++++++++++++------ web_src/src/components/videoList.vue | 11 ++++++--- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/web_src/src/components/devicePosition.vue b/web_src/src/components/devicePosition.vue index 29106234..f6cf19e4 100644 --- a/web_src/src/components/devicePosition.vue +++ b/web_src/src/components/devicePosition.vue @@ -181,10 +181,17 @@ export default { self.total = res.data.length; self.mobilePositionList = res.data; console.log(self.mobilePositionList); - // 防止出现表格错位 - self.$nextTick(() => { - self.showMarkPoints(self); - }); + if (self.total == 0) { + self.$message({ + showClose: true, + message: '未找到符合条件的移动位置信息', + type: 'error' + }); + } else { + self.$nextTick(() => { + self.showMarkPoints(self); + }); + } }) .catch(function (error) { console.log(error); @@ -201,10 +208,17 @@ export default { self.total = res.data.length; self.mobilePositionList.push(res.data); console.log(self.mobilePositionList); - // 防止出现表格错位 - self.$nextTick(() => { - self.showMarkPoints(self); - }); + if (self.total == 0) { + self.$message({ + showClose: true, + message: '未找到符合条件的移动位置信息', + type: 'error' + }); + } else { + self.$nextTick(() => { + self.showMarkPoints(self); + }); + } }) .catch(function (error) { console.log(error); diff --git a/web_src/src/components/videoList.vue b/web_src/src/components/videoList.vue index 450d736f..8a3f1c0e 100644 --- a/web_src/src/components/videoList.vue +++ b/web_src/src/components/videoList.vue @@ -51,10 +51,13 @@ + 刷新 + + 通道 + 定位 + 控制 + + Date: Wed, 3 Feb 2021 11:00:24 +0800 Subject: [PATCH 22/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=9A=E7=A7=8D?= =?UTF-8?q?=E4=BF=A1=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("处理完成,返回结果"); From 85cf36386ecea9e0762e51ef12635f2336388120 Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Wed, 3 Feb 2021 11:05:27 +0800 Subject: [PATCH 23/26] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E6=A0=A1=E9=AA=8C=E5=92=8C=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/utils/NumericUtil.java | 20 ++- .../iot/vmp/gb28181/utils/XmlUtil.java | 119 ++++++++++++------ 2 files changed, 102 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java index 4dc63075..f9fbfb18 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java @@ -15,10 +15,26 @@ public class NumericUtil { public static boolean isDouble(String str) { try { Double num2 = Double.valueOf(str); - System.out.println("Is Number!" + num2); + System.out.println(num2 + " Is an Integer!"); return true; } catch (Exception e) { - System.out.println("Is not Number!"); + System.out.println(str + " Is not an Integer!"); + return false; + } + } + + /** + * 判断是否Double格式 + * @param str + * @return true/false + */ + public static boolean isInteger(String str) { + try { + int num2 = Integer.valueOf(str); + System.out.println(num2 + " Is Number!"); + return true; + } catch (Exception e) { + System.out.println(str + " Is not Number!"); return false; } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index e0d776c2..c82ba600 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -7,6 +7,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; @@ -20,8 +23,7 @@ import org.slf4j.LoggerFactory; * * */ -public class XmlUtil -{ +public class XmlUtil { /** * 日志服务 */ @@ -30,22 +32,18 @@ public class XmlUtil /** * 解析XML为Document对象 * - * @param xml - * 被解析的XMl + * @param xml 被解析的XMl + * * @return Document */ - public static Element parseXml(String xml) - { + public static Element parseXml(String xml) { Document document = null; // StringReader sr = new StringReader(xml); SAXReader saxReader = new SAXReader(); - try - { + try { document = saxReader.read(sr); - } - catch (DocumentException e) - { + } catch (DocumentException e) { LOG.error("解析失败", e); } return null == document ? null : document.getRootElement(); @@ -54,16 +52,12 @@ public class XmlUtil /** * 获取element对象的text的值 * - * @param em - * 节点的对象 - * @param tag - * 节点的tag + * @param em 节点的对象 + * @param tag 节点的tag * @return 节点 */ - public static String getText(Element em, String tag) - { - if (null == em) - { + public static String getText(Element em, String tag) { + if (null == em) { return null; } Element e = em.element(tag); @@ -74,16 +68,12 @@ public class XmlUtil /** * 递归解析xml节点,适用于 多节点数据 * - * @param node - * node - * @param nodeName - * nodeName + * @param node node + * @param nodeName nodeName * @return List> */ - public static List> listNodes(Element node, String nodeName) - { - if (null == node) - { + public static List> listNodes(Element node, String nodeName) { + if (null == node) { return null; } // 初始化返回 @@ -93,12 +83,9 @@ public class XmlUtil Map map = null; // 遍历属性节点 - for (Attribute attribute : list) - { - if (nodeName.equals(node.getName())) - { - if (null == map) - { + for (Attribute attribute : list) { + if (nodeName.equals(node.getName())) { + if (null == map) { map = new HashMap(); listMap.add(map); } @@ -110,12 +97,74 @@ public class XmlUtil // 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称 // 使用递归 Iterator iterator = node.elementIterator(); - while (iterator.hasNext()) - { + while (iterator.hasNext()) { Element e = iterator.next(); listMap.addAll(listNodes(e, nodeName)); } return listMap; } + /** + * xml转json + * + * @param element + * @param json + */ + public static void node2Json(Element element, JSONObject json) { + // 如果是属性 + for (Object o : element.attributes()) { + Attribute attr = (Attribute) o; + if (!isEmpty(attr.getValue())) { + json.put("@" + attr.getName(), attr.getValue()); + } + } + List chdEl = element.elements(); + if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 如果没有子元素,只有一个值 + json.put(element.getName(), element.getText()); + } + + for (Element e : chdEl) { // 有子元素 + if (!e.elements().isEmpty()) { // 子元素也有子元素 + JSONObject chdjson = new JSONObject(); + node2Json(e, chdjson); + Object o = json.get(e.getName()); + if (o != null) { + JSONArray jsona = null; + if (o instanceof JSONObject) { // 如果此元素已存在,则转为jsonArray + JSONObject jsono = (JSONObject) o; + json.remove(e.getName()); + jsona = new JSONArray(); + jsona.add(jsono); + jsona.add(chdjson); + } + if (o instanceof JSONArray) { + jsona = (JSONArray) o; + jsona.add(chdjson); + } + json.put(e.getName(), jsona); + } else { + if (!chdjson.isEmpty()) { + json.put(e.getName(), chdjson); + } + } + } else { // 子元素没有子元素 + for (Object o : element.attributes()) { + Attribute attr = (Attribute) o; + if (!isEmpty(attr.getValue())) { + json.put("@" + attr.getName(), attr.getValue()); + } + } + if (!e.getText().isEmpty()) { + json.put(e.getName(), e.getText()); + } + } + } + } + + public static boolean isEmpty(String str) { + if (str == null || str.trim().isEmpty() || "null".equals(str)) { + return true; + } + return false; + } } From 1457621ebb64893608cda3f5b779104d076c8661 Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Wed, 3 Feb 2021 11:08:10 +0800 Subject: [PATCH 24/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=9A=E7=A7=8D?= =?UTF-8?q?=E4=BF=A1=E4=BB=A4=E7=9A=84API=E8=B0=83=E7=94=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/vmanager/device/DeviceConfig.java | 121 +++++++++ .../vmp/vmanager/device/DeviceControl.java | 238 ++++++++++++++++++ ...DeviceController.java => DeviceQuery.java} | 87 ++++++- .../iot/vmp/vmanager/ptz/PtzController.java | 70 ++++-- 4 files changed, 492 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceControl.java rename src/main/java/com/genersoft/iot/vmp/vmanager/device/{DeviceController.java => DeviceQuery.java} (65%) diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java new file mode 100644 index 00000000..6c4f7a31 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java @@ -0,0 +1,121 @@ +/** + * 设备设置命令API接口 + * + * @author lawrencehj + * @date 2021年2月2日 + */ + +package com.genersoft.iot.vmp.vmanager.device; + +import javax.sip.message.Response; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.async.DeferredResult; + +@CrossOrigin +@RestController +@RequestMapping("/api") +public class DeviceConfig { + + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class); + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private SIPCommander cmder; + + @Autowired + private DeferredResultHolder resultHolder; + + /** + * 看守位控制命令API接口 + * + * @param deviceId + * @param enabled 看守位使能1:开启,0:关闭 + * @param resetTime 自动归位时间间隔(可选) + * @param presetIndex 调用预置位编号(可选) + * @param channelId 通道编码(可选) + */ + @GetMapping("/config/{deviceId}/basicParam") + public DeferredResult> homePositionApi(@PathVariable String deviceId, + @RequestParam(required = false) String channelId, + @RequestParam(required = false) String name, + @RequestParam(required = false) String expiration, + @RequestParam(required = false) String heartBeatInterval, + @RequestParam(required = false) String heartBeatCount) { + if (logger.isDebugEnabled()) { + logger.debug("报警复位API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData(String.format("设备配置操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(3 * 1000L); + result.onTimeout(() -> { + logger.warn(String.format("设备配置操作超时, 设备未返回应答指令")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("Status", "Timeout"); + json.put("Description", "设备配置操作超时, 设备未返回应答指令"); + msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令"); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + return result; + } + + /** + * 设备配置查询请求API接口 + * + * @param deviceId + */ + @GetMapping("/config/{deviceId}/query/{configType}") + public DeferredResult> configDownloadApi(@PathVariable String deviceId, + @PathVariable String configType, + @RequestParam(required = false) String channelId) { + if (logger.isDebugEnabled()) { + logger.debug("设备状态查询API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.deviceConfigQuery(device, channelId, configType, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData(String.format("获取设备配置失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult> (3 * 1000L); + result.onTimeout(()->{ + logger.warn(String.format("获取设备配置超时")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData("Timeout. Device did not response to this command."); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + return result; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceControl.java new file mode 100644 index 00000000..72213594 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceControl.java @@ -0,0 +1,238 @@ +/** + * 设备控制命令API接口 + * + * @author lawrencehj + * @date 2021年2月1日 + */ + +package com.genersoft.iot.vmp.vmanager.device; + +import javax.sip.message.Response; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.async.DeferredResult; + +@CrossOrigin +@RestController +@RequestMapping("/api") +public class DeviceControl { + + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class); + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private SIPCommander cmder; + + @Autowired + private DeferredResultHolder resultHolder; + + /** + * 远程启动控制命令API接口 + * + * @param deviceId + */ + @GetMapping("/control/{deviceId}/teleboot") + @PostMapping("/control/{deviceId}/teleboot") + public ResponseEntity teleBootApi(@PathVariable String deviceId) { + if (logger.isDebugEnabled()) { + logger.debug("设备远程启动API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + boolean sucsess = cmder.teleBootCmd(device); + if (sucsess) { + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("Result", "OK"); + return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK); + } else { + logger.warn("设备远程启动API调用失败!"); + return new ResponseEntity("设备远程启动API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * 录像控制命令API接口 + * + * @param deviceId + * @param recordCmdStr Record:手动录像,StopRecord:停止手动录像 + * @param channelId 通道编码(可选) + */ + @GetMapping("/control/{deviceId}/record/{recordCmdStr}") + public DeferredResult> recordApi(@PathVariable String deviceId, + @PathVariable String recordCmdStr, @RequestParam(required = false) String channelId) { + if (logger.isDebugEnabled()) { + logger.debug("开始/停止录像API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.recordCmd(device, channelId, recordCmdStr, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(3 * 1000L); + result.onTimeout(() -> { + logger.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData("Timeout. Device did not response to this command."); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + return result; + } + + /** + * 报警布防/撤防命令API接口 + * + * @param deviceId + * @param guardCmdStr SetGuard:布防,ResetGuard:撤防 + */ + @GetMapping("/control/{deviceId}/guard/{guardCmdStr}") + public DeferredResult> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) { + if (logger.isDebugEnabled()) { + logger.debug("布防/撤防API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.guardCmd(device, guardCmdStr, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId); + msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(3 * 1000L); + result.onTimeout(() -> { + logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId); + msg.setData("Timeout. Device did not response to this command."); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result); + return result; + } + + /** + * 报警复位API接口 + * + * @param deviceId + * @param alarmMethod 报警方式(可选) + * @param alarmType 报警类型(可选) + */ + @GetMapping("/control/{deviceId}/resetAlarm") + public DeferredResult> resetAlarmApi(@PathVariable String deviceId, + @RequestParam(required = false) String alarmMethod, + @RequestParam(required = false) String alarmType) { + if (logger.isDebugEnabled()) { + logger.debug("报警复位API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.alarmCmd(device, alarmMethod, alarmType, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId); + msg.setData(String.format("报警复位操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(3 * 1000L); + result.onTimeout(() -> { + logger.warn(String.format("报警复位操作超时, 设备未返回应答指令")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId); + msg.setData("Timeout. Device did not response to this command."); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result); + return result; + } + + /** + * 强制关键帧API接口 + * + * @param deviceId + * @param channelId + */ + @GetMapping("/control/{deviceId}/iFrame") + @PostMapping("/control/{deviceId}/iFrame") + public ResponseEntity iFrame(@PathVariable String deviceId, + @RequestParam(required = false) String channelId) { + if (logger.isDebugEnabled()) { + logger.debug("强制关键帧API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + boolean sucsess = cmder.iFrameCmd(device, channelId); + if (sucsess) { + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("ChannelID", channelId); + json.put("Result", "OK"); + return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK); + } else { + logger.warn("强制关键帧API调用失败!"); + return new ResponseEntity("强制关键帧API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * 看守位控制命令API接口 + * + * @param deviceId + * @param enabled 看守位使能1:开启,0:关闭 + * @param resetTime 自动归位时间间隔(可选) + * @param presetIndex 调用预置位编号(可选) + * @param channelId 通道编码(可选) + */ + @GetMapping("/control/{deviceId}/homePosition/{enabled}") + public DeferredResult> homePositionApi(@PathVariable String deviceId, + @PathVariable String enabled, + @RequestParam(required = false) String resetTime, + @RequestParam(required = false) String presetIndex, + @RequestParam(required = false) String channelId) { + if (logger.isDebugEnabled()) { + logger.debug("报警复位API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(3 * 1000L); + result.onTimeout(() -> { + logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + JSONObject json = new JSONObject(); + json.put("DeviceID", deviceId); + json.put("Status", "Timeout"); + json.put("Description", "看守位控制操作超时, 设备未返回应答指令"); + msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令"); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + return result; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java similarity index 65% rename from src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java rename to src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java index 17d1e7d0..350adaa3 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java @@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import javax.sip.message.Response; @@ -24,9 +25,9 @@ import javax.sip.message.Response; @CrossOrigin @RestController @RequestMapping("/api") -public class DeviceController { +public class DeviceQuery { - private final static Logger logger = LoggerFactory.getLogger(DeviceController.class); + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class); @Autowired private IVideoManagerStorager storager; @@ -77,11 +78,9 @@ public class DeviceController { int page, int count, @RequestParam(required = false) String query, @RequestParam(required = false) Boolean online, - @RequestParam(required = false) Boolean channelType - ){ - + @RequestParam(required = false) Boolean channelType) { if (logger.isDebugEnabled()) { - logger.debug("查询所有视频设备API调用"); + logger.debug("查询视频设备通道API调用"); } if (StringUtils.isEmpty(query)) { query = null; @@ -135,8 +134,8 @@ public class DeviceController { json.put("deviceId", deviceId); return new ResponseEntity<>(json.toString(),HttpStatus.OK); } else { - logger.warn("设备预览API调用失败!"); - return new ResponseEntity("设备预览API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR); + logger.warn("设备信息删除API调用失败!"); + return new ResponseEntity("设备信息删除API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -157,7 +156,7 @@ public class DeviceController { @RequestParam(required = false) Boolean channelType){ if (logger.isDebugEnabled()) { - logger.debug("查询所有视频设备API调用"); + logger.debug("查询所有视频通道API调用"); } DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId); if (deviceChannel == null) { @@ -183,4 +182,74 @@ public class DeviceController { storager.updateDevice(device); return new ResponseEntity<>(null,HttpStatus.OK); } + + /** + * 设备状态查询请求API接口 + * + * @param deviceId + */ + @GetMapping("/devices/{deviceId}/status") + public DeferredResult> deviceStatusApi(@PathVariable String deviceId) { + if (logger.isDebugEnabled()) { + logger.debug("设备状态查询API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.deviceStatusQuery(device, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId); + msg.setData(String.format("获取设备状态失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult>(2*1000L); + result.onTimeout(()->{ + logger.warn(String.format("获取设备状态超时")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId); + msg.setData("Timeout. Device did not response to this command."); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, result); + return result; + } + + /** + * 设备报警查询请求API接口 + * + * @param deviceId + */ + @GetMapping("/alarm/{deviceId}") + public DeferredResult> alarmApi(@PathVariable String deviceId, + @RequestParam(required = false) String startPriority, + @RequestParam(required = false) String endPriority, + @RequestParam(required = false) String alarmMethod, + @RequestParam(required = false) String alarmType, + @RequestParam(required = false) String startTime, + @RequestParam(required = false) String endTime) { + if (logger.isDebugEnabled()) { + logger.debug("设备报警查询API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId); + msg.setData(String.format("设备报警查询失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult> (3 * 1000L); + result.onTimeout(()->{ + logger.warn(String.format("设备报警查询超时")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId); + msg.setData("设备报警查询超时"); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, result); + return result; + } + + } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java index 4c41e16f..1efdd3d1 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java @@ -5,14 +5,16 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.async.DeferredResult; + +import javax.sip.message.Response; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @CrossOrigin @@ -28,6 +30,9 @@ public class PtzController { @Autowired private IVideoManagerStorager storager; + @Autowired + private DeferredResultHolder resultHolder; + /*** * 云台控制 * @param deviceId 设备id @@ -49,16 +54,18 @@ public class PtzController { cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed); return new ResponseEntity("success",HttpStatus.OK); } - // public ResponseEntity ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){ - - // if (logger.isDebugEnabled()) { - // logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed)); - // } - // Device device = storager.queryVideoDevice(deviceId); - - // cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed); - // return new ResponseEntity("success",HttpStatus.OK); - // } + + /** + * 通用前端控制命令API接口 + * + * @param deviceId + * @param channelId + * @param cmdCode + * @param parameter1 + * @param parameter2 + * @param combindCode2 + * @return + */ @PostMapping("/frontEndCommand/{deviceId}/{channelId}") public ResponseEntity frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){ @@ -70,4 +77,37 @@ public class PtzController { cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2); return new ResponseEntity("success",HttpStatus.OK); } + + /** + * 预置位查询命令API接口 + * + * @param deviceId + * @param channelId + * @return + */ + @GetMapping("/presetQuery/{deviceId}/{channelId}") + public DeferredResult> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) { + if (logger.isDebugEnabled()) { + logger.debug("设备预置位查询API调用"); + } + Device device = storager.queryVideoDevice(deviceId); + cmder.presetQuery(device, channelId, event -> { + Response response = event.getResponse(); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); + resultHolder.invokeResult(msg); + }); + DeferredResult> result = new DeferredResult> (3 * 1000L); + result.onTimeout(()->{ + logger.warn(String.format("获取设备预置位超时")); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setData("获取设备预置位超时"); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + return result; + } } From bd75cd30a56763c263711847777e27551fe476c3 Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Fri, 5 Feb 2021 15:00:47 +0800 Subject: [PATCH 25/26] =?UTF-8?q?=E5=B0=86=E5=BD=95=E5=83=8F=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BB=9F=E8=AE=A1=E6=94=B9=E4=B8=BA=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E8=BF=9B=E8=A1=8C=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E8=BF=94=E5=9B=9E=E5=B7=B2=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../callback/CheckForAllRecordsThread.java | 78 ++++++++++++ .../request/impl/MessageRequestProcessor.java | 115 +++++++++++------- 2 files changed, 147 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java new file mode 100644 index 00000000..770edf06 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java @@ -0,0 +1,78 @@ +package com.genersoft.iot.vmp.gb28181.transmit.callback; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; +import com.genersoft.iot.vmp.gb28181.bean.RecordItem; +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; + +import org.slf4j.Logger; + +@SuppressWarnings("unchecked") +public class CheckForAllRecordsThread extends Thread { + + private String key; + + private RecordInfo recordInfo; + + private RedisUtil redis; + + private Logger logger; + + private DeferredResultHolder deferredResultHolder; + + public CheckForAllRecordsThread(String key, RecordInfo recordInfo) { + this.key = key; + this.recordInfo = recordInfo; + } + + public void run() { + + String cacheKey = this.key; + + for (long stop = System.nanoTime() + TimeUnit.SECONDS.toNanos(10); stop > System.nanoTime();) { + List cacheKeys = redis.scan(cacheKey + "_*"); + List totalRecordList = new ArrayList(); + for (int i = 0; i < cacheKeys.size(); i++) { + totalRecordList.addAll((List) redis.get(cacheKeys.get(i).toString())); + } + if (totalRecordList.size() < this.recordInfo.getSumNum()) { + logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + this.recordInfo.getSumNum() + "项"); + } else { + logger.info("录像数据已全部获取,共" + this.recordInfo.getSumNum() + "项"); + this.recordInfo.setRecordList(totalRecordList); + for (int i = 0; i < cacheKeys.size(); i++) { + redis.del(cacheKeys.get(i).toString()); + } + break; + } + } + // 自然顺序排序, 元素进行升序排列 + this.recordInfo.getRecordList().sort(Comparator.naturalOrder()); + RequestMessage msg = new RequestMessage(); + String deviceId = recordInfo.getDeviceId(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); + msg.setData(recordInfo); + deferredResultHolder.invokeResult(msg); + logger.info("处理完成,返回结果"); + MessageRequestProcessor.threadNameList.remove(cacheKey); + } + + public void setRedis(RedisUtil redis) { + this.redis = redis; + } + + public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) { + this.deferredResultHolder = deferredResultHolder; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } + +} 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 c865ad39..e7fbfe0d 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 @@ -23,6 +23,7 @@ import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.bean.RecordItem; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; @@ -43,14 +44,17 @@ import org.dom4j.io.SAXReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; + /** * @Description:MESSAGE请求处理器 * @author: swwheihei * @date: 2020年5月3日 下午5:32:41 */ - +@SuppressWarnings(value={"unchecked", "rawtypes"}) public class MessageRequestProcessor extends SIPRequestAbstractProcessor { + public static volatile List threadNameList = new ArrayList(); + private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup"); private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); @@ -240,10 +244,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { try { Element rootElement = getRootElement(evt); String deviceId = XmlUtil.getText(rootElement, "DeviceID"); - String result = XmlUtil.getText(rootElement, "Result"); + //String result = XmlUtil.getText(rootElement, "Result"); // 回复200 OK responseAck(evt); - if (!XmlUtil.isEmpty(result)) { + if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) { // 此处是对本平台发出DeviceControl指令的应答 JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); @@ -272,11 +276,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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指令的应答 + if (rootElement.getName().equals("Response")) { + // 此处是对本平台发出DeviceControl指令的应答 JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); if (logger.isDebugEnabled()) { @@ -287,9 +290,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG); msg.setData(json); deferredResultHolder.invokeResult(msg); - // } else { - // // 此处是上级发出的DeviceConfig指令 - //} + } else { + // 此处是上级发出的DeviceConfig指令 + } } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { e.printStackTrace(); } @@ -304,11 +307,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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指令的应答 + if (rootElement.getName().equals("Response")) { + // 此处是对本平台发出DeviceControl指令的应答 JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); if (logger.isDebugEnabled()) { @@ -319,9 +321,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD); msg.setData(json); deferredResultHolder.invokeResult(msg); - // } else { - // // 此处是上级发出的DeviceConfig指令 - //} + } else { + // 此处是上级发出的DeviceConfig指令 + } } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { e.printStackTrace(); } @@ -336,7 +338,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 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)) { @@ -648,8 +649,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { Element recordListElement = rootElement.element("RecordList"); if (recordListElement == null || recordInfo.getSumNum() == 0) { logger.info("无录像数据"); - // responseAck(evt); - // return; + RequestMessage msg = new RequestMessage(); + msg.setDeviceId(deviceId); + msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); + msg.setData(recordInfo); + deferredResultHolder.invokeResult(msg); } else { Iterator recordListIterator = recordListElement.elementIterator(); List recordList = new ArrayList(); @@ -679,44 +683,63 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { record.setRecorderId(XmlUtil.getText(itemRecord, "RecorderID")); recordList.add(record); } - // recordList.sort(Comparator.naturalOrder()); recordInfo.setRecordList(recordList); } - // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回 - if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { - // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 - String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; - - redis.set(cacheKey + "_" + uuid, recordList, 90); - List cacheKeys = redis.scan(cacheKey + "_*"); - List totalRecordList = new ArrayList(); - for (int i = 0; i < cacheKeys.size(); i++) { - totalRecordList.addAll((List) redis.get(cacheKeys.get(i).toString())); + // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题 + String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + redis.set(cacheKey + "_" + uuid, recordList, 90); + if (!threadNameList.contains(cacheKey)) { + threadNameList.add(cacheKey); + CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); + chk.setName(cacheKey); + chk.setDeferredResultHolder(deferredResultHolder); + chk.setRedis(redis); + chk.setLogger(logger); + chk.start(); + if (logger.isDebugEnabled()) { + logger.debug("Start Thread " + cacheKey + "."); } - if (totalRecordList.size() < recordInfo.getSumNum()) { - logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项"); - return; - } - logger.info("录像数据已全部获取,共" + recordInfo.getSumNum() + "项"); - recordInfo.setRecordList(totalRecordList); - for (int i = 0; i < cacheKeys.size(); i++) { - redis.del(cacheKeys.get(i).toString()); + } else { + if (logger.isDebugEnabled()) { + logger.debug("Thread " + cacheKey + " already started."); } } - // 自然顺序排序, 元素进行升序排列 - recordInfo.getRecordList().sort(Comparator.naturalOrder()); + + // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回 + // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { + // // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 + // String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + + // redis.set(cacheKey + "_" + uuid, recordList, 90); + // List cacheKeys = redis.scan(cacheKey + "_*"); + // List totalRecordList = new ArrayList(); + // for (int i = 0; i < cacheKeys.size(); i++) { + // totalRecordList.addAll((List) redis.get(cacheKeys.get(i).toString())); + // } + // if (totalRecordList.size() < recordInfo.getSumNum()) { + // logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项"); + // return; + // } + // logger.info("录像数据已全部获取,共" + recordInfo.getSumNum() + "项"); + // recordInfo.setRecordList(totalRecordList); + // for (int i = 0; i < cacheKeys.size(); i++) { + // redis.del(cacheKeys.get(i).toString()); + // } + // } + // // 自然顺序排序, 元素进行升序排列 + // recordInfo.getRecordList().sort(Comparator.naturalOrder()); } // 走到这里,有以下可能:1、没有录像信息,第一次收到recordinfo的消息即返回响应数据,无redis操作 // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作 // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据 - RequestMessage msg = new RequestMessage(); - msg.setDeviceId(deviceId); - msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); - msg.setData(recordInfo); - deferredResultHolder.invokeResult(msg); - logger.info("处理完成,返回结果"); + // RequestMessage msg = new RequestMessage(); + // msg.setDeviceId(deviceId); + // msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); + // msg.setData(recordInfo); + // deferredResultHolder.invokeResult(msg); + // logger.info("处理完成,返回结果"); } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } @@ -799,4 +822,4 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { this.redisCatchStorage = redisCatchStorage; } -} +} \ No newline at end of file From 347cac1859d32ff27123a1f9f078b01fe486d3fb Mon Sep 17 00:00:00 2001 From: lawrencehj <1934378145@qq.com> Date: Fri, 5 Feb 2021 15:15:39 +0800 Subject: [PATCH 26/26] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=86=97=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BF=AE=E6=AD=A3=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E6=8A=A5=E8=AD=A6=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/VManageBootstrap.java | 1 - .../iot/vmp/common/VideoManagerConstants.java | 2 +- .../iot/vmp/conf/VManagerConfig.java | 2 +- .../genersoft/iot/vmp/gb28181/SipLayer.java | 2 - .../DigestServerAuthenticationHelper.java | 8 ++- .../iot/vmp/gb28181/bean/RecordInfo.java | 2 +- .../iot/vmp/gb28181/bean/WvpSipDate.java | 5 ++ .../iot/vmp/gb28181/event/SipSubscribe.java | 8 --- .../vmp/gb28181/event/alarm/AlarmEvent.java | 5 ++ .../gb28181/event/offline/OfflineEvent.java | 13 ++--- .../vmp/gb28181/event/online/OnlineEvent.java | 13 ++--- .../gb28181/transmit/SIPProcessorFactory.java | 9 ++- .../callback/DeferredResultHolder.java | 4 +- .../transmit/callback/RequestMessage.java | 2 +- .../gb28181/transmit/cmd/ISIPCommander.java | 1 - .../cmd/SIPRequestHeaderProvider.java | 1 - .../transmit/cmd/impl/SIPCommander.java | 3 - .../request/impl/NotifyRequestProcessor.java | 57 +++++++++---------- .../impl/RegisterRequestProcessor.java | 2 +- .../impl/InviteResponseProcessor.java | 8 +-- .../iot/vmp/gb28181/utils/NumericUtil.java | 8 +-- .../vmp/media/zlm/ZLMHTTPProxyController.java | 18 ++---- .../vmp/media/zlm/ZLMHttpHookListener.java | 38 ++----------- .../vmp/media/zlm/ZLMHttpHookSubscribe.java | 20 ------- .../iot/vmp/media/zlm/ZLMRESTfulUtils.java | 1 - .../iot/vmp/media/zlm/ZLMRunner.java | 10 +--- .../vmp/storager/IVideoManagerStorager.java | 1 + .../storager/impl/RedisCatchStorageImpl.java | 7 +-- .../impl/VideoManagerStoragerImpl.java | 9 ++- .../iot/vmp/utils/redis/RedisUtil.java | 3 +- .../iot/vmp/vmanager/device/DeviceConfig.java | 1 - .../iot/vmp/vmanager/device/DeviceQuery.java | 2 +- .../iot/vmp/vmanager/play/PlayController.java | 7 +-- .../vmanager/playback/PlaybackController.java | 11 +--- .../vmp/vmanager/service/IPlayService.java | 1 - .../service/impl/PlayServiceImpl.java | 3 - .../iot/vmp/vmanager/user/UserController.java | 6 -- .../iot/vmp/web/ApiControlController.java | 3 - .../genersoft/iot/vmp/web/ApiController.java | 2 - .../iot/vmp/web/ApiDeviceController.java | 19 ++++--- .../iot/vmp/web/ApiStreamController.java | 10 ++-- .../genersoft/iot/vmp/web/AuthController.java | 3 - 42 files changed, 114 insertions(+), 217 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java index 990f003b..4a92e093 100644 --- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java +++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp; import java.util.logging.LogManager; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index f80fd0ea..846d3d01 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.common; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 定义常量 * @author: swwheihei * @date: 2019年5月30日 下午3:04:04 * diff --git a/src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java index 4c71b5c9..ff9d6439 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 获取数据库配置 * @author: swwheihei * @date: 2020年5月6日 下午2:46:00 */ diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 25a35a47..c5dc1e5c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -149,8 +149,6 @@ public class SipLayer implements SipListener { } } } - // } else if (status == Response.TRYING) { - // trying不会回复 } else if ((status >= 100) && (status < 200)) { // 增加其它无需回复的响应,如101、180等 } else { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java index 53282e20..4605ede8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java @@ -91,8 +91,10 @@ public class DigestServerAuthenticationHelper { long time = date.getTime(); Random rand = new Random(); long pad = rand.nextLong(); - String nonceString = (new Long(time)).toString() - + (new Long(pad)).toString(); + // String nonceString = (new Long(time)).toString() + // + (new Long(pad)).toString(); + String nonceString = Long.valueOf(time).toString() + + Long.valueOf(pad).toString(); byte mdbytes[] = messageDigest.digest(nonceString.getBytes()); // Convert the mdbytes array into a hex string. return toHexString(mdbytes); @@ -191,7 +193,7 @@ public class DigestServerAuthenticationHelper { // 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。 // 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护 - String cNonce = authHeader.getCNonce(); + //String cNonce = authHeader.getCNonce(); // nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量 int nc = authHeader.getNonceCount(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java index 45a61123..4ec182af 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.gb28181.bean; -import gov.nist.javax.sip.header.SIPDate; +//import gov.nist.javax.sip.header.SIPDate; import java.util.List; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java index 42ad6edd..f2a256b9 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java @@ -10,6 +10,11 @@ import java.util.*; */ public class WvpSipDate extends SIPDate { + /** + * + */ + private static final long serialVersionUID = 1L; + private Calendar javaCal; public WvpSipDate(long timeMillis) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java index 176a435e..e00a59fc 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java @@ -1,22 +1,14 @@ package com.genersoft.iot.vmp.gb28181.event; -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.sip.ResponseEvent; -import javax.sip.message.Request; -import java.util.EventObject; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Component public class SipSubscribe { - private final static Logger logger = LoggerFactory.getLogger(SipSubscribe.class); - private Map errorSubscribes = new ConcurrentHashMap<>(); private Map okSubscribes = new ConcurrentHashMap<>(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java index fecc8b1b..9f91bed9 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java @@ -10,6 +10,11 @@ import org.springframework.context.ApplicationEvent; */ public class AlarmEvent extends ApplicationEvent { + /** + * + */ + private static final long serialVersionUID = 1L; + public AlarmEvent(Object source) { super(source); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java index 55531060..aa45efe6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java @@ -3,18 +3,17 @@ package com.genersoft.iot.vmp.gb28181.event.offline; import org.springframework.context.ApplicationEvent; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 离线事件类 * @author: swwheihei * @date: 2020年5月6日 上午11:33:13 */ public class OfflineEvent extends ApplicationEvent { - /** - * @Title: OutlineEvent - * @Description: TODO(这里用一句话描述这个方法的作用) - * @param: @param source - * @throws - */ + /** + * + */ + private static final long serialVersionUID = 1L; + public OfflineEvent(Object source) { super(source); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java index 86eddc16..e077cb98 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java @@ -3,18 +3,17 @@ package com.genersoft.iot.vmp.gb28181.event.online; import org.springframework.context.ApplicationEvent; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 在线事件类 * @author: swwheihei * @date: 2020年5月6日 上午11:32:56 */ public class OnlineEvent extends ApplicationEvent { - /** - * @Title: OnlineEvent - * @Description: TODO(这里用一句话描述这个方法的作用) - * @param: @param source - * @throws - */ + /** + * + */ + private static final long serialVersionUID = 1L; + public OnlineEvent(Object source) { super(source); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java index b8638659..77e6bd95 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java @@ -8,10 +8,9 @@ import javax.sip.message.Request; import javax.sip.message.Response; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.conf.SipConfig; @@ -40,14 +39,14 @@ import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.redis.RedisUtil; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: SIP信令处理分配 * @author: swwheihei * @date: 2020年5月3日 下午4:24:37 */ @Component public class SIPProcessorFactory { - private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); + // private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); @Autowired private SipConfig sipConfig; 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 edf86797..6fcc2e02 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 @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -10,10 +9,11 @@ import org.springframework.stereotype.Component; import org.springframework.web.context.request.async.DeferredResult; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 异步请求处理 * @author: swwheihei * @date: 2020年5月8日 下午7:59:05 */ +@SuppressWarnings(value = {"rawtypes", "unchecked"}) @Component public class DeferredResultHolder { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java index fcf7e7aa..223092fb 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback; /** - * @Description:TODO(这里用一句话描述这个类的作用) + * @Description: 请求信息定义 * @author: swwheihei * @date: 2020年5月8日 下午1:09:18 */ 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 30fbfe94..6fa4eca9 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 @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; -import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index c89af839..11e3e16e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -18,7 +18,6 @@ import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.Host; /** * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化 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 c174455f..6bab8090 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 @@ -1,21 +1,18 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; import java.text.ParseException; -import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.sip.*; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; -import javax.sip.header.Header; import javax.sip.header.ViaHeader; import javax.sip.message.Request; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java index 8c7d969c..897b6ab8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java @@ -50,26 +50,20 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); - private SIPCommander cmder; - private IVideoManagerStorager storager; private IRedisCatchStorage redisCatchStorage; private EventPublisher publisher; - private RedisUtil redis; - - private DeferredResultHolder deferredResultHolder; - private DeviceOffLineDetector offLineDetector; private static final String NOTIFY_CATALOG = "Catalog"; private static final String NOTIFY_ALARM = "Alarm"; private static final String NOTIFY_MOBILE_POSITION = "MobilePosition"; - @Override - public void process(RequestEvent evt) { + @Override + public void process(RequestEvent evt) { try { Element rootElement = getRootElement(evt); String cmd = XmlUtil.getText(rootElement, "CmdType"); @@ -87,18 +81,19 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { logger.info("接收到消息:" + cmd); response200Ok(evt); } - } catch (DocumentException | SipException |InvalidArgumentException | ParseException e) { + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } - } + } /** * 处理MobilePosition移动位置Notify + * * @param evt */ private void processNotifyMobilePosition(RequestEvent evt) { try { - //回复 200 OK + // 回复 200 OK Element rootElement = getRootElement(evt); MobilePosition mobilePosition = new MobilePosition(); Element deviceIdElement = rootElement.element("DeviceID"); @@ -112,8 +107,8 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID")); mobilePosition.setTime(XmlUtil.getText(rootElement, "Time")); mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); - mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); - if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) { + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) { mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed"))); } else { mobilePosition.setSpeed(0.0); @@ -147,6 +142,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { /*** * 处理alarm设备报警Notify + * * @param evt */ private void processNotifyAlarm(RequestEvent evt) { @@ -180,7 +176,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { deviceAlarm.setLatitude(0.00); } - if ( deviceAlarm.getAlarmMethod().equals("4")) { + if (deviceAlarm.getAlarmMethod().equals("4")) { MobilePosition mobilePosition = new MobilePosition(); mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); mobilePosition.setTime(deviceAlarm.getAlarmTime()); @@ -245,7 +241,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setName(channelName); deviceChannel.setChannelId(channelDeviceId); - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { deviceChannel.setStatus(1); } @@ -259,29 +255,34 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode")); deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block")); deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address")); - if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") { + if (XmlUtil.getText(itemDevice, "Parental") == null + || XmlUtil.getText(itemDevice, "Parental") == "") { deviceChannel.setParental(0); } else { deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental"))); - } + } deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); - if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay")== "") { + if (XmlUtil.getText(itemDevice, "SafetyWay") == null + || XmlUtil.getText(itemDevice, "SafetyWay") == "") { deviceChannel.setSafetyWay(0); } else { deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); } - if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") =="") { + if (XmlUtil.getText(itemDevice, "RegisterWay") == null + || XmlUtil.getText(itemDevice, "RegisterWay") == "") { deviceChannel.setRegisterWay(1); } else { deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); } deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); - if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") { + if (XmlUtil.getText(itemDevice, "Certifiable") == null + || XmlUtil.getText(itemDevice, "Certifiable") == "") { deviceChannel.setCertifiable(0); } else { deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable"))); } - if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") { + if (XmlUtil.getText(itemDevice, "ErrCode") == null + || XmlUtil.getText(itemDevice, "ErrCode") == "") { deviceChannel.setErrCode(0); } else { deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); @@ -289,7 +290,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); - if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") =="") { + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") { deviceChannel.setPort(0); } else { deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); @@ -305,7 +306,8 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { } else { deviceChannel.setLatitude(0.00); } - if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { + if (XmlUtil.getText(itemDevice, "PTZType") == null + || XmlUtil.getText(itemDevice, "PTZType") == "") { deviceChannel.setPTZType(0); } else { deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); @@ -330,9 +332,9 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { } } - - /*** + /*** * 回复200 OK + * * @param evt * @throws SipException * @throws InvalidArgumentException @@ -343,7 +345,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { getServerTransaction(evt).sendResponse(response); } - private Element getRootElement(RequestEvent evt) throws DocumentException { + private Element getRootElement(RequestEvent evt) throws DocumentException { Request request = evt.getRequest(); SAXReader reader = new SAXReader(); reader.setEncoding("gbk"); @@ -352,7 +354,6 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { } public void setCmder(SIPCommander cmder) { - this.cmder = cmder; } public void setStorager(IVideoManagerStorager storager) { @@ -364,11 +365,9 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { } public void setRedis(RedisUtil redis) { - this.redis = redis; } public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) { - this.deferredResultHolder = deferredResultHolder; } public void setOffLineDetector(DeviceOffLineDetector offLineDetector) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java index 18b5de19..22d54a71 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java @@ -145,7 +145,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { // 下发catelog查询目录 if (registerFlag == 1 && device != null) { logger.info("注册成功! deviceId:" + device.getDeviceId()); - boolean exists = storager.exists(device.getDeviceId()); + // boolean exists = storager.exists(device.getDeviceId()); device.setRegisterTimeMillis(System.currentTimeMillis()); storager.updateDevice(device); publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java index 93f533f9..d67267af 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java @@ -12,14 +12,12 @@ import javax.sip.header.ViaHeader; import javax.sip.message.Request; import javax.sip.message.Response; -import gov.nist.javax.sip.header.CSeq; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.SipLayer; -import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; @@ -31,7 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; @Component public class InviteResponseProcessor implements ISIPResponseProcessor { - private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); + // private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); /** * 处理invite响应 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java index f9fbfb18..4a399b89 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java @@ -15,10 +15,10 @@ public class NumericUtil { public static boolean isDouble(String str) { try { Double num2 = Double.valueOf(str); - System.out.println(num2 + " Is an Integer!"); + System.out.println(num2 + " is a valid numeric string!"); return true; } catch (Exception e) { - System.out.println(str + " Is not an Integer!"); + System.out.println(str + " is an invalid numeric string!"); return false; } } @@ -31,10 +31,10 @@ public class NumericUtil { public static boolean isInteger(String str) { try { int num2 = Integer.valueOf(str); - System.out.println(num2 + " Is Number!"); + System.out.println(num2 + " is an integer!"); return true; } catch (Exception e) { - System.out.println(str + " Is not Number!"); + System.out.println(str + " is not an integer!"); return false; } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java index 9daef230..d5c218cd 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java @@ -1,34 +1,28 @@ package com.genersoft.iot.vmp.media.zlm; -import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +// import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.util.Enumeration; @RestController @RequestMapping("/zlm") public class ZLMHTTPProxyController { - private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class); + // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class); - @Autowired - private IVideoManagerStorager storager; + // @Autowired + // private IVideoManagerStorager storager; @Autowired private IRedisCatchStorage redisCatchStorage; diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 66ee1b04..ba1a6f15 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -1,19 +1,13 @@ package com.genersoft.iot.vmp.media.zlm; -import java.math.BigInteger; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.utils.IpUtil; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,8 +51,8 @@ public class ZLMHttpHookListener { @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + // @Autowired + // private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private ZLMHttpHookSubscribe subscribe; @@ -86,9 +80,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -106,8 +97,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_http_access API 调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("err", ""); @@ -127,8 +116,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_play API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -146,15 +133,12 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString()); } - String app = json.getString("app"); - String streamId = json.getString("id"); + // String app = json.getString("app"); + // String streamId = json.getString("id"); ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); if (subscribe != null) subscribe.response(json); - - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -175,8 +159,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_record_mp4 API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -194,8 +176,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_rtsp_realm API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("realm", ""); @@ -214,8 +194,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_rtsp_auth API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("encrypted", false); @@ -234,8 +212,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_shell_login API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -267,8 +243,6 @@ public class ZLMHttpHookListener { redisCatchStorage.stopPlayback(streamInfo); } } - - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -316,8 +290,6 @@ public class ZLMHttpHookListener { if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString()); } - // TODO Auto-generated method stub - if (autoApplyPlay) { String app = json.getString("app"); String streamId = json.getString("stream"); @@ -367,8 +339,6 @@ public class ZLMHttpHookListener { mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); mediaServerConfig.setLocalIP(mediaIp); redisCatchStorage.updateMediaInfo(mediaServerConfig); - // TODO Auto-generated method stub - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java index 0c00b821..995f9166 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java @@ -1,24 +1,8 @@ package com.genersoft.iot.vmp.media.zlm; -import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.util.ConcurrentReferenceHashMap; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; -import java.math.BigInteger; -import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -31,8 +15,6 @@ import java.util.concurrent.ConcurrentHashMap; @Component public class ZLMHttpHookSubscribe { - private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookSubscribe.class); - public enum HookType{ on_flow_report, on_http_access, @@ -72,8 +54,6 @@ public class ZLMHttpHookSubscribe { for (JSONObject key : eventMap.keySet()) { Boolean result = null; for (String s : key.keySet()) { - String string = hookResponse.getString(s); - String string1 = key.getString(s); if (result == null) { result = key.getString(s).equals(hookResponse.getString(s)); }else { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index ac1f51a4..58de847e 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -11,7 +11,6 @@ import org.springframework.stereotype.Component; import java.io.IOException; import java.net.ConnectException; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; @Component diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index 282699f9..490bfd8e 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -5,8 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import okhttp3.*; +//import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -16,9 +15,6 @@ import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; @@ -28,8 +24,8 @@ public class ZLMRunner implements CommandLineRunner { private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class); - @Autowired - private IVideoManagerStorager storager; + // @Autowired + // private IVideoManagerStorager storager; @Autowired private IRedisCatchStorage redisCatchStorage; diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index c0eda001..37f3eb18 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -12,6 +12,7 @@ import com.github.pagehelper.PageInfo; * @author: swwheihei * @date: 2020年5月6日 下午2:14:31 */ +@SuppressWarnings("rawtypes") public interface IVideoManagerStorager { /** diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index d4b6f449..958b38a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -11,7 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -144,9 +143,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public StreamInfo queryPlaybackByDevice(String deviceId, String code) { - String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, - deviceId, - code); + // String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, + // deviceId, + // code); List playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, deviceId, code)); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index cc8320cf..22292ef9 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -9,19 +9,18 @@ import com.genersoft.iot.vmp.storager.dao.DeviceMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; -import io.swagger.models.auth.In; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import org.springframework.util.StringUtils; /** * @Description:视频设备数据存储-jdbc实现 * @author: swwheihei * @date: 2020年5月6日 下午2:31:42 */ +@SuppressWarnings("rawtypes") @Component public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -183,11 +182,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @Override public synchronized boolean online(String deviceId) { Device device = deviceMapper.getDeviceByDeviceId(deviceId); - device.setOnline(1); - System.out.println("更新设备在线"); if (device == null) { return false; } + device.setOnline(1); + System.out.println("更新设备在线"); return deviceMapper.update(device) > 0; } @@ -211,7 +210,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { */ @Override public void cleanChannelsForDevice(String deviceId) { - int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId); + deviceChannelMapper.cleanChannelsByDeviceId(deviceId); } /** diff --git a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java index e0f7e417..f83d5f3e 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java @@ -4,8 +4,6 @@ import java.util.*; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.*; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -16,6 +14,7 @@ import org.springframework.util.CollectionUtils; * @date: 2020年5月6日 下午8:27:29 */ @Component +@SuppressWarnings(value = {"rawtypes", "unchecked"}) public class RedisUtil { @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java index 6c4f7a31..d046c0df 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java @@ -20,7 +20,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java index 350adaa3..997a43b2 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java @@ -17,11 +17,11 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import javax.sip.message.Response; +@SuppressWarnings("rawtypes") @CrossOrigin @RestController @RequestMapping("/api") diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index 3bd828a9..08e5cc43 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java @@ -1,20 +1,16 @@ package com.genersoft.iot.vmp.vmanager.play; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; @@ -31,7 +27,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.springframework.web.context.request.async.DeferredResult; import javax.sip.message.Response; -import java.text.DecimalFormat; import java.util.UUID; @CrossOrigin @@ -145,7 +140,7 @@ public class PlayController { storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid); - Response response = event.getResponse(); + //Response response = event.getResponse(); msg.setData(String.format("success")); resultHolder.invokeResult(msg); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java index 9449d263..020a26c2 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java @@ -1,24 +1,19 @@ package com.genersoft.iot.vmp.vmanager.playback; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.CrossOrigin; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -47,8 +42,8 @@ public class PlaybackController { @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + // @Autowired + // private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private IPlayService playService; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java index a80ab5df..d81bdedd 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.vmanager.service; import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; /** * 点播处理 diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java index 70ca1f31..f0879761 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java @@ -9,15 +9,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.vmanager.play.PlayController; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.text.DecimalFormat; - @Service public class PlayServiceImpl implements IPlayService { diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java index 12ade38d..5ebfd2d3 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java @@ -1,8 +1,5 @@ package com.genersoft.iot.vmp.vmanager.user; -import com.genersoft.iot.vmp.vmanager.play.PlayController; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.CrossOrigin; @@ -14,9 +11,6 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api") public class UserController { - private final static Logger logger = LoggerFactory.getLogger(UserController.class); - - @Value("${auth.username}") private String usernameConfig; diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java index c9a68bfa..c55824a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java @@ -4,12 +4,9 @@ import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.vmanager.ptz.PtzController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; /** diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiController.java index 002b2cc5..43ae7d97 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiController.java @@ -5,11 +5,9 @@ import com.genersoft.iot.vmp.conf.SipConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; /** diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java index 199a9e69..b58a3c5b 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java @@ -4,9 +4,9 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +// import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; +// import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +// import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.github.pagehelper.PageInfo; import org.slf4j.Logger; @@ -19,6 +19,7 @@ import java.util.List; /** * 兼容LiveGBS的API:设备信息 */ +@SuppressWarnings("unchecked") @CrossOrigin @RestController @RequestMapping(value = "/api/v1/device") @@ -29,14 +30,14 @@ public class ApiDeviceController { @Autowired private IVideoManagerStorager storager; - @Autowired - private SIPCommander cmder; + // @Autowired + // private SIPCommander cmder; - @Autowired - private DeferredResultHolder resultHolder; + // @Autowired + // private DeferredResultHolder resultHolder; - @Autowired - private DeviceOffLineDetector offLineDetector; + // @Autowired + // private DeviceOffLineDetector offLineDetector; /** * 分页获取设备列表 TODO 现在直接返回,尚未实现分页 diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java index f31bd603..5a56bef7 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java @@ -1,21 +1,18 @@ package com.genersoft.iot.vmp.web; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +// import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.vmanager.play.PlayController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -23,6 +20,7 @@ import org.springframework.web.context.request.async.DeferredResult; /** * 兼容LiveGBS的API:实时直播 */ +@SuppressWarnings(value = {"rawtypes", "unchecked"}) @CrossOrigin @RestController @RequestMapping(value = "/api/v1/stream") @@ -40,8 +38,8 @@ public class ApiStreamController { private IRedisCatchStorage redisCatchStorage; - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + // @Autowired + // private ZLMRESTfulUtils zlmresTfulUtils; @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/web/AuthController.java b/src/main/java/com/genersoft/iot/vmp/web/AuthController.java index 8fd66ca6..702387cb 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/AuthController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/AuthController.java @@ -1,9 +1,6 @@ package com.genersoft.iot.vmp.web; -import com.genersoft.iot.vmp.gb28181.bean.Device; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*;