Commit 83411ad1277f8d4dfbc95aff2f15900150e84db3
1 parent
641d7d8e
设备信息增加最近注册时间和最近心跳时间,心跳超时时间变为可配置
Showing
16 changed files
with
130 additions
and
70 deletions
sql/mysql.sql
| @@ -12,9 +12,11 @@ create table device | @@ -12,9 +12,11 @@ create table device | ||
| 12 | transport varchar(50) null, | 12 | transport varchar(50) null, |
| 13 | streamMode varchar(50) null, | 13 | streamMode varchar(50) null, |
| 14 | online varchar(50) null, | 14 | online varchar(50) null, |
| 15 | - registerTimeMillis int null, | 15 | + registerTime varchar(50) null, |
| 16 | + keepaliveTime varchar(50) null, | ||
| 16 | ip varchar(50) not null, | 17 | ip varchar(50) not null, |
| 17 | port int not null, | 18 | port int not null, |
| 19 | + expires int not null, | ||
| 18 | hostAddress varchar(50) not null | 20 | hostAddress varchar(50) not null |
| 19 | ); | 21 | ); |
| 20 | 22 |
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
| @@ -23,4 +23,5 @@ public class VManageBootstrap extends LogManager { | @@ -23,4 +23,5 @@ public class VManageBootstrap extends LogManager { | ||
| 23 | VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); | 23 | VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); |
| 24 | 24 | ||
| 25 | } | 25 | } |
| 26 | + | ||
| 26 | } | 27 | } |
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
| @@ -39,7 +39,9 @@ public class VideoManagerConstants { | @@ -39,7 +39,9 @@ public class VideoManagerConstants { | ||
| 39 | public static final String EVENT_ONLINE_REGISTER = "1"; | 39 | public static final String EVENT_ONLINE_REGISTER = "1"; |
| 40 | 40 | ||
| 41 | public static final String EVENT_ONLINE_KEEPLIVE = "2"; | 41 | public static final String EVENT_ONLINE_KEEPLIVE = "2"; |
| 42 | - | 42 | + |
| 43 | + public static final String EVENT_ONLINE_MESSAGE = "3"; | ||
| 44 | + | ||
| 43 | public static final String EVENT_OUTLINE_UNREGISTER = "1"; | 45 | public static final String EVENT_OUTLINE_UNREGISTER = "1"; |
| 44 | 46 | ||
| 45 | public static final String EVENT_OUTLINE_TIMEOUT = "2"; | 47 | public static final String EVENT_OUTLINE_TIMEOUT = "2"; |
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
| @@ -31,6 +31,9 @@ public class SipConfig { | @@ -31,6 +31,9 @@ public class SipConfig { | ||
| 31 | @Value("${sip.ptz.speed:50}") | 31 | @Value("${sip.ptz.speed:50}") |
| 32 | Integer speed; | 32 | Integer speed; |
| 33 | 33 | ||
| 34 | + @Value("${sip.keepaliveTimeOut:180}") | ||
| 35 | + Integer keepaliveTimeOut; | ||
| 36 | + | ||
| 34 | public String getMonitorIp() { | 37 | public String getMonitorIp() { |
| 35 | return monitorIp; | 38 | return monitorIp; |
| 36 | } | 39 | } |
| @@ -63,4 +66,7 @@ public class SipConfig { | @@ -63,4 +66,7 @@ public class SipConfig { | ||
| 63 | return speed; | 66 | return speed; |
| 64 | } | 67 | } |
| 65 | 68 | ||
| 69 | + public Integer getKeepaliveTimeOut() { | ||
| 70 | + return keepaliveTimeOut; | ||
| 71 | + } | ||
| 66 | } | 72 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
| @@ -66,19 +66,24 @@ public class Device { | @@ -66,19 +66,24 @@ public class Device { | ||
| 66 | /** | 66 | /** |
| 67 | * 注册时间 | 67 | * 注册时间 |
| 68 | */ | 68 | */ |
| 69 | - private Long registerTimeMillis; | 69 | + private String registerTime; |
| 70 | 70 | ||
| 71 | 71 | ||
| 72 | /** | 72 | /** |
| 73 | * 心跳时间 | 73 | * 心跳时间 |
| 74 | */ | 74 | */ |
| 75 | - private Long KeepaliveTimeMillis; | 75 | + private String keepaliveTime; |
| 76 | 76 | ||
| 77 | /** | 77 | /** |
| 78 | * 通道个数 | 78 | * 通道个数 |
| 79 | */ | 79 | */ |
| 80 | private int channelCount; | 80 | private int channelCount; |
| 81 | 81 | ||
| 82 | + /** | ||
| 83 | + * 注册有效期 | ||
| 84 | + */ | ||
| 85 | + private int expires; | ||
| 86 | + | ||
| 82 | public String getDeviceId() { | 87 | public String getDeviceId() { |
| 83 | return deviceId; | 88 | return deviceId; |
| 84 | } | 89 | } |
| @@ -175,19 +180,27 @@ public class Device { | @@ -175,19 +180,27 @@ public class Device { | ||
| 175 | this.channelCount = channelCount; | 180 | this.channelCount = channelCount; |
| 176 | } | 181 | } |
| 177 | 182 | ||
| 178 | - public Long getRegisterTimeMillis() { | ||
| 179 | - return registerTimeMillis; | 183 | + public String getRegisterTime() { |
| 184 | + return registerTime; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + public void setRegisterTime(String registerTime) { | ||
| 188 | + this.registerTime = registerTime; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + public String getKeepaliveTime() { | ||
| 192 | + return keepaliveTime; | ||
| 180 | } | 193 | } |
| 181 | 194 | ||
| 182 | - public void setRegisterTimeMillis(Long registerTimeMillis) { | ||
| 183 | - this.registerTimeMillis = registerTimeMillis; | 195 | + public void setKeepaliveTime(String keepaliveTime) { |
| 196 | + this.keepaliveTime = keepaliveTime; | ||
| 184 | } | 197 | } |
| 185 | 198 | ||
| 186 | - public Long getKeepaliveTimeMillis() { | ||
| 187 | - return KeepaliveTimeMillis; | 199 | + public int getExpires() { |
| 200 | + return expires; | ||
| 188 | } | 201 | } |
| 189 | 202 | ||
| 190 | - public void setKeepaliveTimeMillis(Long keepaliveTimeMillis) { | ||
| 191 | - KeepaliveTimeMillis = keepaliveTimeMillis; | 203 | + public void setExpires(int expires) { |
| 204 | + this.expires = expires; | ||
| 192 | } | 205 | } |
| 193 | } | 206 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
| 1 | package com.genersoft.iot.vmp.gb28181.event; | 1 | package com.genersoft.iot.vmp.gb28181.event; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 3 | import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; | 4 | import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; |
| 4 | import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; | 5 | import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; |
| 5 | import org.springframework.beans.factory.annotation.Autowired; | 6 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -22,9 +23,9 @@ public class EventPublisher { | @@ -22,9 +23,9 @@ public class EventPublisher { | ||
| 22 | @Autowired | 23 | @Autowired |
| 23 | private ApplicationEventPublisher applicationEventPublisher; | 24 | private ApplicationEventPublisher applicationEventPublisher; |
| 24 | 25 | ||
| 25 | - public void onlineEventPublish(String deviceId, String from) { | 26 | + public void onlineEventPublish(Device device, String from) { |
| 26 | OnlineEvent onEvent = new OnlineEvent(this); | 27 | OnlineEvent onEvent = new OnlineEvent(this); |
| 27 | - onEvent.setDeviceId(deviceId); | 28 | + onEvent.setDevice(device); |
| 28 | onEvent.setFrom(from); | 29 | onEvent.setFrom(from); |
| 29 | applicationEventPublisher.publishEvent(onEvent); | 30 | applicationEventPublisher.publishEvent(onEvent); |
| 30 | } | 31 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
| 1 | package com.genersoft.iot.vmp.gb28181.event.online; | 1 | package com.genersoft.iot.vmp.gb28181.event.online; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 3 | import org.springframework.context.ApplicationEvent; | 4 | import org.springframework.context.ApplicationEvent; |
| 4 | 5 | ||
| 5 | /** | 6 | /** |
| @@ -18,18 +19,18 @@ public class OnlineEvent extends ApplicationEvent { | @@ -18,18 +19,18 @@ public class OnlineEvent extends ApplicationEvent { | ||
| 18 | super(source); | 19 | super(source); |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | - private String deviceId; | 22 | + private Device device; |
| 22 | 23 | ||
| 23 | private String from; | 24 | private String from; |
| 24 | 25 | ||
| 25 | - public String getDeviceId() { | ||
| 26 | - return deviceId; | 26 | + public Device getDevice() { |
| 27 | + return device; | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | - public void setDeviceId(String deviceId) { | ||
| 30 | - this.deviceId = deviceId; | 30 | + public void setDevice(Device device) { |
| 31 | + this.device = device; | ||
| 31 | } | 32 | } |
| 32 | - | 33 | + |
| 33 | public String getFrom() { | 34 | public String getFrom() { |
| 34 | return from; | 35 | return from; |
| 35 | } | 36 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
| 1 | package com.genersoft.iot.vmp.gb28181.event.online; | 1 | package com.genersoft.iot.vmp.gb28181.event.online; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 4 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 3 | import org.slf4j.Logger; | 5 | import org.slf4j.Logger; |
| 4 | import org.slf4j.LoggerFactory; | 6 | import org.slf4j.LoggerFactory; |
| 5 | import org.springframework.beans.factory.annotation.Autowired; | 7 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -10,6 +12,9 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; | @@ -10,6 +12,9 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 10 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 11 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; | 13 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| 12 | 14 | ||
| 15 | +import java.text.SimpleDateFormat; | ||
| 16 | +import java.util.Date; | ||
| 17 | + | ||
| 13 | /** | 18 | /** |
| 14 | * @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: | 19 | * @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: |
| 15 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} | 20 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} |
| @@ -28,39 +33,46 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | @@ -28,39 +33,46 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | ||
| 28 | @Autowired | 33 | @Autowired |
| 29 | private RedisUtil redis; | 34 | private RedisUtil redis; |
| 30 | 35 | ||
| 36 | + @Autowired | ||
| 37 | + private SipConfig sipConfig; | ||
| 38 | + | ||
| 39 | + private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
| 40 | + | ||
| 31 | @Override | 41 | @Override |
| 32 | public void onApplicationEvent(OnlineEvent event) { | 42 | public void onApplicationEvent(OnlineEvent event) { |
| 33 | 43 | ||
| 34 | if (logger.isDebugEnabled()) { | 44 | if (logger.isDebugEnabled()) { |
| 35 | - logger.debug("设备上线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom()); | 45 | + logger.debug("设备上线事件触发,deviceId:" + event.getDevice().getDeviceId() + ",from:" + event.getFrom()); |
| 36 | } | 46 | } |
| 37 | - | ||
| 38 | - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDeviceId(); | ||
| 39 | - boolean needUpdateStorager = false; | 47 | + Device device = event.getDevice(); |
| 48 | + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDevice().getDeviceId(); | ||
| 40 | 49 | ||
| 41 | switch (event.getFrom()) { | 50 | switch (event.getFrom()) { |
| 42 | // 注册时触发的在线事件,先在redis中增加超时超时监听 | 51 | // 注册时触发的在线事件,先在redis中增加超时超时监听 |
| 43 | case VideoManagerConstants.EVENT_ONLINE_REGISTER: | 52 | case VideoManagerConstants.EVENT_ONLINE_REGISTER: |
| 44 | - // TODO 超时时间暂时写死为180秒 | ||
| 45 | - redis.set(key, event.getDeviceId(), 180); | ||
| 46 | - needUpdateStorager = true; | 53 | + // 超时时间 |
| 54 | + redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut()); | ||
| 55 | + device.setRegisterTime(format.format(new Date(System.currentTimeMillis()))); | ||
| 47 | break; | 56 | break; |
| 48 | - // 设备主动发送心跳触发的离线事件 | 57 | + // 设备主动发送心跳触发的在线事件 |
| 49 | case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: | 58 | case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: |
| 50 | boolean exist = redis.hasKey(key); | 59 | boolean exist = redis.hasKey(key); |
| 51 | // 先判断是否还存在,当设备先心跳超时后又发送心跳时,redis没有监听,需要增加 | 60 | // 先判断是否还存在,当设备先心跳超时后又发送心跳时,redis没有监听,需要增加 |
| 52 | if (!exist) { | 61 | if (!exist) { |
| 53 | - needUpdateStorager = true; | ||
| 54 | - redis.set(key, event.getDeviceId(), 180); | 62 | + redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut()); |
| 55 | } else { | 63 | } else { |
| 56 | - redis.expire(key, 180); | 64 | + redis.expire(key, sipConfig.getKeepaliveTimeOut()); |
| 57 | } | 65 | } |
| 66 | + device.setKeepaliveTime(format.format(new Date(System.currentTimeMillis()))); | ||
| 67 | + break; | ||
| 68 | + // 设备主动发送消息触发的在线事件 | ||
| 69 | + case VideoManagerConstants.EVENT_ONLINE_MESSAGE: | ||
| 70 | + | ||
| 58 | break; | 71 | break; |
| 59 | } | 72 | } |
| 60 | - | ||
| 61 | - if (needUpdateStorager) { | ||
| 62 | - // 处理离线监听 | ||
| 63 | - storager.online(event.getDeviceId()); | ||
| 64 | - } | 73 | + |
| 74 | + device.setOnline(1); | ||
| 75 | + // 处理上线监听 | ||
| 76 | + storager.updateDevice(device); | ||
| 65 | } | 77 | } |
| 66 | } | 78 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | ||
| 2 | 2 | ||
| 3 | import java.io.ByteArrayInputStream; | 3 | import java.io.ByteArrayInputStream; |
| 4 | import java.text.ParseException; | 4 | import java.text.ParseException; |
| 5 | +import java.text.SimpleDateFormat; | ||
| 5 | import java.util.*; | 6 | import java.util.*; |
| 6 | 7 | ||
| 7 | import javax.sip.address.SipURI; | 8 | import javax.sip.address.SipURI; |
| @@ -226,7 +227,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -226,7 +227,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 226 | String name = rootElement.getName(); | 227 | String name = rootElement.getName(); |
| 227 | Element deviceIdElement = rootElement.element("DeviceID"); | 228 | Element deviceIdElement = rootElement.element("DeviceID"); |
| 228 | String deviceId = deviceIdElement.getText(); | 229 | String deviceId = deviceIdElement.getText(); |
| 229 | - | 230 | + Device device = storager.queryVideoDevice(deviceId); |
| 230 | if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求 | 231 | if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求 |
| 231 | logger.info("接收到DeviceStatus查询消息"); | 232 | logger.info("接收到DeviceStatus查询消息"); |
| 232 | FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); | 233 | FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
| @@ -259,7 +260,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -259,7 +260,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 259 | deferredResultHolder.invokeResult(msg); | 260 | deferredResultHolder.invokeResult(msg); |
| 260 | 261 | ||
| 261 | if (offLineDetector.isOnline(deviceId)) { | 262 | if (offLineDetector.isOnline(deviceId)) { |
| 262 | - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | 263 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
| 263 | } else { | 264 | } else { |
| 264 | } | 265 | } |
| 265 | } | 266 | } |
| @@ -452,6 +453,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -452,6 +453,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 452 | String requestName = rootElement.getName(); | 453 | String requestName = rootElement.getName(); |
| 453 | Element deviceIdElement = rootElement.element("DeviceID"); | 454 | Element deviceIdElement = rootElement.element("DeviceID"); |
| 454 | String deviceId = deviceIdElement.getTextTrim().toString(); | 455 | String deviceId = deviceIdElement.getTextTrim().toString(); |
| 456 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 455 | if (requestName.equals("Query")) { | 457 | if (requestName.equals("Query")) { |
| 456 | logger.info("接收到DeviceInfo查询消息"); | 458 | logger.info("接收到DeviceInfo查询消息"); |
| 457 | FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); | 459 | FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
| @@ -468,7 +470,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -468,7 +470,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 468 | } | 470 | } |
| 469 | } else { | 471 | } else { |
| 470 | logger.debug("接收到DeviceInfo应答消息"); | 472 | logger.debug("接收到DeviceInfo应答消息"); |
| 471 | - Device device = storager.queryVideoDevice(deviceId); | ||
| 472 | if (device == null) { | 473 | if (device == null) { |
| 473 | return; | 474 | return; |
| 474 | } | 475 | } |
| @@ -489,7 +490,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -489,7 +490,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 489 | // 回复200 OK | 490 | // 回复200 OK |
| 490 | responseAck(evt); | 491 | responseAck(evt); |
| 491 | if (offLineDetector.isOnline(deviceId)) { | 492 | if (offLineDetector.isOnline(deviceId)) { |
| 492 | - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | 493 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
| 493 | } | 494 | } |
| 494 | } | 495 | } |
| 495 | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | 496 | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { |
| @@ -669,7 +670,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -669,7 +670,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 669 | // 回复200 OK | 670 | // 回复200 OK |
| 670 | responseAck(evt); | 671 | responseAck(evt); |
| 671 | if (offLineDetector.isOnline(deviceId)) { | 672 | if (offLineDetector.isOnline(deviceId)) { |
| 672 | - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | 673 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
| 673 | } | 674 | } |
| 674 | } | 675 | } |
| 675 | } | 676 | } |
| @@ -776,7 +777,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -776,7 +777,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 776 | // 回复200 OK | 777 | // 回复200 OK |
| 777 | responseAck(evt); | 778 | responseAck(evt); |
| 778 | if (offLineDetector.isOnline(deviceId)) { | 779 | if (offLineDetector.isOnline(deviceId)) { |
| 779 | - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | 780 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); |
| 780 | } else { | 781 | } else { |
| 781 | } | 782 | } |
| 782 | }else { | 783 | }else { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java
| @@ -216,13 +216,13 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { | @@ -216,13 +216,13 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 216 | Element rootElement = getRootElement(evt); | 216 | Element rootElement = getRootElement(evt); |
| 217 | Element deviceIdElement = rootElement.element("DeviceID"); | 217 | Element deviceIdElement = rootElement.element("DeviceID"); |
| 218 | String deviceId = deviceIdElement.getText(); | 218 | String deviceId = deviceIdElement.getText(); |
| 219 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 219 | Element deviceListElement = rootElement.element("DeviceList"); | 220 | Element deviceListElement = rootElement.element("DeviceList"); |
| 220 | if (deviceListElement == null) { | 221 | if (deviceListElement == null) { |
| 221 | return; | 222 | return; |
| 222 | } | 223 | } |
| 223 | Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | 224 | Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); |
| 224 | if (deviceListIterator != null) { | 225 | if (deviceListIterator != null) { |
| 225 | - Device device = storager.queryVideoDevice(deviceId); | ||
| 226 | if (device == null) { | 226 | if (device == null) { |
| 227 | return; | 227 | return; |
| 228 | } | 228 | } |
| @@ -324,7 +324,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { | @@ -324,7 +324,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 324 | // 回复200 OK | 324 | // 回复200 OK |
| 325 | response200Ok(evt); | 325 | response200Ok(evt); |
| 326 | if (offLineDetector.isOnline(deviceId)) { | 326 | if (offLineDetector.isOnline(deviceId)) { |
| 327 | - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | 327 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
| 328 | } | 328 | } |
| 329 | } | 329 | } |
| 330 | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | 330 | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
| @@ -2,7 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | @@ -2,7 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | ||
| 2 | 2 | ||
| 3 | import java.security.NoSuchAlgorithmException; | 3 | import java.security.NoSuchAlgorithmException; |
| 4 | import java.text.ParseException; | 4 | import java.text.ParseException; |
| 5 | +import java.text.SimpleDateFormat; | ||
| 6 | +import java.time.LocalDateTime; | ||
| 5 | import java.util.Calendar; | 7 | import java.util.Calendar; |
| 8 | +import java.util.Date; | ||
| 6 | import java.util.Locale; | 9 | import java.util.Locale; |
| 7 | 10 | ||
| 8 | import javax.sip.InvalidArgumentException; | 11 | import javax.sip.InvalidArgumentException; |
| @@ -70,7 +73,11 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -70,7 +73,11 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 70 | boolean passwordCorrect = false; | 73 | boolean passwordCorrect = false; |
| 71 | // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 | 74 | // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 |
| 72 | int registerFlag = 0; | 75 | int registerFlag = 0; |
| 73 | - Device device = null; | 76 | + FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); |
| 77 | + AddressImpl address = (AddressImpl) fromHeader.getAddress(); | ||
| 78 | + SipUri uri = (SipUri) address.getURI(); | ||
| 79 | + String deviceId = uri.getUser(); | ||
| 80 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 74 | AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 81 | AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 75 | // 校验密码是否正确 | 82 | // 校验密码是否正确 |
| 76 | if (authorhead != null) { | 83 | if (authorhead != null) { |
| @@ -103,13 +110,17 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -103,13 +110,17 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 103 | response.addHeader(dateHeader); | 110 | response.addHeader(dateHeader); |
| 104 | 111 | ||
| 105 | ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); | 112 | ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); |
| 113 | + if (expiresHeader == null) { | ||
| 114 | + response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); | ||
| 115 | + getServerTransaction(evt).sendResponse(response); | ||
| 116 | + return; | ||
| 117 | + } | ||
| 106 | // 添加Contact头 | 118 | // 添加Contact头 |
| 107 | response.addHeader(request.getHeader(ContactHeader.NAME)); | 119 | response.addHeader(request.getHeader(ContactHeader.NAME)); |
| 108 | // 添加Expires头 | 120 | // 添加Expires头 |
| 109 | response.addHeader(request.getExpires()); | 121 | response.addHeader(request.getExpires()); |
| 110 | 122 | ||
| 111 | // 获取到通信地址等信息 | 123 | // 获取到通信地址等信息 |
| 112 | - FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); | ||
| 113 | ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | 124 | ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
| 114 | String received = viaHeader.getReceived(); | 125 | String received = viaHeader.getReceived(); |
| 115 | int rPort = viaHeader.getRPort(); | 126 | int rPort = viaHeader.getRPort(); |
| @@ -119,10 +130,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -119,10 +130,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 119 | rPort = viaHeader.getPort(); | 130 | rPort = viaHeader.getPort(); |
| 120 | } | 131 | } |
| 121 | // | 132 | // |
| 122 | - AddressImpl address = (AddressImpl) fromHeader.getAddress(); | ||
| 123 | - SipUri uri = (SipUri) address.getURI(); | ||
| 124 | - String deviceId = uri.getUser(); | ||
| 125 | - device = storager.queryVideoDevice(deviceId); | 133 | + |
| 126 | if (device == null) { | 134 | if (device == null) { |
| 127 | device = new Device(); | 135 | device = new Device(); |
| 128 | device.setStreamMode("UDP"); | 136 | device.setStreamMode("UDP"); |
| @@ -132,11 +140,12 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -132,11 +140,12 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 132 | device.setPort(rPort); | 140 | device.setPort(rPort); |
| 133 | device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); | 141 | device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); |
| 134 | // 注销成功 | 142 | // 注销成功 |
| 135 | - if (expiresHeader != null && expiresHeader.getExpires() == 0) { | 143 | + if (expiresHeader.getExpires() == 0) { |
| 136 | registerFlag = 2; | 144 | registerFlag = 2; |
| 137 | } | 145 | } |
| 138 | // 注册成功 | 146 | // 注册成功 |
| 139 | else { | 147 | else { |
| 148 | + device.setExpires(expiresHeader.getExpires()); | ||
| 140 | registerFlag = 1; | 149 | registerFlag = 1; |
| 141 | // 判断TCP还是UDP | 150 | // 判断TCP还是UDP |
| 142 | boolean isTcp = false; | 151 | boolean isTcp = false; |
| @@ -154,10 +163,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -154,10 +163,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 154 | // 下发catelog查询目录 | 163 | // 下发catelog查询目录 |
| 155 | if (registerFlag == 1 ) { | 164 | if (registerFlag == 1 ) { |
| 156 | logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); | 165 | logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); |
| 157 | - device.setRegisterTimeMillis(System.currentTimeMillis()); | ||
| 158 | - storager.updateDevice(device); | ||
| 159 | - publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); | ||
| 160 | - | 166 | + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER); |
| 161 | // 重新注册更新设备和通道,以免设备替换或更新后信息无法更新 | 167 | // 重新注册更新设备和通道,以免设备替换或更新后信息无法更新 |
| 162 | handler.onRegister(device); | 168 | handler.onRegister(device); |
| 163 | } else if (registerFlag == 2) { | 169 | } else if (registerFlag == 2) { |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| @@ -27,6 +27,9 @@ public interface DeviceMapper { | @@ -27,6 +27,9 @@ public interface DeviceMapper { | ||
| 27 | "ip," + | 27 | "ip," + |
| 28 | "port," + | 28 | "port," + |
| 29 | "hostAddress," + | 29 | "hostAddress," + |
| 30 | + "expires," + | ||
| 31 | + "registerTime," + | ||
| 32 | + "keepaliveTime," + | ||
| 30 | "online" + | 33 | "online" + |
| 31 | ") VALUES (" + | 34 | ") VALUES (" + |
| 32 | "#{deviceId}," + | 35 | "#{deviceId}," + |
| @@ -39,6 +42,9 @@ public interface DeviceMapper { | @@ -39,6 +42,9 @@ public interface DeviceMapper { | ||
| 39 | "#{ip}," + | 42 | "#{ip}," + |
| 40 | "#{port}," + | 43 | "#{port}," + |
| 41 | "#{hostAddress}," + | 44 | "#{hostAddress}," + |
| 45 | + "#{expires}," + | ||
| 46 | + "#{registerTime}," + | ||
| 47 | + "#{keepaliveTime}," + | ||
| 42 | "#{online}" + | 48 | "#{online}" + |
| 43 | ")") | 49 | ")") |
| 44 | int add(Device device); | 50 | int add(Device device); |
| @@ -56,6 +62,9 @@ public interface DeviceMapper { | @@ -56,6 +62,9 @@ public interface DeviceMapper { | ||
| 56 | "<if test=\"port != null\">, port=${port}</if>" + | 62 | "<if test=\"port != null\">, port=${port}</if>" + |
| 57 | "<if test=\"hostAddress != null\">, hostAddress='${hostAddress}'</if>" + | 63 | "<if test=\"hostAddress != null\">, hostAddress='${hostAddress}'</if>" + |
| 58 | "<if test=\"online != null\">, online=${online}</if>" + | 64 | "<if test=\"online != null\">, online=${online}</if>" + |
| 65 | + "<if test=\"registerTime != null\">, registerTime='${registerTime}'</if>" + | ||
| 66 | + "<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" + | ||
| 67 | + "<if test=\"expires != null\">, expires=${expires}</if>" + | ||
| 59 | "WHERE deviceId='${deviceId}'"+ | 68 | "WHERE deviceId='${deviceId}'"+ |
| 60 | " </script>"}) | 69 | " </script>"}) |
| 61 | int update(Device device); | 70 | int update(Device device); |
src/main/resources/all-application.yml
| @@ -63,8 +63,10 @@ sip: | @@ -63,8 +63,10 @@ sip: | ||
| 63 | domain: 4401020049 | 63 | domain: 4401020049 |
| 64 | # [可选] | 64 | # [可选] |
| 65 | id: 44010200492000000001 | 65 | id: 44010200492000000001 |
| 66 | - # [可选] 默认设备认证密码,后续扩展使用设备单独密码 | 66 | + # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验 |
| 67 | password: admin123 | 67 | password: admin123 |
| 68 | + # [可选] 心跳超时时间, 建议设置为心跳周期的三倍 | ||
| 69 | + keepaliveTimeOut: 180 | ||
| 68 | 70 | ||
| 69 | #zlm服务器配置 | 71 | #zlm服务器配置 |
| 70 | media: | 72 | media: |
src/main/resources/application-dev.yml
| @@ -39,7 +39,7 @@ sip: | @@ -39,7 +39,7 @@ sip: | ||
| 39 | domain: 4401020049 | 39 | domain: 4401020049 |
| 40 | # [可选] | 40 | # [可选] |
| 41 | id: 44010200492000000001 | 41 | id: 44010200492000000001 |
| 42 | - # [可选] 默认设备认证密码,后续扩展使用设备单独密码 | 42 | + # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验 |
| 43 | password: admin123 | 43 | password: admin123 |
| 44 | 44 | ||
| 45 | #zlm服务器配置 | 45 | #zlm服务器配置 |
src/main/resources/wvp.sqlite
No preview for this file type
web_src/src/components/DeviceList.vue
| @@ -14,22 +14,16 @@ | @@ -14,22 +14,16 @@ | ||
| 14 | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> | 14 | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> |
| 15 | <!--设备列表--> | 15 | <!--设备列表--> |
| 16 | <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> | 16 | <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> |
| 17 | - <el-table-column prop="name" label="名称" width="180" align="center"> | 17 | + <el-table-column prop="name" label="名称" align="center"> |
| 18 | </el-table-column> | 18 | </el-table-column> |
| 19 | - <el-table-column prop="deviceId" label="设备编号" width="240" align="center"> | ||
| 20 | - </el-table-column> | ||
| 21 | - <el-table-column label="地址" width="180" align="center"> | ||
| 22 | - <template slot-scope="scope"> | ||
| 23 | - <div slot="reference" class="name-wrapper"> | ||
| 24 | - <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag> | ||
| 25 | - </div> | ||
| 26 | - </template> | 19 | + <el-table-column prop="deviceId" label="设备编号" width="180" align="center"> |
| 27 | </el-table-column> | 20 | </el-table-column> |
| 21 | + | ||
| 28 | <el-table-column prop="manufacturer" label="厂家" align="center"> | 22 | <el-table-column prop="manufacturer" label="厂家" align="center"> |
| 29 | </el-table-column> | 23 | </el-table-column> |
| 30 | - <el-table-column prop="model" label="固件版本" align="center"> | 24 | + <el-table-column prop="model" label="固件版本" align="center" width="120"> |
| 31 | </el-table-column> | 25 | </el-table-column> |
| 32 | - <el-table-column label="流传输模式" align="center" width="160"> | 26 | + <el-table-column label="流传输模式" align="center" width="120"> |
| 33 | <template slot-scope="scope"> | 27 | <template slot-scope="scope"> |
| 34 | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择"> | 28 | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择"> |
| 35 | <el-option key="UDP" label="UDP" value="UDP"></el-option> | 29 | <el-option key="UDP" label="UDP" value="UDP"></el-option> |
| @@ -40,7 +34,7 @@ | @@ -40,7 +34,7 @@ | ||
| 40 | </el-table-column> | 34 | </el-table-column> |
| 41 | <el-table-column prop="channelCount" label="通道数" align="center"> | 35 | <el-table-column prop="channelCount" label="通道数" align="center"> |
| 42 | </el-table-column> | 36 | </el-table-column> |
| 43 | - <el-table-column label="状态" width="80" align="center"> | 37 | + <el-table-column label="状态" width="120" align="center"> |
| 44 | <template slot-scope="scope"> | 38 | <template slot-scope="scope"> |
| 45 | <div slot="reference" class="name-wrapper"> | 39 | <div slot="reference" class="name-wrapper"> |
| 46 | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> | 40 | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| @@ -48,7 +42,17 @@ | @@ -48,7 +42,17 @@ | ||
| 48 | </div> | 42 | </div> |
| 49 | </template> | 43 | </template> |
| 50 | </el-table-column> | 44 | </el-table-column> |
| 51 | - | 45 | + <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140"> |
| 46 | + </el-table-column> | ||
| 47 | + <el-table-column prop="registerTime" label="最近注册" align="center" width="140"> | ||
| 48 | + </el-table-column> | ||
| 49 | + <el-table-column label="地址" width="180" align="center"> | ||
| 50 | + <template slot-scope="scope"> | ||
| 51 | + <div slot="reference" class="name-wrapper"> | ||
| 52 | + <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag> | ||
| 53 | + </div> | ||
| 54 | + </template> | ||
| 55 | + </el-table-column> | ||
| 52 | <el-table-column label="操作" width="360" align="center" fixed="right"> | 56 | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| 53 | <template slot-scope="scope"> | 57 | <template slot-scope="scope"> |
| 54 | <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> | 58 | <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> |