调整心跳间隔的设置机制以及状态的判断
parent
ea12e3465f
commit
d08248aae9
|
@ -104,7 +104,21 @@ public class Device {
|
|||
* 心跳间隔
|
||||
*/
|
||||
@Schema(description = "心跳间隔")
|
||||
private int keepaliveIntervalTime;
|
||||
private Integer heartBeatInterval;
|
||||
|
||||
|
||||
/**
|
||||
* 心跳超时次数
|
||||
*/
|
||||
@Schema(description = "心跳超时次数")
|
||||
private Integer heartBeatCount;
|
||||
|
||||
|
||||
/**
|
||||
* 定位功能支持情况
|
||||
*/
|
||||
@Schema(description = "定位功能支持情况。取值:0-不支持;1-支持 GPS定位;2-支持北斗定位(可选,默认取值为0")
|
||||
private Integer positionCapability;
|
||||
|
||||
/**
|
||||
* 通道个数
|
||||
|
|
|
@ -65,7 +65,7 @@ public class DeviceConfig {
|
|||
@Parameter(name = "heartBeatInterval", description = "心跳间隔")
|
||||
@Parameter(name = "heartBeatCount", description = "心跳计数")
|
||||
public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
|
||||
String channelId,
|
||||
@RequestParam(required = false) String channelId,
|
||||
@RequestParam(required = false) String name,
|
||||
@RequestParam(required = false) String expiration,
|
||||
@RequestParam(required = false) String heartBeatInterval,
|
||||
|
@ -124,7 +124,7 @@ public class DeviceConfig {
|
|||
if (log.isDebugEnabled()) {
|
||||
log.debug("设备状态查询API调用");
|
||||
}
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : deviceId + channelId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||
try {
|
||||
|
|
|
@ -66,7 +66,9 @@ public interface DeviceMapper {
|
|||
"expires," +
|
||||
"register_time," +
|
||||
"keepalive_time," +
|
||||
"keepalive_interval_time," +
|
||||
"heart_beat_interval," +
|
||||
"heart_beat_count," +
|
||||
"position_capability," +
|
||||
"create_time," +
|
||||
"update_time," +
|
||||
"charset," +
|
||||
|
@ -96,7 +98,9 @@ public interface DeviceMapper {
|
|||
"#{expires}," +
|
||||
"#{registerTime}," +
|
||||
"#{keepaliveTime}," +
|
||||
"#{keepaliveIntervalTime}," +
|
||||
"#{heartBeatInterval}," +
|
||||
"#{heartBeatCount}," +
|
||||
"#{positionCapability}," +
|
||||
"#{createTime}," +
|
||||
"#{updateTime}," +
|
||||
"#{charset}," +
|
||||
|
@ -128,7 +132,9 @@ public interface DeviceMapper {
|
|||
"<if test=\"onLine != null\">, on_line=#{onLine}</if>" +
|
||||
"<if test=\"registerTime != null\">, register_time=#{registerTime}</if>" +
|
||||
"<if test=\"keepaliveTime != null\">, keepalive_time=#{keepaliveTime}</if>" +
|
||||
"<if test=\"keepaliveIntervalTime != null\">, keepalive_interval_time=#{keepaliveIntervalTime}</if>" +
|
||||
"<if test=\"heartBeatInterval != null\">, heart_beat_interval=#{heartBeatInterval}</if>" +
|
||||
"<if test=\"positionCapability != null\">, position_capability=#{positionCapability}</if>" +
|
||||
"<if test=\"heartBeatCount != null\">, heart_beat_count=#{heartBeatCount}</if>" +
|
||||
"<if test=\"expires != null\">, expires=#{expires}</if>" +
|
||||
"WHERE device_id=#{deviceId}"+
|
||||
" </script>"})
|
||||
|
|
|
@ -166,4 +166,5 @@ public interface IDeviceService {
|
|||
|
||||
void subscribeMobilePosition(int id, int cycle, int interval);
|
||||
|
||||
void updateDeviceHeartInfo(Device device);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import javax.sip.SipException;
|
|||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -110,9 +111,12 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||
}
|
||||
device.setUpdateTime(now);
|
||||
device.setKeepaliveTime(now);
|
||||
if (device.getKeepaliveIntervalTime() == 0) {
|
||||
// 默认心跳间隔60
|
||||
device.setKeepaliveIntervalTime(60);
|
||||
if (device.getHeartBeatCount() == null) {
|
||||
// 读取设备配置, 获取心跳间隔和心跳超时次数, 在次之前暂时设置为默认值
|
||||
device.setHeartBeatCount(3);
|
||||
device.setHeartBeatInterval(60);
|
||||
device.setPositionCapability(0);
|
||||
|
||||
}
|
||||
if (sipTransactionInfo != null) {
|
||||
device.setSipTransactionInfo(sipTransactionInfo);
|
||||
|
@ -132,6 +136,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||
redisCatchStorage.updateDevice(device);
|
||||
try {
|
||||
commander.deviceInfoQuery(device);
|
||||
commander.deviceConfigQuery(device, null, "BasicParam", null);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
log.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
|
||||
}
|
||||
|
@ -178,18 +183,8 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||
// 刷新过期任务
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3);
|
||||
|
||||
//
|
||||
// try {
|
||||
// cmder.alarmSubscribe(device, 600, "0", "4", "0", "2023-7-27T00:00:00", "2023-7-28T00:00:00");
|
||||
// } catch (InvalidArgumentException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// } catch (SipException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// } catch (ParseException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "三次心跳超时"),
|
||||
device.getHeartBeatInterval() * 1000 * device.getHeartBeatCount());
|
||||
|
||||
}
|
||||
|
||||
|
@ -202,7 +197,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||
return;
|
||||
}
|
||||
log.info("[设备离线] device:{}, 当前心跳间隔: {}, 上次心跳时间:{}, 上次注册时间: {}", deviceId,
|
||||
device.getKeepaliveIntervalTime(), device.getKeepaliveTime(), device.getRegisterTime());
|
||||
device.getHeartBeatInterval(), device.getKeepaliveTime(), device.getRegisterTime());
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId;
|
||||
dynamicTask.stop(registerExpireTaskKey);
|
||||
if (device.isOnLine()) {
|
||||
|
@ -588,4 +583,24 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||
redisCatchStorage.updateDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDeviceHeartInfo(Device device) {
|
||||
Device deviceInDb = deviceMapper.query(device.getId());
|
||||
if (deviceInDb == null) {
|
||||
return;
|
||||
}
|
||||
if (!Objects.equals(deviceInDb.getHeartBeatCount(), device.getHeartBeatCount())
|
||||
|| !Objects.equals(deviceInDb.getHeartBeatInterval(), device.getHeartBeatInterval())) {
|
||||
// 刷新过期任务
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "三次心跳超时"),
|
||||
device.getHeartBeatInterval() * 1000 * device.getHeartBeatCount());
|
||||
deviceInDb.setHeartBeatCount(device.getHeartBeatCount());
|
||||
deviceInDb.setHeartBeatInterval(device.getHeartBeatInterval());
|
||||
deviceInDb.setPositionCapability(device.getPositionCapability());
|
||||
updateDevice(deviceInDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,18 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify
|
|||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipMsgInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -95,10 +97,10 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
}
|
||||
Device device = sipMsgInfo.getDevice();
|
||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||
if (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) {
|
||||
log.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
||||
return;
|
||||
}
|
||||
// if (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) {
|
||||
// log.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
||||
// return;
|
||||
// }
|
||||
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
||||
|
@ -114,14 +116,6 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
});
|
||||
}
|
||||
}
|
||||
if (device.getKeepaliveTime() == null) {
|
||||
device.setKeepaliveIntervalTime(60);
|
||||
} else {
|
||||
long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime());
|
||||
if (System.currentTimeMillis() / 1000 - lastTime > 10) {
|
||||
device.setKeepaliveIntervalTime(Long.valueOf(System.currentTimeMillis() / 1000 - lastTime).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
device.setKeepaliveTime(DateUtil.getNow());
|
||||
|
||||
|
@ -138,7 +132,8 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
// 刷新过期任务
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果三次心跳失败,则设置设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, () -> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime() * 1000 * 3);
|
||||
dynamicTask.startDelay(registerExpireTaskKey, () -> deviceService.offline(device.getDeviceId(), "三次心跳超时"),
|
||||
device.getHeartBeatInterval() * 1000 * device.getHeartBeatCount());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
|
|||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
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.event.request.SIPRequestProcessorParent;
|
||||
|
@ -36,6 +37,9 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
|
|||
@Autowired
|
||||
private DeferredResultHolder deferredResultHolder;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
responseMessageHandler.addHandler(cmdType, this);
|
||||
|
@ -45,7 +49,12 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
|
|||
@Override
|
||||
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||
String channelId = getText(element, "DeviceID");
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
|
||||
String key;
|
||||
if (device.getDeviceId().equals(channelId)) {
|
||||
key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId();
|
||||
}else {
|
||||
key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
|
||||
}
|
||||
try {
|
||||
// 回复200 OK
|
||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||
|
@ -58,6 +67,18 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
|
|||
if (log.isDebugEnabled()) {
|
||||
log.debug(json.toJSONString());
|
||||
}
|
||||
JSONObject basicParam = json.getJSONObject("BasicParam");
|
||||
Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval");
|
||||
Integer heartBeatCount = basicParam.getInteger("HeartBeatCount");
|
||||
Integer positionCapability = basicParam.getInteger("PositionCapability");
|
||||
device.setHeartBeatInterval(heartBeatInterval);
|
||||
device.setHeartBeatCount(heartBeatCount);
|
||||
device.setPositionCapability(positionCapability);
|
||||
|
||||
deviceService.updateDeviceHeartInfo(device);
|
||||
|
||||
|
||||
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setKey(key);
|
||||
msg.setData(json);
|
||||
|
|
|
@ -95,6 +95,8 @@
|
|||
布防</el-dropdown-item>
|
||||
<el-dropdown-item command="resetGuard" v-bind:disabled="!scope.row.onLine">
|
||||
撤防</el-dropdown-item>
|
||||
<el-dropdown-item command="syncBasicParam" v-bind:disabled="!scope.row.onLine">
|
||||
基础配置同步</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
@ -355,6 +357,8 @@ export default {
|
|||
this.resetGuard(itemData)
|
||||
}else if (command === "delete") {
|
||||
this.deleteDevice(itemData)
|
||||
}else if (command === "syncBasicParam") {
|
||||
this.syncBasicParam(itemData)
|
||||
}
|
||||
},
|
||||
setGuard: function (itemData) {
|
||||
|
@ -462,6 +466,33 @@ export default {
|
|||
message: error.message
|
||||
})
|
||||
});
|
||||
},
|
||||
syncBasicParam: function (data) {
|
||||
console.log(data)
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/device/config/query/${data.deviceId}/BasicParam`,
|
||||
params: {
|
||||
// channelId: data.deviceId
|
||||
}
|
||||
}).then( (res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
message: `配置已同步,当前心跳间隔: ${res.data.data.BasicParam.HeartBeatInterval} 心跳间隔:${res.data.data.BasicParam.HeartBeatCount}`
|
||||
})
|
||||
}else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
}).catch( (error)=> {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error.message
|
||||
})
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -31,7 +31,9 @@ create table wvp_device
|
|||
local_ip character varying(50),
|
||||
password character varying(255),
|
||||
as_message_channel bool default false,
|
||||
keepalive_interval_time integer,
|
||||
heart_beat_interval integer,
|
||||
heart_beat_count integer,
|
||||
position_capability integer,
|
||||
broadcast_push_after_ack bool default false,
|
||||
constraint uk_device_device unique (device_id)
|
||||
);
|
||||
|
|
|
@ -31,7 +31,9 @@ create table wvp_device
|
|||
local_ip character varying(50),
|
||||
password character varying(255),
|
||||
as_message_channel bool default false,
|
||||
keepalive_interval_time integer,
|
||||
heart_beat_interval integer,
|
||||
heart_beat_count integer,
|
||||
position_capability integer,
|
||||
broadcast_push_after_ack bool default false,
|
||||
constraint uk_device_device unique (device_id)
|
||||
);
|
||||
|
|
|
@ -40,4 +40,11 @@ alter table wvp_stream_proxy add relates_media_server_id character varying(50);
|
|||
*/
|
||||
drop index uk_stream_push_app_stream_path on wvp_cloud_record;
|
||||
alter table wvp_cloud_record change folder folder varchar(500) null;
|
||||
alter table wvp_cloud_record change file_path file_path varchar(500) null;
|
||||
alter table wvp_cloud_record change file_path file_path varchar(500) null;
|
||||
|
||||
/*
|
||||
* 20250211
|
||||
*/
|
||||
alter table wvp_device change keepalive_interval_time heart_beat_interval integer;
|
||||
alter table wvp_device add heart_beat_count integer;
|
||||
alter table wvp_device add position_capability integer;
|
|
@ -39,4 +39,11 @@ alter table wvp_stream_proxy add relates_media_server_id character varying(50);
|
|||
*/
|
||||
drop index uk_stream_push_app_stream_path on wvp_cloud_record;
|
||||
alter table wvp_cloud_record change folder folder varchar(500) null;
|
||||
alter table wvp_cloud_record change file_path file_path varchar(500) null;
|
||||
alter table wvp_cloud_record change file_path file_path varchar(500) null;
|
||||
|
||||
/*
|
||||
* 20250211
|
||||
*/
|
||||
alter table wvp_device change keepalive_interval_time heart_beat_interval integer;
|
||||
alter table wvp_device add heart_beat_count integer;
|
||||
alter table wvp_device add position_capability integer;
|
Loading…
Reference in New Issue