Merge pull request #42 from lawrencehj/wvp-28181-2.0
增加报警事件处理功能等
| | |
| | | 16. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址 |
| | | 17. 支持国标网络校时 |
| | | 18. 支持公网部署, 支持wvp与zlm分开部署 |
| | | 19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false). |
| | | 19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false) |
| | | 20. 报警信息处理,支持向前端推送报警信息 |
| | | |
| | | # 2.0 支持特性 |
| | | - [ ] 国标通道向上级联 |
| | |
| | | /**
|
| | | * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情-
|
| | | */
|
| | | private String alarmPriorit;
|
| | | private String alarmPriority;
|
| | |
|
| | | /**
|
| | | * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
| | |
| | | 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() {
|
| | |
| | | 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;
|
| | |
|
| | |
| | | PlatformNotRegisterEvent platformNotRegisterEvent = new PlatformNotRegisterEvent(this);
|
| | | platformNotRegisterEvent.setPlatformGbID(platformGbId);
|
| | | applicationEventPublisher.publishEvent(platformNotRegisterEvent);
|
| | | }
|
| | | }
|
| | | |
| | | /**
|
| | | * 设备报警事件
|
| | | * @param deviceAlarm
|
| | | */
|
| | | public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) {
|
| | | AlarmEvent alarmEvent = new AlarmEvent(this);
|
| | | alarmEvent.setAlarmInfo(deviceAlarm);
|
| | | applicationEventPublisher.publishEvent(alarmEvent);
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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; |
| | | } |
| | | } |
New file |
| | |
| | | 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<AlarmEvent> { |
| | | |
| | | 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 = "<strong>设备编码:</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>" |
| | | + "<br><strong>报警描述:</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>" |
| | | + "<br><strong>报警时间:</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>" |
| | | + "<br><strong>定位经度:</strong> <i>" + event.getAlarmInfo().getLongitude() + "</i>" |
| | | + "<br><strong>定位纬度:</strong> <i>" + event.getAlarmInfo().getLatitude() + "</i>"; |
| | | emitter.send(msg); |
| | | } catch (IOException e) { |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug("SSE 通道已关闭"); |
| | | } |
| | | // e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | |
| | | SipUri uri = (SipUri) address.getURI();
|
| | | String platformId = uri.getUser();
|
| | | // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
|
| | | if (name == "Query") { // 区分是Response——查询响应,还是Query——查询请求
|
| | | if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
| | | // TODO 后续将代码拆分
|
| | | ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
|
| | | if (parentPlatform == null) {
|
| | |
| | | // 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) {
|
New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | }); |
| | | }, |
| | | chooseChannel: function(platform) { |
| | | this.$refs.chooseChannelDialog.openDialog(platform.deviceGBId, ()=>{ |
| | | this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, ()=>{ |
| | | this.initData() |
| | | }) |
| | | }, |
| | |
| | | <el-menu router :default-active="this.$route.path" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> |
| | | <el-menu-item index="/">控制台</el-menu-item> |
| | | <el-menu-item index="/videoList">设备列表</el-menu-item> |
| | | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> |
| | | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> |
| | | <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> |
| | | <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item> |
| | | </el-menu> |
| | | </div> |
| | |
| | | <script> |
| | | export default { |
| | | name: "UiHeader", |
| | | components: { Notification }, |
| | | data() { |
| | | return { |
| | | alarmNotify: true, |
| | | sseSource: null, |
| | | }; |
| | | }, |
| | | methods:{ |
| | | |
| | | loginout(){ |
| | | // 删除cookie,回到登录页面 |
| | | this.$cookies.remove("session"); |
| | | this.$router.push('/login'); |
| | | this.sseSource.close(); |
| | | }, |
| | | } |
| | | } |
| | | beforeunloadHandler() { |
| | | this.sseSource.close(); |
| | | }, |
| | | sseControl() { |
| | | let that = this; |
| | | if (this.alarmNotify) { |
| | | this.sseSource = new EventSource('/api/emit'); |
| | | this.sseSource.addEventListener('message', function(evt) { |
| | | that.$notify({ |
| | | title: '收到报警信息', |
| | | dangerouslyUseHTMLString: true, |
| | | message: evt.data, |
| | | type: 'warning' |
| | | }); |
| | | console.log("收到信息:" + evt.data); |
| | | }); |
| | | this.sseSource.addEventListener('open', function(e) { |
| | | console.log("SSE连接打开."); |
| | | }, false); |
| | | this.sseSource.addEventListener('error', function(e) { |
| | | if (e.target.readyState == EventSource.CLOSED) { |
| | | console.log("SSE连接关闭"); |
| | | } else { |
| | | console.log(e.target.readyState); |
| | | } |
| | | }, false); |
| | | } else { |
| | | this.sseSource.removeEventListener('open', null); |
| | | this.sseSource.removeEventListener('message', null); |
| | | this.sseSource.removeEventListener('error', null); |
| | | this.sseSource.close(); |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | window.addEventListener('beforeunload', e => this.beforeunloadHandler(e)) |
| | | // window.addEventListener('unload', e => this.unloadHandler(e)) |
| | | this.sseControl(); |
| | | }, |
| | | destroyed() { |
| | | window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e)) |
| | | // window.removeEventListener('unload', e => this.unloadHandler(e)) |
| | | }, |
| | | } |
| | | |
| | | </script> |
| | |
| | | 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 : ""; |
| | | |