Merge branch 'dev/数据库统合'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceQuery.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
This commit is contained in:
lin 2025-03-12 14:20:28 +08:00
commit b904e594a1
136 changed files with 4446 additions and 1908 deletions

View File

@ -199,13 +199,6 @@
<artifactId>springdoc-openapi-security</artifactId> <artifactId>springdoc-openapi-security</artifactId>
<version>1.6.10</version> <version>1.6.10</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
<!--在线文档 --> <!--在线文档 -->
<dependency> <dependency>

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp; package com.genersoft.iot.vmp;
import com.genersoft.iot.vmp.jt1078.util.ClassUtil;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -33,6 +34,7 @@ public class VManageBootstrap extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {
VManageBootstrap.args = args; VManageBootstrap.args = args;
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
ClassUtil.context = VManageBootstrap.context;
GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil"); GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil");
if (gitUtil == null) { if (gitUtil == null) {
log.info("获取版本信息失败"); log.info("获取版本信息失败");
@ -62,6 +64,5 @@ public class VManageBootstrap extends SpringBootServletInitializer {
); );
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true); sessionCookieConfig.setHttpOnly(true);
} }
} }

View File

@ -0,0 +1,23 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.utils.DateUtil;
import lombok.Data;
@Data
public class ServerInfo {
private String ip;
private int port;
/**
* 现在使用的线程数
*/
private String createTime;
public static ServerInfo create(String ip, int port) {
ServerInfo serverInfo = new ServerInfo();
serverInfo.setIp(ip);
serverInfo.setPort(port);
serverInfo.setCreateTime(DateUtil.getNow());
return serverInfo;
}
}

View File

@ -10,6 +10,8 @@ public class VideoManagerConstants {
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_"; public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
public static final String WVP_SERVER_LIST = "VMP_SERVER_LIST";
public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_"; public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_INFO:"; public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_INFO:";

View File

@ -6,6 +6,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List;
@Component @Component
@ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true) @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true)
@Order(0) @Order(0)
@ -16,6 +18,8 @@ public class SipConfig {
private String showIp; private String showIp;
private List<String> monitorIps;
private Integer port; private Integer port;
private String domain; private String domain;
@ -30,5 +34,5 @@ public class SipConfig {
private boolean alarm = false; private boolean alarm = false;
private long timeout = 15; private long timeout = 150;
} }

View File

@ -31,10 +31,13 @@ public class SipPlatformRunner implements CommandLineRunner {
@Autowired @Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform; private ISIPCommanderForPlatform sipCommanderForPlatform;
@Autowired
private UserSetting userSetting;
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
// 获取所有启用的平台 // 获取所有启用的平台
List<Platform> parentPlatforms = platformService.queryEnablePlatformList(); List<Platform> parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId());
for (Platform platform : parentPlatforms) { for (Platform platform : parentPlatforms) {

View File

@ -37,6 +37,11 @@ public class UserSetting {
*/ */
private Integer playTimeout = 10000; private Integer playTimeout = 10000;
/**
* 获取设备录像数据超时时间,单位毫秒
*/
private Integer recordInfoTimeout = 15000;
/** /**
* 上级点播等待超时时间,单位毫秒 * 上级点播等待超时时间,单位毫秒
*/ */
@ -180,4 +185,10 @@ public class UserSetting {
*/ */
private String jwkFile = "classpath:jwk.json"; private String jwkFile = "classpath:jwk.json";
/**
* wvp集群模式下如果注册向上级的wvp奔溃则自动选择一个其他wvp继续注册到上级
*/
private boolean autoRegisterPlatform = false;
} }

View File

@ -1,12 +1,14 @@
package com.genersoft.iot.vmp.conf; package com.genersoft.iot.vmp.conf;
import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.ServerInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component @Component
public class WVPTimerTask { public class WVPTimerTask {
@ -19,11 +21,8 @@ public class WVPTimerTask {
@Autowired @Autowired
private SipConfig sipConfig; private SipConfig sipConfig;
@Scheduled(fixedDelay = 2 * 1000) //每3秒执行一次 @Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
public void execute(){ public void execute(){
JSONObject jsonObject = new JSONObject(); redisCatchStorage.updateWVPInfo(ServerInfo.create(sipConfig.getShowIp(), serverPort), 3);
jsonObject.put("ip", sipConfig.getShowIp());
jsonObject.put("port", serverPort);
redisCatchStorage.updateWVPInfo(jsonObject, 3);
} }
} }

View File

@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.conf.redis;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcClassHandler;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.service.redisMsg.control.RedisRpcController; import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -16,8 +18,10 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.message.Response;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -36,9 +40,6 @@ public class RedisRpcConfig implements MessageListener {
@Autowired @Autowired
private UserSetting userSetting; private UserSetting userSetting;
@Autowired
private RedisRpcController redisRpcController;
@Autowired @Autowired
private RedisTemplate<Object, Object> redisTemplate; private RedisTemplate<Object, Object> redisTemplate;
@ -48,6 +49,40 @@ public class RedisRpcConfig implements MessageListener {
@Autowired @Autowired
private ThreadPoolTaskExecutor taskExecutor; private ThreadPoolTaskExecutor taskExecutor;
private final static Map<String, RedisRpcClassHandler> protocolHash = new HashMap<>();
public void addHandler(String path, RedisRpcClassHandler handler) {
protocolHash.put(path, handler);
}
// @Override
// public void run(String... args) throws Exception {
// List<Class<?>> classList = ClassUtil.getClassList("com.genersoft.iot.vmp.service.redisMsg.control", RedisRpcController.class);
// for (Class<?> handlerClass : classList) {
// String controllerPath = handlerClass.getAnnotation(RedisRpcController.class).value();
// Object bean = ClassUtil.getBean(controllerPath, handlerClass);
// // 扫描其下的方法
// Method[] methods = handlerClass.getDeclaredMethods();
// for (Method method : methods) {
// RedisRpcMapping annotation = method.getAnnotation(RedisRpcMapping.class);
// if (annotation != null) {
// String methodPath = annotation.value();
// if (methodPath != null) {
// protocolHash.put(controllerPath + "/" + methodPath, new RedisRpcClassHandler(bean, method));
// }
// }
//
// }
//
// }
// for (String s : protocolHash.keySet()) {
// System.out.println(s);
// }
// if (log.isDebugEnabled()) {
// log.debug("消息ID缓存表 protocolHash:{}", protocolHash);
// }
// }
@Override @Override
public void onMessage(Message message, byte[] pattern) { public void onMessage(Message message, byte[] pattern) {
boolean isEmpty = taskQueue.isEmpty(); boolean isEmpty = taskQueue.isEmpty();
@ -63,10 +98,10 @@ public class RedisRpcConfig implements MessageListener {
} else if (redisRpcMessage.getResponse() != null){ } else if (redisRpcMessage.getResponse() != null){
handlerResponse(redisRpcMessage.getResponse()); handlerResponse(redisRpcMessage.getResponse());
} else { } else {
log.error("[redis rpc 解析失败] {}", JSON.toJSONString(redisRpcMessage)); log.error("[redis-rpc]解析失败 {}", JSON.toJSONString(redisRpcMessage));
} }
} catch (Exception e) { } catch (Exception e) {
log.error("[redis rpc 解析异常] ", e); log.error("[redis-rpc]解析异常 {}",new String(msg.getBody()), e);
} }
} }
}); });
@ -87,17 +122,23 @@ public class RedisRpcConfig implements MessageListener {
return; return;
} }
log.info("[redis-rpc] << {}", request); log.info("[redis-rpc] << {}", request);
Method method = getMethod(request.getUri()); RedisRpcClassHandler redisRpcClassHandler = protocolHash.get(request.getUri());
if (redisRpcClassHandler == null) {
log.error("[redis-rpc] 路径: {}不存在", request.getUri());
return;
}
RpcController controller = redisRpcClassHandler.getController();
Method method = redisRpcClassHandler.getMethod();
// 没有携带目标ID的可以理解为哪个wvp有结果就哪个回复携带目标ID但是如果是不存在的uri则直接回复404 // 没有携带目标ID的可以理解为哪个wvp有结果就哪个回复携带目标ID但是如果是不存在的uri则直接回复404
if (userSetting.getServerId().equals(request.getToId())) { if (userSetting.getServerId().equals(request.getToId())) {
if (method == null) { if (method == null) {
// 回复404结果 // 回复404结果
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setStatusCode(404); response.setStatusCode(ErrorCode.ERROR404.getCode());
sendResponse(response); sendResponse(response);
return; return;
} }
RedisRpcResponse response = (RedisRpcResponse)method.invoke(redisRpcController, request); RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request);
if(response != null) { if(response != null) {
sendResponse(response); sendResponse(response);
} }
@ -105,26 +146,14 @@ public class RedisRpcConfig implements MessageListener {
if (method == null) { if (method == null) {
return; return;
} }
RedisRpcResponse response = (RedisRpcResponse)method.invoke(redisRpcController, request); RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request);
if (response != null) { if (response != null) {
sendResponse(response); sendResponse(response);
} }
} }
}catch (InvocationTargetException | IllegalAccessException e) { }catch (InvocationTargetException | IllegalAccessException e) {
log.error("[redis rpc ] 处理请求失败 ", e); log.error("[redis-rpc ] 处理请求失败 ", e);
} }
}
private Method getMethod(String name) {
// 启动后扫描所有的路径注解
Method[] methods = redisRpcController.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(name)) {
return method;
}
}
return null;
} }
private void sendResponse(RedisRpcResponse response){ private void sendResponse(RedisRpcResponse response){
@ -142,23 +171,28 @@ public class RedisRpcConfig implements MessageListener {
redisTemplate.convertAndSend(REDIS_REQUEST_CHANNEL_KEY, message); redisTemplate.convertAndSend(REDIS_REQUEST_CHANNEL_KEY, message);
} }
private final Map<Long, SynchronousQueue<RedisRpcResponse>> topicSubscribers = new ConcurrentHashMap<>(); private final Map<Long, SynchronousQueue<RedisRpcResponse>> topicSubscribers = new ConcurrentHashMap<>();
private final Map<Long, CommonCallback<RedisRpcResponse>> callbacks = new ConcurrentHashMap<>(); private final Map<Long, CommonCallback<RedisRpcResponse>> callbacks = new ConcurrentHashMap<>();
public RedisRpcResponse request(RedisRpcRequest request, int timeOut) { public RedisRpcResponse request(RedisRpcRequest request, long timeOut) {
return request(request, timeOut, TimeUnit.SECONDS);
}
public RedisRpcResponse request(RedisRpcRequest request, long timeOut, TimeUnit timeUnit) {
request.setSn((long) random.nextInt(1000) + 1); request.setSn((long) random.nextInt(1000) + 1);
SynchronousQueue<RedisRpcResponse> subscribe = subscribe(request.getSn()); SynchronousQueue<RedisRpcResponse> subscribe = subscribe(request.getSn());
try { try {
sendRequest(request); sendRequest(request);
return subscribe.poll(timeOut, TimeUnit.SECONDS); return subscribe.poll(timeOut, timeUnit);
} catch (InterruptedException e) { } catch (InterruptedException e) {
log.warn("[redis rpc timeout] uri: {}, sn: {}", request.getUri(), request.getSn(), e); log.warn("[redis rpc timeout] uri: {}, sn: {}", request.getUri(), request.getSn(), e);
RedisRpcResponse redisRpcResponse = new RedisRpcResponse();
redisRpcResponse.setStatusCode(ErrorCode.ERROR486.getCode());
return redisRpcResponse;
} finally { } finally {
this.unsubscribe(request.getSn()); this.unsubscribe(request.getSn());
} }
return null;
} }
public void request(RedisRpcRequest request, CommonCallback<RedisRpcResponse> callback) { public void request(RedisRpcRequest request, CommonCallback<RedisRpcResponse> callback) {
@ -209,6 +243,9 @@ public class RedisRpcConfig implements MessageListener {
return callbacks.size(); return callbacks.size();
} }
// @Scheduled(fixedRate = 1000) //每1秒执行一次 // @Scheduled(fixedRate = 1000) //每1秒执行一次
// public void execute(){ // public void execute(){
// logger.info("callbacks的长度: " + callbacks.size()); // logger.info("callbacks的长度: " + callbacks.size());

View File

@ -0,0 +1,18 @@
package com.genersoft.iot.vmp.conf.redis.bean;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import lombok.Data;
import java.lang.reflect.Method;
@Data
public class RedisRpcClassHandler {
private RpcController controller;
private Method method;
public RedisRpcClassHandler(RpcController controller, Method method) {
this.controller = controller;
this.method = method;
}
}

View File

@ -80,11 +80,12 @@ public class SipLayer implements CommandLineRunner {
monitorIps.add(sipConfig.getIp()); monitorIps.add(sipConfig.getIp());
} }
} }
sipConfig.setMonitorIps(monitorIps);
if (ObjectUtils.isEmpty(sipConfig.getShowIp())){ if (ObjectUtils.isEmpty(sipConfig.getShowIp())){
sipConfig.setShowIp(String.join(",", monitorIps)); sipConfig.setShowIp(String.join(",", monitorIps));
} }
SipFactory.getInstance().setPathName("gov.nist"); SipFactory.getInstance().setPathName("gov.nist");
if (monitorIps.size() > 0) { if (!monitorIps.isEmpty()) {
for (String monitorIp : monitorIps) { for (String monitorIp : monitorIps) {
addListeningPoint(monitorIp, sipConfig.getPort()); addListeningPoint(monitorIp, sipConfig.getPort());
} }

View File

@ -0,0 +1,49 @@
package com.genersoft.iot.vmp.gb28181.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 基础配置
*/
@Data
@Schema(description = "基础配置")
public class BasicParam {
@Schema(description = "设备ID")
private String deviceId;
@Schema(description = "通道ID如果时对设备配置直接设置同设备ID一样即可")
private String channelId;
@Schema(description = "名称")
private String name;
@Schema(description = "注册过期时间")
private String expiration;
@Schema(description = "心跳间隔时间")
private Integer heartBeatInterval;
@Schema(description = "心跳超时次数")
private Integer heartBeatCount;
@Schema(description = "定位功能支持情况。取值:0-不支持;1-支持 GPS定位;2-支持北斗定位(可选,默认取值为0)" +
"用于接受配置查询结果, 基础配置时无效")
private Integer positionCapability;
@Schema(description = "经度(可选),用于接受配置查询结果, 基础配置时无效")
private Double longitude;
@Schema(description = "纬度(可选),用于接受配置查询结果, 基础配置时无效")
private Double latitude;
public static BasicParam getInstance(String name, String expiration, Integer heartBeatInterval, Integer heartBeatCount) {
BasicParam basicParam = new BasicParam();
basicParam.setName(name);
basicParam.setExpiration(expiration);
basicParam.setHeartBeatInterval(heartBeatInterval);
basicParam.setHeartBeatCount(heartBeatCount);
return basicParam;
}
}

View File

@ -209,4 +209,7 @@ public class Device {
@Schema(description = "控制语音对讲流程释放收到ACK后发流") @Schema(description = "控制语音对讲流程释放收到ACK后发流")
private boolean broadcastPushAfterAck; private boolean broadcastPushAfterAck;
@Schema(description = "所属服务Id")
private String serverId;
} }

View File

@ -244,5 +244,15 @@ public class DeviceChannel extends CommonGBChannel {
return deviceChannel; return deviceChannel;
} }
public CommonGBChannel buildCommonGBChannelForStatus() {
CommonGBChannel commonGBChannel = new CommonGBChannel();
commonGBChannel.setGbId(id);
commonGBChannel.setGbDeviceId(deviceId);
commonGBChannel.setGbName(name);
commonGBChannel.setDataType(ChannelDataType.GB28181.value);
commonGBChannel.setDataDeviceId(getDataDeviceId());
return commonGBChannel;
}
} }

View File

@ -0,0 +1,34 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "拉框放大/缩小控制参数")
public class DragZoomParam {
@MessageElement("Length")
@Schema(description = "播放窗口长度像素值(必选)")
protected Integer length;
@MessageElement("Width")
@Schema(description = "播放窗口宽度像素值(必选)")
protected Integer width;
@MessageElement("MidPointX")
@Schema(description = "拉框中心的横轴坐标像素值(必选)")
protected Integer midPointX;
@MessageElement("MidPointY")
@Schema(description = "拉框中心的纵轴坐标像素值(必选)")
protected Integer midPointY;
@MessageElement("LengthX")
@Schema(description = "拉框长度像素值(必选)")
protected Integer lengthX;
@MessageElement("LengthY")
@Schema(description = "拉框宽度像素值(必选)")
protected Integer lengthY;
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean; package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.gb28181.utils.MessageElement; import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
import lombok.Data;
/** /**
* 设备信息查询响应 * 设备信息查询响应
@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
* @version 1.0 * @version 1.0
* @date 2022/6/28 14:55 * @date 2022/6/28 14:55
*/ */
@Data
public class DragZoomRequest { public class DragZoomRequest {
/** /**
* 序列号 * 序列号
@ -20,124 +22,9 @@ public class DragZoomRequest {
private String deviceId; private String deviceId;
@MessageElement(value = "DragZoomIn") @MessageElement(value = "DragZoomIn")
private DragZoom dragZoomIn; private DragZoomParam dragZoomIn;
@MessageElement(value = "DragZoomOut") @MessageElement(value = "DragZoomOut")
private DragZoom dragZoomOut; private DragZoomParam dragZoomOut;
/**
* 基本参数
*/
public static class DragZoom {
/**
* 播放窗口长度像素值
*/
@MessageElement("Length")
protected Integer length;
/**
* 播放窗口宽度像素值
*/
@MessageElement("Width")
protected Integer width;
/**
* 拉框中心的横轴坐标像素值
*/
@MessageElement("MidPointX")
protected Integer midPointX;
/**
* 拉框中心的纵轴坐标像素值
*/
@MessageElement("MidPointY")
protected Integer midPointY;
/**
* 拉框长度像素值
*/
@MessageElement("LengthX")
protected Integer lengthX;
/**
* 拉框宽度像素值
*/
@MessageElement("LengthY")
protected Integer lengthY;
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getMidPointX() {
return midPointX;
}
public void setMidPointX(Integer midPointX) {
this.midPointX = midPointX;
}
public Integer getMidPointY() {
return midPointY;
}
public void setMidPointY(Integer midPointY) {
this.midPointY = midPointY;
}
public Integer getLengthX() {
return lengthX;
}
public void setLengthX(Integer lengthX) {
this.lengthX = lengthX;
}
public Integer getLengthY() {
return lengthY;
}
public void setLengthY(Integer lengthY) {
this.lengthY = lengthY;
}
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public DragZoom getDragZoomIn() {
return dragZoomIn;
}
public void setDragZoomIn(DragZoom dragZoomIn) {
this.dragZoomIn = dragZoomIn;
}
public DragZoom getDragZoomOut() {
return dragZoomOut;
}
public void setDragZoomOut(DragZoom dragZoomOut) {
this.dragZoomOut = dragZoomOut;
}
} }

View File

@ -4,7 +4,7 @@ import lombok.Data;
// 从INVITE消息中解析需要的信息 // 从INVITE消息中解析需要的信息
@Data @Data
public class InviteInfo { public class InviteMessageInfo {
private String requesterId; private String requesterId;
private String targetChannelId; private String targetChannelId;
private String sourceChannelId; private String sourceChannelId;

View File

@ -127,4 +127,7 @@ public class Platform {
@Schema(description = "保密属性必选缺省为00-不涉密1-涉密") @Schema(description = "保密属性必选缺省为00-不涉密1-涉密")
private int secrecy = 0; private int secrecy = 0;
@Schema(description = "执行注册的服务ID")
private String serverId;
} }

View File

@ -7,30 +7,22 @@
package com.genersoft.iot.vmp.gb28181.controller; package com.genersoft.iot.vmp.gb28181.controller;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.bean.BasicParam;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; 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.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils; import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID;
@Slf4j @Slf4j
@Tag(name = "国标设备配置") @Tag(name = "国标设备配置")
@RestController @RestController
@ -40,117 +32,60 @@ public class DeviceConfig {
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired @GetMapping("/basicParam")
private SIPCommander cmder;
@Autowired
private DeferredResultHolder resultHolder;
/**
* 看守位控制命令API接口
* @param deviceId 设备ID
* @param channelId 通道ID
* @param name 名称
* @param expiration 到期时间
* @param heartBeatInterval 心跳间隔
* @param heartBeatCount 心跳计数
* @return
*/
@GetMapping("/basicParam/{deviceId}")
@Operation(summary = "基本配置设置命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "基本配置设置命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "basicParam", description = "基础配置参数", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) public DeferredResult<WVPResult<String>> homePositionApi(BasicParam basicParam) {
@Parameter(name = "name", description = "名称")
@Parameter(name = "expiration", description = "到期时间")
@Parameter(name = "heartBeatInterval", description = "心跳间隔")
@Parameter(name = "heartBeatCount", description = "心跳计数")
public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
@RequestParam(required = false) String channelId,
@RequestParam(required = false) String name,
@RequestParam(required = false) String expiration,
@RequestParam(required = false) String heartBeatInterval,
@RequestParam(required = false) String heartBeatCount) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("报警复位API调用"); log.debug("基本配置设置命令API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Assert.notNull(basicParam.getDeviceId(), "设备ID必须存在");
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId; Device device = deviceService.getDeviceByDeviceId(basicParam.getDeviceId());
try { Assert.notNull(device, "设备不存在");
cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
RequestMessage msg = new RequestMessage(); DeferredResult<WVPResult<String>> deferredResult = new DeferredResult<>();
msg.setId(uuid); deviceService.deviceBasicConfig(device, basicParam, (code, msg, data) -> {
msg.setKey(key); deferredResult.setResult(new WVPResult<>(code, msg, data));
msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 设备配置: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
DeferredResult<String> result = new DeferredResult<String>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
JSONObject json = new JSONObject();
json.put("DeviceID", deviceId);
json.put("Status", "Timeout");
json.put("Description", "设备配置操作超时, 设备未返回应答指令");
msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
resultHolder.invokeResult(msg);
}); });
resultHolder.put(key, uuid, result);
return result; deferredResult.onTimeout(() -> {
log.warn("[设备配置] 超时, {}", device.getDeviceId());
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
});
return deferredResult;
} }
/** @Operation(summary = "设备配置查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
* 设备配置查询请求API接口
* @param deviceId 设备ID
* @param configType 配置类型
* @param channelId 通道ID
* @return
*/
@Operation(summary = "设备配置查询请求", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "configType", description = "配置类型") @Parameter(name = "configType", description = "配置类型, 可选值," +
@GetMapping("/query/{deviceId}/{configType}") "基本参数配置:BasicParam," +
public DeferredResult<String> configDownloadApi(@PathVariable String deviceId, "视频参数范围:VideoParamOpt, " +
@PathVariable String configType, "SVAC编码配置:SVACEncodeConfig, " +
@RequestParam(required = false) String channelId) { "SVAC解码配置:SVACDecodeConfig。" +
"可同时查询多个配置类型,各类型以“/”分隔,")
@GetMapping("/query")
public DeferredResult<WVPResult<Object>> configDownloadApi(String deviceId,String configType,
@RequestParam(required = false) String channelId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("设备状态查询API调用"); log.debug("设备配置查询请求API调用");
} }
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : deviceId + channelId);
String uuid = UUID.randomUUID().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
try { Assert.notNull(device, "设备不存在");
cmder.deviceConfigQuery(device, channelId, configType, event -> {
RequestMessage msg = new RequestMessage(); DeferredResult<WVPResult<Object>> deferredResult = new DeferredResult<>();
msg.setId(uuid);
msg.setKey(key); deviceService.deviceConfigQuery(device, channelId, configType, (code, msg, data) -> {
msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg)); deferredResult.setResult(new WVPResult<>(code, msg, data));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
DeferredResult<String> result = new DeferredResult<String > (3 * 1000L);
result.onTimeout(()->{
log.warn(String.format("获取设备配置超时"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData("Timeout. Device did not response to this command.");
resultHolder.invokeResult(msg);
}); });
resultHolder.put(key, uuid, result);
return result; deferredResult.onTimeout(() -> {
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
});
return deferredResult;
} }
} }

View File

@ -7,13 +7,8 @@
package com.genersoft.iot.vmp.gb28181.controller; package com.genersoft.iot.vmp.gb28181.controller;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
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.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
@ -23,16 +18,10 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID;
@Tag(name = "国标设备控制") @Tag(name = "国标设备控制")
@Slf4j @Slf4j
@RestController @RestController
@ -42,18 +31,8 @@ public class DeviceControl {
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired
private ISIPCommander cmder;
@Autowired @Operation(summary = "远程启动", security = @SecurityRequirement(name = JwtUtils.HEADER))
private DeferredResultHolder resultHolder;
/**
* 远程启动控制命令API接口
*
* @param deviceId 设备ID
*/
@Operation(summary = "远程启动控制命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@GetMapping("/teleboot/{deviceId}") @GetMapping("/teleboot/{deviceId}")
public void teleBootApi(@PathVariable String deviceId) { public void teleBootApi(@PathVariable String deviceId) {
@ -61,194 +40,104 @@ public class DeviceControl {
log.debug("设备远程启动API调用"); log.debug("设备远程启动API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
try { Assert.notNull(device, "设备不存在");
cmder.teleBootCmd(device); deviceService.teleboot(device);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 远程启动: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
/**
* 录像控制命令API接口
*
* @param deviceId 设备ID
* @param recordCmdStr Record手动录像StopRecord停止手动录像
* @param channelId 通道编码可选
*/
@Operation(summary = "录像控制", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "录像控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "recordCmdStr", description = "命令, 可选值Record手动录像StopRecord停止手动录像", required = true) @Parameter(name = "recordCmdStr", description = "命令, 可选值Record手动录像StopRecord停止手动录像", required = true)
@GetMapping("/record/{deviceId}/{recordCmdStr}") @GetMapping("/record")
public DeferredResult<ResponseEntity<WVPResult<String>>> recordApi(@PathVariable String deviceId, public DeferredResult<WVPResult<String>> recordApi(String deviceId, String recordCmdStr, String channelId) {
@PathVariable String recordCmdStr, String channelId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("开始/停止录像API调用"); log.debug("开始/停止录像API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String uuid = UUID.randomUUID().toString(); Assert.notNull(device, "设备不存在");
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; DeferredResult<WVPResult<String>> deferredResult = new DeferredResult<>();
DeferredResult<ResponseEntity<WVPResult<String>>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeAllResult(msg);
});
if (resultHolder.exist(key, null)){
return result;
}
resultHolder.put(key, uuid, result);
try {
cmder.recordCmd(device, channelId, recordCmdStr, event -> {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg)));
resultHolder.invokeAllResult(msg);
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
return result; deviceService.record(device, channelId, recordCmdStr, (code, msg, data) -> {
deferredResult.setResult(new WVPResult<>(code, msg, data));
});
deferredResult.onTimeout(() -> {
log.warn("[开始/停止录像] 操作超时, 设备未返回应答指令, {}", deviceId);
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
});
return deferredResult;
} }
/** @Operation(summary = "布防/撤防", security = @SecurityRequirement(name = JwtUtils.HEADER))
* 报警布防/撤防命令API接口
*
* @param deviceId 设备ID
* @param guardCmdStr SetGuard布防ResetGuard撤防
*/
@Operation(summary = "布防/撤防命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true) @Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true)
@GetMapping("/guard/{deviceId}/{guardCmdStr}") @GetMapping("/guard")
public DeferredResult<WVPResult<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) { public DeferredResult<WVPResult<String>> guardApi(String deviceId, String guardCmdStr) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("布防/撤防API调用"); log.debug("布防/撤防API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + deviceId; Assert.notNull(device, "设备不存在");
String uuid =UUID.randomUUID().toString(); DeferredResult<WVPResult<String>> result = new DeferredResult<>();
try { deviceService.guard(device, guardCmdStr, (code, msg, data) -> {
cmder.guardCmd(device, guardCmdStr, event -> { result.setResult(new WVPResult<>(code, msg, data));
RequestMessage msg = new RequestMessage(); });
msg.setId(uuid); result.onTimeout(() -> {
msg.setKey(key); log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg))); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
DeferredResult<WVPResult<String>> result = new DeferredResult<>(3 * 1000L);
resultHolder.put(key, uuid, result);
result.onTimeout(() -> {
log.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
}); });
return result; return result;
} }
/**
* 报警复位API接口
*
* @param deviceId 设备ID
* @param alarmMethod 报警方式可选
* @param alarmType 报警类型可选
*/
@Operation(summary = "报警复位", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "报警复位", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "alarmMethod", description = "报警方式") @Parameter(name = "alarmMethod", description = "报警方式, 报警方式条件(可选),取值0为全部,1为电话报警,2为设备报警,3为短信报警,4为\n" +
@Parameter(name = "alarmType", description = "报警类型") "GPS报警,5为视频报警,6为设备故障报警,7其他报警;可以为直接组合如12为电话报警或设备报警")
@GetMapping("/reset_alarm/{deviceId}") @Parameter(name = "alarmType", description = "报警类型, " +
public DeferredResult<ResponseEntity<WVPResult<String>>> resetAlarmApi(@PathVariable String deviceId, String channelId, "报警类型。" +
"报警方式为2时,不携带 AlarmType为默认的报警设备报警," +
"携带 AlarmType取值及对应报警类型如下:" +
"1-视频丢失报警;2-设备防拆报警;3-存储设备磁盘满报警;4-设备高温报警;5-设备低温报警。" +
"报警方式为5时,取值如下:" +
"1-人工视频报警;2-运动目标检测报警;3-遗留物检测报警;4-物体移除检测报警;5-绊线检测报警;" +
"6-入侵检测报警;7-逆行检测报警;8-徘徊检测报警;9-流量统计报警;10-密度检测报警;" +
"11-视频异常检测报警;12-快速移动报警。" +
"报警方式为6时,取值如下:" +
"1-存储设备磁盘故障报警;2-存储设备风扇故障报警")
@GetMapping("/reset_alarm")
public DeferredResult<WVPResult<String>> resetAlarm(String deviceId, String channelId,
@RequestParam(required = false) String alarmMethod, @RequestParam(required = false) String alarmMethod,
@RequestParam(required = false) String alarmType) { @RequestParam(required = false) String alarmType) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("报警复位API调用"); log.debug("报警复位API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String uuid = UUID.randomUUID().toString(); Assert.notNull(device, "设备不存在");
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; DeferredResult<WVPResult<String>> result = new DeferredResult<>();
try { deviceService.resetAlarm(device, channelId, alarmMethod, alarmType, (code, msg, data) -> {
cmder.alarmCmd(device, alarmMethod, alarmType, event -> { result.setResult(new WVPResult<>(code, msg, data));
RequestMessage msg = new RequestMessage(); });
msg.setId(uuid); result.onTimeout(() -> {
msg.setKey(key); log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("操作失败,错误码: %s, %s", event.statusCode, event.msg))); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 报警复位: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
DeferredResult<ResponseEntity<WVPResult<String>>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
}); });
resultHolder.put(key, uuid, result);
return result; return result;
} }
/**
* 强制关键帧API接口
*
* @param deviceId 设备ID
* @param channelId 通道ID
*/
@Operation(summary = "强制关键帧", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "强制关键帧", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号") @Parameter(name = "channelId", description = "通道国标编号")
@GetMapping("/i_frame/{deviceId}") @GetMapping("/i_frame")
public JSONObject iFrame(@PathVariable String deviceId, public void iFrame(String deviceId, @RequestParam(required = false) String channelId) {
@RequestParam(required = false) String channelId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("强制关键帧API调用"); log.debug("强制关键帧API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
try { Assert.notNull(device, "设备不存在");
cmder.iFrameCmd(device, channelId); deviceService.iFrame(device, channelId);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
JSONObject json = new JSONObject();
json.put("DeviceID", deviceId);
json.put("ChannelID", channelId);
json.put("Result", "OK");
return json;
} }
/**
* 看守位控制命令API接口
*
* @param deviceId 设备ID
* @param enabled 看守位使能1:开启,0:关闭
* @param resetTime 自动归位时间间隔可选
* @param presetIndex 调用预置位编号可选
* @param channelId 通道编码可选
*/
@Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@ -260,99 +149,54 @@ public class DeviceControl {
@RequestParam(required = false) Integer resetTime, @RequestParam(required = false) Integer resetTime,
@RequestParam(required = false) Integer presetIndex) { @RequestParam(required = false) Integer presetIndex) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("报警复位API调用"); log.debug("看守位控制API调用");
} }
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
String uuid = UUID.randomUUID().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
try { Assert.notNull(device, "设备不存在");
cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> { DeferredResult<WVPResult<String>> result = new DeferredResult<>();
RequestMessage msg = new RequestMessage(); deviceService.homePosition(device, channelId, enabled, resetTime, presetIndex, (code, msg, data) -> {
msg.setId(uuid); result.setResult(new WVPResult<>(code, msg, data));
msg.setKey(key); });
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("操作失败,错误码: %s, %s", event.statusCode, event.msg))); result.onTimeout(() -> {
resultHolder.invokeResult(msg); log.warn("[看守位控制] 操作超时, 设备未返回应答指令, {}", deviceId);
},null); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 看守位控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
DeferredResult<WVPResult<String>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); //("看守位控制操作超时, 设备未返回应答指令");
resultHolder.invokeResult(msg);
}); });
resultHolder.put(key, uuid, result);
return result; return result;
} }
/**
* 拉框放大
* @param deviceId 设备id
* @param channelId 通道id
* @param length 播放窗口长度像素值
* @param width 播放窗口宽度像素值
* @param midpointx 拉框中心的横轴坐标像素值
* @param midpointy 拉框中心的纵轴坐标像素值
* @param lengthx 拉框长度像素值
* @param lengthy 拉框宽度像素值
* @return
*/
@Operation(summary = "拉框放大", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "拉框放大", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "length", description = "播放窗口长度像素值", required = true) @Parameter(name = "length", description = "播放窗口长度像素值", required = true)
@Parameter(name = "width", description = "播放窗口宽度像素值", required = true)
@Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true) @Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true)
@Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true) @Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true)
@Parameter(name = "lengthx", description = "拉框长度像素值", required = true) @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
@Parameter(name = "lengthy", description = "lengthy", required = true) @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
@GetMapping("drag_zoom/zoom_in") @GetMapping("drag_zoom/zoom_in")
public void dragZoomIn(@RequestParam String deviceId, public DeferredResult<WVPResult<String>> dragZoomIn(@RequestParam String deviceId, String channelId,
@RequestParam(required = false) String channelId,
@RequestParam int length, @RequestParam int length,
@RequestParam int width, @RequestParam int width,
@RequestParam int midpointx, @RequestParam int midpointx,
@RequestParam int midpointy, @RequestParam int midpointy,
@RequestParam int lengthx, @RequestParam int lengthx,
@RequestParam int lengthy) throws RuntimeException { @RequestParam int lengthy) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(String.format("设备拉框放大 API调用deviceId%s channelId%s length%d width%d midpointx%d midpointy%d lengthx%d lengthy%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy)); log.debug(String.format("设备拉框放大 API调用deviceId%s channelId%s length%d width%d midpointx%d midpointy%d lengthx%d lengthy%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
StringBuffer cmdXml = new StringBuffer(200); Assert.notNull(device, "设备不存在");
cmdXml.append("<DragZoomIn>\r\n"); DeferredResult<WVPResult<String>> result = new DeferredResult<>();
cmdXml.append("<Length>" + length+ "</Length>\r\n"); deviceService.dragZoomIn(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> {
cmdXml.append("<Width>" + width+ "</Width>\r\n"); result.setResult(new WVPResult<>(code, msg, data));
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n"); });
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n"); result.onTimeout(() -> {
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n"); log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId);
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
cmdXml.append("</DragZoomIn>\r\n"); });
try { return result;
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框放大: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
/**
* 拉框缩小
* @param deviceId 设备id
* @param channelId 通道id
* @param length 播放窗口长度像素值
* @param width 播放窗口宽度像素值
* @param midpointx 拉框中心的横轴坐标像素值
* @param midpointy 拉框中心的纵轴坐标像素值
* @param lengthx 拉框长度像素值
* @param lengthy 拉框宽度像素值
* @return
*/
@Operation(summary = "拉框缩小", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "拉框缩小", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号") @Parameter(name = "channelId", description = "通道国标编号")
@ -363,7 +207,7 @@ public class DeviceControl {
@Parameter(name = "lengthx", description = "拉框长度像素值", required = true) @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true) @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
@GetMapping("/drag_zoom/zoom_out") @GetMapping("/drag_zoom/zoom_out")
public void dragZoomOut(@RequestParam String deviceId, public DeferredResult<WVPResult<String>> dragZoomOut(@RequestParam String deviceId,
@RequestParam(required = false) String channelId, @RequestParam(required = false) String channelId,
@RequestParam int length, @RequestParam int length,
@RequestParam int width, @RequestParam int width,
@ -376,20 +220,15 @@ public class DeviceControl {
log.debug(String.format("设备拉框缩小 API调用deviceId%s channelId%s length%d width%d midpointx%d midpointy%d lengthx%d lengthy%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy)); log.debug(String.format("设备拉框缩小 API调用deviceId%s channelId%s length%d width%d midpointx%d midpointy%d lengthx%d lengthy%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
StringBuffer cmdXml = new StringBuffer(200); Assert.notNull(device, "设备不存在");
cmdXml.append("<DragZoomOut>\r\n"); DeferredResult<WVPResult<String>> result = new DeferredResult<>();
cmdXml.append("<Length>" + length+ "</Length>\r\n"); deviceService.dragZoomOut(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> {
cmdXml.append("<Width>" + width+ "</Width>\r\n"); result.setResult(new WVPResult<>(code, msg, data));
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n"); });
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n"); result.onTimeout(() -> {
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n"); log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId);
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
cmdXml.append("</DragZoomOut>\r\n"); });
try { return result;
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框缩小: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
} }

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.controller;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -16,6 +17,7 @@ import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -27,9 +29,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.IOUtils;
import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Options;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -37,17 +37,13 @@ import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
@Tag(name = "国标设备查询", description = "国标设备查询") @Tag(name = "国标设备查询", description = "国标设备查询")
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@ -63,22 +59,23 @@ public class DeviceQuery {
private IInviteStreamService inviteStreamService; private IInviteStreamService inviteStreamService;
@Autowired @Autowired
private IDeviceService deviceService;
@Autowired
private ISIPCommander cmder; private ISIPCommander cmder;
@Autowired @Autowired
private DeferredResultHolder resultHolder; private DeferredResultHolder resultHolder;
@Autowired @Autowired
private IDeviceService deviceService; private UserSetting userSetting;
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
/** @Autowired
* 使用ID查询国标设备 private IRedisRpcService redisRpcService;
* @param deviceId 国标ID
* @return 国标设备
*/
@Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@GetMapping("/devices/{deviceId}") @GetMapping("/devices/{deviceId}")
@ -87,12 +84,7 @@ public class DeviceQuery {
return deviceService.getDeviceByDeviceId(deviceId); return deviceService.getDeviceByDeviceId(deviceId);
} }
/**
* 分页查询国标设备
* @param page 当前页
* @param count 每页查询数量
* @return 分页国标列表
*/
@Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "page", description = "当前页", required = true) @Parameter(name = "page", description = "当前页", required = true)
@Parameter(name = "count", description = "每页查询数量", required = true) @Parameter(name = "count", description = "每页查询数量", required = true)
@ -107,9 +99,7 @@ public class DeviceQuery {
return deviceService.getAll(page, count, query, status); return deviceService.getAll(page, count, query, status);
} }
/**
* 分页查询通道数
*/
@GetMapping("/devices/{deviceId}/channels") @GetMapping("/devices/{deviceId}/channels")
@Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@ -130,9 +120,7 @@ public class DeviceQuery {
return deviceChannelService.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count); return deviceChannelService.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count);
} }
/**
* 同步设备通道
*/
@Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@GetMapping("/devices/{deviceId}/sync") @GetMapping("/devices/{deviceId}/sync")
@ -142,37 +130,11 @@ public class DeviceQuery {
log.debug("设备通道信息同步API调用deviceId" + deviceId); log.debug("设备通道信息同步API调用deviceId" + deviceId);
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
boolean status = deviceService.isSyncRunning(deviceId);
// 已存在则返回进度
if (deviceService.isSyncRunning(deviceId)) {
SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
WVPResult wvpResult = new WVPResult();
if (channelSyncStatus.getErrorMsg() != null) {
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(channelSyncStatus.getErrorMsg());
}else if (channelSyncStatus.getTotal() == null || channelSyncStatus.getTotal() == 0){
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg("等待通道信息...");
}else {
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(channelSyncStatus);
}
return wvpResult;
}
deviceService.sync(device);
WVPResult<SyncStatus> wvpResult = new WVPResult<>(); return deviceService.devicesSync(device);
wvpResult.setCode(0);
wvpResult.setMsg("开始同步");
return wvpResult;
} }
/**
* 移除设备
* @param deviceId 设备id
* @return
*/
@Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@DeleteMapping("/devices/{deviceId}/delete") @DeleteMapping("/devices/{deviceId}/delete")
@ -207,17 +169,6 @@ public class DeviceQuery {
} }
} }
/**
* 分页查询子目录通道
* @param deviceId 通道id
* @param channelId 通道id
* @param page 当前页
* @param count 每页条数
* @param query 查询内容
* @param online 是否在线
* @param channelType 通道类型
* @return 子通道列表
*/
@Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@ -260,12 +211,7 @@ public class DeviceQuery {
deviceChannelService.updateChannelStreamIdentification(channel); deviceChannelService.updateChannelStreamIdentification(channel);
} }
/**
* 修改数据流传输模式
* @param deviceId 设备id
* @param streamMode 数据流传输模式
* @return
*/
@Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "streamMode", description = "数据流传输模式, 取值:" + @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" +
@ -277,11 +223,7 @@ public class DeviceQuery {
deviceService.updateCustomDevice(device); deviceService.updateCustomDevice(device);
} }
/**
* 添加设备信息
* @param device 设备信息
* @return
*/
@Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "device", description = "设备", required = true) @Parameter(name = "device", description = "设备", required = true)
@PostMapping("/device/add/") @PostMapping("/device/add/")
@ -299,11 +241,7 @@ public class DeviceQuery {
deviceService.addDevice(device); deviceService.addDevice(device);
} }
/**
* 更新设备信息
* @param device 设备信息
* @return
*/
@Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "device", description = "设备", required = true) @Parameter(name = "device", description = "设备", required = true)
@PostMapping("/device/update/") @PostMapping("/device/update/")
@ -314,72 +252,37 @@ public class DeviceQuery {
deviceService.updateCustomDevice(device); deviceService.updateCustomDevice(device);
} }
/**
* 设备状态查询请求API接口
*
* @param deviceId 设备id
*/
@Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@GetMapping("/devices/{deviceId}/status") @GetMapping("/devices/{deviceId}/status")
public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) { public DeferredResult<WVPResult<String>> deviceStatusApi(@PathVariable String deviceId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("设备状态查询API调用"); log.debug("设备状态查询API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String uuid = UUID.randomUUID().toString(); Assert.notNull(device, "设备不存在");
String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId; DeferredResult<WVPResult<String>> result = new DeferredResult<>();
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L); deviceService.deviceStatus(device, (code, msg, data) -> {
if(device == null) { result.setResult(new WVPResult<>(code, msg, data));
result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK)); });
return result; result.onTimeout(() -> {
} log.warn("[设备状态查询] 操作超时, 设备未返回应答指令, {}", deviceId);
try { result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
cmder.deviceStatusQuery(device, event -> {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
result.onTimeout(()->{
log.warn(String.format("获取设备状态超时"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData("Timeout. Device did not response to this command.");
resultHolder.invokeResult(msg);
}); });
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, uuid, result);
return result; return result;
} }
/**
* 设备报警查询请求API接口
* @param deviceId 设备id
* @param startPriority 报警起始级别可选
* @param endPriority 报警终止级别可选
* @param alarmMethod 报警方式条件可选
* @param alarmType 报警类型
* @param startTime 报警发生起始时间可选
* @param endTime 报警发生终止时间可选
* @return true = 命令发送成功
*/
@Operation(summary = "设备报警查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "设备报警查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "startPriority", description = "报警起始级别") @Parameter(name = "startPriority", description = "报警起始级别, 0为全部,1为一级警情,2为二级警情,3为三级警情,4为四级警情")
@Parameter(name = "endPriority", description = "报警终止级别") @Parameter(name = "endPriority", description = "报警终止级别, ,0为全部,1为一级警情,2为二级警情,3为三级警情,4为四级警情")
@Parameter(name = "alarmMethod", description = "报警方式条件") @Parameter(name = "alarmMethod", description = "报警方式条件,取值0为全部,1为电话报警,2为设备报警,3为短信报警,4为GPS报警," +
"5为视频报警,6为设备故障报警,7其他报警;可以为直接组合如12为电话报警或设备报警")
@Parameter(name = "alarmType", description = "报警类型") @Parameter(name = "alarmType", description = "报警类型")
@Parameter(name = "startTime", description = "报警发生起始时间") @Parameter(name = "startTime", description = "报警发生起始时间")
@Parameter(name = "endTime", description = "报警发生终止时间") @Parameter(name = "endTime", description = "报警发生终止时间")
@GetMapping("/alarm/{deviceId}") @GetMapping("/alarm")
public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId, public DeferredResult<WVPResult<Object>> alarmApi(String deviceId,
@RequestParam(required = false) String startPriority, @RequestParam(required = false) String startPriority,
@RequestParam(required = false) String endPriority, @RequestParam(required = false) String endPriority,
@RequestParam(required = false) String alarmMethod, @RequestParam(required = false) String alarmMethod,
@ -390,31 +293,35 @@ public class DeviceQuery {
log.debug("设备报警查询API调用"); log.debug("设备报警查询API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; Assert.notNull(device, "设备不存在");
String uuid = UUID.randomUUID().toString(); DeferredResult<WVPResult<Object>> result = new DeferredResult<>();
try { deviceService.alarm(device, startPriority,endPriority ,alarmMethod ,alarmType ,startTime ,endTime, (code, msg, data) -> {
cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> { result.setResult(new WVPResult<>(code, msg, data));
RequestMessage msg = new RequestMessage(); });
msg.setId(uuid); result.onTimeout(() -> {
msg.setKey(key); log.warn("[设备报警查询] 操作超时, 设备未返回应答指令, {}", deviceId);
msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg)); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg); });
}); return result;
} catch (InvalidArgumentException | SipException | ParseException e) { }
log.error("[命令发送失败] 设备报警查询: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); @Operation(summary = "设备信息查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
} @Parameter(name = "deviceId", description = "设备国标编号", required = true)
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L); @GetMapping("/info")
result.onTimeout(()->{ public DeferredResult<WVPResult<Object>> deviceInfo(String deviceId) {
log.warn(String.format("设备报警查询超时")); if (log.isDebugEnabled()) {
// 释放rtpserver log.debug("设备信息查询API调用");
RequestMessage msg = new RequestMessage(); }
msg.setId(uuid); Device device = deviceService.getDeviceByDeviceId(deviceId);
msg.setKey(key); Assert.notNull(device, "设备不存在");
msg.setData("设备报警查询超时"); DeferredResult<WVPResult<Object>> result = new DeferredResult<>();
resultHolder.invokeResult(msg); deviceService.deviceInfo(device, (code, msg, data) -> {
result.setResult(new WVPResult<>(code, msg, data));
});
result.onTimeout(() -> {
log.warn("[设备信息查询] 操作超时, 设备未返回应答指令, {}", deviceId);
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
}); });
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, uuid, result);
return result; return result;
} }

View File

@ -1,9 +1,9 @@
package com.genersoft.iot.vmp.gb28181.controller; package com.genersoft.iot.vmp.gb28181.controller;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
@ -32,10 +32,8 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Tag(name = "国标录像") @Tag(name = "国标录像")
@Slf4j @Slf4j
@ -72,7 +70,7 @@ public class GBRecordController {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(String.format("录像信息查询 API调用deviceId%s startTime%s endTime%s",deviceId, startTime, endTime)); log.debug(String.format("录像信息查询 API调用deviceId%s startTime%s endTime%s",deviceId, startTime, endTime));
} }
DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>(); DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>(Long.valueOf(userSetting.getRecordInfoTimeout()), TimeUnit.MILLISECONDS);
if (!DateUtil.verification(startTime, DateUtil.formatter)){ if (!DateUtil.verification(startTime, DateUtil.formatter)){
throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN); throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN);
} }
@ -81,35 +79,25 @@ public class GBRecordController {
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
// 指定超时时间 1分钟30秒 if (device == null) {
String uuid = UUID.randomUUID().toString(); throw new ControllerException(ErrorCode.ERROR100.getCode(), deviceId + " 不存在");
int sn = (int)((Math.random()*9+1)*100000);
String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
try {
cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
WVPResult<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}));
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
} }
DeviceChannel channel = channelService.getOneForSource(device.getId(), channelId);
// 录像查询以channelId作为deviceId查询 if (channel == null) {
resultHolder.put(key, uuid, result); throw new ControllerException(ErrorCode.ERROR100.getCode(), channelId + " 不存在");
}
channelService.queryRecordInfo(device, channel, startTime, endTime, (code, msg, data)->{
WVPResult<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(code);
wvpResult.setMsg(msg);
wvpResult.setData(data);
result.setResult(wvpResult);
});
result.onTimeout(()->{ result.onTimeout(()->{
msg.setData("timeout");
WVPResult<RecordInfo> wvpResult = new WVPResult<>(); WVPResult<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(ErrorCode.ERROR100.getCode()); wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("timeout"); wvpResult.setMsg("timeout");
msg.setData(wvpResult); result.setResult(wvpResult);
resultHolder.invokeResult(msg);
}); });
return result; return result;
} }
@ -179,7 +167,7 @@ public class GBRecordController {
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "stream", description = "流ID", required = true) @Parameter(name = "stream", description = "流ID", required = true)
@GetMapping("/download/stop/{deviceId}/{channelId}/{stream}") @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { public void downloadStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId)); log.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId));
@ -191,14 +179,13 @@ public class GBRecordController {
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
if (device == null) { if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "未找到"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到");
} }
DeviceChannel deviceChannel = channelService.getOneForSource(deviceId, channelId);
try { if (deviceChannel == null) {
cmder.streamByeCmd(device, channelId, "rtp", stream, null, null); throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + channelId + " 未找到");
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
log.warn("[停止历史媒体下载]停止历史媒体下载发送BYE失败 {}", e.getMessage());
} }
playService.stop(InviteSessionType.DOWNLOAD, device, deviceChannel, stream);
} }
@Operation(summary = "获取历史媒体下载进度", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "获取历史媒体下载进度", security = @SecurityRequirement(name = JwtUtils.HEADER))

View File

@ -19,6 +19,7 @@ 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.callback.RequestMessage;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
@ -91,31 +92,22 @@ public class PlayController {
Assert.notNull(deviceId, "设备不存在"); Assert.notNull(deviceId, "设备不存在");
DeviceChannel channel = deviceChannelService.getOne(deviceId, channelId); DeviceChannel channel = deviceChannelService.getOne(deviceId, channelId);
Assert.notNull(channel, "通道不存在"); Assert.notNull(channel, "通道不存在");
MediaServer newMediaServerItem = playService.getNewMediaServerItem(device);
RequestMessage requestMessage = new RequestMessage();
String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
requestMessage.setKey(key);
String uuid = UUID.randomUUID().toString();
requestMessage.setId(uuid);
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
result.onTimeout(()->{ result.onTimeout(()->{
log.info("[点播等待超时] deviceId{}, channelId{}, ", deviceId, channelId); log.info("[点播等待超时] deviceId{}, channelId{}, ", deviceId, channelId);
// 释放rtpserver // 释放rtpserver
WVPResult<StreamInfo> wvpResult = new WVPResult<>(); WVPResult<StreamContent> wvpResult = new WVPResult<>();
wvpResult.setCode(ErrorCode.ERROR100.getCode()); wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("点播超时"); wvpResult.setMsg("点播超时");
requestMessage.setData(wvpResult); result.setResult(wvpResult);
resultHolder.invokeAllResult(requestMessage);
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, channel.getId()); inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, channel.getId());
deviceChannelService.stopPlay(channel.getId()); deviceChannelService.stopPlay(channel.getId());
}); });
// 录像查询以channelId作为deviceId查询 ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
resultHolder.put(key, uuid, result);
playService.play(newMediaServerItem, deviceId, channelId, null, (code, msg, streamInfo) -> {
WVPResult<StreamContent> wvpResult = new WVPResult<>(); WVPResult<StreamContent> wvpResult = new WVPResult<>();
if (code == InviteErrorCode.SUCCESS.getCode()) { if (code == InviteErrorCode.SUCCESS.getCode()) {
wvpResult.setCode(ErrorCode.SUCCESS.getCode()); wvpResult.setCode(ErrorCode.SUCCESS.getCode());
@ -133,8 +125,8 @@ public class PlayController {
} }
streamInfo.channgeStreamIp(host); streamInfo.channgeStreamIp(host);
} }
if (!ObjectUtils.isEmpty(newMediaServerItem.getTranscodeSuffix()) && !"null".equalsIgnoreCase(newMediaServerItem.getTranscodeSuffix())) { if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix()) && !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) {
streamInfo.setStream(streamInfo.getStream() + "_" + newMediaServerItem.getTranscodeSuffix()); streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix());
} }
wvpResult.setData(new StreamContent(streamInfo)); wvpResult.setData(new StreamContent(streamInfo));
}else { }else {
@ -145,10 +137,9 @@ public class PlayController {
wvpResult.setCode(code); wvpResult.setCode(code);
wvpResult.setMsg(msg); wvpResult.setMsg(msg);
} }
requestMessage.setData(wvpResult); result.setResult(wvpResult);
// 此处必须释放所有请求 };
resultHolder.invokeAllResult(requestMessage); playService.play(device, channel, callback);
});
return result; return result;
} }
@ -207,16 +198,8 @@ public class PlayController {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("语音广播API调用"); log.debug("语音广播API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId);
if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到设备: " + deviceId);
}
DeviceChannel channel = deviceChannelService.getOne(deviceId, channelId);
if (channel == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到通道: " + channelId);
}
return playService.audioBroadcast(device, channel, broadcastMode); return playService.audioBroadcast(deviceId, channelId, broadcastMode);
} }

View File

@ -156,7 +156,7 @@ public class PlaybackController {
} }
DeviceChannel deviceChannel = channelService.getOneForSource(deviceId, channelId); DeviceChannel deviceChannel = channelService.getOneForSource(deviceId, channelId);
if (deviceChannel == null) { if (deviceChannel == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + deviceChannel + " 未找到"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + channelId + " 未找到");
} }
playService.stop(InviteSessionType.PLAYBACK, device, deviceChannel, stream); playService.stop(InviteSessionType.PLAYBACK, device, deviceChannel, stream);
} }
@ -166,8 +166,7 @@ public class PlaybackController {
@Parameter(name = "streamId", description = "回放流ID", required = true) @Parameter(name = "streamId", description = "回放流ID", required = true)
@GetMapping("/pause/{streamId}") @GetMapping("/pause/{streamId}")
public void playPause(@PathVariable String streamId) { public void playPause(@PathVariable String streamId) {
log.info("playPause: "+streamId); log.info("[回放暂停] streamId: {}", streamId);
try { try {
playService.pauseRtp(streamId); playService.pauseRtp(streamId);
} catch (ServiceException e) { } catch (ServiceException e) {

View File

@ -7,9 +7,9 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IPTZService; import com.genersoft.iot.vmp.gb28181.service.IPTZService;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@ -17,18 +17,12 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID;
@Tag(name = "前端设备控制") @Tag(name = "前端设备控制")
@Slf4j @Slf4j
@RestController @RestController
@ -225,40 +219,22 @@ public class PtzController {
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@GetMapping("/preset/query/{deviceId}/{channelId}") @GetMapping("/preset/query/{deviceId}/{channelId}")
public DeferredResult<String> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) { public DeferredResult<WVPResult<Object>> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("设备预置位查询API调用"); log.debug("设备预置位查询API调用");
} }
Device device = deviceService.getDeviceByDeviceId(deviceId); Device device = deviceService.getDeviceByDeviceId(deviceId);
String uuid = UUID.randomUUID().toString(); Assert.notNull(device, "设备不存在");
String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); DeferredResult<WVPResult<Object>> deferredResult = new DeferredResult<> (3 * 1000L);
DeferredResult<String> result = new DeferredResult<String> (3 * 1000L); deviceService.queryPreset(device, channelId, (code, msg, data) -> {
result.onTimeout(()->{ deferredResult.setResult(new WVPResult<>(code, msg, data));
log.warn(String.format("获取设备预置位超时"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData("获取设备预置位超时");
resultHolder.invokeResult(msg);
}); });
if (resultHolder.exist(key, null)) {
return result; deferredResult.onTimeout(()->{
} log.warn("[获取设备预置位] 超时, {}", device.getDeviceId());
resultHolder.put(key, uuid, result); deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
try { });
cmder.presetQuery(device, channelId, event -> { return deferredResult;
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
return result;
} }
@Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))

View File

@ -43,6 +43,7 @@ public interface DeviceMapper {
"as_message_channel," + "as_message_channel," +
"geo_coord_sys," + "geo_coord_sys," +
"on_line," + "on_line," +
"server_id,"+
"media_server_id," + "media_server_id," +
"broadcast_push_after_ack," + "broadcast_push_after_ack," +
"(SELECT count(0) FROM wvp_device_channel dc WHERE dc.data_type = 1 and dc.data_device_id= de.id) as channel_count "+ "(SELECT count(0) FROM wvp_device_channel dc WHERE dc.data_type = 1 and dc.data_device_id= de.id) as channel_count "+
@ -80,6 +81,7 @@ public interface DeviceMapper {
"as_message_channel,"+ "as_message_channel,"+
"broadcast_push_after_ack,"+ "broadcast_push_after_ack,"+
"geo_coord_sys,"+ "geo_coord_sys,"+
"server_id,"+
"on_line"+ "on_line"+
") VALUES (" + ") VALUES (" +
"#{deviceId}," + "#{deviceId}," +
@ -112,6 +114,7 @@ public interface DeviceMapper {
"#{asMessageChannel}," + "#{asMessageChannel}," +
"#{broadcastPushAfterAck}," + "#{broadcastPushAfterAck}," +
"#{geoCoordSys}," + "#{geoCoordSys}," +
"#{serverId}," +
"#{onLine}" + "#{onLine}" +
")") ")")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@ -136,6 +139,7 @@ public interface DeviceMapper {
"<if test=\"positionCapability != null\">, position_capability=#{positionCapability}</if>" + "<if test=\"positionCapability != null\">, position_capability=#{positionCapability}</if>" +
"<if test=\"heartBeatCount != null\">, heart_beat_count=#{heartBeatCount}</if>" + "<if test=\"heartBeatCount != null\">, heart_beat_count=#{heartBeatCount}</if>" +
"<if test=\"expires != null\">, expires=#{expires}</if>" + "<if test=\"expires != null\">, expires=#{expires}</if>" +
"<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
"WHERE device_id=#{deviceId}"+ "WHERE device_id=#{deviceId}"+
" </script>"}) " </script>"})
int update(Device device); int update(Device device);
@ -213,9 +217,43 @@ public interface DeviceMapper {
"as_message_channel,"+ "as_message_channel,"+
"broadcast_push_after_ack,"+ "broadcast_push_after_ack,"+
"geo_coord_sys,"+ "geo_coord_sys,"+
"server_id,"+
"on_line"+ "on_line"+
" FROM wvp_device WHERE on_line = true") " FROM wvp_device WHERE on_line = true")
List<Device> getOnlineDevices(); List<Device> getOnlineDevices();
@Select("SELECT " +
"id, " +
"device_id, " +
"coalesce(custom_name, name) as name, " +
"password, " +
"manufacturer, " +
"model, " +
"firmware, " +
"transport," +
"stream_mode," +
"ip," +
"sdp_ip,"+
"local_ip,"+
"port,"+
"host_address,"+
"expires,"+
"register_time,"+
"keepalive_time,"+
"create_time,"+
"update_time,"+
"charset,"+
"subscribe_cycle_for_catalog,"+
"subscribe_cycle_for_mobile_position,"+
"mobile_position_submission_interval,"+
"subscribe_cycle_for_alarm,"+
"ssrc_check,"+
"as_message_channel,"+
"broadcast_push_after_ack,"+
"geo_coord_sys,"+
"server_id,"+
"on_line"+
" FROM wvp_device WHERE on_line = true and server_id = #{serverId}")
List<Device> getOnlineDevicesByServerId(@Param("serverId") String serverId);
@Select("SELECT " + @Select("SELECT " +
"id,"+ "id,"+
@ -274,6 +312,7 @@ public interface DeviceMapper {
"geo_coord_sys,"+ "geo_coord_sys,"+
"on_line,"+ "on_line,"+
"stream_mode," + "stream_mode," +
"server_id," +
"media_server_id"+ "media_server_id"+
") VALUES (" + ") VALUES (" +
"#{deviceId}," + "#{deviceId}," +
@ -289,6 +328,7 @@ public interface DeviceMapper {
"#{geoCoordSys}," + "#{geoCoordSys}," +
"#{onLine}," + "#{onLine}," +
"#{streamMode}," + "#{streamMode}," +
"#{serverId}," +
"#{mediaServerId}" + "#{mediaServerId}" +
")") ")")
void addCustomDevice(Device device); void addCustomDevice(Device device);
@ -331,6 +371,7 @@ public interface DeviceMapper {
"geo_coord_sys,"+ "geo_coord_sys,"+
"on_line,"+ "on_line,"+
"media_server_id,"+ "media_server_id,"+
"server_id,"+
"(SELECT count(0) FROM wvp_device_channel dc WHERE dc.data_type = #{dataType} and dc.data_device_id= de.id) as channel_count " + "(SELECT count(0) FROM wvp_device_channel dc WHERE dc.data_type = #{dataType} and dc.data_device_id= de.id) as channel_count " +
" FROM wvp_device de" + " FROM wvp_device de" +
" where 1 = 1 "+ " where 1 = 1 "+

View File

@ -58,7 +58,10 @@ public interface PlatformChannelMapper {
"where dc.channel_type = 0 and dc.channel_id = #{channelId} and pgc.platform_id=#{platformId}") "where dc.channel_type = 0 and dc.channel_id = #{channelId} and pgc.platform_id=#{platformId}")
List<Device> queryDeviceInfoByPlatformIdAndChannelId(@Param("platformId") String platformId, @Param("channelId") String channelId); List<Device> queryDeviceInfoByPlatformIdAndChannelId(@Param("platformId") String platformId, @Param("channelId") String channelId);
@Select("SELECT pgc.* from wvp_platform_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE dc.channel_type = 0 and dc.device_id=#{channelId}") @Select(" SELECT wp.* from wvp_platform_channel pgc " +
" left join wvp_device_channel dc on dc.id = pgc.device_channel_id " +
" left join wvp_platform wp on wp.id = pgc.platform_id" +
" WHERE dc.channel_type = 0 and dc.device_id=#{channelId}")
List<Platform> queryParentPlatformByChannelId(@Param("channelId") String channelId); List<Platform> queryParentPlatformByChannelId(@Param("channelId") String channelId);
@Select("<script>" + @Select("<script>" +

View File

@ -16,11 +16,11 @@ public interface PlatformMapper {
@Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+ @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+
" device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,status,catalog_group, update_time," + " device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,status,catalog_group, update_time," +
" create_time, as_message_channel, send_stream_ip, auto_push_channel, catalog_with_platform,catalog_with_group,catalog_with_region, "+ " create_time, as_message_channel, send_stream_ip, auto_push_channel, catalog_with_platform,catalog_with_group,catalog_with_region, "+
" civil_code,manufacturer,model,address,register_way,secrecy) " + " civil_code,manufacturer,model,address,register_way,secrecy,server_id) " +
" VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIp}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIp}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
" #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{status}, #{catalogGroup},#{updateTime}," + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{status}, #{catalogGroup},#{updateTime}," +
" #{createTime}, #{asMessageChannel}, #{sendStreamIp}, #{autoPushChannel}, #{catalogWithPlatform}, #{catalogWithGroup},#{catalogWithRegion}, " + " #{createTime}, #{asMessageChannel}, #{sendStreamIp}, #{autoPushChannel}, #{catalogWithPlatform}, #{catalogWithGroup},#{catalogWithRegion}, " +
" #{civilCode}, #{manufacturer}, #{model}, #{address}, #{registerWay}, #{secrecy})") " #{civilCode}, #{manufacturer}, #{model}, #{address}, #{registerWay}, #{secrecy}, #{serverId})")
int add(Platform parentPlatform); int add(Platform parentPlatform);
@Update("UPDATE wvp_platform " + @Update("UPDATE wvp_platform " +
@ -55,6 +55,7 @@ public interface PlatformMapper {
" model=#{model}, " + " model=#{model}, " +
" address=#{address}, " + " address=#{address}, " +
" register_way=#{registerWay}, " + " register_way=#{registerWay}, " +
" server_id=#{serverId}, " +
" secrecy=#{secrecy} " + " secrecy=#{secrecy} " +
"WHERE id=#{id}") "WHERE id=#{id}")
int update(Platform parentPlatform); int update(Platform parentPlatform);
@ -76,8 +77,8 @@ public interface PlatformMapper {
" </script>") " </script>")
List<Platform> queryList(@Param("query") String query); List<Platform> queryList(@Param("query") String query);
@Select("SELECT * FROM wvp_platform WHERE enable=#{enable} ") @Select("SELECT * FROM wvp_platform WHERE server_id=#{serverId} and enable=#{enable} ")
List<Platform> getEnableParentPlatformList(boolean enable); List<Platform> queryEnableParentPlatformList(@Param("serverId") String serverId, @Param("enable") boolean enable);
@Select("SELECT * FROM wvp_platform WHERE enable=true and as_message_channel=true") @Select("SELECT * FROM wvp_platform WHERE enable=true and as_message_channel=true")
List<Platform> queryEnablePlatformListWithAsMessageChannel(); List<Platform> queryEnablePlatformListWithAsMessageChannel();
@ -91,7 +92,9 @@ public interface PlatformMapper {
@Update("UPDATE wvp_platform SET status=#{online} WHERE server_gb_id=#{platformGbID}" ) @Update("UPDATE wvp_platform SET status=#{online} WHERE server_gb_id=#{platformGbID}" )
int updateStatus(@Param("platformGbID") String platformGbID, @Param("online") boolean online); int updateStatus(@Param("platformGbID") String platformGbID, @Param("online") boolean online);
@Select("SELECT * FROM wvp_platform WHERE enable=true") @Select("SELECT server_id FROM wvp_platform WHERE enable=true and server_id != #{serverId} group by server_id")
List<Platform> queryEnablePlatformList(); List<String> queryServerIdsWithEnableAndNotInServer(@Param("serverId") String serverId);
@Select("SELECT * FROM wvp_platform WHERE server_id = #{serverId}")
List<Platform> queryByServerId(@Param("serverId") String serverId);
} }

View File

@ -1,13 +1,19 @@
package com.genersoft.iot.vmp.gb28181.event; package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition.MobilePositionEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition.MobilePositionEvent;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOfflineEvent; import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOfflineEvent;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOnlineEvent; import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOnlineEvent;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import org.springframework.beans.factory.annotation.Autowired; 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;
@ -28,6 +34,12 @@ public class EventPublisher {
@Autowired @Autowired
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private UserSetting userSetting;
@Autowired
private IRedisRpcService redisRpcService;
/** /**
* 设备报警事件 * 设备报警事件
* @param deviceAlarm * @param deviceAlarm
@ -58,6 +70,18 @@ public class EventPublisher {
} }
public void catalogEventPublish(Platform platform, List<CommonGBChannel> deviceChannels, String type) { public void catalogEventPublish(Platform platform, List<CommonGBChannel> deviceChannels, String type) {
catalogEventPublish(platform, deviceChannels, type, true);
}
public void catalogEventPublish(Platform platform, List<CommonGBChannel> deviceChannels, String type, boolean share) {
if (platform != null && !userSetting.getServerId().equals(platform.getServerId())) {
// 指定了上级平台的推送则发送到指定的设备未指定的则全部发送 接收后各自处理自己的
CatalogEvent outEvent = new CatalogEvent(this);
outEvent.setChannels(deviceChannels);
outEvent.setType(type);
outEvent.setPlatform(platform);
redisRpcService.catalogEventPublish(platform.getServerId(), outEvent);
return;
}
CatalogEvent outEvent = new CatalogEvent(this); CatalogEvent outEvent = new CatalogEvent(this);
List<CommonGBChannel> channels = new ArrayList<>(); List<CommonGBChannel> channels = new ArrayList<>();
if (deviceChannels.size() > 1) { if (deviceChannels.size() > 1) {
@ -76,6 +100,10 @@ public class EventPublisher {
outEvent.setType(type); outEvent.setType(type);
outEvent.setPlatform(platform); outEvent.setPlatform(platform);
applicationEventPublisher.publishEvent(outEvent); applicationEventPublisher.publishEvent(outEvent);
if (platform == null && share) {
// 如果没指定上级平台则推送消息到所有在线的wvp处理自己含有的平台的目录更新
redisRpcService.catalogEventPublish(null, outEvent);
}
} }
public void mobilePositionEventPublish(MobilePosition mobilePosition) { public void mobilePositionEventPublish(MobilePosition mobilePosition) {
@ -84,9 +112,5 @@ public class EventPublisher {
applicationEventPublisher.publishEvent(event); applicationEventPublisher.publishEvent(event);
} }
public void recordEndEventPush(RecordInfo recordInfo) {
RecordEndEvent outEvent = new RecordEndEvent(this);
outEvent.setRecordInfo(recordInfo);
applicationEventPublisher.publishEvent(outEvent);
}
} }

View File

@ -0,0 +1,73 @@
package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.event.sip.MessageEvent;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
/**
* @author lin
*/
@Slf4j
@Component
public class MessageSubscribe {
private final Map<String, MessageEvent<?>> subscribes = new ConcurrentHashMap<>();
private final DelayQueue<MessageEvent<?>> delayQueue = new DelayQueue<>();
@Scheduled(fixedDelay = 200) //每200毫秒执行
public void execute(){
while (!delayQueue.isEmpty()) {
try {
MessageEvent<?> take = delayQueue.take();
// 出现超时异常
if(take.getCallback() != null) {
take.getCallback().run(ErrorCode.ERROR486.getCode(), "消息超时未回复", null);
}
subscribes.remove(take.getKey());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public void addSubscribe(MessageEvent<?> event) {
MessageEvent<?> messageEvent = subscribes.get(event.getKey());
if (messageEvent != null) {
subscribes.remove(event.getKey());
delayQueue.remove(messageEvent);
}
subscribes.put(event.getKey(), event);
delayQueue.offer(event);
}
public MessageEvent<?> getSubscribe(String key) {
return subscribes.get(key);
}
public void removeSubscribe(String key) {
if(key == null){
return;
}
MessageEvent<?> messageEvent = subscribes.get(key);
if (messageEvent != null) {
subscribes.remove(key);
delayQueue.remove(messageEvent);
}
}
public boolean isEmpty(){
return subscribes.isEmpty();
}
public Integer size() {
return subscribes.size();
}
}

View File

@ -29,24 +29,24 @@ public class SipSubscribe {
private final DelayQueue<SipEvent> delayQueue = new DelayQueue<>(); private final DelayQueue<SipEvent> delayQueue = new DelayQueue<>();
@Scheduled(fixedDelay = 200) //每200毫秒执行 @Scheduled(fixedDelay = 200) //每200毫秒执行
public void execute(){ public void execute(){
if (delayQueue.isEmpty()) { while (!delayQueue.isEmpty()) {
return; try {
} SipEvent take = delayQueue.take();
try { // 出现超时异常
SipEvent take = delayQueue.take(); if(take.getErrorEvent() != null) {
// 出现超时异常 EventResult<Object> eventResult = new EventResult<>();
if(take.getErrorEvent() != null) { eventResult.type = EventResultType.timeout;
EventResult<Object> eventResult = new EventResult<>(); eventResult.msg = "消息超时未回复";
eventResult.type = EventResultType.timeout; eventResult.statusCode = -1024;
eventResult.msg = "消息超时未回复"; take.getErrorEvent().response(eventResult);
eventResult.statusCode = -1024; }
take.getErrorEvent().response(eventResult); subscribes.remove(take.getKey());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} }
subscribes.remove(take.getKey());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} }
} }
@ -78,7 +78,9 @@ public class SipSubscribe {
// 消息发送失败 // 消息发送失败
cmdSendFailEvent, cmdSendFailEvent,
// 消息发送失败 // 消息发送失败
failedToGetPort failedToGetPort,
// 收到失败的回复
failedResult
} }
public static class EventResult<EventObject>{ public static class EventResult<EventObject>{

View File

@ -1,7 +1,8 @@
package com.genersoft.iot.vmp.gb28181.event.record; package com.genersoft.iot.vmp.gb28181.event.record;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
/** /**
@ -9,24 +10,18 @@ import org.springframework.context.ApplicationEvent;
* @author: pan * @author: pan
* @data: 2022-02-23 * @data: 2022-02-23
*/ */
@Setter
public class RecordEndEvent extends ApplicationEvent { @Getter
public class RecordInfoEndEvent extends ApplicationEvent {
/** /**
* *
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public RecordEndEvent(Object source) { public RecordInfoEndEvent(Object source) {
super(source); super(source);
} }
private RecordInfo recordInfo; private RecordInfo recordInfo;
public RecordInfo getRecordInfo() {
return recordInfo;
}
public void setRecordInfo(RecordInfo recordInfo) {
this.recordInfo = recordInfo;
}
} }

View File

@ -0,0 +1,27 @@
package com.genersoft.iot.vmp.gb28181.event.record;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
/**
* @description: 录像查询结束时间
* @author: pan
* @data: 2022-02-23
*/
@Setter
@Getter
public class RecordInfoEvent extends ApplicationEvent {
/**
*
*/
private static final long serialVersionUID = 1L;
public RecordInfoEvent(Object source) {
super(source);
}
private RecordInfo recordInfo;
}

View File

@ -15,15 +15,15 @@ import java.util.concurrent.ConcurrentHashMap;
*/ */
@Slf4j @Slf4j
@Component @Component
public class RecordEndEventListener implements ApplicationListener<RecordEndEvent> { public class RecordInfoEventListener implements ApplicationListener<RecordInfoEvent> {
private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>(); private final Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
public interface RecordEndEventHandler{ public interface RecordEndEventHandler{
void handler(RecordInfo recordInfo); void handler(RecordInfo recordInfo);
} }
@Override @Override
public void onApplicationEvent(RecordEndEvent event) { public void onApplicationEvent(RecordInfoEvent event) {
String deviceId = event.getRecordInfo().getDeviceId(); String deviceId = event.getRecordInfo().getDeviceId();
String channelId = event.getRecordInfo().getChannelId(); String channelId = event.getRecordInfo().getChannelId();
int count = event.getRecordInfo().getCount(); int count = event.getRecordInfo().getCount();
@ -45,9 +45,6 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
/** /**
* 添加 * 添加
* @param device
* @param channelId
* @param recordEndEventHandler
*/ */
public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) { public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) {
log.info("录像查询事件添加监听deviceId{}, channelId: {}", device, channelId); log.info("录像查询事件添加监听deviceId{}, channelId: {}", device, channelId);
@ -55,8 +52,6 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
} }
/** /**
* 添加 * 添加
* @param device
* @param channelId
*/ */
public void delEndEventHandler(String device, String channelId) { public void delEndEventHandler(String device, String channelId) {
log.info("录像查询事件移除监听deviceId{}, channelId: {}", device, channelId); log.info("录像查询事件移除监听deviceId{}, channelId: {}", device, channelId);

View File

@ -0,0 +1,56 @@
package com.genersoft.iot.vmp.gb28181.event.sip;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
@Data
public class MessageEvent<T> implements Delayed {
/**
* 超时时间(单位 毫秒)
*/
private long delay;
private String cmdType;
private String sn;
private String deviceId;
private String result;
private T t;
private ErrorCallback<T> callback;
@Override
public long getDelay(@NotNull TimeUnit unit) {
return unit.convert(delay - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(@NotNull Delayed o) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
}
public String getKey(){
return cmdType + sn;
}
public static <T> MessageEvent<T> getInstance(String cmdType, String sn, String deviceId, Long delay, ErrorCallback<T> callback){
MessageEvent<T> messageEvent = new MessageEvent<>();
messageEvent.cmdType = cmdType;
messageEvent.sn = sn;
messageEvent.deviceId = deviceId;
messageEvent.callback = callback;
if (delay == null) {
messageEvent.delay = System.currentTimeMillis() + 1000;
}else {
messageEvent.delay = System.currentTimeMillis() + delay;
}
return messageEvent;
}
}

View File

@ -32,13 +32,13 @@ public class SipEvent implements Delayed {
sipEvent.setKey(key); sipEvent.setKey(key);
sipEvent.setOkEvent(okEvent); sipEvent.setOkEvent(okEvent);
sipEvent.setErrorEvent(errorEvent); sipEvent.setErrorEvent(errorEvent);
sipEvent.setDelay(delay); sipEvent.setDelay(System.currentTimeMillis() + delay);
return sipEvent; return sipEvent;
} }
@Override @Override
public long getDelay(@NotNull TimeUnit unit) { public long getDelay(@NotNull TimeUnit unit) {
return unit.convert(delay, TimeUnit.MILLISECONDS); return unit.convert(delay - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog; package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel; import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
@ -7,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService; import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService; import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
@ -15,10 +17,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* catalog事件 * catalog事件
@ -30,9 +29,6 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
@Autowired @Autowired
private IPlatformChannelService platformChannelService; private IPlatformChannelService platformChannelService;
@Autowired
private IPlatformService platformService;
@Autowired @Autowired
private ISIPCommanderForPlatform sipCommanderFroPlatform; private ISIPCommanderForPlatform sipCommanderFroPlatform;

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service; package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.common.enums.DeviceControlType; import com.genersoft.iot.vmp.common.enums.DeviceControlType;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
@ -131,4 +132,9 @@ public interface IDeviceChannelService {
List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId); List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId);
void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback); void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback);
void queryRecordInfo(Device device, DeviceChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> object);
void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> object);
} }

View File

@ -1,10 +1,10 @@
package com.genersoft.iot.vmp.gb28181.service; package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import java.util.List; import java.util.List;
@ -86,7 +86,7 @@ public interface IDeviceService {
* 获取所有在线设备 * 获取所有在线设备
* @return 设备列表 * @return 设备列表
*/ */
List<Device> getAllOnlineDevice(); List<Device> getAllOnlineDevice(String serverId);
List<Device> getAllByStatus(Boolean status); List<Device> getAllByStatus(Boolean status);
@ -166,5 +166,35 @@ public interface IDeviceService {
void subscribeMobilePosition(int id, int cycle, int interval); void subscribeMobilePosition(int id, int cycle, int interval);
WVPResult<SyncStatus> devicesSync(Device device);
void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback);
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback);
void teleboot(Device device);
void record(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback);
void guard(Device device, String guardCmdStr, ErrorCallback<String> callback);
void resetAlarm(Device device, String channelId, String alarmMethod, String alarmType, ErrorCallback<String> callback);
void iFrame(Device device, String channelId);
void homePosition(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback);
void dragZoomIn(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback);
void dragZoomOut(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback);
void deviceStatus(Device device, ErrorCallback<String> callback);
void updateDeviceHeartInfo(Device device); void updateDeviceHeartInfo(Device device);
void alarm(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime, ErrorCallback<Object> callback);
void deviceInfo(Device device, ErrorCallback<Object> callback);
void queryPreset(Device device, String channelId, ErrorCallback<Object> callback);
} }

View File

@ -1,20 +1,33 @@
package com.genersoft.iot.vmp.gb28181.service; package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel; import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.InviteInfo; import com.genersoft.iot.vmp.gb28181.bean.InviteMessageInfo;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.ErrorCallback;
public interface IGbChannelPlayService { public interface IGbChannelPlayService {
void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback); void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback);
void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream);
void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback); void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback);
void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback); void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream);
void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback); void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
void stopPlayProxy(CommonGBChannel channel);
void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback); void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback);
void stopPlayPush(CommonGBChannel channel);
void pauseRtp(String streamId);
void resumeRtp(String streamId);
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service; package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.streamPush.bean.StreamPush; import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -87,4 +88,6 @@ public interface IGbChannelService {
PageInfo<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasRecordPlan, Integer channelType); PageInfo<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback);
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service; package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Preset; import com.genersoft.iot.vmp.gb28181.bean.Preset;
@ -18,4 +19,6 @@ public interface IPTZService {
void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed); void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed);
void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2); void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2);
void frontEndCommand(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2);
} }

View File

@ -43,6 +43,8 @@ public interface IPlatformChannelService {
CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId); CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId);
List<CommonGBChannel> queryChannelByPlatformIdAndChannelIds(Integer platformId, List<Integer> channelIds);
void checkRegionAdd(List<CommonGBChannel> channelList); void checkRegionAdd(List<CommonGBChannel> channelList);
void checkRegionRemove(List<CommonGBChannel> channelList, List<Region> regionList); void checkRegionRemove(List<CommonGBChannel> channelList, List<Region> regionList);

View File

@ -82,7 +82,7 @@ public interface IPlatformService {
Platform queryOne(Integer platformId); Platform queryOne(Integer platformId);
List<Platform> queryEnablePlatformList(); List<Platform> queryEnablePlatformList(String serverId);
void delete(Integer platformId, CommonCallback<Object> callback); void delete(Integer platformId, CommonCallback<Object> callback);
} }

View File

@ -25,6 +25,8 @@ public interface IPlayService {
SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback); SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback);
void play(Device device, DeviceChannel channel, ErrorCallback<StreamInfo> callback);
StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, Device device, DeviceChannel channel); StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, Device device, DeviceChannel channel);
MediaServer getNewMediaServerItem(Device device); MediaServer getNewMediaServerItem(Device device);
@ -38,7 +40,7 @@ public interface IPlayService {
void zlmServerOnline(MediaServer mediaServer); void zlmServerOnline(MediaServer mediaServer);
AudioBroadcastResult audioBroadcast(Device device, DeviceChannel deviceChannel, Boolean broadcastMode); AudioBroadcastResult audioBroadcast(String deviceId, String channelDeviceId, Boolean broadcastMode);
boolean audioBroadcastCmd(Device device, DeviceChannel channel, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; boolean audioBroadcastCmd(Device device, DeviceChannel channel, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException;
@ -66,8 +68,12 @@ public interface IPlayService {
void play(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback); void play(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
void stop(InviteSessionType inviteSessionType, CommonGBChannel channel, String stream);
void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback); void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback);
void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback); void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback);
} }

View File

@ -1,9 +1,8 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.service.IDeviceAlarmService;
import com.genersoft.iot.vmp.gb28181.dao.DeviceAlarmMapper; import com.genersoft.iot.vmp.gb28181.dao.DeviceAlarmMapper;
import com.genersoft.iot.vmp.gb28181.service.IDeviceAlarmService;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -12,7 +11,6 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service @Service
@DS("master")
public class DeviceAlarmServiceImpl implements IDeviceAlarmService { public class DeviceAlarmServiceImpl implements IDeviceAlarmService {
@Autowired @Autowired

View File

@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.common.enums.ChannelDataType;
@ -15,6 +14,7 @@ import com.genersoft.iot.vmp.gb28181.dao.DeviceMapper;
import com.genersoft.iot.vmp.gb28181.dao.DeviceMobilePositionMapper; import com.genersoft.iot.vmp.gb28181.dao.DeviceMobilePositionMapper;
import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper; import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.record.RecordInfoEndEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService; import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService; import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
@ -22,6 +22,8 @@ import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@ -32,18 +34,25 @@ import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element; import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.text.ParseException; import java.text.ParseException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@ -52,7 +61,6 @@ import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
*/ */
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class DeviceChannelServiceImpl implements IDeviceChannelService { public class DeviceChannelServiceImpl implements IDeviceChannelService {
@Autowired @Autowired
@ -82,6 +90,26 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
@Autowired @Autowired
private IPlatformChannelService platformChannelService; private IPlatformChannelService platformChannelService;
@Autowired
private IRedisRpcPlayService redisRpcPlayService;
@Autowired
private ISIPCommander commander;
// 记录录像查询的结果等待
private final Map<String, SynchronousQueue<RecordInfo>> topicSubscribers = new ConcurrentHashMap<>();
/**
* 监听录像查询结束事件
*/
@Async("taskExecutor")
@org.springframework.context.event.EventListener
public void onApplicationEvent(RecordInfoEndEvent event) {
SynchronousQueue<RecordInfo> queue = topicSubscribers.get("record" + event.getRecordInfo().getSn());
if (queue != null) {
queue.offer(event.getRecordInfo());
}
}
@Autowired @Autowired
private ISIPCommander cmder; private ISIPCommander cmder;
@ -179,10 +207,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
@Override @Override
public ResourceBaseInfo getOverview() { public ResourceBaseInfo getOverview() {
int online = channelMapper.getOnlineCount(); int online = channelMapper.getOnlineCount();
int total = channelMapper.getAllChannelCount(); int total = channelMapper.getAllChannelCount();
return new ResourceBaseInfo(total, online); return new ResourceBaseInfo(total, online);
} }
@ -555,7 +581,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
List<Platform> platformList = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getDeviceId()); List<Platform> platformList = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getDeviceId());
if (!CollectionUtils.isEmpty(platformList)){ if (!CollectionUtils.isEmpty(platformList)){
platformList.forEach(platform->{ platformList.forEach(platform->{
eventPublisher.catalogEventPublish(platform, deviceChannel, deviceChannel.getStatus().equals("ON")? CatalogEvent.ON:CatalogEvent.OFF); eventPublisher.catalogEventPublish(platform, deviceChannel.buildCommonGBChannelForStatus(), deviceChannel.getStatus().equals("ON")? CatalogEvent.ON:CatalogEvent.OFF);
}); });
} }
} }
@ -755,4 +781,57 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
public void updateChannelForNotify(DeviceChannel channel) { public void updateChannelForNotify(DeviceChannel channel) {
channelMapper.updateChannelForNotify(channel); channelMapper.updateChannelForNotify(channel);
} }
@Override
public void queryRecordInfo(Device device, DeviceChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
if (!userSetting.getServerId().equals(device.getServerId())){
redisRpcPlayService.queryRecordInfo(device.getServerId(), channel.getId(), startTime, endTime, callback);
return;
}
try {
int sn = (int)((Math.random()*9+1)*100000);
commander.recordInfoQuery(device, channel.getDeviceId(), startTime, endTime, sn, null, null, eventResult -> {
try {
// 消息发送成功, 监听等待数据到来
SynchronousQueue<RecordInfo> queue = new SynchronousQueue<>();
topicSubscribers.put("record" + sn, queue);
RecordInfo recordInfo = queue.poll(userSetting.getRecordInfoTimeout(), TimeUnit.MILLISECONDS);
if (recordInfo != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), recordInfo);
}else {
callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), recordInfo);
}
} catch (InterruptedException e) {
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
} finally {
this.topicSubscribers.remove("record" + sn);
}
}, (eventResult -> {
callback.run(ErrorCode.ERROR100.getCode(), "查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg, null);
}));
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
if (channel.getDataType() != ChannelDataType.GB28181.value){
// 只支持国标的语音喊话
log.warn("[INFO 消息] 非国标设备, 通道ID {}", channel.getGbId());
callback.run(ErrorCode.ERROR100.getCode(), "非国标设备", null);
return;
}
Device device = deviceMapper.query(channel.getDataDeviceId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
callback.run(ErrorCode.ERROR100.getCode(), "设备不存在", null);
return;
}
DeviceChannel deviceChannel = getOneForSourceById(channel.getGbId());
queryRecordInfo(device, deviceChannel, startTime, endTime, callback);
}
} }

View File

@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.common.enums.ChannelDataType;
@ -24,10 +23,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respons
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.ISendRtpServerService; import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -49,7 +51,6 @@ import java.util.concurrent.TimeUnit;
*/ */
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class DeviceServiceImpl implements IDeviceService { public class DeviceServiceImpl implements IDeviceService {
@Autowired @Autowired
@ -94,6 +95,9 @@ public class DeviceServiceImpl implements IDeviceService {
@Autowired @Autowired
private AudioBroadcastManager audioBroadcastManager; private AudioBroadcastManager audioBroadcastManager;
@Autowired
private IRedisRpcService redisRpcService;
private Device getDeviceByDeviceIdFromDb(String deviceId) { private Device getDeviceByDeviceIdFromDb(String deviceId) {
return deviceMapper.getDeviceByDeviceId(deviceId); return deviceMapper.getDeviceByDeviceId(deviceId);
} }
@ -135,7 +139,7 @@ public class DeviceServiceImpl implements IDeviceService {
deviceMapper.add(device); deviceMapper.add(device);
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
try { try {
commander.deviceInfoQuery(device); commander.deviceInfoQuery(device, null);
commander.deviceConfigQuery(device, null, "BasicParam", null); commander.deviceConfigQuery(device, null, "BasicParam", null);
} catch (InvalidArgumentException | SipException | ParseException e) { } catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); log.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
@ -150,7 +154,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (userSetting.getSyncChannelOnDeviceOnline()) { if (userSetting.getSyncChannelOnDeviceOnline()) {
log.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); log.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
try { try {
commander.deviceInfoQuery(device); commander.deviceInfoQuery(device, null);
} catch (InvalidArgumentException | SipException | ParseException e) { } catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); log.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
} }
@ -214,7 +218,7 @@ public class DeviceServiceImpl implements IDeviceService {
// deviceChannelMapper.offlineByDeviceId(deviceId); // deviceChannelMapper.offlineByDeviceId(deviceId);
// 离线释放所有ssrc // 离线释放所有ssrc
List<SsrcTransaction> ssrcTransactions = sessionManager.getSsrcTransactionByDeviceId(deviceId); List<SsrcTransaction> ssrcTransactions = sessionManager.getSsrcTransactionByDeviceId(deviceId);
if (ssrcTransactions != null && ssrcTransactions.size() > 0) { if (ssrcTransactions != null && !ssrcTransactions.isEmpty()) {
for (SsrcTransaction ssrcTransaction : ssrcTransactions) { for (SsrcTransaction ssrcTransaction : ssrcTransactions) {
mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
@ -338,6 +342,13 @@ public class DeviceServiceImpl implements IDeviceService {
@Override @Override
public SyncStatus getChannelSyncStatus(String deviceId) { public SyncStatus getChannelSyncStatus(String deviceId) {
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (device == null) {
throw new ControllerException(ErrorCode.ERROR404.getCode(), "设备不存在");
}
if (!userSetting.getServerId().equals(device.getServerId())) {
return redisRpcService.getChannelSyncStatus(device.getServerId(), deviceId);
}
return catalogResponseMessageHandler.getChannelSyncProgress(deviceId); return catalogResponseMessageHandler.getChannelSyncProgress(deviceId);
} }
@ -381,8 +392,8 @@ public class DeviceServiceImpl implements IDeviceService {
} }
@Override @Override
public List<Device> getAllOnlineDevice() { public List<Device> getAllOnlineDevice(String serverId) {
return deviceMapper.getOnlineDevices(); return deviceMapper.getOnlineDevicesByServerId(serverId);
} }
@Override @Override
@ -470,9 +481,7 @@ public class DeviceServiceImpl implements IDeviceService {
@Transactional @Transactional
public boolean delete(String deviceId) { public boolean delete(String deviceId) {
Device device = getDeviceByDeviceIdFromDb(deviceId); Device device = getDeviceByDeviceIdFromDb(deviceId);
if (device == null) { Assert.notNull(device, "未找到设备");
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备:" + deviceId);
}
platformChannelMapper.delChannelForDeviceId(deviceId); platformChannelMapper.delChannelForDeviceId(deviceId);
deviceChannelMapper.cleanChannelsByDeviceId(device.getId()); deviceChannelMapper.cleanChannelsByDeviceId(device.getId());
deviceMapper.del(deviceId); deviceMapper.del(deviceId);
@ -523,10 +532,14 @@ public class DeviceServiceImpl implements IDeviceService {
public void subscribeCatalog(int id, int cycle) { public void subscribeCatalog(int id, int cycle) {
Device device = deviceMapper.query(id); Device device = deviceMapper.query(id);
Assert.notNull(device, "未找到设备"); Assert.notNull(device, "未找到设备");
if (device.getSubscribeCycleForCatalog() == cycle) { if (device.getSubscribeCycleForCatalog() == cycle) {
return; return;
} }
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.subscribeCatalog(id, cycle);
return;
}
// 目录订阅相关的信息 // 目录订阅相关的信息
if (device.getSubscribeCycleForCatalog() > 0) { if (device.getSubscribeCycleForCatalog() > 0) {
// 订阅周期不同则先取消 // 订阅周期不同则先取消
@ -556,7 +569,10 @@ public class DeviceServiceImpl implements IDeviceService {
if (device.getSubscribeCycleForMobilePosition() == cycle) { if (device.getSubscribeCycleForMobilePosition() == cycle) {
return; return;
} }
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.subscribeMobilePosition(id, cycle, interval);
return;
}
// 目录订阅相关的信息 // 目录订阅相关的信息
if (device.getSubscribeCycleForMobilePosition() > 0) { if (device.getSubscribeCycleForMobilePosition() > 0) {
// 订阅周期已经开启则先取消 // 订阅周期已经开启则先取消
@ -602,4 +618,297 @@ public class DeviceServiceImpl implements IDeviceService {
updateDevice(deviceInDb); updateDevice(deviceInDb);
} }
} }
@Override
public WVPResult<SyncStatus> devicesSync(Device device) {
if (!userSetting.getServerId().equals(device.getServerId())) {
return redisRpcService.devicesSync(device.getServerId(), device.getDeviceId());
}
// 已存在则返回进度
if (isSyncRunning(device.getDeviceId())) {
SyncStatus channelSyncStatus = getChannelSyncStatus(device.getDeviceId());
WVPResult<SyncStatus> wvpResult = new WVPResult();
if (channelSyncStatus.getErrorMsg() != null) {
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(channelSyncStatus.getErrorMsg());
}else if (channelSyncStatus.getTotal() == null || channelSyncStatus.getTotal() == 0){
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg("等待通道信息...");
}else {
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(channelSyncStatus);
}
return wvpResult;
}
sync(device);
WVPResult<SyncStatus> wvpResult = new WVPResult<>();
wvpResult.setCode(0);
wvpResult.setMsg("开始同步");
return wvpResult;
}
@Override
public void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceBasicConfig(device.getServerId(), device, basicParam);
if (result.getCode() == ErrorCode.SUCCESS.getCode()) {
callback.run(result.getCode(), result.getMsg(), result.getData());
}
return;
}
try {
sipCommander.deviceBasicConfigCmd(device, basicParam, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 设备配置: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceConfigQuery(device.getServerId(), device, channelId, configType);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceConfigQuery(device, channelId, configType, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void teleboot(Device device) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.teleboot(device.getServerId(), device);
}
try {
sipCommander.teleBootCmd(device);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 远程启动: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void record(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.recordControl(device.getServerId(), device, channelId, recordCmdStr);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.recordCmd(device, channelId, recordCmdStr, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void guard(Device device, String guardCmdStr, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.guard(device.getServerId(), device, guardCmdStr);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.guardCmd(device, guardCmdStr, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void resetAlarm(Device device, String channelId, String alarmMethod, String alarmType, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.resetAlarm(device.getServerId(), device, channelId, alarmMethod, alarmType);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.alarmResetCmd(device, alarmMethod, alarmType, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void iFrame(Device device, String channelId) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.iFrame(device.getServerId(), device, channelId);
return;
}
try {
sipCommander.iFrameCmd(device, channelId);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 强制关键帧操作: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void homePosition(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.homePosition(device.getServerId(), device, channelId, enabled, resetTime, presetIndex);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 看守位控制: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void dragZoomIn(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.dragZoomIn(device.getServerId(), device, channelId, length, width, midpointx, midpointy, lengthx, lengthy);
return;
}
StringBuffer cmdXml = new StringBuffer(200);
cmdXml.append("<DragZoomIn>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomIn>\r\n");
try {
sipCommander.dragZoomCmd(device, channelId, cmdXml.toString(), callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框放大: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void dragZoomOut(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.dragZoomOut(device.getServerId(), device, channelId, length, width, midpointx, midpointy, lengthx, lengthy);
return;
}
StringBuffer cmdXml = new StringBuffer(200);
cmdXml.append("<DragZoomOut>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomOut>\r\n");
try {
sipCommander.dragZoomCmd(device, channelId, cmdXml.toString(), callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框放大: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void deviceStatus(Device device, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceStatus(device.getServerId(), device);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceStatusQuery(device, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void alarm(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.alarm(device.getServerId(), device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
String startAlarmTime = "";
if (startTime != null) {
startAlarmTime = DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime);
}
String endAlarmTime = "";
if (startTime != null) {
endAlarmTime = DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime);
}
try {
sipCommander.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startAlarmTime, endAlarmTime, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void deviceInfo(Device device, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<Object> result = redisRpcService.deviceInfo(device.getServerId(), device);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceInfoQuery(device, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备信息: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void queryPreset(Device device, String channelId, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<Object> result = redisRpcService.queryPreset(device.getServerId(), device, channelId);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.presetQuery(device, channelId, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 预制位查询: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
} }

View File

@ -1,10 +1,12 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ServiceException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.common.enums.ChannelDataType;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel; import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.InviteInfo;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.PlayException; import com.genersoft.iot.vmp.gb28181.bean.PlayException;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService; import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
@ -16,7 +18,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException;
@Slf4j @Slf4j
@Service @Service
@ -36,7 +41,7 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
@Override @Override
public void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback) { public void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback) {
if (channel == null || inviteInfo == null || callback == null || channel.getDataType() == null) { if (channel == null || inviteInfo == null || callback == null || channel.getDataType() == null) {
log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null); log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error"); throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
@ -92,6 +97,24 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
} }
} }
@Override
public void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream) {
if (channel.getDataType() == ChannelDataType.GB28181.value) {
// 国标通道
stopPlayDeviceChannel(type, channel, stream);
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
// 拉流代理
stopPlayProxy(channel);
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
// 推流
stopPlayPush(channel);
} else {
// 通道数据异常
log.error("[点播通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}
@Override @Override
public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback) { public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback) {
if (channel.getDataType() == ChannelDataType.GB28181.value) { if (channel.getDataType() == ChannelDataType.GB28181.value) {
@ -128,6 +151,16 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
} }
} }
@Override
public void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream) {
// 国标通道
try {
deviceChannelPlayService.stop(type, channel, stream);
} catch (Exception e) {
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
}
}
@Override @Override
public void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback){ public void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback){
// 拉流代理通道 // 拉流代理通道
@ -138,6 +171,16 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
} }
} }
@Override
public void stopPlayProxy(CommonGBChannel channel) {
// 拉流代理通道
try {
streamProxyPlayService.stop(channel.getDataDeviceId());
}catch (Exception e) {
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
}
}
@Override @Override
public void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback){ public void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback){
// 推流 // 推流
@ -151,6 +194,16 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
} }
} }
@Override
public void stopPlayPush(CommonGBChannel channel) {
// 推流
try {
streamPushPlayService.stop(channel.getDataDeviceId());
}catch (Exception e) {
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
}
}
private void playbackGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback){ private void playbackGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback){
try { try {
deviceChannelPlayService.playBack(channel, startTime, stopTime, callback); deviceChannelPlayService.playBack(channel, startTime, stopTime, callback);
@ -161,6 +214,20 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
} }
} }
@Override
public void pauseRtp(String streamId) {
try {
deviceChannelPlayService.pauseRtp(streamId);
} catch (ServiceException | InvalidArgumentException | ParseException | SipException ignore) {}
}
@Override
public void resumeRtp(String streamId) {
try {
deviceChannelPlayService.resumeRtp(streamId);
} catch (ServiceException | InvalidArgumentException | ParseException | SipException ignore) {}
}
private void downloadGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, private void downloadGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed,
ErrorCallback<StreamInfo> callback){ ErrorCallback<StreamInfo> callback){
try { try {
@ -171,4 +238,6 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
callback.run(Response.BUSY_HERE, "busy here", null); callback.run(Response.BUSY_HERE, "busy here", null);
} }
} }
} }

View File

@ -9,8 +9,10 @@ import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.gb28181.dao.RegionMapper; import com.genersoft.iot.vmp.gb28181.dao.RegionMapper;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService; import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService; import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.streamPush.bean.StreamPush; import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@ -23,7 +25,11 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.util.*; import javax.sip.message.Response;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Slf4j @Slf4j
@Service @Service
@ -47,6 +53,9 @@ public class GbChannelServiceImpl implements IGbChannelService {
@Autowired @Autowired
private GroupMapper groupMapper; private GroupMapper groupMapper;
@Autowired
private IDeviceChannelService deviceChannelService;
@Override @Override
public CommonGBChannel queryByDeviceId(String gbDeviceId) { public CommonGBChannel queryByDeviceId(String gbDeviceId) {
return commonGBChannelMapper.queryByDeviceId(gbDeviceId); return commonGBChannelMapper.queryByDeviceId(gbDeviceId);
@ -722,4 +731,23 @@ public class GbChannelServiceImpl implements IGbChannelService {
List<CommonGBChannel> all = commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType); List<CommonGBChannel> all = commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType);
return new PageInfo<>(all); return new PageInfo<>(all);
} }
@Override
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
if (channel.getDataType() == ChannelDataType.GB28181.value) {
deviceChannelService.queryRecordInfo(channel, startTime, endTime, callback);
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
// 拉流代理
log.warn("[下载通用通道录像] 不支持下载拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
// 推流
log.warn("[下载通用通道录像] 不支持下载推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else {
// 通道数据异常
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}
} }

View File

@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -28,7 +27,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class InviteStreamServiceImpl implements IInviteStreamService { public class InviteStreamServiceImpl implements IInviteStreamService {
private final Map<String, List<ErrorCallback<StreamInfo>>> inviteErrorCallbackMap = new ConcurrentHashMap<>(); private final Map<String, List<ErrorCallback<StreamInfo>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();

View File

@ -1,14 +1,22 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.Preset; import com.genersoft.iot.vmp.gb28181.bean.Preset;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IPTZService; import com.genersoft.iot.vmp.gb28181.service.IPTZService;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
@ -24,6 +32,18 @@ public class PTZServiceImpl implements IPTZService {
@Autowired @Autowired
private SIPCommander cmder; private SIPCommander cmder;
@Autowired
private UserSetting userSetting;
@Autowired
private IRedisRpcPlayService redisRpcPlayService;
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private IDeviceService deviceService;
@Override @Override
public void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) { public void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) {
@ -37,6 +57,17 @@ public class PTZServiceImpl implements IPTZService {
@Override @Override
public void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2) { public void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2) {
// 判断设备是否属于当前平台, 如果不属于则发起自动调用
if (!userSetting.getServerId().equals(device.getServerId())) {
// 通道ID
DeviceChannel deviceChannel = deviceChannelService.getOneForSource(device.getDeviceId(), channelId);
Assert.notNull(deviceChannel, "通道不存在");
String msg = redisRpcPlayService.frontEndCommand(device.getServerId(), deviceChannel.getId(), cmdCode, parameter1, parameter2, combindCode2);
if (msg != null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), msg);
}
return;
}
try { try {
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2); cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
@ -45,6 +76,21 @@ public class PTZServiceImpl implements IPTZService {
} }
} }
@Override
public void frontEndCommand(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2) {
if (channel.getDataType() != ChannelDataType.GB28181.value) {
// 只有国标通道的支持云台控制
log.warn("[INFO 消息] 只有国标通道的支持云台控制, 通道ID {}", channel.getGbId());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持");
}
Device device = deviceService.getDevice(channel.getDataDeviceId());
if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备ID");
}
DeviceChannel deviceChannel = deviceChannelService.getOneById(channel.getGbId());
frontEndCommand(device, deviceChannel.getDeviceId(), cmdCode, parameter1, parameter2, combindCode2);
}
@Override @Override
public List<Preset> queryPresetList(String deviceId, String channelDeviceId) { public List<Preset> queryPresetList(String deviceId, String channelDeviceId) {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.common.enums.ChannelDataType;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.dao.*; import com.genersoft.iot.vmp.gb28181.dao.*;
@ -26,7 +25,6 @@ import java.util.*;
*/ */
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class PlatformChannelServiceImpl implements IPlatformChannelService { public class PlatformChannelServiceImpl implements IPlatformChannelService {
@Autowired @Autowired
@ -598,4 +596,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
public CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId) { public CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId) {
return platformChannelMapper.queryShareChannel(platformId, channelId); return platformChannelMapper.queryShareChannel(platformId, channelId);
} }
@Override
public List<CommonGBChannel> queryChannelByPlatformIdAndChannelIds(Integer platformId, List<Integer> channelIds) {
return platformChannelMapper.queryShare(platformId, channelIds);
}
} }

View File

@ -1,9 +1,9 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.media.event.mediaServer.MediaSendRtpStoppedEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.ISendRtpServerService; import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.service.bean.*;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
@ -35,6 +36,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -47,13 +49,13 @@ import java.text.ParseException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.Vector; import java.util.Vector;
import java.util.concurrent.TimeUnit;
/** /**
* @author lin * @author lin
*/ */
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class PlatformServiceImpl implements IPlatformService { public class PlatformServiceImpl implements IPlatformService {
private final static String REGISTER_KEY_PREFIX = "platform_register_"; private final static String REGISTER_KEY_PREFIX = "platform_register_";
@ -67,6 +69,7 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired @Autowired
private SSRCFactory ssrcFactory; private SSRCFactory ssrcFactory;
@ -85,6 +88,12 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired @Autowired
private UserSetting userSetting; private UserSetting userSetting;
@Autowired
private IRedisRpcService redisRpcService;
@Autowired
private SipConfig sipConfig;
@Autowired @Autowired
private SipInviteSessionManager sessionManager; private SipInviteSessionManager sessionManager;
@ -100,6 +109,85 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired @Autowired
private ISendRtpServerService sendRtpServerService; private ISendRtpServerService sendRtpServerService;
// 定时监听国标级联所进行的WVP服务是否正常 如果异常则选择新的wvp执行
@Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
public void execute(){
if (!userSetting.isAutoRegisterPlatform()) {
return;
}
// 查找非平台的国标级联执行服务Id
List<String> serverIds = platformMapper.queryServerIdsWithEnableAndNotInServer(userSetting.getServerId());
if (serverIds == null || serverIds.isEmpty()) {
return;
}
serverIds.forEach(serverId -> {
// 检查每个是否存活
ServerInfo serverInfo = redisCatchStorage.queryServerInfo(serverId);
if (serverInfo != null) {
return;
}
log.info("[集群] 检测到 {} 已离线", serverId);
String chooseServerId = redisCatchStorage.chooseOneServer(serverId);
if (!userSetting.getServerId().equals(chooseServerId)){
return;
}
// 此平台需要选择新平台处理 确定由当前平台即开始处理
List<Platform> platformList = platformMapper.queryByServerId(serverId);
platformList.forEach(platform -> {
log.info("[集群] 由本平台开启上级平台{}({})的注册", platform.getName(), platform.getServerGBId());
// 设置平台使用当前平台的IP
platform.setAddress(getIpWithSameNetwork(platform.getAddress()));
platform.setServerId(userSetting.getServerId());
platformMapper.update(platform);
// 更新redis
redisCatchStorage.delPlatformCatchInfo(platform.getServerGBId());
PlatformCatch platformCatch = new PlatformCatch();
platformCatch.setPlatform(platform);
platformCatch.setId(platform.getServerGBId());
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
// 开始注册
// 注册成功时由程序直接调用了online方法
try {
commanderForPlatform.register(platform, eventResult -> {
log.info("[国标级联] {}{},添加向上级注册失败,请确定上级平台可用时重新保存", platform.getName(), platform.getServerGBId());
}, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
}
});
});
}
/**
* 获取同网段的IP
*/
private String getIpWithSameNetwork(String ip){
if (ip == null || sipConfig.getMonitorIps().size() == 1) {
return sipConfig.getMonitorIps().get(0);
}
String[] ipSplit = ip.split("\\.");
String ip1 = null, ip2 = null, ip3 = null;
for (String monitorIp : sipConfig.getMonitorIps()) {
String[] monitorIpSplit = monitorIp.split("\\.");
if (monitorIpSplit[0].equals(ipSplit[0]) && monitorIpSplit[1].equals(ipSplit[1]) && monitorIpSplit[2].equals(ipSplit[2])) {
ip3 = monitorIp;
}else if (monitorIpSplit[0].equals(ipSplit[0]) && monitorIpSplit[1].equals(ipSplit[1])) {
ip2 = monitorIp;
}else if (monitorIpSplit[0].equals(ipSplit[0])) {
ip1 = monitorIp;
}
}
if (ip3 != null) {
return ip3;
}else if (ip2 != null) {
return ip2;
}else if (ip1 != null) {
return ip1;
}else {
return sipConfig.getMonitorIps().get(0);
}
}
/** /**
* 流离开的处理 * 流离开的处理
*/ */
@ -175,6 +263,7 @@ public class PlatformServiceImpl implements IPlatformService {
// 每次发送目录的数量默认为1 // 每次发送目录的数量默认为1
platform.setCatalogGroup(1); platform.setCatalogGroup(1);
} }
platform.setServerId(userSetting.getServerId());
int result = platformMapper.add(platform); int result = platformMapper.add(platform);
// 添加缓存 // 添加缓存
PlatformCatch platformCatch = new PlatformCatch(); PlatformCatch platformCatch = new PlatformCatch();
@ -201,6 +290,11 @@ public class PlatformServiceImpl implements IPlatformService {
log.info("[国标级联] 更新平台 {}({})", platform.getName(), platform.getDeviceGBId()); log.info("[国标级联] 更新平台 {}({})", platform.getName(), platform.getDeviceGBId());
platform.setCharacterSet(platform.getCharacterSet().toUpperCase()); platform.setCharacterSet(platform.getCharacterSet().toUpperCase());
Platform platformInDb = platformMapper.query(platform.getId()); Platform platformInDb = platformMapper.query(platform.getId());
Assert.notNull(platformInDb, "平台不存在");
if (!userSetting.getServerId().equals(platformInDb.getServerId())) {
return redisRpcService.updatePlatform(platformInDb.getServerId(), platform);
}
PlatformCatch platformCatchOld = redisCatchStorage.queryPlatformCatchInfo(platformInDb.getServerGBId()); PlatformCatch platformCatchOld = redisCatchStorage.queryPlatformCatchInfo(platformInDb.getServerGBId());
platform.setUpdateTime(DateUtil.getNow()); platform.setUpdateTime(DateUtil.getNow());
@ -782,8 +876,8 @@ public class PlatformServiceImpl implements IPlatformService {
} }
@Override @Override
public List<Platform> queryEnablePlatformList() { public List<Platform> queryEnablePlatformList(String serverId) {
return platformMapper.queryEnablePlatformList(); return platformMapper.queryEnableParentPlatformList(serverId,true);
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.gb28181.service.impl; package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
@ -32,6 +31,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.IReceiveRtpServerService; import com.genersoft.iot.vmp.service.IReceiveRtpServerService;
import com.genersoft.iot.vmp.service.ISendRtpServerService; import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.service.bean.*;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.CloudRecordUtils; import com.genersoft.iot.vmp.utils.CloudRecordUtils;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
@ -64,8 +64,7 @@ import java.util.Vector;
@SuppressWarnings(value = {"rawtypes", "unchecked"}) @SuppressWarnings(value = {"rawtypes", "unchecked"})
@Slf4j @Slf4j
@Service @Service("playService")
@DS("master")
public class PlayServiceImpl implements IPlayService { public class PlayServiceImpl implements IPlayService {
@Autowired @Autowired
@ -125,6 +124,9 @@ public class PlayServiceImpl implements IPlayService {
@Autowired @Autowired
private ICloudRecordService cloudRecordService; private ICloudRecordService cloudRecordService;
@Autowired
private IRedisRpcPlayService redisRpcPlayService;
/** /**
* 流到来的处理 * 流到来的处理
*/ */
@ -287,6 +289,21 @@ public class PlayServiceImpl implements IPlayService {
} }
} }
@Override
public void play(Device device, DeviceChannel channel, ErrorCallback<StreamInfo> callback) {
// 判断设备是否属于当前平台, 如果不属于则发起自动调用
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.play(device.getServerId(), channel.getId(), callback);
return;
}
MediaServer mediaServerItem = getNewMediaServerItem(device);
if (mediaServerItem == null) {
log.warn("[点播] 未找到可用的zlm deviceId: {},channelId:{}", device.getDeviceId(), channel.getDeviceId());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
}
play(mediaServerItem, device, channel, null, userSetting.getRecordSip(), callback);
}
@Override @Override
public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback) { public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback) {
@ -736,6 +753,11 @@ public class PlayServiceImpl implements IPlayService {
if (channel == null) { if (channel == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "通道不存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "通道不存在");
} }
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.playback(device.getServerId(), channel.getId(), startTime, endTime, callback);
return;
}
MediaServer newMediaServerItem = getNewMediaServerItem(device); MediaServer newMediaServerItem = getNewMediaServerItem(device);
if (newMediaServerItem == null) { if (newMediaServerItem == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的节点"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的节点");
@ -946,6 +968,11 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public void download(Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) { public void download(Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.download(device.getServerId(), channel.getId(), startTime, endTime, downloadSpeed, callback);
return;
}
MediaServer newMediaServerItem = this.getNewMediaServerItem(device); MediaServer newMediaServerItem = this.getNewMediaServerItem(device);
if (newMediaServerItem == null) { if (newMediaServerItem == null) {
callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(),
@ -1075,6 +1102,8 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public StreamInfo getDownLoadInfo(Device device, DeviceChannel channel, String stream) { public StreamInfo getDownLoadInfo(Device device, DeviceChannel channel, String stream) {
InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channel.getId(), stream); InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channel.getId(), stream);
if (inviteInfo == null) { if (inviteInfo == null) {
String app = "rtp"; String app = "rtp";
@ -1216,10 +1245,19 @@ public class PlayServiceImpl implements IPlayService {
} }
@Override @Override
public AudioBroadcastResult audioBroadcast(Device device, DeviceChannel deviceChannel, Boolean broadcastMode) { public AudioBroadcastResult audioBroadcast(String deviceId, String channelDeviceId, Boolean broadcastMode) {
// TODO 必须多端口模式才支持语音喊话鹤语音对讲
if (device == null || deviceChannel == null) { Device device = deviceService.getDeviceByDeviceId(deviceId);
return null; if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到设备: " + deviceId);
}
DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channelDeviceId);
if (deviceChannel == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到通道: " + channelDeviceId);
}
if (!userSetting.getServerId().equals(device.getServerId())) {
return redisRpcPlayService.audioBroadcast(device.getServerId(), deviceId, channelDeviceId, broadcastMode);
} }
log.info("[语音喊话] device {}, channel: {}", device.getDeviceId(), deviceChannel.getDeviceId()); log.info("[语音喊话] device {}, channel: {}", device.getDeviceId(), deviceChannel.getDeviceId());
MediaServer mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); MediaServer mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
@ -1351,11 +1389,20 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
log.warn("streamId不存在!"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "streamId不存在");
throw new ServiceException("streamId不存在");
} }
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备不存在");
}
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.pauseRtp(device.getServerId(), streamId);
return;
}
inviteInfo.getStreamInfo().setPause(true); inviteInfo.getStreamInfo().setPause(true);
inviteStreamService.updateInviteInfo(inviteInfo); inviteStreamService.updateInviteInfo(inviteInfo);
MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer(); MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer();
@ -1373,7 +1420,7 @@ public class PlayServiceImpl implements IPlayService {
if (!result) { if (!result) {
throw new ServiceException("暂停RTP接收失败"); throw new ServiceException("暂停RTP接收失败");
} }
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId()); DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId());
cmder.playPauseCmd(device, channel, inviteInfo.getStreamInfo()); cmder.playPauseCmd(device, channel, inviteInfo.getStreamInfo());
} }
@ -1382,9 +1429,17 @@ public class PlayServiceImpl implements IPlayService {
public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
log.warn("streamId不存在!"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "streamId不存在");
throw new ServiceException("streamId不存在");
} }
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备不存在");
}
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.resumeRtp(device.getServerId(), streamId);
return;
}
inviteInfo.getStreamInfo().setPause(false); inviteInfo.getStreamInfo().setPause(false);
inviteStreamService.updateInviteInfo(inviteInfo); inviteStreamService.updateInviteInfo(inviteInfo);
MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer(); MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer();
@ -1392,7 +1447,6 @@ public class PlayServiceImpl implements IPlayService {
log.warn("mediaServer 不存在!"); log.warn("mediaServer 不存在!");
throw new ServiceException("mediaServer不存在"); throw new ServiceException("mediaServer不存在");
} }
// zlm 暂停RTP超时检查
// 使用zlm中的流ID // 使用zlm中的流ID
String streamKey = inviteInfo.getStream(); String streamKey = inviteInfo.getStream();
if (!mediaServerItem.isRtpEnable()) { if (!mediaServerItem.isRtpEnable()) {
@ -1402,7 +1456,6 @@ public class PlayServiceImpl implements IPlayService {
if (!result) { if (!result) {
throw new ServiceException("继续RTP接收失败"); throw new ServiceException("继续RTP接收失败");
} }
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId()); DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId());
cmder.playResumeCmd(device, channel, inviteInfo.getStreamInfo()); cmder.playResumeCmd(device, channel, inviteInfo.getStreamInfo());
} }
@ -1598,30 +1651,34 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public void stop(InviteSessionType type, Device device, DeviceChannel channel, String stream) { public void stop(InviteSessionType type, Device device, DeviceChannel channel, String stream) {
InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, channel.getId(), stream); if (!userSetting.getServerId().equals(device.getServerId())) {
if (inviteInfo == null) { redisRpcPlayService.stop(device.getServerId(), type, channel.getId(), stream);
if (type == InviteSessionType.PLAY) { }else {
InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, channel.getId(), stream);
if (inviteInfo == null) {
if (type == InviteSessionType.PLAY) {
deviceChannelService.stopPlay(channel.getId());
}
return;
}
inviteStreamService.removeInviteInfo(inviteInfo);
if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
try {
log.info("[停止点播/回放/下载] {}/{}", device.getDeviceId(), channel.getDeviceId());
cmder.streamByeCmd(device, channel.getDeviceId(), "rtp", inviteInfo.getStream(), null, null);
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
if (inviteInfo.getType() == InviteSessionType.PLAY) {
deviceChannelService.stopPlay(channel.getId()); deviceChannelService.stopPlay(channel.getId());
} }
return; if (inviteInfo.getStreamInfo() != null) {
} receiveRtpServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getSsrcInfo());
inviteStreamService.removeInviteInfo(inviteInfo);
if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
try {
log.info("[停止点播/回放/下载] {}/{}", device.getDeviceId(), channel.getDeviceId());
cmder.streamByeCmd(device, channel.getDeviceId(), "rtp", inviteInfo.getStream(), null, null);
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
} }
} }
if (inviteInfo.getType() == InviteSessionType.PLAY) {
deviceChannelService.stopPlay(channel.getId());
}
if (inviteInfo.getStreamInfo() != null) {
receiveRtpServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getSsrcInfo());
}
} }
@Override @Override
@ -1662,13 +1719,19 @@ public class PlayServiceImpl implements IPlayService {
log.warn("[点播] 未找到通道{}的设备信息", channel); log.warn("[点播] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error"); throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
} }
MediaServer mediaServer = getNewMediaServerItem(device); DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
if (mediaServer == null) { play(device, deviceChannel, callback);
log.warn("[点播] 未找到可用媒体节点"); }
@Override
public void stop(InviteSessionType inviteSessionType, CommonGBChannel channel, String stream) {
Device device = deviceService.getDevice(channel.getDataDeviceId());
if (device == null) {
log.warn("[停止播放] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error"); throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
} }
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
play(mediaServer, device, deviceChannel, null, record, callback); stop(inviteSessionType, device, deviceChannel, stream);
} }
@Override @Override

View File

@ -1,92 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEventListener;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author lin
*/
@Component
public class RecordDataCatch {
public static Map<String, RecordInfo> data = new ConcurrentHashMap<>();
@Autowired
private DeferredResultHolder deferredResultHolder;
@Autowired
private RecordEndEventListener recordEndEventListener;
public int put(String deviceId,String channelId, String sn, int sumNum, List<RecordItem> recordItems) {
String key = deviceId + sn;
RecordInfo recordInfo = data.get(key);
if (recordInfo == null) {
recordInfo = new RecordInfo();
recordInfo.setDeviceId(deviceId);
recordInfo.setChannelId(channelId);
recordInfo.setSn(sn.trim());
recordInfo.setSumNum(sumNum);
recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>()));
recordInfo.setLastTime(Instant.now());
recordInfo.getRecordList().addAll(recordItems);
data.put(key, recordInfo);
}else {
// 同一个设备的通道同步请求只考虑一个其他的直接忽略
if (!Objects.equals(sn.trim(), recordInfo.getSn())) {
return 0;
}
recordInfo.getRecordList().addAll(recordItems);
recordInfo.setLastTime(Instant.now());
}
return recordInfo.getRecordList().size();
}
@Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
private void timerTask(){
Set<String> keys = data.keySet();
// 获取五秒前的时刻
Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5));
for (String key : keys) {
RecordInfo recordInfo = data.get(key);
// 超过五秒收不到消息任务超时 只更新这一部分数据
if ( recordInfo.getLastTime().isBefore(instantBefore5S)) {
// 处理录像数据 返回给前端
String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn();
// 对数据进行排序
Collections.sort(recordInfo.getRecordList());
RequestMessage msg = new RequestMessage();
msg.setKey(msgKey);
msg.setData(recordInfo);
deferredResultHolder.invokeAllResult(msg);
recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId());
data.remove(key);
}
}
}
public boolean isComplete(String deviceId, String sn) {
RecordInfo recordInfo = data.get(deviceId + sn);
return recordInfo != null && recordInfo.getRecordList().size() == recordInfo.getSumNum();
}
public RecordInfo getRecordInfo(String deviceId, String sn) {
return data.get(deviceId + sn);
}
public void remove(String deviceId, String sn) {
data.remove(deviceId + sn);
}
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.task; package com.genersoft.iot.vmp.gb28181.task;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel; import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
@ -60,9 +61,12 @@ public class SipRunner implements CommandLineRunner {
@Autowired @Autowired
private ISendRtpServerService sendRtpServerService; private ISendRtpServerService sendRtpServerService;
@Autowired
private UserSetting userSetting;
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
List<Device> deviceList = deviceService.getAllOnlineDevice(); List<Device> deviceList = deviceService.getAllOnlineDevice(userSetting.getServerId());
for (Device device : deviceList) { for (Device device : deviceList) {
if (deviceService.expire(device)){ if (deviceService.expire(device)){
@ -86,7 +90,8 @@ public class SipRunner implements CommandLineRunner {
deviceMapInDb.put(device.getDeviceId(), device); deviceMapInDb.put(device.getDeviceId(), device);
}); });
devicesInRedis.parallelStream().forEach(device -> { devicesInRedis.parallelStream().forEach(device -> {
if (deviceMapInDb.get(device.getDeviceId()) == null) { if (deviceMapInDb.get(device.getDeviceId()) == null
&& userSetting.getServerId().equals(device.getServerId())) {
redisCatchStorage.removeDevice(device.getDeviceId()); redisCatchStorage.removeDevice(device.getDeviceId());
} }
}); });

View File

@ -94,7 +94,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
SipSubscribe.EventResult<ResponseEvent> eventResult = new SipSubscribe.EventResult<>(responseEvent); SipSubscribe.EventResult<ResponseEvent> eventResult = new SipSubscribe.EventResult<>(responseEvent);
sipEvent.getOkEvent().response(eventResult); sipEvent.getOkEvent().response(eventResult);
} }
sipSubscribe.removeSubscribe(callIdHeader.getCallId()); sipSubscribe.removeSubscribe(callIdHeader.getCallId() + cSeqHeader.getSeqNumber());
} }
} }
} }
@ -118,7 +118,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
SipSubscribe.EventResult<ResponseEvent> eventResult = new SipSubscribe.EventResult<>(responseEvent); SipSubscribe.EventResult<ResponseEvent> eventResult = new SipSubscribe.EventResult<>(responseEvent);
sipEvent.getErrorEvent().response(eventResult); sipEvent.getErrorEvent().response(eventResult);
} }
sipSubscribe.removeSubscribe(callIdHeader.getCallId()); sipSubscribe.removeSubscribe(callIdHeader.getCallId() + cSeqHeader.getSeqNumber());
} }
} }
} }

View File

@ -75,12 +75,12 @@ public class SIPSender {
CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME); CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME);
String key = callIdHeader.getCallId() + cSeqHeader.getSeqNumber(); String key = callIdHeader.getCallId() + cSeqHeader.getSeqNumber();
SipEvent sipEvent = SipEvent.getInstance(key, eventResult -> { SipEvent sipEvent = SipEvent.getInstance(key, eventResult -> {
sipSubscribe.removeSubscribe(callIdHeader.getCallId()); sipSubscribe.removeSubscribe(key);
if(okEvent != null) { if(okEvent != null) {
okEvent.response(eventResult); okEvent.response(eventResult);
} }
}, (eventResult -> { }, (eventResult -> {
sipSubscribe.removeSubscribe(callIdHeader.getCallId()); sipSubscribe.removeSubscribe(key);
if (errorEvent != null) { if (errorEvent != null) {
errorEvent.response(eventResult); errorEvent.response(eventResult);
} }

View File

@ -19,40 +19,17 @@ import java.util.concurrent.ConcurrentHashMap;
@Component @Component
public class DeferredResultHolder { public class DeferredResultHolder {
public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY"; public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK"; public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK";
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD"; public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY";
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL"; public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL";
public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION"; public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION";
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP"; public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP";
private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>(); private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();

View File

@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
@ -142,7 +143,7 @@ public interface ISIPCommander {
* @param channelId 预览通道 * @param channelId 预览通道
* @param recordCmdStr 录像命令Record / StopRecord * @param recordCmdStr 录像命令Record / StopRecord
*/ */
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; void recordCmd(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 远程启动控制命令 * 远程启动控制命令
@ -156,7 +157,7 @@ public interface ISIPCommander {
* *
* @param device 视频设备 * @param device 视频设备
*/ */
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; void guardCmd(Device device, String guardCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 报警复位命令 * 报警复位命令
@ -165,7 +166,7 @@ public interface ISIPCommander {
* @param alarmMethod 报警方式可选 * @param alarmMethod 报警方式可选
* @param alarmType 报警类型可选 * @param alarmType 报警类型可选
*/ */
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; void alarmResetCmd(Device device, String alarmMethod, String alarmType, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@ -179,7 +180,7 @@ public interface ISIPCommander {
* 看守位控制命令 * 看守位控制命令
* *
*/ */
void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 设备配置命令 * 设备配置命令
@ -190,30 +191,24 @@ public interface ISIPCommander {
/** /**
* 设备配置命令basicParam * 设备配置命令basicParam
*
* @param device 视频设备
* @param channelId 通道编码可选
* @param name 设备/通道名称可选
* @param expiration 注册过期时间可选
* @param heartBeatInterval 心跳间隔时间可选
* @param heartBeatCount 心跳超时次数可选
*/ */
void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; void deviceBasicConfigCmd(Device device, BasicParam basicParam, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备状态 * 查询设备状态
* *
* @param device 视频设备 * @param device 视频设备
*/ */
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; void deviceStatusQuery(Device device, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备信息 * 查询设备信息
* *
* @param device 视频设备 * @param device 视频设备
* @param callback
* @return * @return
*/ */
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException; void deviceInfoQuery(Device device, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询目录列表 * 查询目录列表
@ -245,7 +240,7 @@ public interface ISIPCommander {
* @return true = 命令发送成功 * @return true = 命令发送成功
*/ */
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备配置 * 查询设备配置
@ -254,14 +249,14 @@ public interface ISIPCommander {
* @param channelId 通道编码可选 * @param channelId 通道编码可选
* @param configType 配置类型 * @param configType 配置类型
*/ */
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备预置位置 * 查询设备预置位置
* *
* @param device 视频设备 * @param device 视频设备
*/ */
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询移动设备位置数据 * 查询移动设备位置数据
@ -304,7 +299,7 @@ public interface ISIPCommander {
* @param channelId 通道id * @param channelId 通道id
* @param cmdString 前端控制指令串 * @param cmdString 前端控制指令串
*/ */
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException; void dragZoomCmd(Device device, String channelId, String cmdString, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
void playbackControlCmd(Device device, DeviceChannel channel, String stream, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException; void playbackControlCmd(Device device, DeviceChannel channel, String stream, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;

View File

@ -7,7 +7,9 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.MessageSubscribe;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.event.sip.MessageEvent;
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager; import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
@ -19,8 +21,10 @@ import com.genersoft.iot.vmp.media.event.hook.Hook;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.event.hook.HookType;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.message.SIPResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -71,6 +75,9 @@ public class SIPCommander implements ISIPCommander {
@Autowired @Autowired
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;
@Autowired
private MessageSubscribe messageSubscribe;
/** /**
@ -671,13 +678,16 @@ public class SIPCommander implements ISIPCommander {
* @param recordCmdStr 录像命令Record / StopRecord * @param recordCmdStr 录像命令Record / StopRecord
*/ */
@Override @Override
public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { public void recordCmd(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
final String cmdType = "DeviceControl";
final int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n"); cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else { } else {
@ -686,10 +696,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n"); cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
cmdXml.append("</Control>\r\n"); cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
},null);
} }
/** /**
@ -723,22 +737,29 @@ public class SIPCommander implements ISIPCommander {
* @param guardCmdStr "SetGuard"/"ResetGuard" * @param guardCmdStr "SetGuard"/"ResetGuard"
*/ */
@Override @Override
public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { public void guardCmd(Device device, String guardCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceControl";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n"); cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
cmdXml.append("</Control>\r\n"); cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -747,14 +768,17 @@ public class SIPCommander implements ISIPCommander {
* @param device 视频设备 * @param device 视频设备
*/ */
@Override @Override
public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { public void alarmResetCmd(Device device, String alarmMethod, String alarmType, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceControl";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n"); cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n"); cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
@ -771,10 +795,14 @@ public class SIPCommander implements ISIPCommander {
} }
cmdXml.append("</Control>\r\n"); cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -816,19 +844,21 @@ public class SIPCommander implements ISIPCommander {
* @param presetIndex 调用预置位编号开启看守位时使用取值范围0~255 * @param presetIndex 调用预置位编号开启看守位时使用取值范围0~255
*/ */
@Override @Override
public void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { public void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceControl";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n"); cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); channelId = device.getDeviceId();
} else {
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
} }
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
cmdXml.append("<HomePosition>\r\n"); cmdXml.append("<HomePosition>\r\n");
if (enabled) { if (enabled) {
cmdXml.append("<Enabled>1</Enabled>\r\n"); cmdXml.append("<Enabled>1</Enabled>\r\n");
@ -840,10 +870,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("</HomePosition>\r\n"); cmdXml.append("</HomePosition>\r\n");
cmdXml.append("</Control>\r\n"); cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -858,55 +892,50 @@ public class SIPCommander implements ISIPCommander {
/** /**
* 设备配置命令basicParam * 设备配置命令basicParam
*
* @param device 视频设备
* @param channelId 通道编码可选
* @param name 设备/通道名称可选
* @param expiration 注册过期时间可选
* @param heartBeatInterval 心跳间隔时间可选
* @param heartBeatCount 心跳超时次数可选
*/ */
@Override @Override
public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, public void deviceBasicConfigCmd(Device device, BasicParam basicParam, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
int sn = (int) ((Math.random() * 9 + 1) * 100000);
String cmdType = "DeviceConfig";
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n"); cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
String channelId = basicParam.getChannelId();
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); channelId = device.getDeviceId();
} else {
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
} }
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
cmdXml.append("<BasicParam>\r\n"); cmdXml.append("<BasicParam>\r\n");
if (!ObjectUtils.isEmpty(name)) { if (!ObjectUtils.isEmpty(basicParam.getName())) {
cmdXml.append("<Name>" + name + "</Name>\r\n"); cmdXml.append("<Name>" + basicParam.getName() + "</Name>\r\n");
} }
if (NumericUtil.isInteger(expiration)) { if (NumericUtil.isInteger(basicParam.getExpiration())) {
if (Integer.valueOf(expiration) > 0) { if (Integer.parseInt(basicParam.getExpiration()) > 0) {
cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n"); cmdXml.append("<Expiration>" + basicParam.getExpiration() + "</Expiration>\r\n");
} }
} }
if (NumericUtil.isInteger(heartBeatInterval)) { if (basicParam.getHeartBeatInterval() != null && basicParam.getHeartBeatInterval() > 0) {
if (Integer.valueOf(heartBeatInterval) > 0) { cmdXml.append("<HeartBeatInterval>" + basicParam.getHeartBeatInterval() + "</HeartBeatInterval>\r\n");
cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
}
} }
if (NumericUtil.isInteger(heartBeatCount)) { if (basicParam.getHeartBeatCount() != null && basicParam.getHeartBeatCount() > 0) {
if (Integer.valueOf(heartBeatCount) > 0) { cmdXml.append("<HeartBeatCount>" + basicParam.getHeartBeatCount() + "</HeartBeatCount>\r\n");
cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
}
} }
cmdXml.append("</BasicParam>\r\n"); cmdXml.append("</BasicParam>\r\n");
cmdXml.append("</Control>\r\n"); cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -915,46 +944,63 @@ public class SIPCommander implements ISIPCommander {
* @param device 视频设备 * @param device 视频设备
*/ */
@Override @Override
public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { public void deviceStatusQuery(Device device, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceStatus";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
String charset = device.getCharset(); String charset = device.getCharset();
StringBuffer catalogXml = new StringBuffer(200); StringBuffer catalogXml = new StringBuffer(200);
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
catalogXml.append("<Query>\r\n"); catalogXml.append("<Query>\r\n");
catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); catalogXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<SN>" + sn + "</SN>\r\n");
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
catalogXml.append("</Query>\r\n"); catalogXml.append("</Query>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
* 查询设备信息 * 查询设备信息
* *
* @param device 视频设备 * @param device 视频设备
* @param callback
*/ */
@Override @Override
public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException { public void deviceInfoQuery(Device device, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceInfo";
String sn = (int) ((Math.random() * 9 + 1) * 100000) + "";
StringBuffer catalogXml = new StringBuffer(200); StringBuffer catalogXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
catalogXml.append("<Query>\r\n"); catalogXml.append("<Query>\r\n");
catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); catalogXml.append("<CmdType>" + cmdType +"</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<SN>" + sn + "</SN>\r\n");
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
catalogXml.append("</Query>\r\n"); catalogXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn, device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
}
});
} }
@ -1040,14 +1086,17 @@ public class SIPCommander implements ISIPCommander {
*/ */
@Override @Override
public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { String startTime, String endTime, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "Alarm";
String sn = (int) ((Math.random() * 9 + 1) * 100000) + "";
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n"); cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
if (!ObjectUtils.isEmpty(startPriority)) { if (!ObjectUtils.isEmpty(startPriority)) {
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
@ -1069,10 +1118,14 @@ public class SIPCommander implements ISIPCommander {
} }
cmdXml.append("</Query>\r\n"); cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn, device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -1083,14 +1136,16 @@ public class SIPCommander implements ISIPCommander {
* @param configType 配置类型 * @param configType 配置类型
*/ */
@Override @Override
public void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { public void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "ConfigDownload";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n"); cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else { } else {
@ -1099,10 +1154,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n"); cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
cmdXml.append("</Query>\r\n"); cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -1111,14 +1170,17 @@ public class SIPCommander implements ISIPCommander {
* @param device 视频设备 * @param device 视频设备
*/ */
@Override @Override
public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { public void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "PresetQuery";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n"); cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n"); cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else { } else {
@ -1126,9 +1188,14 @@ public class SIPCommander implements ISIPCommander {
} }
cmdXml.append("</Query>\r\n"); cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
} }
/** /**
@ -1267,14 +1334,17 @@ public class SIPCommander implements ISIPCommander {
} }
@Override @Override
public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException { public void dragZoomCmd(Device device, String channelId, String cmdString, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
String cmdType = "DeviceControl";
int sn = (int) ((Math.random() * 9 + 1) * 100000);
StringBuffer dragXml = new StringBuffer(200); StringBuffer dragXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
dragXml.append("<Control>\r\n"); dragXml.append("<Control>\r\n");
dragXml.append("<CmdType>DeviceControl</CmdType>\r\n"); dragXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); dragXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) { if (ObjectUtils.isEmpty(channelId)) {
dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else { } else {
@ -1283,8 +1353,10 @@ public class SIPCommander implements ISIPCommander {
dragXml.append(cmdString); dragXml.append(cmdString);
dragXml.append("</Control>\r\n"); dragXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
log.debug("拉框信令: " + request.toString());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request);
} }

View File

@ -121,7 +121,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
SIPRequest request = (SIPRequest)evt.getRequest(); SIPRequest request = (SIPRequest)evt.getRequest();
try { try {
InviteInfo inviteInfo = decode(evt); InviteMessageInfo inviteInfo = decode(evt);
// 查询请求是否来自上级平台\设备 // 查询请求是否来自上级平台\设备
Platform platform = platformService.queryPlatformByServerGBId(inviteInfo.getRequesterId()); Platform platform = platformService.queryPlatformByServerGBId(inviteInfo.getRequesterId());
@ -247,9 +247,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} }
} }
private InviteInfo decode(RequestEvent evt) throws SdpException { private InviteMessageInfo decode(RequestEvent evt) throws SdpException {
InviteInfo inviteInfo = new InviteInfo(); InviteMessageInfo inviteInfo = new InviteMessageInfo();
SIPRequest request = (SIPRequest)evt.getRequest(); SIPRequest request = (SIPRequest)evt.getRequest();
String[] channelIdArrayFromSub = SipUtils.getChannelIdFromRequest(request); String[] channelIdArrayFromSub = SipUtils.getChannelIdFromRequest(request);
@ -349,7 +349,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} }
private String createSendSdp(SendRtpInfo sendRtpItem, InviteInfo inviteInfo, String sdpIp) { private String createSendSdp(SendRtpInfo sendRtpItem, InviteMessageInfo inviteInfo, String sdpIp) {
StringBuilder content = new StringBuilder(200); StringBuilder content = new StringBuilder(200);
content.append("v=0\r\n"); content.append("v=0\r\n");
content.append("o=" + inviteInfo.getTargetChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n"); content.append("o=" + inviteInfo.getTargetChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n");
@ -393,7 +393,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} }
} }
public void inviteFromDeviceHandle(SIPRequest request, InviteInfo inviteInfo) { public void inviteFromDeviceHandle(SIPRequest request, InviteMessageInfo inviteInfo) {
if (inviteInfo.getSourceChannelId() == null) { if (inviteInfo.getSourceChannelId() == null) {
log.warn("来自设备的Invite请求无法从请求信息中确定请求来自的通道已忽略requesterId {}", inviteInfo.getRequesterId()); log.warn("来自设备的Invite请求无法从请求信息中确定请求来自的通道已忽略requesterId {}", inviteInfo.getRequesterId());

View File

@ -183,7 +183,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
device.setGeoCoordSys("WGS84"); device.setGeoCoordSys("WGS84");
} }
} }
device.setServerId(userSetting.getServerId());
device.setIp(remoteAddressInfo.getIp()); device.setIp(remoteAddressInfo.getIp());
device.setPort(remoteAddressInfo.getPort()); device.setPort(remoteAddressInfo.getPort());
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));

View File

@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.ControlMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.ControlMessageHandler;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element; import org.dom4j.Element;
@ -316,7 +317,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
private void handleDragZoom(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) { private void handleDragZoom(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) {
if (channel.getDataType() != ChannelDataType.GB28181.value) { if (channel.getDataType() != ChannelDataType.GB28181.value) {
// 只支持国标的云台控制 // 只支持国标的云台控制
log.warn("[INFO 消息] 只支持国标的拉框控制, 通道ID {}", channel.getGbId()); log.warn("[deviceControl-DragZoom] 只支持国标的拉框控制, 通道ID {}", channel.getGbId());
try { try {
responseAck(request, Response.FORBIDDEN, ""); responseAck(request, Response.FORBIDDEN, "");
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
@ -328,7 +329,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
Device device = deviceService.getDevice(channel.getDataDeviceId()); Device device = deviceService.getDevice(channel.getDataDeviceId());
if (device == null) { if (device == null) {
// 不存在则回复404 // 不存在则回复404
log.warn("[INFO 消息] 通道所属设备不存在, 通道ID {}", channel.getGbId()); log.warn("[deviceControl-DragZoom] 通道所属设备不存在, 通道ID {}", channel.getGbId());
try { try {
responseAck(request, Response.NOT_FOUND, "device not found"); responseAck(request, Response.NOT_FOUND, "device not found");
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
@ -339,7 +340,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
if (deviceChannel == null) { if (deviceChannel == null) {
log.warn("[deviceControl] 未找到设备原始通道, 设备: {}{}),通道编号:{}", device.getName(), log.warn("[deviceControl-DragZoom] 未找到设备原始通道, 设备: {}{}),通道编号:{}", device.getName(),
device.getDeviceId(), channel.getGbId()); device.getDeviceId(), channel.getGbId());
try { try {
responseAck(request, Response.NOT_FOUND, "channel not found"); responseAck(request, Response.NOT_FOUND, "channel not found");
@ -352,7 +353,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
deviceChannel.getName(), deviceChannel.getDeviceId()); deviceChannel.getName(), deviceChannel.getDeviceId());
try { try {
DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class); DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class);
DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn(); DragZoomParam dragZoom = dragZoomRequest.getDragZoomIn();
if (dragZoom == null) { if (dragZoom == null) {
dragZoom = dragZoomRequest.getDragZoomOut(); dragZoom = dragZoomRequest.getDragZoomOut();
} }
@ -365,7 +366,9 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n"); cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n");
cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n"); cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n");
cmdXml.append("</" + type.getVal() + ">\r\n"); cmdXml.append("</" + type.getVal() + ">\r\n");
cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString()); cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString(), (code, msg, data) -> {
});
responseAck(request, Response.OK); responseAck(request, Response.OK);
} catch (Exception e) { } catch (Exception e) {
log.error("[命令发送失败] 拉框控制: {}", e.getMessage()); log.error("[命令发送失败] 拉框控制: {}", e.getMessage());
@ -417,9 +420,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class); HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class);
//获取整个消息主体我们只需要修改请求头即可 //获取整个消息主体我们只需要修改请求头即可
HomePositionRequest.HomePosition info = homePosition.getHomePosition(); HomePositionRequest.HomePosition info = homePosition.getHomePosition();
cmder.homePositionCmd(device, deviceChannel.getDeviceId(), !"0".equals(info.getEnabled()), Integer.parseInt(info.getResetTime()), Integer.parseInt(info.getPresetIndex()), cmder.homePositionCmd(device, deviceChannel.getDeviceId(), !"0".equals(info.getEnabled()), Integer.parseInt(info.getResetTime()), Integer.parseInt(info.getPresetIndex()), (code, msg, data) -> {
errorResult -> onError(request, errorResult), if (code == ErrorCode.SUCCESS.getCode()) {
okResult -> onOk(request, okResult)); onOk(request);
}else {
onError(request, code, msg);
}
});
} catch (Exception e) { } catch (Exception e) {
log.error("[命令发送失败] 看守位设置: {}", e.getMessage()); log.error("[命令发送失败] 看守位设置: {}", e.getMessage());
} }
@ -463,9 +470,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
} }
} }
try { try {
cmder.alarmCmd(device, alarmMethod, alarmType, cmder.alarmResetCmd(device, alarmMethod, alarmType, (code, msg, data) -> {
errorResult -> onError(request, errorResult), if (code == ErrorCode.SUCCESS.getCode()) {
okResult -> onOk(request, okResult)); onOk(request);
}else {
onError(request, code, msg);
}
});
} catch (InvalidArgumentException | SipException | ParseException e) { } catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 告警消息: {}", e.getMessage()); log.error("[命令发送失败] 告警消息: {}", e.getMessage());
} }
@ -515,9 +526,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
//获取整个消息主体我们只需要修改请求头即可 //获取整个消息主体我们只需要修改请求头即可
String cmdString = getText(rootElement, type.getVal()); String cmdString = getText(rootElement, type.getVal());
try { try {
cmder.recordCmd(device, deviceChannel.getDeviceId(), cmdString, cmder.recordCmd(device, deviceChannel.getDeviceId(), cmdString, (code, msg, data) -> {
errorResult -> onError(request, errorResult), if (code == ErrorCode.SUCCESS.getCode()) {
okResult -> onOk(request, okResult)); onOk(request);
}else {
onError(request, code, msg);
}
});
} catch (InvalidArgumentException | SipException | ParseException e) { } catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 录像控制: {}", e.getMessage()); log.error("[命令发送失败] 录像控制: {}", e.getMessage());
} }
@ -552,40 +567,47 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
//获取整个消息主体我们只需要修改请求头即可 //获取整个消息主体我们只需要修改请求头即可
String cmdString = getText(rootElement, type.getVal()); String cmdString = getText(rootElement, type.getVal());
try { try {
cmder.guardCmd(device, cmdString, cmder.guardCmd(device, cmdString,(code, msg, data) -> {
errorResult -> onError(request, errorResult), if (code == ErrorCode.SUCCESS.getCode()) {
okResult -> onOk(request, okResult)); onOk(request);
}else {
onError(request, code, msg);
}
});
} catch (InvalidArgumentException | SipException | ParseException e) { } catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage()); log.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage());
} }
} }
/** /**
* 错误响应处理 * 错误响应处理
* *
* @param request 请求
* @param eventResult 响应结构
*/ */
private void onError(SIPRequest request, SipSubscribe.EventResult eventResult) { private void onError(SIPRequest request, Integer code, String msg) {
// 失败的回复 // 失败的回复
try { try {
responseAck(request, eventResult.statusCode, eventResult.msg); responseAck(request, code, msg);
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 回复: {}", e.getMessage()); log.error("[命令发送失败] 回复: {}", e.getMessage());
} }
} }
private void onError(SIPRequest request, SipSubscribe.EventResult errorResult) {
onError(request, errorResult.statusCode, errorResult.msg);
}
/** /**
* 成功响应处理 * 成功响应处理
* *
* @param request 请求 * @param request 请求
* @param eventResult 响应结构
*/ */
private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) { private void onOk(SIPRequest request) {
// 成功的回复 // 成功的回复
try { try {
responseAck(request, eventResult.statusCode); responseAck(request, Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 回复: {}", e.getMessage()); log.error("[命令发送失败] 回复: {}", e.getMessage());
} }

View File

@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEventListener; import com.genersoft.iot.vmp.gb28181.event.record.RecordInfoEventListener;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService; import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService; import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
@ -53,7 +53,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
private SIPCommander commander; private SIPCommander commander;
@Autowired @Autowired
private RecordEndEventListener recordEndEventListener; private RecordInfoEventListener recordInfoEventListener;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
@ -127,7 +127,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
// 获取通道的原始信息 // 获取通道的原始信息
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
// 接收录像数据 // 接收录像数据
recordEndEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{ recordInfoEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{
try { try {
log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId); log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId);
cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo); cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo);

View File

@ -1,11 +1,20 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.event.MessageSubscribe;
import com.genersoft.iot.vmp.gb28181.event.sip.MessageEvent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.RequestEvent;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
/** /**
* 命令类型 请求动作的应答 * 命令类型 请求动作的应答
* 命令类型 设备控制, 报警通知, 设备目录信息查询, 目录信息查询, 目录收到, 设备信息查询, 设备状态信息查询 ...... * 命令类型 设备控制, 报警通知, 设备目录信息查询, 目录信息查询, 目录收到, 设备信息查询, 设备状态信息查询 ......
@ -18,8 +27,32 @@ public class ResponseMessageHandler extends MessageHandlerAbstract implements In
@Autowired @Autowired
private MessageRequestProcessor messageRequestProcessor; private MessageRequestProcessor messageRequestProcessor;
@Autowired
private MessageSubscribe messageSubscribe;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
messageRequestProcessor.addHandler(messageType, this); messageRequestProcessor.addHandler(messageType, this);
} }
@Override
public void handForDevice(RequestEvent evt, Device device, Element element) {
super.handForDevice(evt, device, element);
handMessageEvent(element, null);
}
public void handMessageEvent(Element element, Object data) {
String cmd = getText(element, "CmdType");
String sn = getText(element, "SN");
MessageEvent<Object> subscribe = (MessageEvent<Object>)messageSubscribe.getSubscribe(cmd + sn);
if (subscribe != null) {
String result = getText(element, "Result");
if (result == null || "OK".equalsIgnoreCase(result) || data != null) {
subscribe.getCallback().run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data);
}else {
subscribe.getCallback().run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), result);
}
messageSubscribe.removeSubscribe(cmd + sn);
}
}
} }

View File

@ -4,18 +4,22 @@ import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element; import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@Slf4j @Slf4j
@Component @Component
@ -36,18 +40,18 @@ public class AlarmResponseMessageHandler extends SIPRequestProcessorParent imple
@Override @Override
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
Element deviceIdElement = rootElement.element("DeviceID"); // 回复200 OK
String channelId = deviceIdElement.getText().toString(); try {
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + device.getDeviceId() + channelId; responseAck((SIPRequest) evt.getRequest(), Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
}
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
XmlUtil.node2Json(rootElement, json); XmlUtil.node2Json(rootElement, json);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(json.toJSONString()); log.debug(json.toJSONString());
} }
RequestMessage msg = new RequestMessage(); responseMessageHandler.handMessageEvent(rootElement, null);
msg.setKey(key);
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
} }
@Override @Override

View File

@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; 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.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
@ -23,8 +22,6 @@ import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@Slf4j @Slf4j
@Component @Component
public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@ -48,13 +45,6 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
@Override @Override
public void handForDevice(RequestEvent evt, Device device, Element element) { public void handForDevice(RequestEvent evt, Device device, Element element) {
String channelId = getText(element, "DeviceID");
String key;
if (device.getDeviceId().equals(channelId)) {
key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId();
}else {
key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
}
try { try {
// 回复200 OK // 回复200 OK
responseAck((SIPRequest) evt.getRequest(), Response.OK); responseAck((SIPRequest) evt.getRequest(), Response.OK);
@ -67,23 +57,33 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(json.toJSONString()); log.debug(json.toJSONString());
} }
JSONObject jsonObject = new JSONObject();
if (json.get("BasicParam") != null) {
jsonObject.put("BasicParam", json.getJSONObject("BasicParam"));
}
if (json.get("VideoParamOpt") != null) {
jsonObject.put("VideoParamOpt", json.getJSONObject("VideoParamOpt"));
}
if (json.get("SVACEncodeConfig") != null) {
jsonObject.put("SVACEncodeConfig", json.getJSONObject("SVACEncodeConfig"));
}
if (json.get("SVACDecodeConfig") != null) {
jsonObject.put("SVACDecodeConfig", json.getJSONObject("SVACDecodeConfig"));
}
responseMessageHandler.handMessageEvent(element, jsonObject);
JSONObject basicParam = json.getJSONObject("BasicParam"); JSONObject basicParam = json.getJSONObject("BasicParam");
Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval"); if (basicParam != null) {
Integer heartBeatCount = basicParam.getInteger("HeartBeatCount"); Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval");
Integer positionCapability = basicParam.getInteger("PositionCapability"); Integer heartBeatCount = basicParam.getInteger("HeartBeatCount");
device.setHeartBeatInterval(heartBeatInterval); Integer positionCapability = basicParam.getInteger("PositionCapability");
device.setHeartBeatCount(heartBeatCount); device.setHeartBeatInterval(heartBeatInterval);
device.setPositionCapability(positionCapability); device.setHeartBeatCount(heartBeatCount);
device.setPositionCapability(positionCapability);
deviceService.updateDeviceHeartInfo(device);
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
deviceService.updateDeviceHeartInfo(device);
}
} }

View File

@ -1,57 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
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.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
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.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sip.RequestEvent;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@Slf4j
@Component
public class DeviceConfigResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
private final String cmdType = "DeviceConfig";
@Autowired
private ResponseMessageHandler responseMessageHandler;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Override
public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this);
}
@Override
public void handForDevice(RequestEvent evt, Device device, Element element) {
JSONObject json = new JSONObject();
XmlUtil.node2Json(element, json);
String channelId = getText(element, "DeviceID");
if (log.isDebugEnabled()) {
log.debug(json.toJSONString());
}
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + device.getDeviceId() + channelId;
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
}
@Override
public void handForPlatform(RequestEvent evt, Platform parentPlatform, Element rootElement) {
}
}

View File

@ -1,75 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
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.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
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.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@Slf4j
@Component
public class DeviceControlResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
private final String cmdType = "DeviceControl";
@Autowired
private ResponseMessageHandler responseMessageHandler;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Override
public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this);
}
@Override
public void handForDevice(RequestEvent evt, Device device, Element element) {
// 此处是对本平台发出DeviceControl指令的应答
try {
responseAck((SIPRequest) evt.getRequest(), Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 设备控制: {}", e.getMessage());
}
JSONObject json = new JSONObject();
String channelId = getText(element, "DeviceID");
String result = getText(element, "Result");
RequestMessage msg = new RequestMessage();
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + device.getDeviceId() + channelId;
msg.setKey(key);
if ("OK".equalsIgnoreCase(result)) {
msg.setData(WVPResult.success());
}else {
msg.setData(WVPResult.fail(ErrorCode.ERROR100));
}
if (log.isDebugEnabled()) {
log.debug(json.toJSONString());
}
deferredResultHolder.invokeAllResult(msg);
}
@Override
public void handForPlatform(RequestEvent evt, Platform parentPlatform, Element rootElement) {
}
}

View File

@ -2,12 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
@ -37,9 +35,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
@Autowired @Autowired
private ResponseMessageHandler responseMessageHandler; private ResponseMessageHandler responseMessageHandler;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@ -70,9 +65,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
} }
return; return;
} }
Element deviceIdElement = rootElement.element("DeviceID");
String channelId = deviceIdElement.getTextTrim();
String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + device.getDeviceId() + channelId;
device.setName(getText(rootElement, "DeviceName")); device.setName(getText(rootElement, "DeviceName"));
device.setManufacturer(getText(rootElement, "Manufacturer")); device.setManufacturer(getText(rootElement, "Manufacturer"));
@ -82,11 +74,8 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
device.setStreamMode("TCP-PASSIVE"); device.setStreamMode("TCP-PASSIVE");
} }
deviceService.updateDevice(device); deviceService.updateDevice(device);
responseMessageHandler.handMessageEvent(rootElement, device);
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setData(device);
deferredResultHolder.invokeAllResult(msg);
} catch (DocumentException e) { } catch (DocumentException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -3,14 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element; import org.dom4j.Element;
@ -33,15 +30,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
@Autowired @Autowired
private ResponseMessageHandler responseMessageHandler; private ResponseMessageHandler responseMessageHandler;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this); responseMessageHandler.addHandler(cmdType, this);
@ -60,9 +51,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage()); log.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage());
} }
Element deviceIdElement = element.element("DeviceID");
Element onlineElement = element.element("Online"); Element onlineElement = element.element("Online");
String channelId = deviceIdElement.getText();
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
XmlUtil.node2Json(element, json); XmlUtil.node2Json(element, json);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -74,10 +63,8 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
}else { }else {
deviceService.offline(device.getDeviceId(), "设备状态查询结果:" + text.trim()); deviceService.offline(device.getDeviceId(), "设备状态查询结果:" + text.trim());
} }
RequestMessage msg = new RequestMessage(); responseMessageHandler.handMessageEvent(element, text);
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId());
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
} }
@Override @Override

View File

@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.Preset; import com.genersoft.iot.vmp.gb28181.bean.Preset;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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; 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.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
@ -25,8 +24,6 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
/** /**
* 设备预置位查询应答 * 设备预置位查询应答
*/ */
@ -68,8 +65,6 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
Element presetListNumElement = rootElement.element("PresetList"); Element presetListNumElement = rootElement.element("PresetList");
Element snElement = rootElement.element("SN"); Element snElement = rootElement.element("SN");
//该字段可能为通道或则设备的id //该字段可能为通道或则设备的id
String deviceId = getText(rootElement, "DeviceID");
String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
if (snElement == null || presetListNumElement == null) { if (snElement == null || presetListNumElement == null) {
try { try {
responseAck(request, Response.BAD_REQUEST, "xml error"); responseAck(request, Response.BAD_REQUEST, "xml error");
@ -98,10 +93,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
presetQuerySipReqList.add(presetQuerySipReq); presetQuerySipReqList.add(presetQuerySipReq);
} }
} }
RequestMessage requestMessage = new RequestMessage(); responseMessageHandler.handMessageEvent(rootElement, presetQuerySipReqList);
requestMessage.setKey(key);
requestMessage.setData(presetQuerySipReqList);
deferredResultHolder.invokeAllResult(requestMessage);
try { try {
responseAck(request, Response.OK); responseAck(request, Response.OK);
} catch (InvalidArgumentException | ParseException | SipException e) { } catch (InvalidArgumentException | ParseException | SipException e) {

View File

@ -6,6 +6,8 @@ import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.bean.RecordItem; import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.record.RecordInfoEndEvent;
import com.genersoft.iot.vmp.gb28181.event.record.RecordInfoEvent;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -19,6 +21,7 @@ import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -48,14 +51,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
private ResponseMessageHandler responseMessageHandler; private ResponseMessageHandler responseMessageHandler;
@Autowired @Autowired
private DeferredResultHolder deferredResultHolder; private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private EventPublisher eventPublisher;
@Qualifier("taskExecutor")
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired @Autowired
private RedisTemplate<Object, Object> redisTemplate; private RedisTemplate<Object, Object> redisTemplate;
@ -75,88 +71,89 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
}catch (SipException | InvalidArgumentException | ParseException e) { }catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage()); log.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage());
} }
taskExecutor.execute(()->{ try {
try { String sn = getText(rootElement, "SN");
String sn = getText(rootElement, "SN"); String channelId = getText(rootElement, "DeviceID");
String channelId = getText(rootElement, "DeviceID"); RecordInfo recordInfo = new RecordInfo();
RecordInfo recordInfo = new RecordInfo(); recordInfo.setChannelId(channelId);
recordInfo.setChannelId(channelId); recordInfo.setDeviceId(device.getDeviceId());
recordInfo.setDeviceId(device.getDeviceId()); recordInfo.setSn(sn);
recordInfo.setSn(sn); recordInfo.setName(getText(rootElement, "Name"));
recordInfo.setName(getText(rootElement, "Name")); String sumNumStr = getText(rootElement, "SumNum");
String sumNumStr = getText(rootElement, "SumNum"); int sumNum = 0;
int sumNum = 0; if (!ObjectUtils.isEmpty(sumNumStr)) {
if (!ObjectUtils.isEmpty(sumNumStr)) { sumNum = Integer.parseInt(sumNumStr);
sumNum = Integer.parseInt(sumNumStr);
}
recordInfo.setSumNum(sumNum);
Element recordListElement = rootElement.element("RecordList");
if (recordListElement == null || sumNum == 0) {
log.info("无录像数据");
recordInfo.setCount(sumNum);
eventPublisher.recordEndEventPush(recordInfo);
releaseRequest(device.getDeviceId(), sn,recordInfo);
} else {
Iterator<Element> recordListIterator = recordListElement.elementIterator();
if (recordListIterator != null) {
List<RecordItem> recordList = new ArrayList<>();
// 遍历DeviceList
while (recordListIterator.hasNext()) {
Element itemRecord = recordListIterator.next();
Element recordElement = itemRecord.element("DeviceID");
if (recordElement == null) {
log.info("记录为空,下一个...");
continue;
}
RecordItem record = new RecordItem();
record.setDeviceId(getText(itemRecord, "DeviceID"));
record.setName(getText(itemRecord, "Name"));
record.setFilePath(getText(itemRecord, "FilePath"));
record.setFileSize(getText(itemRecord, "FileSize"));
record.setAddress(getText(itemRecord, "Address"));
String startTimeStr = getText(itemRecord, "StartTime");
record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
String endTimeStr = getText(itemRecord, "EndTime");
record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
: Integer.parseInt(getText(itemRecord, "Secrecy")));
record.setType(getText(itemRecord, "Type"));
record.setRecorderId(getText(itemRecord, "RecorderID"));
recordList.add(record);
}
Map<String, String> map = recordList.stream()
.filter(record -> record.getDeviceId() != null)
.collect(Collectors.toMap(record -> record.getStartTime()+ record.getEndTime(), UJson::writeJson));
// 获取任务结果数据
String resKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_PRE + channelId + sn;
redisTemplate.opsForHash().putAll(resKey, map);
redisTemplate.expire(resKey, recordInfoTtl, TimeUnit.SECONDS);
String resCountKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_COUNT_PRE + channelId + sn;
long incr = redisTemplate.opsForValue().increment(resCountKey, map.size());
redisTemplate.expire(resCountKey, recordInfoTtl, TimeUnit.SECONDS);
recordInfo.setRecordList(recordList);
recordInfo.setCount(Math.toIntExact(incr));
eventPublisher.recordEndEventPush(recordInfo);
if (incr < sumNum) {
return;
}
// 已接收完成
List<RecordItem> resList = redisTemplate.opsForHash().entries(resKey).values().stream().map(e -> UJson.readJson(e.toString(), RecordItem.class)).collect(Collectors.toList());
if (resList.size() < sumNum) {
return;
}
recordInfo.setRecordList(resList);
releaseRequest(device.getDeviceId(), sn,recordInfo);
}
}
} catch (Exception e) {
log.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest());
log.error("[国标录像] 异常内容: ", e);
} }
}); recordInfo.setSumNum(sumNum);
Element recordListElement = rootElement.element("RecordList");
if (recordListElement == null || sumNum == 0) {
log.info("无录像数据");
recordInfo.setCount(sumNum);
recordInfoEventPush(recordInfo);
recordInfoEndEventPush(recordInfo);
} else {
Iterator<Element> recordListIterator = recordListElement.elementIterator();
if (recordListIterator != null) {
List<RecordItem> recordList = new ArrayList<>();
// 遍历DeviceList
while (recordListIterator.hasNext()) {
Element itemRecord = recordListIterator.next();
Element recordElement = itemRecord.element("DeviceID");
if (recordElement == null) {
log.info("记录为空,下一个...");
continue;
}
RecordItem record = new RecordItem();
record.setDeviceId(getText(itemRecord, "DeviceID"));
record.setName(getText(itemRecord, "Name"));
record.setFilePath(getText(itemRecord, "FilePath"));
record.setFileSize(getText(itemRecord, "FileSize"));
record.setAddress(getText(itemRecord, "Address"));
String startTimeStr = getText(itemRecord, "StartTime");
record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
String endTimeStr = getText(itemRecord, "EndTime");
record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
: Integer.parseInt(getText(itemRecord, "Secrecy")));
record.setType(getText(itemRecord, "Type"));
record.setRecorderId(getText(itemRecord, "RecorderID"));
recordList.add(record);
}
Map<String, String> map = recordList.stream()
.filter(record -> record.getDeviceId() != null)
.collect(Collectors.toMap(record -> record.getStartTime()+ record.getEndTime(), UJson::writeJson));
// 获取任务结果数据
String resKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_PRE + channelId + sn;
redisTemplate.opsForHash().putAll(resKey, map);
redisTemplate.expire(resKey, recordInfoTtl, TimeUnit.SECONDS);
String resCountKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_COUNT_PRE + channelId + sn;
Long incr = redisTemplate.opsForValue().increment(resCountKey, map.size());
if (incr == null) {
incr = 0L;
}
redisTemplate.expire(resCountKey, recordInfoTtl, TimeUnit.SECONDS);
recordInfo.setRecordList(recordList);
recordInfo.setCount(Math.toIntExact(incr));
recordInfoEventPush(recordInfo);
if (incr < sumNum) {
return;
}
// 已接收完成
List<RecordItem> resList = redisTemplate.opsForHash().entries(resKey).values().stream().map(e -> UJson.readJson(e.toString(), RecordItem.class)).collect(Collectors.toList());
if (resList.size() < sumNum) {
return;
}
recordInfo.setRecordList(resList);
recordInfoEndEventPush(recordInfo);
}
}
} catch (Exception e) {
log.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest());
log.error("[国标录像] 异常内容: ", e);
}
} }
@Override @Override
@ -164,18 +161,31 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
} }
public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){ private void recordInfoEventPush(RecordInfo recordInfo) {
String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; if (recordInfo == null) {
// 对数据进行排序 return;
if(recordInfo!=null && recordInfo.getRecordList()!=null) { }
if(recordInfo.getRecordList() != null) {
Collections.sort(recordInfo.getRecordList()); Collections.sort(recordInfo.getRecordList());
}else{ }else{
recordInfo.setRecordList(new ArrayList<>()); recordInfo.setRecordList(new ArrayList<>());
} }
RecordInfoEvent outEvent = new RecordInfoEvent(this);
outEvent.setRecordInfo(recordInfo);
applicationEventPublisher.publishEvent(outEvent);
}
RequestMessage msg = new RequestMessage(); private void recordInfoEndEventPush(RecordInfo recordInfo) {
msg.setKey(key); if (recordInfo == null) {
msg.setData(recordInfo); return;
deferredResultHolder.invokeAllResult(msg); }
if(recordInfo.getRecordList() != null) {
Collections.sort(recordInfo.getRecordList());
}else{
recordInfo.setRecordList(new ArrayList<>());
}
RecordInfoEndEvent outEvent = new RecordInfoEndEvent(this);
outEvent.setRecordInfo(recordInfo);
applicationEventPublisher.publishEvent(outEvent);
} }
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.jt1078.util; package com.genersoft.iot.vmp.jt1078.util;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver;
@ -12,6 +13,12 @@ import java.util.List;
@Slf4j @Slf4j
public class ClassUtil { public class ClassUtil {
public static ConfigurableApplicationContext context;
public static <T> T getBean(String beanName, Class<T> clazz) {
return context.getBean(beanName, clazz);
}
public static Object getBean(Class<?> clazz) { public static Object getBean(Class<?> clazz) {
if (clazz != null) { if (clazz != null) {
try { try {

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.media; package com.genersoft.iot.vmp.media;
import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent; import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
@ -30,6 +31,9 @@ public class MediaServerConfig implements CommandLineRunner {
@Autowired @Autowired
private MediaConfig mediaConfig; private MediaConfig mediaConfig;
@Autowired
private UserSetting userSetting;
@Override @Override
public void run(String... strings) throws Exception { public void run(String... strings) throws Exception {
@ -37,6 +41,7 @@ public class MediaServerConfig implements CommandLineRunner {
mediaServerService.clearMediaServerForOnline(); mediaServerService.clearMediaServerForOnline();
MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer(); MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer();
MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem(); MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem();
mediaSerItemInConfig.setServerId(userSetting.getServerId());
if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) { if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) {
mediaServerService.update(mediaSerItemInConfig); mediaServerService.update(mediaSerItemInConfig);
}else { }else {

View File

@ -103,6 +103,9 @@ public class MediaServer {
@Schema(description = "转码的前缀") @Schema(description = "转码的前缀")
private String transcodeSuffix; private String transcodeSuffix;
@Schema(description = "服务Id")
private String serverId;
public MediaServer() { public MediaServer() {
} }
@ -388,4 +391,12 @@ public class MediaServer {
public void setTranscodeSuffix(String transcodeSuffix) { public void setTranscodeSuffix(String transcodeSuffix) {
this.transcodeSuffix = transcodeSuffix; this.transcodeSuffix = transcodeSuffix;
} }
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
} }

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.media.service.impl; package com.genersoft.iot.vmp.media.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
@ -50,7 +49,6 @@ import java.util.*;
*/ */
@Slf4j @Slf4j
@Service @Service
@DS("master")
public class MediaServerServiceImpl implements IMediaServerService { public class MediaServerServiceImpl implements IMediaServerService {
@Autowired @Autowired
@ -305,7 +303,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
mediaServerMapper.update(mediaSerItem); mediaServerMapper.update(mediaSerItem);
MediaServer mediaServerInRedis = getOne(mediaSerItem.getId()); MediaServer mediaServerInRedis = getOne(mediaSerItem.getId());
// 获取完整数据 // 获取完整数据
MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId(), userSetting.getServerId());
if (mediaServerInDataBase == null) { if (mediaServerInDataBase == null) {
return; return;
} }
@ -352,7 +350,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public List<MediaServer> getAll() { public List<MediaServer> getAll() {
List<MediaServer> mediaServerList = mediaServerMapper.queryAll(); List<MediaServer> mediaServerList = mediaServerMapper.queryAll(userSetting.getServerId());
if (mediaServerList.isEmpty()) { if (mediaServerList.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
@ -368,7 +366,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public List<MediaServer> getAllFromDatabase() { public List<MediaServer> getAllFromDatabase() {
return mediaServerMapper.queryAll(); return mediaServerMapper.queryAll(userSetting.getServerId());
} }
@Override @Override
@ -405,7 +403,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public MediaServer getDefaultMediaServer() { public MediaServer getDefaultMediaServer() {
return mediaServerMapper.queryDefault(); return mediaServerMapper.queryDefault(userSetting.getServerId());
} }
@Override @Override
@ -425,7 +423,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
log.info("[添加媒体节点] 失败, mediaServer的类型为空"); log.info("[添加媒体节点] 失败, mediaServer的类型为空");
return; return;
} }
if (mediaServerMapper.queryOne(mediaServer.getId()) != null) { if (mediaServerMapper.queryOne(mediaServer.getId(), userSetting.getServerId()) != null) {
log.info("[添加媒体节点] 失败, 媒体服务ID已存在请修改媒体服务器配置, {}", mediaServer.getId()); log.info("[添加媒体节点] 失败, 媒体服务ID已存在请修改媒体服务器配置, {}", mediaServer.getId());
throw new ControllerException(ErrorCode.ERROR100.getCode(),"保存失败媒体服务ID [ " + mediaServer.getId() + " ] 已存在,请修改媒体服务器配置"); throw new ControllerException(ErrorCode.ERROR100.getCode(),"保存失败媒体服务ID [ " + mediaServer.getId() + " ] 已存在,请修改媒体服务器配置");
} }
@ -523,7 +521,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public MediaServer checkMediaServer(String ip, int port, String secret, String type) { public MediaServer checkMediaServer(String ip, int port, String secret, String type) {
if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) { if (mediaServerMapper.queryOneByHostAndPort(ip, port, userSetting.getServerId()) != null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "此连接已存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "此连接已存在");
} }
@ -534,7 +532,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
} }
MediaServer mediaServer = mediaNodeServerService.checkMediaServer(ip, port, secret); MediaServer mediaServer = mediaNodeServerService.checkMediaServer(ip, port, secret);
if (mediaServer != null) { if (mediaServer != null) {
if (mediaServerMapper.queryOne(mediaServer.getId()) != null) { if (mediaServerMapper.queryOne(mediaServer.getId(), userSetting.getServerId()) != null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "媒体服务ID [" + mediaServer.getId() + " ] 已存在,请修改媒体服务器配置"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "媒体服务ID [" + mediaServer.getId() + " ] 已存在,请修改媒体服务器配置");
} }
} }
@ -562,7 +560,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public void delete(MediaServer mediaServer) { public void delete(MediaServer mediaServer) {
mediaServerMapper.delOne(mediaServer.getId()); mediaServerMapper.delOne(mediaServer.getId(), userSetting.getServerId());
redisTemplate.opsForZSet().remove(VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(), mediaServer.getId()); redisTemplate.opsForZSet().remove(VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(), mediaServer.getId());
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServer.getId(); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServer.getId();
redisTemplate.delete(key); redisTemplate.delete(key);
@ -574,13 +572,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public MediaServer getOneFromDatabase(String mediaServerId) { public MediaServer getOneFromDatabase(String mediaServerId) {
return mediaServerMapper.queryOne(mediaServerId); return mediaServerMapper.queryOne(mediaServerId, userSetting.getServerId());
} }
@Override @Override
public void syncCatchFromDatabase() { public void syncCatchFromDatabase() {
List<MediaServer> allInCatch = getAllOnlineList(); List<MediaServer> allInCatch = getAllOnlineList();
List<MediaServer> allInDatabase = mediaServerMapper.queryAll(); List<MediaServer> allInDatabase = mediaServerMapper.queryAll(userSetting.getServerId());
Map<String, MediaServer> mediaServerMap = new HashMap<>(); Map<String, MediaServer> mediaServerMap = new HashMap<>();
for (MediaServer mediaServer : allInDatabase) { for (MediaServer mediaServer : allInDatabase) {
@ -608,7 +606,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public List<MediaServer> getAllWithAssistPort() { public List<MediaServer> getAllWithAssistPort() {
return mediaServerMapper.queryAllWithAssistPort(); return mediaServerMapper.queryAllWithAssistPort(userSetting.getServerId());
} }

View File

@ -89,6 +89,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
@Override @Override
public MediaServer checkMediaServer(String ip, int port, String secret) { public MediaServer checkMediaServer(String ip, int port, String secret) {
MediaServer mediaServer = new MediaServer(); MediaServer mediaServer = new MediaServer();
mediaServer.setServerId(userSetting.getServerId());
mediaServer.setIp(ip); mediaServer.setIp(ip);
mediaServer.setHttpPort(port); mediaServer.setHttpPort(port);
mediaServer.setFlvPort(port); mediaServer.setFlvPort(port);

View File

@ -2,12 +2,14 @@ package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event; import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.utils.MediaServerUtils; import com.genersoft.iot.vmp.utils.MediaServerUtils;
import lombok.Data;
import java.util.Map; import java.util.Map;
/** /**
* 云端录像数据 * 云端录像数据
*/ */
@Data
public class CloudRecordItem { public class CloudRecordItem {
/** /**
* 主键 * 主键
@ -79,6 +81,11 @@ public class CloudRecordItem {
*/ */
private long timeLen; private long timeLen;
/**
* 所属服务ID
*/
private String serverId;
public static CloudRecordItem getInstance(MediaRecordMp4Event param) { public static CloudRecordItem getInstance(MediaRecordMp4Event param) {
CloudRecordItem cloudRecordItem = new CloudRecordItem(); CloudRecordItem cloudRecordItem = new CloudRecordItem();
cloudRecordItem.setApp(param.getApp()); cloudRecordItem.setApp(param.getApp());
@ -98,115 +105,4 @@ public class CloudRecordItem {
return cloudRecordItem; return cloudRecordItem;
} }
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFolder() {
return folder;
}
public void setFolder(String folder) {
this.folder = folder;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public long getTimeLen() {
return timeLen;
}
public void setTimeLen(long timeLen) {
this.timeLen = timeLen;
}
public Boolean getCollect() {
return collect;
}
public void setCollect(Boolean collect) {
this.collect = collect;
}
public Boolean getReserve() {
return reserve;
}
public void setReserve(Boolean reserve) {
this.reserve = reserve;
}
} }

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.service.ICloudRecordService; import com.genersoft.iot.vmp.gb28181.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper; import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
import com.genersoft.iot.vmp.utils.CloudRecordUtils; import com.genersoft.iot.vmp.utils.CloudRecordUtils;
@ -36,7 +37,6 @@ import java.util.Set;
@Slf4j @Slf4j
@Service @Service
@DS("share")
public class CloudRecordServiceImpl implements ICloudRecordService { public class CloudRecordServiceImpl implements ICloudRecordService {
@Autowired @Autowired
@ -51,8 +51,15 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
@Autowired @Autowired
private AssistRESTfulUtils assistRESTfulUtils; private AssistRESTfulUtils assistRESTfulUtils;
@Autowired
private UserSetting userSetting;
@Autowired
private IRedisRpcPlayService redisRpcPlayService;
@Override @Override
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId) { public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime,
String endTime, List<MediaServer> mediaServerItems, String callId) {
// 开始时间和结束时间在数据库中都是以秒为单位的 // 开始时间和结束时间在数据库中都是以秒为单位的
Long startTimeStamp = null; Long startTimeStamp = null;
Long endTimeStamp = null; Long endTimeStamp = null;
@ -109,6 +116,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
@EventListener @EventListener
public void onApplicationEvent(MediaRecordMp4Event event) { public void onApplicationEvent(MediaRecordMp4Event event) {
CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event); CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event);
cloudRecordItem.setServerId(userSetting.getServerId());
if (ObjectUtils.isEmpty(cloudRecordItem.getCallId())) { if (ObjectUtils.isEmpty(cloudRecordItem.getCallId())) {
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream()); StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream());
if (streamAuthorityInfo != null) { if (streamAuthorityInfo != null) {
@ -237,6 +245,9 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
if (recordItem == null) { if (recordItem == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在");
} }
if (!userSetting.getServerId().equals(recordItem.getServerId())) {
return redisRpcPlayService.getRecordPlayUrl(recordItem.getServerId(), recordId);
}
String filePath = recordItem.getFilePath(); String filePath = recordItem.getFilePath();
MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId()); MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath); return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.service.impl; package com.genersoft.iot.vmp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.service.IRoleService; import com.genersoft.iot.vmp.service.IRoleService;
import com.genersoft.iot.vmp.storager.dao.RoleMapper; import com.genersoft.iot.vmp.storager.dao.RoleMapper;
import com.genersoft.iot.vmp.storager.dao.dto.Role; import com.genersoft.iot.vmp.storager.dao.dto.Role;
@ -10,7 +9,6 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service @Service
@DS("master")
public class RoleServerImpl implements IRoleService { public class RoleServerImpl implements IRoleService {
@Autowired @Autowired

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.service.impl; package com.genersoft.iot.vmp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.service.IUserApiKeyService; import com.genersoft.iot.vmp.service.IUserApiKeyService;
import com.genersoft.iot.vmp.storager.dao.UserApiKeyMapper; import com.genersoft.iot.vmp.storager.dao.UserApiKeyMapper;
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey; import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
@ -15,7 +14,6 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service @Service
@DS("master")
public class UserApiKeyServiceImpl implements IUserApiKeyService { public class UserApiKeyServiceImpl implements IUserApiKeyService {
@Autowired @Autowired

View File

@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.service.impl; package com.genersoft.iot.vmp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.service.IUserService; import com.genersoft.iot.vmp.service.IUserService;
import com.genersoft.iot.vmp.storager.dao.UserMapper; import com.genersoft.iot.vmp.storager.dao.UserMapper;
import com.genersoft.iot.vmp.storager.dao.dto.User; import com.genersoft.iot.vmp.storager.dao.dto.User;
@ -13,7 +12,6 @@ import org.springframework.util.DigestUtils;
import java.util.List; import java.util.List;
@Service @Service
@DS("master")
public class UserServiceImpl implements IUserService { public class UserServiceImpl implements IUserService {
@Autowired @Autowired

View File

@ -0,0 +1,39 @@
package com.genersoft.iot.vmp.service.redisMsg;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
public interface IRedisRpcPlayService {
void play(String serverId, Integer channelId, ErrorCallback<StreamInfo> callback);
void stop(String serverId, InviteSessionType type, int channelId, String stream);
void playback(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback<StreamInfo> callback);
void download(String serverId, Integer channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback);
void queryRecordInfo(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback<RecordInfo> callback);
void pauseRtp(String serverId, String streamId);
void resumeRtp(String serverId, String streamId);
String frontEndCommand(String serverId, Integer channelId, int cmdCode, int parameter1, int parameter2, int combindCode2);
void playPush(Integer id, ErrorCallback<StreamInfo> callback);
StreamInfo playProxy(String serverId, int id);
void stopProxy(String serverId, int id);
DownloadFileInfo getRecordPlayUrl(String serverId, Integer recordId);
AudioBroadcastResult audioBroadcast(String serverId, String deviceId, String channelDeviceId, Boolean broadcastMode);
}

View File

@ -2,7 +2,8 @@ package com.genersoft.iot.vmp.service.redisMsg;
import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
public interface IRedisRpcService { public interface IRedisRpcService {
@ -23,4 +24,44 @@ public interface IRedisRpcService {
long onStreamOnlineEvent(String app, String stream, CommonCallback<StreamInfo> callback); long onStreamOnlineEvent(String app, String stream, CommonCallback<StreamInfo> callback);
void unPushStreamOnlineEvent(String app, String stream); void unPushStreamOnlineEvent(String app, String stream);
void subscribeCatalog(int id, int cycle);
void subscribeMobilePosition(int id, int cycle, int interval);
boolean updatePlatform(String serverId, Platform platform);
void catalogEventPublish(String serverId, CatalogEvent catalogEvent);
WVPResult<SyncStatus> devicesSync(String serverId, String deviceId);
SyncStatus getChannelSyncStatus(String serverId, String deviceId);
WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam);
WVPResult<String> deviceConfigQuery(String serverId, Device device, String channelId, String configType);
void teleboot(String serverId, Device device);
WVPResult<String> recordControl(String serverId, Device device, String channelId, String recordCmdStr);
WVPResult<String> guard(String serverId, Device device, String guardCmdStr);
WVPResult<String> resetAlarm(String serverId, Device device, String channelId, String alarmMethod, String alarmType);
void iFrame(String serverId, Device device, String channelId);
WVPResult<String> homePosition(String serverId, Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex);
void dragZoomIn(String serverId, Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy);
void dragZoomOut(String serverId, Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy);
WVPResult<String> deviceStatus(String serverId, Device device);
WVPResult<String> alarm(String serverId, Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
WVPResult<Object> deviceInfo(String serverId, Device device);
WVPResult<Object> queryPreset(String serverId, Device device, String channelId);
} }

View File

@ -105,7 +105,7 @@ public class RedisAlarmMsgListener implements MessageListener {
if (ObjectUtils.isEmpty(gbId)) { if (ObjectUtils.isEmpty(gbId)) {
if (userSetting.getSendToPlatformsWhenIdLost()) { if (userSetting.getSendToPlatformsWhenIdLost()) {
// 发送给所有的上级 // 发送给所有的上级
List<Platform> parentPlatforms = platformService.queryEnablePlatformList(); List<Platform> parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId());
if (!parentPlatforms.isEmpty()) { if (!parentPlatforms.isEmpty()) {
for (Platform parentPlatform : parentPlatforms) { for (Platform parentPlatform : parentPlatforms) {
try { try {

View File

@ -0,0 +1,348 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.InviteMessageInfo;
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.sip.message.Response;
@Component
@Slf4j
@RedisRpcController("channel")
public class RedisRpcChannelPlayController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IGbChannelService channelService;
@Autowired
private IGbChannelPlayService channelPlayService;
@Autowired
private IPTZService iptzService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 点播国标设备
*/
@RedisRpcMapping("play")
public RedisRpcResponse playChannel(RedisRpcRequest request) {
int channelId = Integer.parseInt(request.getParam().toString());
RedisRpcResponse response = request.getResponse();
if (channelId <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
InviteMessageInfo inviteInfo = new InviteMessageInfo();
inviteInfo.setSessionName("Play");
channelPlayService.start(channel, inviteInfo, null, (code, msg, data) ->{
if (code == InviteErrorCode.SUCCESS.getCode()) {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(data);
}else {
response.setStatusCode(code);
}
// 手动发送结果
sendResponse(response);
});
return null;
}
/**
* 点播国标设备
*/
@RedisRpcMapping("queryRecordInfo")
public RedisRpcResponse queryRecordInfo(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int channelId = paramJson.getIntValue("channelId");
String startTime = paramJson.getString("startTime");
String endTime = paramJson.getString("endTime");
RedisRpcResponse response = request.getResponse();
if (channelId <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
channelService.queryRecordInfo(channel, startTime, endTime, (code, msg, data) ->{
if (code == InviteErrorCode.SUCCESS.getCode()) {
response.setStatusCode(code);
response.setBody(data);
}else {
response.setStatusCode(code);
}
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(ErrorCode.ERROR100.getCode());
response.setBody(e.getMessage());
}
return null;
}
/**
* 暂停录像回放
*/
@RedisRpcMapping("pauseRtp")
public RedisRpcResponse pauseRtp(RedisRpcRequest request) {
String streamId = request.getParam().toString();
RedisRpcResponse response = request.getResponse();
if (streamId == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
channelPlayService.pauseRtp(streamId);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
}catch (ControllerException e) {
response.setStatusCode(ErrorCode.ERROR100.getCode());
response.setBody(e.getMessage());
}
return response;
}
/**
* 恢复录像回放
*/
@RedisRpcMapping("resumeRtp")
public RedisRpcResponse resumeRtp(RedisRpcRequest request) {
String streamId = request.getParam().toString();
RedisRpcResponse response = request.getResponse();
if (streamId == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
channelPlayService.resumeRtp(streamId);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
}catch (ControllerException e) {
response.setStatusCode(ErrorCode.ERROR100.getCode());
response.setBody(e.getMessage());
}
return response;
}
/**
* 停止点播国标设备
*/
@RedisRpcMapping("stop")
public RedisRpcResponse stop(RedisRpcRequest request) {
JSONObject jsonObject = JSONObject.parseObject(request.getParam().toString());
RedisRpcResponse response = request.getResponse();
Integer channelId = jsonObject.getIntValue("channelId");
if (channelId == null || channelId <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
String stream = jsonObject.getString("stream");
InviteSessionType type = jsonObject.getObject("inviteSessionType", InviteSessionType.class);
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
channelPlayService.stopPlay(type, channel, stream);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
}catch (Exception e){
response.setStatusCode(Response.SERVER_INTERNAL_ERROR);
response.setBody(e.getMessage());
}
return response;
}
/**
* 录像回放国标设备
*/
@RedisRpcMapping("playback")
public RedisRpcResponse playbackChannel(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int channelId = paramJson.getIntValue("channelId");
String startTime = paramJson.getString("startTime");
String endTime = paramJson.getString("endTime");
RedisRpcResponse response = request.getResponse();
if (channelId <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
InviteMessageInfo inviteInfo = new InviteMessageInfo();
inviteInfo.setSessionName("Playback");
inviteInfo.setStartTime(DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime));
inviteInfo.setStopTime(DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime));
channelPlayService.start(channel, inviteInfo, null, (code, msg, data) ->{
if (code == InviteErrorCode.SUCCESS.getCode()) {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(data);
}else {
response.setStatusCode(code);
}
// 手动发送结果
sendResponse(response);
});
return null;
}
/**
* 录像回放国标设备
*/
@RedisRpcMapping("download")
public RedisRpcResponse downloadChannel(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int channelId = paramJson.getIntValue("channelId");
String startTime = paramJson.getString("startTime");
String endTime = paramJson.getString("endTime");
int downloadSpeed = paramJson.getIntValue("downloadSpeed");
RedisRpcResponse response = request.getResponse();
if (channelId <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
InviteMessageInfo inviteInfo = new InviteMessageInfo();
inviteInfo.setSessionName("Download");
inviteInfo.setStartTime(DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime));
inviteInfo.setStopTime(DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime));
inviteInfo.setDownloadSpeed(downloadSpeed + "");
channelPlayService.start(channel, inviteInfo, null, (code, msg, data) ->{
if (code == InviteErrorCode.SUCCESS.getCode()) {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(data);
}else {
response.setStatusCode(code);
}
// 手动发送结果
sendResponse(response);
});
return null;
}
/**
* 云台控制
*/
@RedisRpcMapping("ptz/frontEndCommand")
public RedisRpcResponse frontEndCommand(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int channelId = paramJson.getIntValue("channelId");
int cmdCode = paramJson.getIntValue("cmdCode");
int parameter1 = paramJson.getIntValue("parameter1");
int parameter2 = paramJson.getIntValue("parameter2");
int combindCode2 = paramJson.getIntValue("combindCode2");
RedisRpcResponse response = request.getResponse();
if (channelId <= 0 || cmdCode < 0 || parameter1 < 0 || parameter2 < 0 || combindCode2 < 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
// 获取对应的设备和通道信息
CommonGBChannel channel = channelService.getOne(channelId);
if (channel == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
iptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, combindCode2);
}catch (ControllerException e) {
response.setStatusCode(ErrorCode.ERROR100.getCode());
response.setBody(e.getMessage());
return response;
}
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
}

View File

@ -0,0 +1,66 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.service.ICloudRecordService;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RedisRpcController("cloudRecord")
public class RedisRpcCloudRecordController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private ICloudRecordService cloudRecordService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 播放
*/
@RedisRpcMapping("play")
public RedisRpcResponse play(RedisRpcRequest request) {
int id = Integer.parseInt(request.getParam().toString());
RedisRpcResponse response = request.getResponse();
if (id <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
DownloadFileInfo downloadFileInfo = cloudRecordService.getPlayUrlPath(id);
if (downloadFileInfo == null) {
response.setStatusCode(ErrorCode.ERROR100.getCode());
response.setBody("get play url error");
return response;
}
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(JSONObject.toJSONString(downloadFileInfo));
return response;
}
}

View File

@ -0,0 +1,498 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.BasicParam;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RedisRpcController("device")
public class RedisRpcDeviceController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IDeviceService deviceService;
@Autowired
private IStreamProxyService streamProxyService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 通道同步
*/
@RedisRpcMapping("devicesSync")
public RedisRpcResponse devicesSync(RedisRpcRequest request) {
String deviceId = request.getParam().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
WVPResult<SyncStatus> result = deviceService.devicesSync(device);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(JSONObject.toJSONString(result));
return response;
}
/**
* 获取通道同步状态
*/
@RedisRpcMapping("getChannelSyncStatus")
public RedisRpcResponse getChannelSyncStatus(RedisRpcRequest request) {
String deviceId = request.getParam().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(JSONObject.toJSONString(channelSyncStatus));
return response;
}
@RedisRpcMapping("deviceBasicConfig")
public RedisRpcResponse deviceBasicConfig(RedisRpcRequest request) {
BasicParam basicParam = JSONObject.parseObject(request.getParam().toString(), BasicParam.class);
Device device = deviceService.getDeviceByDeviceId(basicParam.getDeviceId());
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
deviceService.deviceBasicConfig(device, basicParam, (code, msg, data) -> {
response.setStatusCode(code);
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
return null;
}
@RedisRpcMapping("deviceConfigQuery")
public RedisRpcResponse deviceConfigQuery(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
String configType = paramJson.getString("configType");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
deviceService.deviceConfigQuery(device, channelId, configType, (code, msg, data) -> {
response.setStatusCode(code);
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
return null;
}
@RedisRpcMapping("teleboot")
public RedisRpcResponse teleboot(RedisRpcRequest request) {
String deviceId = request.getParam().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.teleboot(device);
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
return response;
}
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(WVPResult.success());
return response;
}
@RedisRpcMapping("record")
public RedisRpcResponse record(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
String recordCmdStr = paramJson.getString("recordCmdStr");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.record(device, channelId, recordCmdStr, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("guard")
public RedisRpcResponse guard(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String guardCmdStr = paramJson.getString("guardCmdStr");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.guard(device, guardCmdStr, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("resetAlarm")
public RedisRpcResponse resetAlarm(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
String alarmMethod = paramJson.getString("alarmMethod");
String alarmType = paramJson.getString("alarmType");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.resetAlarm(device, channelId, alarmMethod, alarmType, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("iFrame")
public RedisRpcResponse iFrame(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.iFrame(device, channelId);
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("homePosition")
public RedisRpcResponse homePosition(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
Boolean enabled = paramJson.getBoolean("enabled");
Integer resetTime = paramJson.getInteger("resetTime");
Integer presetIndex = paramJson.getInteger("presetIndex");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.homePosition(device, channelId, enabled, resetTime, presetIndex, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("dragZoomIn")
public RedisRpcResponse dragZoomIn(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
Integer length = paramJson.getInteger("length");
Integer width = paramJson.getInteger("width");
Integer midpointx = paramJson.getInteger("midpointx");
Integer midpointy = paramJson.getInteger("midpointy");
Integer lengthx = paramJson.getInteger("lengthx");
Integer lengthy = paramJson.getInteger("lengthy");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.dragZoomIn(device, channelId, length, width, midpointx, midpointy, lengthx, lengthy, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("dragZoomOut")
public RedisRpcResponse dragZoomOut(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
Integer length = paramJson.getInteger("length");
Integer width = paramJson.getInteger("width");
Integer midpointx = paramJson.getInteger("midpointx");
Integer midpointy = paramJson.getInteger("midpointy");
Integer lengthx = paramJson.getInteger("lengthx");
Integer lengthy = paramJson.getInteger("lengthy");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.dragZoomOut(device, channelId, length, width, midpointx, midpointy, lengthx, lengthy, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("alarm")
public RedisRpcResponse alarm(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String startPriority = paramJson.getString("startPriority");
String endPriority = paramJson.getString("endPriority");
String alarmMethod = paramJson.getString("alarmMethod");
String alarmType = paramJson.getString("alarmType");
String startTime = paramJson.getString("startTime");
String endTime = paramJson.getString("endTime");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.alarm(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("deviceStatus")
public RedisRpcResponse deviceStatus(RedisRpcRequest request) {
String deviceId = request.getParam().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.deviceStatus(device, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("info")
public RedisRpcResponse info(RedisRpcRequest request) {
String deviceId = request.getParam().toString();
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.deviceInfo(device, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
@RedisRpcMapping("info")
public RedisRpcResponse queryPreset(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelId = paramJson.getString("channelId");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
try {
deviceService.queryPreset(device, channelId, (code, msg, data) -> {
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(new WVPResult<>(code, msg, data));
// 手动发送结果
sendResponse(response);
});
}catch (ControllerException e) {
response.setStatusCode(e.getCode());
response.setBody(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMsg()));
sendResponse(response);
}
return null;
}
}

View File

@ -0,0 +1,74 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RedisRpcController("devicePlay")
public class RedisRpcDevicePlayController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IDeviceService deviceService;
@Autowired
private IPlayService playService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 获取通道同步状态
*/
@RedisRpcMapping("audioBroadcast")
public RedisRpcResponse audioBroadcast(RedisRpcRequest request) {
JSONObject paramJson = JSON.parseObject(request.getParam().toString());
String deviceId = paramJson.getString("deviceId");
String channelDeviceId = paramJson.getString("channelDeviceId");
Boolean broadcastMode = paramJson.getBoolean("broadcastMode");
Device device = deviceService.getDeviceByDeviceId(deviceId);
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
AudioBroadcastResult audioBroadcastResult = playService.audioBroadcast(deviceId, channelDeviceId, broadcastMode);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(JSONObject.toJSONString(audioBroadcastResult));
return response;
}
}

View File

@ -0,0 +1,99 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.InviteMessageInfo;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.sip.message.Response;
@Component
@Slf4j
@RedisRpcController("device")
public class RedisRpcGbDeviceController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IDeviceService deviceService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 目录订阅
*/
@RedisRpcMapping("subscribeCatalog")
public RedisRpcResponse subscribeCatalog(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int id = paramJson.getIntValue("id");
int cycle = paramJson.getIntValue("cycle");
RedisRpcResponse response = request.getResponse();
if (id <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
deviceService.subscribeCatalog(id, cycle);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
/**
* 移动位置订阅
*/
@RedisRpcMapping("subscribeMobilePosition")
public RedisRpcResponse subscribeMobilePosition(RedisRpcRequest request) {
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
int id = paramJson.getIntValue("id");
int cycle = paramJson.getIntValue("cycle");
int interval = paramJson.getIntValue("interval");
RedisRpcResponse response = request.getResponse();
if (id <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
deviceService.subscribeMobilePosition(id, cycle, interval);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
}

View File

@ -0,0 +1,83 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
@RedisRpcController("platform")
public class RedisRpcPlatformController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IPlatformService platformService;
@Autowired
private IPlatformChannelService platformChannelService;
@Autowired
private EventPublisher eventPublisher;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 更新
*/
@RedisRpcMapping("update")
public RedisRpcResponse play(RedisRpcRequest request) {
Platform platform = JSONObject.parseObject(request.getParam().toString(), Platform.class);
RedisRpcResponse response = request.getResponse();
boolean update = platformService.update(platform);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(Boolean.toString(update));
return response;
}
/**
* 目录更新推送
*/
@RedisRpcMapping("catalogEventPublish")
public RedisRpcResponse catalogEventPublish(RedisRpcRequest request) {
JSONObject jsonObject = JSONObject.parseObject(request.getParam().toString());
Platform platform = jsonObject.getObject("platform", Platform.class);
List<CommonGBChannel> channels = jsonObject.getJSONArray("channels").toJavaList(CommonGBChannel.class);
String type = jsonObject.getString("type");
eventPublisher.catalogEventPublish(platform, channels, type, false);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
}

View File

@ -0,0 +1,165 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sip.message.Response;
@Component
@Slf4j
@RedisRpcController("sendRtp")
public class RedisRpcSendRtpController extends RpcController {
@Autowired
private SSRCFactory ssrcFactory;
@Autowired
private IMediaServerService mediaServerService;
@Autowired
private ISendRtpServerService sendRtpServerService;
@Autowired
private UserSetting userSetting;
/**
* 获取发流的信息
*/
@RedisRpcMapping("getSendRtpItem")
public RedisRpcResponse getSendRtpItem(RedisRpcRequest request) {
String callId = request.getParam().toString();
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId);
if (sendRtpItem == null) {
log.info("[redis-rpc] 获取发流的信息, 未找到redis中的发流信息 callId{}", callId);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
log.info("[redis-rpc] 获取发流的信息: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
// 查询本级是否有这个流
MediaServer mediaServerItem = mediaServerService.getMediaServerByAppAndStream(sendRtpItem.getApp(), sendRtpItem.getStream());
if (mediaServerItem == null) {
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
}
// 自平台内容
int localPort = sendRtpServerService.getNextPort(mediaServerItem);
if (localPort == 0) {
log.info("[redis-rpc] getSendRtpItem->服务器端口资源不足" );
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
}
// 写入redis 超时时回复
sendRtpItem.setStatus(1);
sendRtpItem.setServerId(userSetting.getServerId());
sendRtpItem.setLocalIp(mediaServerItem.getSdpIp());
if (sendRtpItem.getSsrc() == null) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
sendRtpItem.setSsrc(ssrc);
}
sendRtpServerService.update(sendRtpItem);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(callId);
return response;
}
/**
* 开始发流
*/
@RedisRpcMapping("startSendRtp")
public RedisRpcResponse startSendRtp(RedisRpcRequest request) {
String callId = request.getParam().toString();
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
if (sendRtpItem == null) {
log.info("[redis-rpc] 开始发流, 未找到redis中的发流信息 callId{}", callId);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到redis中的发流信息");
response.setBody(wvpResult);
return response;
}
log.info("[redis-rpc] 开始发流: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (mediaServer == null) {
log.info("[redis-rpc] startSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() );
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer");
response.setBody(wvpResult);
return response;
}
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream());
if (mediaInfo == null) {
log.info("[redis-rpc] startSendRtp->流不在线: {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream() );
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "流不在线");
response.setBody(wvpResult);
return response;
}
try {
mediaServerService.startSendRtp(mediaServer, sendRtpItem);
}catch (ControllerException exception) {
log.info("[redis-rpc] 发流失败: {}/{}, 目标地址: {}{} {}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), exception.getMsg());
WVPResult wvpResult = WVPResult.fail(exception.getCode(), exception.getMsg());
response.setBody(wvpResult);
return response;
}
log.info("[redis-rpc] 发流成功: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
WVPResult wvpResult = WVPResult.success();
response.setBody(wvpResult);
return response;
}
/**
* 停止发流
*/
@RedisRpcMapping("stopSendRtp")
public RedisRpcResponse stopSendRtp(RedisRpcRequest request) {
String callId = request.getParam().toString();
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
if (sendRtpItem == null) {
log.info("[redis-rpc] 停止推流, 未找到redis中的发流信息 key{}", callId);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到redis中的发流信息");
response.setBody(wvpResult);
return response;
}
log.info("[redis-rpc] 停止推流: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() );
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (mediaServer == null) {
log.info("[redis-rpc] stopSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() );
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer");
response.setBody(wvpResult);
return response;
}
try {
mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
}catch (ControllerException exception) {
log.info("[redis-rpc] 停止推流失败: {}/{}, 目标地址: {}{} code {}, msg: {}", sendRtpItem.getApp(),
sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), exception.getCode(), exception.getMsg() );
response.setBody(WVPResult.fail(exception.getCode(), exception.getMsg()));
return response;
}
log.info("[redis-rpc] 停止推流成功: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() );
response.setBody(WVPResult.success());
return response;
}
}

View File

@ -0,0 +1,95 @@
package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy;
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyPlayService;
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RedisRpcController("streamProxy")
public class RedisRpcStreamProxyController extends RpcController {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IStreamProxyPlayService streamProxyPlayService;
@Autowired
private IStreamProxyService streamProxyService;
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
/**
* 播放
*/
@RedisRpcMapping("play")
public RedisRpcResponse play(RedisRpcRequest request) {
int id = Integer.parseInt(request.getParam().toString());
RedisRpcResponse response = request.getResponse();
if (id <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
StreamProxy streamProxy = streamProxyService.getStreamProxy(id);
if (streamProxy == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
StreamInfo streamInfo = streamProxyPlayService.startProxy(streamProxy);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
response.setBody(JSONObject.toJSONString(streamInfo));
return response;
}
/**
* 停止
*/
@RedisRpcMapping("stop")
public RedisRpcResponse stop(RedisRpcRequest request) {
int id = Integer.parseInt(request.getParam().toString());
RedisRpcResponse response = request.getResponse();
if (id <= 0) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
StreamProxy streamProxy = streamProxyService.getStreamProxy(id);
if (streamProxy == null) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
streamProxyPlayService.stopProxy(streamProxy);
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
}

View File

@ -3,33 +3,32 @@ package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig; import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo; import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.hook.Hook; import com.genersoft.iot.vmp.media.event.hook.Hook;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.event.hook.HookType;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.ISendRtpServerService; import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcMapping;
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
import com.genersoft.iot.vmp.streamPush.service.IStreamPushPlayService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* 其他wvp发起的rpc调用这里的方法被 RedisRpcConfig 通过反射寻找对应的方法名称调用
*/
@Slf4j
@Component @Component
public class RedisRpcController { @Slf4j
@RedisRpcController("streamPush")
public class RedisRpcStreamPushController extends RpcController {
@Autowired @Autowired
private SSRCFactory ssrcFactory; private SSRCFactory ssrcFactory;
@ -49,52 +48,22 @@ public class RedisRpcController {
@Autowired @Autowired
private RedisTemplate<Object, Object> redisTemplate; private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private IStreamPushPlayService streamPushPlayService;
/**
* 获取发流的信息 private void sendResponse(RedisRpcResponse response){
*/ log.info("[redis-rpc] >> {}", response);
public RedisRpcResponse getSendRtpItem(RedisRpcRequest request) { response.setToId(userSetting.getServerId());
String callId = request.getParam().toString(); RedisRpcMessage message = new RedisRpcMessage();
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId); message.setResponse(response);
if (sendRtpItem == null) { redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
log.info("[redis-rpc] 获取发流的信息, 未找到redis中的发流信息 callId{}", callId);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(200);
return response;
}
log.info("[redis-rpc] 获取发流的信息: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
// 查询本级是否有这个流
MediaServer mediaServerItem = mediaServerService.getMediaServerByAppAndStream(sendRtpItem.getApp(), sendRtpItem.getStream());
if (mediaServerItem == null) {
RedisRpcResponse response = request.getResponse();
response.setStatusCode(200);
}
// 自平台内容
int localPort = sendRtpServerService.getNextPort(mediaServerItem);
if (localPort == 0) {
log.info("[redis-rpc] getSendRtpItem->服务器端口资源不足" );
RedisRpcResponse response = request.getResponse();
response.setStatusCode(200);
}
// 写入redis 超时时回复
sendRtpItem.setStatus(1);
sendRtpItem.setServerId(userSetting.getServerId());
sendRtpItem.setLocalIp(mediaServerItem.getSdpIp());
if (sendRtpItem.getSsrc() == null) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
sendRtpItem.setSsrc(ssrc);
}
sendRtpServerService.update(sendRtpItem);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(200);
response.setBody(callId);
return response;
} }
/** /**
* 监听流上线 * 监听流上线
*/ */
@RedisRpcMapping("waitePushStreamOnline")
public RedisRpcResponse waitePushStreamOnline(RedisRpcRequest request) { public RedisRpcResponse waitePushStreamOnline(RedisRpcRequest request) {
SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class); SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class);
log.info("[redis-rpc] 监听流上线: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort()); log.info("[redis-rpc] 监听流上线: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
@ -115,7 +84,7 @@ public class RedisRpcController {
sendRtpServerService.update(sendRtpItem); sendRtpServerService.update(sendRtpItem);
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setBody(sendRtpItem.getChannelId()); response.setBody(sendRtpItem.getChannelId());
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
} }
// 监听流上线 流上线直接发送sendRtpItem消息给实际的信令处理者 // 监听流上线 流上线直接发送sendRtpItem消息给实际的信令处理者
Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null); Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null);
@ -134,7 +103,7 @@ public class RedisRpcController {
redisTemplate.opsForValue().set(sendRtpItem.getChannelId(), sendRtpItem); redisTemplate.opsForValue().set(sendRtpItem.getChannelId(), sendRtpItem);
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setBody(sendRtpItem.getChannelId()); response.setBody(sendRtpItem.getChannelId());
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
// 手动发送结果 // 手动发送结果
sendResponse(response); sendResponse(response);
hookSubscribe.removeSubscribe(hook); hookSubscribe.removeSubscribe(hook);
@ -146,6 +115,7 @@ public class RedisRpcController {
/** /**
* 监听流上线 * 监听流上线
*/ */
@RedisRpcMapping("onStreamOnlineEvent")
public RedisRpcResponse onStreamOnlineEvent(RedisRpcRequest request) { public RedisRpcResponse onStreamOnlineEvent(RedisRpcRequest request) {
StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class); StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class);
log.info("[redis-rpc] 监听流信息,等待流上线: {}/{}", streamInfo.getApp(), streamInfo.getStream()); log.info("[redis-rpc] 监听流信息,等待流上线: {}/{}", streamInfo.getApp(), streamInfo.getStream());
@ -155,7 +125,7 @@ public class RedisRpcController {
log.info("[redis-rpc] 监听流上线时发现流已存在直接返回: {}/{}", streamInfo.getApp(), streamInfo.getStream()); log.info("[redis-rpc] 监听流上线时发现流已存在直接返回: {}/{}", streamInfo.getApp(), streamInfo.getStream());
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setBody(JSONObject.toJSONString(streamInfoInServer)); response.setBody(JSONObject.toJSONString(streamInfoInServer));
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response; return response;
} }
// 监听流上线 流上线直接发送sendRtpItem消息给实际的信令处理者 // 监听流上线 流上线直接发送sendRtpItem消息给实际的信令处理者
@ -168,7 +138,7 @@ public class RedisRpcController {
streamInfo.getApp(), streamInfo.getStream(), hookData.getMediaInfo(), streamInfo.getApp(), streamInfo.getStream(), hookData.getMediaInfo(),
hookData.getMediaInfo() != null ? hookData.getMediaInfo().getCallId() : null); hookData.getMediaInfo() != null ? hookData.getMediaInfo().getCallId() : null);
response.setBody(JSONObject.toJSONString(streamInfoByAppAndStream)); response.setBody(JSONObject.toJSONString(streamInfoByAppAndStream));
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
// 手动发送结果 // 手动发送结果
sendResponse(response); sendResponse(response);
hookSubscribe.removeSubscribe(hook); hookSubscribe.removeSubscribe(hook);
@ -179,6 +149,7 @@ public class RedisRpcController {
/** /**
* 停止监听流上线 * 停止监听流上线
*/ */
@RedisRpcMapping("stopWaitePushStreamOnline")
public RedisRpcResponse stopWaitePushStreamOnline(RedisRpcRequest request) { public RedisRpcResponse stopWaitePushStreamOnline(RedisRpcRequest request) {
SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class); SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class);
log.info("[redis-rpc] 停止监听流上线: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() ); log.info("[redis-rpc] 停止监听流上线: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() );
@ -186,13 +157,14 @@ public class RedisRpcController {
Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null); Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null);
hookSubscribe.removeSubscribe(hook); hookSubscribe.removeSubscribe(hook);
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response; return response;
} }
/** /**
* 停止监听流上线 * 停止监听流上线
*/ */
@RedisRpcMapping("unPushStreamOnlineEvent")
public RedisRpcResponse unPushStreamOnlineEvent(RedisRpcRequest request) { public RedisRpcResponse unPushStreamOnlineEvent(RedisRpcRequest request) {
StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class); StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class);
log.info("[redis-rpc] 停止监听流上线: {}/{}", streamInfo.getApp(), streamInfo.getStream()); log.info("[redis-rpc] 停止监听流上线: {}/{}", streamInfo.getApp(), streamInfo.getStream());
@ -200,94 +172,30 @@ public class RedisRpcController {
Hook hook = Hook.getInstance(HookType.on_media_arrival, streamInfo.getApp(), streamInfo.getStream(), null); Hook hook = Hook.getInstance(HookType.on_media_arrival, streamInfo.getApp(), streamInfo.getStream(), null);
hookSubscribe.removeSubscribe(hook); hookSubscribe.removeSubscribe(hook);
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setStatusCode(200); response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
/**
* 开始发流
*/
public RedisRpcResponse startSendRtp(RedisRpcRequest request) {
String callId = request.getParam().toString();
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId);
RedisRpcResponse response = request.getResponse();
response.setStatusCode(200);
if (sendRtpItem == null) {
log.info("[redis-rpc] 开始发流, 未找到redis中的发流信息 callId{}", callId);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到redis中的发流信息");
response.setBody(wvpResult);
return response;
}
log.info("[redis-rpc] 开始发流: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (mediaServer == null) {
log.info("[redis-rpc] startSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() );
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer");
response.setBody(wvpResult);
return response;
}
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream());
if (mediaInfo == null) {
log.info("[redis-rpc] startSendRtp->流不在线: {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream() );
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "流不在线");
response.setBody(wvpResult);
return response;
}
try {
mediaServerService.startSendRtp(mediaServer, sendRtpItem);
}catch (ControllerException exception) {
log.info("[redis-rpc] 发流失败: {}/{}, 目标地址: {}{} {}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), exception.getMsg());
WVPResult wvpResult = WVPResult.fail(exception.getCode(), exception.getMsg());
response.setBody(wvpResult);
return response;
}
log.info("[redis-rpc] 发流成功: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
WVPResult wvpResult = WVPResult.success();
response.setBody(wvpResult);
return response; return response;
} }
/** /**
* 停止发流 * 停止监听流上线
*/ */
public RedisRpcResponse stopSendRtp(RedisRpcRequest request) { @RedisRpcMapping("play")
String callId = request.getParam().toString(); public RedisRpcResponse play(RedisRpcRequest request) {
SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId); int id = Integer.parseInt(request.getParam().toString());
RedisRpcResponse response = request.getResponse(); RedisRpcResponse response = request.getResponse();
response.setStatusCode(200); if (id <= 0) {
if (sendRtpItem == null) { response.setStatusCode(ErrorCode.ERROR400.getCode());
log.info("[redis-rpc] 停止推流, 未找到redis中的发流信息 key{}", callId); response.setBody("param error");
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到redis中的发流信息");
response.setBody(wvpResult);
return response; return response;
} }
log.info("[redis-rpc] 停止推流: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() ); streamPushPlayService.start(id, (code, msg, data) -> {
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); if (code == ErrorCode.SUCCESS.getCode()) {
if (mediaServer == null) { response.setStatusCode(ErrorCode.SUCCESS.getCode());
log.info("[redis-rpc] stopSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() ); response.setBody(JSONObject.toJSONString(data));
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer"); sendResponse(response);
response.setBody(wvpResult); }
return response; }, null, null);
} return null;
try {
mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
}catch (ControllerException exception) {
log.info("[redis-rpc] 停止推流失败: {}/{}, 目标地址: {}{} code {}, msg: {}", sendRtpItem.getApp(),
sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), exception.getCode(), exception.getMsg() );
response.setBody(WVPResult.fail(exception.getCode(), exception.getMsg()));
return response;
}
log.info("[redis-rpc] 停止推流成功: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() );
response.setBody(WVPResult.success());
return response;
} }
private void sendResponse(RedisRpcResponse response){
log.info("[redis-rpc] >> {}", response);
response.setToId(userSetting.getServerId());
RedisRpcMessage message = new RedisRpcMessage();
message.setResponse(response);
redisTemplate.convertAndSend(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY, message);
}
} }

View File

@ -0,0 +1,13 @@
package com.genersoft.iot.vmp.service.redisMsg.dto;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisRpcController {
/**
* 请求路径
*/
String value() default "";
}

View File

@ -0,0 +1,13 @@
package com.genersoft.iot.vmp.service.redisMsg.dto;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisRpcMapping {
/**
* 请求路径
*/
String value() default "";
}

View File

@ -0,0 +1,33 @@
package com.genersoft.iot.vmp.service.redisMsg.dto;
import com.genersoft.iot.vmp.conf.redis.RedisRpcConfig;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcClassHandler;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
public class RpcController {
@Autowired
private RedisRpcConfig redisRpcConfig;
@PostConstruct
public void init() {
String controllerPath = this.getClass().getAnnotation(RedisRpcController.class).value();
// 扫描其下的方法
Method[] methods = this.getClass().getDeclaredMethods();
for (Method method : methods) {
RedisRpcMapping annotation = method.getAnnotation(RedisRpcMapping.class);
if (annotation != null) {
String methodPath = annotation.value();
if (methodPath != null) {
redisRpcConfig.addHandler(controllerPath + "/" + methodPath, new RedisRpcClassHandler(this, method));
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More