commit
2c47c8c86b
|
@ -33,7 +33,8 @@ https://gitee.com/18010473990/wvp-GB28181.git
|
||||||
16. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址
|
16. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址
|
||||||
17. 支持国标网络校时
|
17. 支持国标网络校时
|
||||||
18. 支持公网部署, 支持wvp与zlm分开部署
|
18. 支持公网部署, 支持wvp与zlm分开部署
|
||||||
19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false).
|
19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false)
|
||||||
|
20. 报警信息处理,支持向前端推送报警信息
|
||||||
|
|
||||||
# 2.0 支持特性
|
# 2.0 支持特性
|
||||||
- [ ] 国标通道向上级联
|
- [ ] 国标通道向上级联
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class DeviceAlarm {
|
||||||
/**
|
/**
|
||||||
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情-
|
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情-
|
||||||
*/
|
*/
|
||||||
private String alarmPriorit;
|
private String alarmPriority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
* 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
||||||
|
@ -53,12 +53,12 @@ public class DeviceAlarm {
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlarmPriorit() {
|
public String getAlarmPriority() {
|
||||||
return alarmPriorit;
|
return alarmPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlarmPriorit(String alarmPriorit) {
|
public void setAlarmPriority(String alarmPriority) {
|
||||||
this.alarmPriorit = alarmPriorit;
|
this.alarmPriority = alarmPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlarmMethod() {
|
public String getAlarmMethod() {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Component;
|
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.offline.OfflineEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
||||||
|
|
||||||
|
@ -53,4 +55,14 @@ public class EventPublisher {
|
||||||
platformNotRegisterEvent.setPlatformGbID(platformGbId);
|
platformNotRegisterEvent.setPlatformGbID(platformGbId);
|
||||||
applicationEventPublisher.publishEvent(platformNotRegisterEvent);
|
applicationEventPublisher.publishEvent(platformNotRegisterEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备报警事件
|
||||||
|
* @param deviceAlarm
|
||||||
|
*/
|
||||||
|
public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) {
|
||||||
|
AlarmEvent alarmEvent = new AlarmEvent(this);
|
||||||
|
alarmEvent.setAlarmInfo(deviceAlarm);
|
||||||
|
applicationEventPublisher.publishEvent(alarmEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -174,7 +174,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
SipUri uri = (SipUri) address.getURI();
|
SipUri uri = (SipUri) address.getURI();
|
||||||
String platformId = uri.getUser();
|
String platformId = uri.getUser();
|
||||||
// if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
|
// if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
|
||||||
if (name == "Query") { // 区分是Response——查询响应,还是Query——查询请求
|
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
||||||
// TODO 后续将代码拆分
|
// TODO 后续将代码拆分
|
||||||
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
|
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
|
||||||
if (parentPlatform == null) {
|
if (parentPlatform == null) {
|
||||||
|
@ -324,19 +324,41 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
// storager.queryChannel(deviceId)
|
// storager.queryChannel(deviceId)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
device.setName(XmlUtil.getText(rootElement, "DeviceName"));
|
|
||||||
device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
|
DeviceAlarm deviceAlarm = new DeviceAlarm();
|
||||||
device.setModel(XmlUtil.getText(rootElement, "Model"));
|
deviceAlarm.setDeviceId(deviceId);
|
||||||
device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
|
deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
|
||||||
if (StringUtils.isEmpty(device.getStreamMode())) {
|
deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
|
||||||
device.setStreamMode("UDP");
|
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);
|
//cmder.catalogQuery(device, null);
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt);
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
publisher.deviceAlarmEventPublish(deviceAlarm);
|
||||||
}
|
}
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
// } catch (DocumentException e) {
|
// } catch (DocumentException e) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,7 +137,7 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
chooseChannel: function(platform) {
|
chooseChannel: function(platform) {
|
||||||
this.$refs.chooseChannelDialog.openDialog(platform.deviceGBId, ()=>{
|
this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, ()=>{
|
||||||
this.initData()
|
this.initData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<el-menu-item index="/">控制台</el-menu-item>
|
<el-menu-item index="/">控制台</el-menu-item>
|
||||||
<el-menu-item index="/videoList">设备列表</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-item style="float: right;" @click="loginout">退出</el-menu-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,14 +13,63 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "UiHeader",
|
name: "UiHeader",
|
||||||
|
components: { Notification },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
alarmNotify: true,
|
||||||
|
sseSource: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
|
||||||
loginout(){
|
loginout(){
|
||||||
// 删除cookie,回到登录页面
|
// 删除cookie,回到登录页面
|
||||||
this.$cookies.remove("session");
|
this.$cookies.remove("session");
|
||||||
this.$router.push('/login');
|
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>
|
</script>
|
||||||
|
|
|
@ -9,10 +9,13 @@ import VueCookies from 'vue-cookies';
|
||||||
import echarts from 'echarts';
|
import echarts from 'echarts';
|
||||||
|
|
||||||
import VueClipboard from 'vue-clipboard2'
|
import VueClipboard from 'vue-clipboard2'
|
||||||
|
import { Notification } from 'element-ui';
|
||||||
|
|
||||||
Vue.use(VueClipboard)
|
Vue.use(VueClipboard)
|
||||||
Vue.use(ElementUI);
|
Vue.use(ElementUI);
|
||||||
Vue.use(VueCookies);
|
Vue.use(VueCookies);
|
||||||
Vue.prototype.$axios = axios;
|
Vue.prototype.$axios = axios;
|
||||||
|
Vue.prototype.$notify = Notification;
|
||||||
|
|
||||||
axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : "";
|
axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : "";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue