设备信息增加最近注册时间和最近心跳时间,心跳超时时间变为可配置

pull/110/head
64850858 2021-06-07 15:11:53 +08:00
parent 641d7d8e42
commit 83411ad127
16 changed files with 130 additions and 70 deletions

View File

@ -12,9 +12,11 @@ create table device
transport varchar(50) null, transport varchar(50) null,
streamMode varchar(50) null, streamMode varchar(50) null,
online varchar(50) null, online varchar(50) null,
registerTimeMillis int null, registerTime varchar(50) null,
keepaliveTime varchar(50) null,
ip varchar(50) not null, ip varchar(50) not null,
port int not null, port int not null,
expires int not null,
hostAddress varchar(50) not null hostAddress varchar(50) not null
); );

View File

@ -23,4 +23,5 @@ public class VManageBootstrap extends LogManager {
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
} }
} }

View File

@ -40,6 +40,8 @@ public class VideoManagerConstants {
public static final String EVENT_ONLINE_KEEPLIVE = "2"; public static final String EVENT_ONLINE_KEEPLIVE = "2";
public static final String EVENT_ONLINE_MESSAGE = "3";
public static final String EVENT_OUTLINE_UNREGISTER = "1"; public static final String EVENT_OUTLINE_UNREGISTER = "1";
public static final String EVENT_OUTLINE_TIMEOUT = "2"; public static final String EVENT_OUTLINE_TIMEOUT = "2";

View File

@ -31,6 +31,9 @@ public class SipConfig {
@Value("${sip.ptz.speed:50}") @Value("${sip.ptz.speed:50}")
Integer speed; Integer speed;
@Value("${sip.keepaliveTimeOut:180}")
Integer keepaliveTimeOut;
public String getMonitorIp() { public String getMonitorIp() {
return monitorIp; return monitorIp;
} }
@ -63,4 +66,7 @@ public class SipConfig {
return speed; return speed;
} }
public Integer getKeepaliveTimeOut() {
return keepaliveTimeOut;
}
} }

View File

@ -66,19 +66,24 @@ public class Device {
/** /**
* *
*/ */
private Long registerTimeMillis; private String registerTime;
/** /**
* *
*/ */
private Long KeepaliveTimeMillis; private String keepaliveTime;
/** /**
* *
*/ */
private int channelCount; private int channelCount;
/**
*
*/
private int expires;
public String getDeviceId() { public String getDeviceId() {
return deviceId; return deviceId;
} }
@ -175,19 +180,27 @@ public class Device {
this.channelCount = channelCount; this.channelCount = channelCount;
} }
public Long getRegisterTimeMillis() { public String getRegisterTime() {
return registerTimeMillis; return registerTime;
} }
public void setRegisterTimeMillis(Long registerTimeMillis) { public void setRegisterTime(String registerTime) {
this.registerTimeMillis = registerTimeMillis; this.registerTime = registerTime;
} }
public Long getKeepaliveTimeMillis() { public String getKeepaliveTime() {
return KeepaliveTimeMillis; return keepaliveTime;
} }
public void setKeepaliveTimeMillis(Long keepaliveTimeMillis) { public void setKeepaliveTime(String keepaliveTime) {
KeepaliveTimeMillis = keepaliveTimeMillis; this.keepaliveTime = keepaliveTime;
}
public int getExpires() {
return expires;
}
public void setExpires(int expires) {
this.expires = expires;
} }
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event; package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent;
import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -22,9 +23,9 @@ public class EventPublisher {
@Autowired @Autowired
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
public void onlineEventPublish(String deviceId, String from) { public void onlineEventPublish(Device device, String from) {
OnlineEvent onEvent = new OnlineEvent(this); OnlineEvent onEvent = new OnlineEvent(this);
onEvent.setDeviceId(deviceId); onEvent.setDevice(device);
onEvent.setFrom(from); onEvent.setFrom(from);
applicationEventPublisher.publishEvent(onEvent); applicationEventPublisher.publishEvent(onEvent);
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event.online; package com.genersoft.iot.vmp.gb28181.event.online;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
/** /**
@ -18,16 +19,16 @@ public class OnlineEvent extends ApplicationEvent {
super(source); super(source);
} }
private String deviceId; private Device device;
private String from; private String from;
public String getDeviceId() { public Device getDevice() {
return deviceId; return device;
} }
public void setDeviceId(String deviceId) { public void setDevice(Device device) {
this.deviceId = deviceId; this.device = device;
} }
public String getFrom() { public String getFrom() {

View File

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.gb28181.event.online; package com.genersoft.iot.vmp.gb28181.event.online;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -10,6 +12,9 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
/** /**
* @Description: 线线线 线 * @Description: 线线线 线
* 1{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} * 1{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
@ -28,39 +33,46 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> {
@Autowired @Autowired
private RedisUtil redis; private RedisUtil redis;
@Autowired
private SipConfig sipConfig;
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override @Override
public void onApplicationEvent(OnlineEvent event) { public void onApplicationEvent(OnlineEvent event) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("设备上线事件触发deviceId" + event.getDeviceId() + ",from:" + event.getFrom()); logger.debug("设备上线事件触发deviceId" + event.getDevice().getDeviceId() + ",from:" + event.getFrom());
} }
Device device = event.getDevice();
String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDeviceId(); String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDevice().getDeviceId();
boolean needUpdateStorager = false;
switch (event.getFrom()) { switch (event.getFrom()) {
// 注册时触发的在线事件先在redis中增加超时超时监听 // 注册时触发的在线事件先在redis中增加超时超时监听
case VideoManagerConstants.EVENT_ONLINE_REGISTER: case VideoManagerConstants.EVENT_ONLINE_REGISTER:
// TODO 超时时间暂时写死为180秒 // 超时时间
redis.set(key, event.getDeviceId(), 180); redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut());
needUpdateStorager = true; device.setRegisterTime(format.format(new Date(System.currentTimeMillis())));
break; break;
// 设备主动发送心跳触发的线事件 // 设备主动发送心跳触发的线事件
case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE:
boolean exist = redis.hasKey(key); boolean exist = redis.hasKey(key);
// 先判断是否还存在当设备先心跳超时后又发送心跳时redis没有监听需要增加 // 先判断是否还存在当设备先心跳超时后又发送心跳时redis没有监听需要增加
if (!exist) { if (!exist) {
needUpdateStorager = true; redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut());
redis.set(key, event.getDeviceId(), 180);
} else { } else {
redis.expire(key, 180); redis.expire(key, sipConfig.getKeepaliveTimeOut());
} }
device.setKeepaliveTime(format.format(new Date(System.currentTimeMillis())));
break;
// 设备主动发送消息触发的在线事件
case VideoManagerConstants.EVENT_ONLINE_MESSAGE:
break; break;
} }
if (needUpdateStorager) { device.setOnline(1);
// 处理离线监听 // 处理上线监听
storager.online(event.getDeviceId()); storager.updateDevice(device);
}
} }
} }

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
@ -226,7 +227,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
String name = rootElement.getName(); String name = rootElement.getName();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText(); String deviceId = deviceIdElement.getText();
Device device = storager.queryVideoDevice(deviceId);
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应还是Query——查询请求 if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应还是Query——查询请求
logger.info("接收到DeviceStatus查询消息"); logger.info("接收到DeviceStatus查询消息");
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
@ -259,7 +260,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
deferredResultHolder.invokeResult(msg); deferredResultHolder.invokeResult(msg);
if (offLineDetector.isOnline(deviceId)) { if (offLineDetector.isOnline(deviceId)) {
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
} else { } else {
} }
} }
@ -452,6 +453,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
String requestName = rootElement.getName(); String requestName = rootElement.getName();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getTextTrim().toString(); String deviceId = deviceIdElement.getTextTrim().toString();
Device device = storager.queryVideoDevice(deviceId);
if (requestName.equals("Query")) { if (requestName.equals("Query")) {
logger.info("接收到DeviceInfo查询消息"); logger.info("接收到DeviceInfo查询消息");
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
@ -468,7 +470,6 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
} }
} else { } else {
logger.debug("接收到DeviceInfo应答消息"); logger.debug("接收到DeviceInfo应答消息");
Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return; return;
} }
@ -489,7 +490,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK // 回复200 OK
responseAck(evt); responseAck(evt);
if (offLineDetector.isOnline(deviceId)) { if (offLineDetector.isOnline(deviceId)) {
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
} }
} }
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
@ -669,7 +670,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK // 回复200 OK
responseAck(evt); responseAck(evt);
if (offLineDetector.isOnline(deviceId)) { if (offLineDetector.isOnline(deviceId)) {
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
} }
} }
} }
@ -776,7 +777,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK // 回复200 OK
responseAck(evt); responseAck(evt);
if (offLineDetector.isOnline(deviceId)) { if (offLineDetector.isOnline(deviceId)) {
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
} else { } else {
} }
}else { }else {

View File

@ -216,13 +216,13 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
Element rootElement = getRootElement(evt); Element rootElement = getRootElement(evt);
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText(); String deviceId = deviceIdElement.getText();
Device device = storager.queryVideoDevice(deviceId);
Element deviceListElement = rootElement.element("DeviceList"); Element deviceListElement = rootElement.element("DeviceList");
if (deviceListElement == null) { if (deviceListElement == null) {
return; return;
} }
Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
if (deviceListIterator != null) { if (deviceListIterator != null) {
Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return; return;
} }
@ -324,7 +324,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK // 回复200 OK
response200Ok(evt); response200Ok(evt);
if (offLineDetector.isOnline(deviceId)) { if (offLineDetector.isOnline(deviceId)) {
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
} }
} }
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {

View File

@ -2,7 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.Locale; import java.util.Locale;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
@ -70,7 +73,11 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
boolean passwordCorrect = false; boolean passwordCorrect = false;
// 注册标志 0未携带授权头或者密码错误 1注册成功 2注销成功 // 注册标志 0未携带授权头或者密码错误 1注册成功 2注销成功
int registerFlag = 0; int registerFlag = 0;
Device device = null; FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
String deviceId = uri.getUser();
Device device = storager.queryVideoDevice(deviceId);
AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
// 校验密码是否正确 // 校验密码是否正确
if (authorhead != null) { if (authorhead != null) {
@ -103,13 +110,17 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
response.addHeader(dateHeader); response.addHeader(dateHeader);
ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
if (expiresHeader == null) {
response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
getServerTransaction(evt).sendResponse(response);
return;
}
// 添加Contact头 // 添加Contact头
response.addHeader(request.getHeader(ContactHeader.NAME)); response.addHeader(request.getHeader(ContactHeader.NAME));
// 添加Expires头 // 添加Expires头
response.addHeader(request.getExpires()); response.addHeader(request.getExpires());
// 获取到通信地址等信息 // 获取到通信地址等信息
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
String received = viaHeader.getReceived(); String received = viaHeader.getReceived();
int rPort = viaHeader.getRPort(); int rPort = viaHeader.getRPort();
@ -119,10 +130,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
rPort = viaHeader.getPort(); rPort = viaHeader.getPort();
} }
// //
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
String deviceId = uri.getUser();
device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
device = new Device(); device = new Device();
device.setStreamMode("UDP"); device.setStreamMode("UDP");
@ -132,11 +140,12 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
device.setPort(rPort); device.setPort(rPort);
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
// 注销成功 // 注销成功
if (expiresHeader != null && expiresHeader.getExpires() == 0) { if (expiresHeader.getExpires() == 0) {
registerFlag = 2; registerFlag = 2;
} }
// 注册成功 // 注册成功
else { else {
device.setExpires(expiresHeader.getExpires());
registerFlag = 1; registerFlag = 1;
// 判断TCP还是UDP // 判断TCP还是UDP
boolean isTcp = false; boolean isTcp = false;
@ -154,10 +163,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
// 下发catelog查询目录 // 下发catelog查询目录
if (registerFlag == 1 ) { if (registerFlag == 1 ) {
logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress);
device.setRegisterTimeMillis(System.currentTimeMillis()); publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER);
storager.updateDevice(device);
publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新 // 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
handler.onRegister(device); handler.onRegister(device);
} else if (registerFlag == 2) { } else if (registerFlag == 2) {

View File

@ -27,6 +27,9 @@ public interface DeviceMapper {
"ip," + "ip," +
"port," + "port," +
"hostAddress," + "hostAddress," +
"expires," +
"registerTime," +
"keepaliveTime," +
"online" + "online" +
") VALUES (" + ") VALUES (" +
"#{deviceId}," + "#{deviceId}," +
@ -39,6 +42,9 @@ public interface DeviceMapper {
"#{ip}," + "#{ip}," +
"#{port}," + "#{port}," +
"#{hostAddress}," + "#{hostAddress}," +
"#{expires}," +
"#{registerTime}," +
"#{keepaliveTime}," +
"#{online}" + "#{online}" +
")") ")")
int add(Device device); int add(Device device);
@ -56,6 +62,9 @@ public interface DeviceMapper {
"<if test=\"port != null\">, port=${port}</if>" + "<if test=\"port != null\">, port=${port}</if>" +
"<if test=\"hostAddress != null\">, hostAddress='${hostAddress}'</if>" + "<if test=\"hostAddress != null\">, hostAddress='${hostAddress}'</if>" +
"<if test=\"online != null\">, online=${online}</if>" + "<if test=\"online != null\">, online=${online}</if>" +
"<if test=\"registerTime != null\">, registerTime='${registerTime}'</if>" +
"<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" +
"<if test=\"expires != null\">, expires=${expires}</if>" +
"WHERE deviceId='${deviceId}'"+ "WHERE deviceId='${deviceId}'"+
" </script>"}) " </script>"})
int update(Device device); int update(Device device);

View File

@ -63,8 +63,10 @@ sip:
domain: 4401020049 domain: 4401020049
# [可选] # [可选]
id: 44010200492000000001 id: 44010200492000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码 # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
password: admin123 password: admin123
# [可选] 心跳超时时间, 建议设置为心跳周期的三倍
keepaliveTimeOut: 180
#zlm服务器配置 #zlm服务器配置
media: media:

View File

@ -39,7 +39,7 @@ sip:
domain: 4401020049 domain: 4401020049
# [可选] # [可选]
id: 44010200492000000001 id: 44010200492000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码 # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
password: admin123 password: admin123
#zlm服务器配置 #zlm服务器配置

Binary file not shown.

View File

@ -14,22 +14,16 @@
<!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
<!--设备列表--> <!--设备列表-->
<el-table :data="deviceList" border style="width: 100%" :height="winHeight"> <el-table :data="deviceList" border style="width: 100%" :height="winHeight">
<el-table-column prop="name" label="名称" width="180" align="center"> <el-table-column prop="name" label="名称" align="center">
</el-table-column> </el-table-column>
<el-table-column prop="deviceId" label="设备编号" width="240" align="center"> <el-table-column prop="deviceId" label="设备编号" width="180" align="center">
</el-table-column>
<el-table-column label="地址" width="180" align="center">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
</div>
</template>
</el-table-column> </el-table-column>
<el-table-column prop="manufacturer" label="厂家" align="center"> <el-table-column prop="manufacturer" label="厂家" align="center">
</el-table-column> </el-table-column>
<el-table-column prop="model" label="固件版本" align="center"> <el-table-column prop="model" label="固件版本" align="center" width="120">
</el-table-column> </el-table-column>
<el-table-column label="流传输模式" align="center" width="160"> <el-table-column label="流传输模式" align="center" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择"> <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择">
<el-option key="UDP" label="UDP" value="UDP"></el-option> <el-option key="UDP" label="UDP" value="UDP"></el-option>
@ -40,7 +34,7 @@
</el-table-column> </el-table-column>
<el-table-column prop="channelCount" label="通道数" align="center"> <el-table-column prop="channelCount" label="通道数" align="center">
</el-table-column> </el-table-column>
<el-table-column label="状态" width="80" align="center"> <el-table-column label="状态" width="120" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.online == 1">线</el-tag> <el-tag size="medium" v-if="scope.row.online == 1">线</el-tag>
@ -48,7 +42,17 @@
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140">
</el-table-column>
<el-table-column prop="registerTime" label="最近注册" align="center" width="140">
</el-table-column>
<el-table-column label="地址" width="180" align="center">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="360" align="center" fixed="right"> <el-table-column label="操作" width="360" align="center" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<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> <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>