diff --git a/pom.xml b/pom.xml index e13d5975c..19d3e8396 100644 --- a/pom.xml +++ b/pom.xml @@ -199,13 +199,6 @@ springdoc-openapi-security 1.6.10 - - - com.baomidou - dynamic-datasource-spring-boot-starter - 3.6.1 - - diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java index acd6092fd..9a7912d20 100644 --- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java +++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java @@ -1,5 +1,6 @@ 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.SpringBeanFactory; import lombok.extern.slf4j.Slf4j; @@ -33,6 +34,7 @@ public class VManageBootstrap extends SpringBootServletInitializer { public static void main(String[] args) { VManageBootstrap.args = args; VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); + ClassUtil.context = VManageBootstrap.context; GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil"); if (gitUtil == null) { log.info("获取版本信息失败"); @@ -62,6 +64,5 @@ public class VManageBootstrap extends SpringBootServletInitializer { ); SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); sessionCookieConfig.setHttpOnly(true); - } } diff --git a/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java b/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java new file mode 100644 index 000000000..fb1941a13 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java @@ -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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index c89653b14..cee1993fa 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -10,6 +10,8 @@ public class VideoManagerConstants { 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 MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_INFO:"; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java index 4742daa55..67c926e61 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java @@ -6,6 +6,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import java.util.List; + @Component @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true) @Order(0) @@ -16,6 +18,8 @@ public class SipConfig { private String showIp; + private List monitorIps; + private Integer port; private String domain; @@ -30,5 +34,5 @@ public class SipConfig { private boolean alarm = false; - private long timeout = 15; + private long timeout = 150; } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java index e6a9006a0..cb12754e6 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java @@ -31,10 +31,13 @@ public class SipPlatformRunner implements CommandLineRunner { @Autowired private ISIPCommanderForPlatform sipCommanderForPlatform; + @Autowired + private UserSetting userSetting; + @Override public void run(String... args) throws Exception { // 获取所有启用的平台 - List parentPlatforms = platformService.queryEnablePlatformList(); + List parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId()); for (Platform platform : parentPlatforms) { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index 194bfd3a1..ca346dfab 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -37,6 +37,11 @@ public class UserSetting { */ private Integer playTimeout = 10000; + /** + * 获取设备录像数据超时时间,单位:毫秒 + */ + private Integer recordInfoTimeout = 15000; + /** * 上级点播等待超时时间,单位:毫秒 */ @@ -180,4 +185,10 @@ public class UserSetting { */ private String jwkFile = "classpath:jwk.json"; + /** + * wvp集群模式下如果注册向上级的wvp奔溃,则自动选择一个其他wvp继续注册到上级 + */ + private boolean autoRegisterPlatform = false; + + } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java index 6da0caf3a..4a2098a27 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java @@ -1,12 +1,14 @@ 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.util.concurrent.TimeUnit; + @Component public class WVPTimerTask { @@ -19,11 +21,8 @@ public class WVPTimerTask { @Autowired private SipConfig sipConfig; - @Scheduled(fixedDelay = 2 * 1000) //每3秒执行一次 + @Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次 public void execute(){ - JSONObject jsonObject = new JSONObject(); - jsonObject.put("ip", sipConfig.getShowIp()); - jsonObject.put("port", serverPort); - redisCatchStorage.updateWVPInfo(jsonObject, 3); + redisCatchStorage.updateWVPInfo(ServerInfo.create(sipConfig.getShowIp(), serverPort), 3); } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java index b762838c6..b541f7448 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java @@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.conf.redis; import com.alibaba.fastjson2.JSON; import com.genersoft.iot.vmp.common.CommonCallback; 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.RedisRpcRequest; 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 org.springframework.beans.factory.annotation.Autowired; 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.stereotype.Component; +import javax.sip.message.Response; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; @@ -36,9 +40,6 @@ public class RedisRpcConfig implements MessageListener { @Autowired private UserSetting userSetting; - @Autowired - private RedisRpcController redisRpcController; - @Autowired private RedisTemplate redisTemplate; @@ -48,6 +49,40 @@ public class RedisRpcConfig implements MessageListener { @Autowired private ThreadPoolTaskExecutor taskExecutor; + private final static Map protocolHash = new HashMap<>(); + + public void addHandler(String path, RedisRpcClassHandler handler) { + protocolHash.put(path, handler); + } + +// @Override +// public void run(String... args) throws Exception { +// List> 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 public void onMessage(Message message, byte[] pattern) { boolean isEmpty = taskQueue.isEmpty(); @@ -63,10 +98,10 @@ public class RedisRpcConfig implements MessageListener { } else if (redisRpcMessage.getResponse() != null){ handlerResponse(redisRpcMessage.getResponse()); } else { - log.error("[redis rpc 解析失败] {}", JSON.toJSONString(redisRpcMessage)); + log.error("[redis-rpc]解析失败 {}", JSON.toJSONString(redisRpcMessage)); } } 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; } 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 if (userSetting.getServerId().equals(request.getToId())) { if (method == null) { // 回复404结果 RedisRpcResponse response = request.getResponse(); - response.setStatusCode(404); + response.setStatusCode(ErrorCode.ERROR404.getCode()); sendResponse(response); return; } - RedisRpcResponse response = (RedisRpcResponse)method.invoke(redisRpcController, request); + RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request); if(response != null) { sendResponse(response); } @@ -105,26 +146,14 @@ public class RedisRpcConfig implements MessageListener { if (method == null) { return; } - RedisRpcResponse response = (RedisRpcResponse)method.invoke(redisRpcController, request); + RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request); if (response != null) { sendResponse(response); } } }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){ @@ -142,23 +171,28 @@ public class RedisRpcConfig implements MessageListener { redisTemplate.convertAndSend(REDIS_REQUEST_CHANNEL_KEY, message); } - private final Map> topicSubscribers = new ConcurrentHashMap<>(); private final Map> 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); SynchronousQueue subscribe = subscribe(request.getSn()); try { sendRequest(request); - return subscribe.poll(timeOut, TimeUnit.SECONDS); + return subscribe.poll(timeOut, timeUnit); } catch (InterruptedException 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 { this.unsubscribe(request.getSn()); } - return null; } public void request(RedisRpcRequest request, CommonCallback callback) { @@ -209,6 +243,9 @@ public class RedisRpcConfig implements MessageListener { return callbacks.size(); } + + + // @Scheduled(fixedRate = 1000) //每1秒执行一次 // public void execute(){ // logger.info("callbacks的长度: " + callbacks.size()); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/bean/RedisRpcClassHandler.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/bean/RedisRpcClassHandler.java new file mode 100644 index 000000000..1fab24bbe --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/redis/bean/RedisRpcClassHandler.java @@ -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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index cbbb29596..78351bc2f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -80,11 +80,12 @@ public class SipLayer implements CommandLineRunner { monitorIps.add(sipConfig.getIp()); } } + sipConfig.setMonitorIps(monitorIps); if (ObjectUtils.isEmpty(sipConfig.getShowIp())){ sipConfig.setShowIp(String.join(",", monitorIps)); } SipFactory.getInstance().setPathName("gov.nist"); - if (monitorIps.size() > 0) { + if (!monitorIps.isEmpty()) { for (String monitorIp : monitorIps) { addListeningPoint(monitorIp, sipConfig.getPort()); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/BasicParam.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/BasicParam.java new file mode 100644 index 000000000..1ec7a721f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/BasicParam.java @@ -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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 7e1286c5a..aa4bd0a69 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -209,4 +209,7 @@ public class Device { @Schema(description = "控制语音对讲流程,释放收到ACK后发流") private boolean broadcastPushAfterAck; + + @Schema(description = "所属服务Id") + private String serverId; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index 924a8ca72..ab35ac51a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -244,5 +244,15 @@ public class DeviceChannel extends CommonGBChannel { 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; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomParam.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomParam.java new file mode 100644 index 000000000..d9b3a81d6 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomParam.java @@ -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; +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomRequest.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomRequest.java index 86fdb4d29..1a58c10fd 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomRequest.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomRequest.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181.bean; 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 * @date 2022/6/28 14:55 */ +@Data public class DragZoomRequest { /** * 序列号 @@ -20,124 +22,9 @@ public class DragZoomRequest { private String deviceId; @MessageElement(value = "DragZoomIn") - private DragZoom dragZoomIn; + private DragZoomParam dragZoomIn; @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; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteMessageInfo.java similarity index 93% rename from src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteInfo.java rename to src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteMessageInfo.java index 57e83bd10..beadb6901 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteMessageInfo.java @@ -4,7 +4,7 @@ import lombok.Data; // 从INVITE消息中解析需要的信息 @Data -public class InviteInfo { +public class InviteMessageInfo { private String requesterId; private String targetChannelId; private String sourceChannelId; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Platform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Platform.java index 74afd9ff7..13ec2c8b9 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Platform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Platform.java @@ -127,4 +127,7 @@ public class Platform { @Schema(description = "保密属性(必选)缺省为0;0-不涉密,1-涉密") private int secrecy = 0; + + @Schema(description = "执行注册的服务ID") + private String serverId; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceConfig.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceConfig.java index d3b40e81b..f2402cf8f 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceConfig.java @@ -7,30 +7,22 @@ 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.gb28181.bean.BasicParam; import com.genersoft.iot.vmp.gb28181.bean.Device; 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.WVPResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; 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.context.request.async.DeferredResult; -import javax.sip.InvalidArgumentException; -import javax.sip.SipException; -import java.text.ParseException; -import java.util.UUID; - @Slf4j @Tag(name = "国标设备配置") @RestController @@ -40,117 +32,60 @@ public class DeviceConfig { @Autowired private IDeviceService deviceService; - @Autowired - 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}") + @GetMapping("/basicParam") @Operation(summary = "基本配置设置命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) - @Parameter(name = "deviceId", description = "设备国标编号", required = true) - @Parameter(name = "channelId", description = "通道国标编号", required = true) - @Parameter(name = "name", description = "名称") - @Parameter(name = "expiration", description = "到期时间") - @Parameter(name = "heartBeatInterval", description = "心跳间隔") - @Parameter(name = "heartBeatCount", description = "心跳计数") - public DeferredResult 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) { + @Parameter(name = "basicParam", description = "基础配置参数", required = true) + public DeferredResult> homePositionApi(BasicParam basicParam) { if (log.isDebugEnabled()) { - log.debug("报警复位API调用"); + log.debug("基本配置设置命令API调用"); } - Device device = deviceService.getDeviceByDeviceId(deviceId); - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId; - try { - cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, 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()); - } - DeferredResult result = new DeferredResult(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); + Assert.notNull(basicParam.getDeviceId(), "设备ID必须存在"); + + Device device = deviceService.getDeviceByDeviceId(basicParam.getDeviceId()); + Assert.notNull(device, "设备不存在"); + + DeferredResult> deferredResult = new DeferredResult<>(); + deviceService.deviceBasicConfig(device, basicParam, (code, msg, data) -> { + deferredResult.setResult(new WVPResult<>(code, msg, data)); }); - resultHolder.put(key, uuid, result); - return result; + + deferredResult.onTimeout(() -> { + log.warn("[设备配置] 超时, {}", device.getDeviceId()); + deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时")); + }); + return deferredResult; + } - /** - * 设备配置查询请求API接口 - * @param deviceId 设备ID - * @param configType 配置类型 - * @param channelId 通道ID - * @return - */ - @Operation(summary = "设备配置查询请求", security = @SecurityRequirement(name = JwtUtils.HEADER)) + @Operation(summary = "设备配置查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) - @Parameter(name = "configType", description = "配置类型") - @GetMapping("/query/{deviceId}/{configType}") - public DeferredResult configDownloadApi(@PathVariable String deviceId, - @PathVariable String configType, - @RequestParam(required = false) String channelId) { + @Parameter(name = "configType", description = "配置类型, 可选值," + + "基本参数配置:BasicParam," + + "视频参数范围:VideoParamOpt, " + + "SVAC编码配置:SVACEncodeConfig, " + + "SVAC解码配置:SVACDecodeConfig。" + + "可同时查询多个配置类型,各类型以“/”分隔,") + @GetMapping("/query") + public DeferredResult> configDownloadApi(String deviceId,String configType, + @RequestParam(required = false) String channelId) { 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); - try { - cmder.deviceConfigQuery(device, channelId, configType, 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()); - } - DeferredResult result = new DeferredResult (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); + Assert.notNull(device, "设备不存在"); + + DeferredResult> deferredResult = new DeferredResult<>(); + + deviceService.deviceConfigQuery(device, channelId, configType, (code, msg, data) -> { + deferredResult.setResult(new WVPResult<>(code, msg, data)); }); - resultHolder.put(key, uuid, result); - return result; + + deferredResult.onTimeout(() -> { + log.warn("[获取设备配置] 超时, {}", device.getDeviceId()); + deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时")); + }); + return deferredResult; } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceControl.java index 55017deb7..43a10e1e2 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceControl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceControl.java @@ -7,13 +7,8 @@ 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.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.vmanager.bean.ErrorCode; 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 lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.util.ObjectUtils; +import org.springframework.util.Assert; import org.springframework.web.bind.annotation.*; 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 = "国标设备控制") @Slf4j @RestController @@ -42,18 +31,8 @@ public class DeviceControl { @Autowired private IDeviceService deviceService; - @Autowired - private ISIPCommander cmder; - @Autowired - private DeferredResultHolder resultHolder; - - /** - * 远程启动控制命令API接口 - * - * @param deviceId 设备ID - */ - @Operation(summary = "远程启动控制命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) + @Operation(summary = "远程启动", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @GetMapping("/teleboot/{deviceId}") public void teleBootApi(@PathVariable String deviceId) { @@ -61,194 +40,104 @@ public class DeviceControl { log.debug("设备远程启动API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - try { - cmder.teleBootCmd(device); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 远程启动: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); - } + Assert.notNull(device, "设备不存在"); + deviceService.teleboot(device); } - /** - * 录像控制命令API接口 - * - * @param deviceId 设备ID - * @param recordCmdStr Record:手动录像,StopRecord:停止手动录像 - * @param channelId 通道编码(可选) - */ + @Operation(summary = "录像控制", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "recordCmdStr", description = "命令, 可选值:Record(手动录像),StopRecord(停止手动录像)", required = true) - @GetMapping("/record/{deviceId}/{recordCmdStr}") - public DeferredResult>> recordApi(@PathVariable String deviceId, - @PathVariable String recordCmdStr, String channelId) { + @GetMapping("/record") + public DeferredResult> recordApi(String deviceId, String recordCmdStr, String channelId) { if (log.isDebugEnabled()) { log.debug("开始/停止录像API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; - DeferredResult>> 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()); - } + Assert.notNull(device, "设备不存在"); + DeferredResult> deferredResult = new DeferredResult<>(); - 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; } - /** - * 报警布防/撤防命令API接口 - * - * @param deviceId 设备ID - * @param guardCmdStr SetGuard:布防,ResetGuard:撤防 - */ - @Operation(summary = "布防/撤防命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) + @Operation(summary = "布防/撤防", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true) - @GetMapping("/guard/{deviceId}/{guardCmdStr}") - public DeferredResult> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) { + @GetMapping("/guard") + public DeferredResult> guardApi(String deviceId, String guardCmdStr) { if (log.isDebugEnabled()) { log.debug("布防/撤防API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + deviceId; - String uuid =UUID.randomUUID().toString(); - try { - cmder.guardCmd(device, guardCmdStr, 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.invokeResult(msg); - },null); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage()); - } - DeferredResult> 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); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.guard(device, guardCmdStr, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); }); - return result; } - /** - * 报警复位API接口 - * - * @param deviceId 设备ID - * @param alarmMethod 报警方式(可选) - * @param alarmType 报警类型(可选) - */ @Operation(summary = "报警复位", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) - @Parameter(name = "alarmMethod", description = "报警方式") - @Parameter(name = "alarmType", description = "报警类型") - @GetMapping("/reset_alarm/{deviceId}") - public DeferredResult>> resetAlarmApi(@PathVariable String deviceId, String channelId, + @Parameter(name = "alarmMethod", description = "报警方式, 报警方式条件(可选),取值0为全部,1为电话报警,2为设备报警,3为短信报警,4为\n" + + "GPS报警,5为视频报警,6为设备故障报警,7其他报警;可以为直接组合如12为电话报警或设备报警") + @Parameter(name = "alarmType", description = "报警类型, " + + "报警类型。" + + "报警方式为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> resetAlarm(String deviceId, String channelId, @RequestParam(required = false) String alarmMethod, @RequestParam(required = false) String alarmType) { if (log.isDebugEnabled()) { log.debug("报警复位API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; - try { - cmder.alarmCmd(device, alarmMethod, alarmType, 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.invokeResult(msg); - },null); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 报警复位: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); - } - DeferredResult>> 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); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.resetAlarm(device, channelId, alarmMethod, alarmType, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); }); - resultHolder.put(key, uuid, result); return result; } - /** - * 强制关键帧API接口 - * - * @param deviceId 设备ID - * @param channelId 通道ID - */ @Operation(summary = "强制关键帧", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号") - @GetMapping("/i_frame/{deviceId}") - public JSONObject iFrame(@PathVariable String deviceId, - @RequestParam(required = false) String channelId) { + @GetMapping("/i_frame") + public void iFrame(String deviceId, @RequestParam(required = false) String channelId) { if (log.isDebugEnabled()) { log.debug("强制关键帧API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - try { - cmder.iFrameCmd(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; + Assert.notNull(device, "设备不存在"); + deviceService.iFrame(device, channelId); } - /** - * 看守位控制命令API接口 - * - * @param deviceId 设备ID - * @param enabled 看守位使能1:开启,0:关闭 - * @param resetTime 自动归位时间间隔(可选) - * @param presetIndex 调用预置位编号(可选) - * @param channelId 通道编码(可选) - */ @Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", 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 presetIndex) { 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); - try { - cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, 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.invokeResult(msg); - },null); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 看守位控制: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); - } - DeferredResult> 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); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.homePosition(device, channelId, enabled, resetTime, presetIndex, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[看守位控制] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); }); - resultHolder.put(key, uuid, 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)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "length", description = "播放窗口长度像素值", required = true) + @Parameter(name = "width", description = "播放窗口宽度像素值", required = true) @Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true) @Parameter(name = "midpointy", 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") - public void dragZoomIn(@RequestParam String deviceId, - @RequestParam(required = false) String channelId, + public DeferredResult> dragZoomIn(@RequestParam String deviceId, String channelId, @RequestParam int length, @RequestParam int width, @RequestParam int midpointx, @RequestParam int midpointy, @RequestParam int lengthx, - @RequestParam int lengthy) throws RuntimeException { + @RequestParam int lengthy) { 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)); } Device device = deviceService.getDeviceByDeviceId(deviceId); - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("" + length+ "\r\n"); - cmdXml.append("" + width+ "\r\n"); - cmdXml.append("" + midpointx+ "\r\n"); - cmdXml.append("" + midpointy+ "\r\n"); - cmdXml.append("" + lengthx+ "\r\n"); - cmdXml.append("" + lengthy+ "\r\n"); - cmdXml.append("\r\n"); - try { - cmder.dragZoomCmd(device, channelId, cmdXml.toString()); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 拉框放大: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); - } + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.dragZoomIn(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); + }); + 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)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号") @@ -363,7 +207,7 @@ public class DeviceControl { @Parameter(name = "lengthx", description = "拉框长度像素值", required = true) @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true) @GetMapping("/drag_zoom/zoom_out") - public void dragZoomOut(@RequestParam String deviceId, + public DeferredResult> dragZoomOut(@RequestParam String deviceId, @RequestParam(required = false) String channelId, @RequestParam int length, @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)); } Device device = deviceService.getDeviceByDeviceId(deviceId); - StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); - cmdXml.append("" + length+ "\r\n"); - cmdXml.append("" + width+ "\r\n"); - cmdXml.append("" + midpointx+ "\r\n"); - cmdXml.append("" + midpointy+ "\r\n"); - cmdXml.append("" + lengthx+ "\r\n"); - cmdXml.append("" + lengthy+ "\r\n"); - cmdXml.append("\r\n"); - try { - cmder.dragZoomCmd(device, channelId, cmdXml.toString()); - } catch (InvalidArgumentException | SipException | ParseException e) { - log.error("[命令发送失败] 拉框缩小: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); - } + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.dragZoomOut(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); + }); + return result; } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceQuery.java index 6924b0f7a..1e65c1c11 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/DeviceQuery.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.controller; import com.alibaba.fastjson2.JSONObject; 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.security.JwtUtils; 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.RequestMessage; 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.WVPResult; import com.github.pagehelper.PageInfo; @@ -27,9 +29,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.IOUtils; import org.apache.ibatis.annotations.Options; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; 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.http.HttpServletResponse; -import javax.sip.InvalidArgumentException; -import javax.sip.SipException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; -import java.text.ParseException; import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.UUID; @Tag(name = "国标设备查询", description = "国标设备查询") @SuppressWarnings("rawtypes") @@ -61,24 +57,25 @@ public class DeviceQuery { @Autowired private IInviteStreamService inviteStreamService; - - @Autowired - private ISIPCommander cmder; - - @Autowired - private DeferredResultHolder resultHolder; @Autowired private IDeviceService deviceService; + @Autowired + private ISIPCommander cmder; + + @Autowired + private DeferredResultHolder resultHolder; + + @Autowired + private UserSetting userSetting; + @Autowired private DynamicTask dynamicTask; - /** - * 使用ID查询国标设备 - * @param deviceId 国标ID - * @return 国标设备 - */ + @Autowired + private IRedisRpcService redisRpcService; + @Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @GetMapping("/devices/{deviceId}") @@ -87,12 +84,7 @@ public class DeviceQuery { return deviceService.getDeviceByDeviceId(deviceId); } - /** - * 分页查询国标设备 - * @param page 当前页 - * @param count 每页查询数量 - * @return 分页国标列表 - */ + @Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "page", description = "当前页", required = true) @Parameter(name = "count", description = "每页查询数量", required = true) @@ -107,9 +99,7 @@ public class DeviceQuery { return deviceService.getAll(page, count, query, status); } - /** - * 分页查询通道数 - */ + @GetMapping("/devices/{deviceId}/channels") @Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @@ -130,9 +120,7 @@ public class DeviceQuery { return deviceChannelService.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count); } - /** - * 同步设备通道 - */ + @Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @GetMapping("/devices/{deviceId}/sync") @@ -142,37 +130,11 @@ public class DeviceQuery { log.debug("设备通道信息同步API调用,deviceId:" + 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 wvpResult = new WVPResult<>(); - wvpResult.setCode(0); - wvpResult.setMsg("开始同步"); - return wvpResult; + return deviceService.devicesSync(device); + } - /** - * 移除设备 - * @param deviceId 设备id - * @return - */ @Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @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)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @@ -260,12 +211,7 @@ public class DeviceQuery { deviceChannelService.updateChannelStreamIdentification(channel); } - /** - * 修改数据流传输模式 - * @param deviceId 设备id - * @param streamMode 数据流传输模式 - * @return - */ + @Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" + @@ -277,11 +223,7 @@ public class DeviceQuery { deviceService.updateCustomDevice(device); } - /** - * 添加设备信息 - * @param device 设备信息 - * @return - */ + @Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "device", description = "设备", required = true) @PostMapping("/device/add/") @@ -299,11 +241,7 @@ public class DeviceQuery { deviceService.addDevice(device); } - /** - * 更新设备信息 - * @param device 设备信息 - * @return - */ + @Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "device", description = "设备", required = true) @PostMapping("/device/update/") @@ -314,72 +252,37 @@ public class DeviceQuery { deviceService.updateCustomDevice(device); } - /** - * 设备状态查询请求API接口 - * - * @param deviceId 设备id - */ @Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @GetMapping("/devices/{deviceId}/status") - public DeferredResult> deviceStatusApi(@PathVariable String deviceId) { + public DeferredResult> deviceStatusApi(@PathVariable String deviceId) { if (log.isDebugEnabled()) { log.debug("设备状态查询API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId; - DeferredResult> result = new DeferredResult>(2*1000L); - if(device == null) { - result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK)); - return result; - } - try { - 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); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.deviceStatus(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_DEVICESTATUS + deviceId, uuid, 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)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) - @Parameter(name = "startPriority", description = "报警起始级别") - @Parameter(name = "endPriority", description = "报警终止级别") - @Parameter(name = "alarmMethod", description = "报警方式条件") + @Parameter(name = "startPriority", description = "报警起始级别, 0为全部,1为一级警情,2为二级警情,3为三级警情,4为四级警情") + @Parameter(name = "endPriority", description = "报警终止级别, ,0为全部,1为一级警情,2为二级警情,3为三级警情,4为四级警情") + @Parameter(name = "alarmMethod", description = "报警方式条件,取值0为全部,1为电话报警,2为设备报警,3为短信报警,4为GPS报警," + + "5为视频报警,6为设备故障报警,7其他报警;可以为直接组合如12为电话报警或设备报警") @Parameter(name = "alarmType", description = "报警类型") @Parameter(name = "startTime", description = "报警发生起始时间") @Parameter(name = "endTime", description = "报警发生终止时间") - @GetMapping("/alarm/{deviceId}") - public DeferredResult> alarmApi(@PathVariable String deviceId, + @GetMapping("/alarm") + public DeferredResult> alarmApi(String deviceId, @RequestParam(required = false) String startPriority, @RequestParam(required = false) String endPriority, @RequestParam(required = false) String alarmMethod, @@ -390,31 +293,35 @@ public class DeviceQuery { log.debug("设备报警查询API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; - String uuid = UUID.randomUUID().toString(); - try { - cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, 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()); - } - DeferredResult> result = new DeferredResult> (3 * 1000L); - result.onTimeout(()->{ - log.warn(String.format("设备报警查询超时")); - // 释放rtpserver - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("设备报警查询超时"); - resultHolder.invokeResult(msg); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + deviceService.alarm(device, startPriority,endPriority ,alarmMethod ,alarmType ,startTime ,endTime, (code, msg, data) -> { + result.setResult(new WVPResult<>(code, msg, data)); + }); + result.onTimeout(() -> { + log.warn("[设备报警查询] 操作超时, 设备未返回应答指令, {}", deviceId); + result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); + }); + return result; + } + + @Operation(summary = "设备信息查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) + @Parameter(name = "deviceId", description = "设备国标编号", required = true) + @GetMapping("/info") + public DeferredResult> deviceInfo(String deviceId) { + if (log.isDebugEnabled()) { + log.debug("设备信息查询API调用"); + } + Device device = deviceService.getDeviceByDeviceId(deviceId); + Assert.notNull(device, "设备不存在"); + DeferredResult> result = new DeferredResult<>(); + 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; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/GBRecordController.java index 102b7ee91..c56389b22 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/GBRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/GBRecordController.java @@ -1,9 +1,9 @@ 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.conf.UserSetting; 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.gb28181.bean.Device; 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 javax.servlet.http.HttpServletRequest; -import javax.sip.InvalidArgumentException; -import javax.sip.SipException; -import java.text.ParseException; import java.util.UUID; +import java.util.concurrent.TimeUnit; @Tag(name = "国标录像") @Slf4j @@ -72,7 +70,7 @@ public class GBRecordController { if (log.isDebugEnabled()) { log.debug(String.format("录像信息查询 API调用,deviceId:%s ,startTime:%s, endTime:%s",deviceId, startTime, endTime)); } - DeferredResult> result = new DeferredResult<>(); + DeferredResult> result = new DeferredResult<>(Long.valueOf(userSetting.getRecordInfoTimeout()), TimeUnit.MILLISECONDS); if (!DateUtil.verification(startTime, DateUtil.formatter)){ throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN); } @@ -81,35 +79,25 @@ public class GBRecordController { } Device device = deviceService.getDeviceByDeviceId(deviceId); - // 指定超时时间 1分钟30秒 - String uuid = UUID.randomUUID().toString(); - 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 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()); + if (device == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), deviceId + " 不存在"); } - - // 录像查询以channelId作为deviceId查询 - resultHolder.put(key, uuid, result); + DeviceChannel channel = channelService.getOneForSource(device.getId(), channelId); + if (channel == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), channelId + " 不存在"); + } + channelService.queryRecordInfo(device, channel, startTime, endTime, (code, msg, data)->{ + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(code); + wvpResult.setMsg(msg); + wvpResult.setData(data); + result.setResult(wvpResult); + }); result.onTimeout(()->{ - msg.setData("timeout"); WVPResult wvpResult = new WVPResult<>(); wvpResult.setCode(ErrorCode.ERROR100.getCode()); wvpResult.setMsg("timeout"); - msg.setData(wvpResult); - resultHolder.invokeResult(msg); + result.setResult(wvpResult); }); return result; } @@ -179,7 +167,7 @@ public class GBRecordController { @Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "stream", description = "流ID", required = true) @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()) { log.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); @@ -191,14 +179,13 @@ public class GBRecordController { Device device = deviceService.getDeviceByDeviceId(deviceId); if (device == null) { - throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "未找到"); + throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到"); } - - try { - cmder.streamByeCmd(device, channelId, "rtp", stream, null, null); - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { - log.warn("[停止历史媒体下载]停止历史媒体下载,发送BYE失败 {}", e.getMessage()); + DeviceChannel deviceChannel = channelService.getOneForSource(deviceId, channelId); + if (deviceChannel == null) { + throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + channelId + " 未找到"); } + playService.stop(InviteSessionType.DOWNLOAD, device, deviceChannel, stream); } @Operation(summary = "获取历史媒体下载进度", security = @SecurityRequirement(name = JwtUtils.HEADER)) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlayController.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlayController.java index e7a8b1c87..6d5352fe1 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlayController.java @@ -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.media.bean.MediaServer; 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.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; @@ -91,31 +92,22 @@ public class PlayController { Assert.notNull(deviceId, "设备不存在"); DeviceChannel channel = deviceChannelService.getOne(deviceId, channelId); 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> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); result.onTimeout(()->{ log.info("[点播等待超时] deviceId:{}, channelId:{}, ", deviceId, channelId); // 释放rtpserver - WVPResult wvpResult = new WVPResult<>(); + WVPResult wvpResult = new WVPResult<>(); wvpResult.setCode(ErrorCode.ERROR100.getCode()); wvpResult.setMsg("点播超时"); - requestMessage.setData(wvpResult); - resultHolder.invokeAllResult(requestMessage); + result.setResult(wvpResult); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, channel.getId()); deviceChannelService.stopPlay(channel.getId()); }); - // 录像查询以channelId作为deviceId查询 - resultHolder.put(key, uuid, result); - - playService.play(newMediaServerItem, deviceId, channelId, null, (code, msg, streamInfo) -> { + ErrorCallback callback = (code, msg, streamInfo) -> { WVPResult wvpResult = new WVPResult<>(); if (code == InviteErrorCode.SUCCESS.getCode()) { wvpResult.setCode(ErrorCode.SUCCESS.getCode()); @@ -133,8 +125,8 @@ public class PlayController { } streamInfo.channgeStreamIp(host); } - if (!ObjectUtils.isEmpty(newMediaServerItem.getTranscodeSuffix()) && !"null".equalsIgnoreCase(newMediaServerItem.getTranscodeSuffix())) { - streamInfo.setStream(streamInfo.getStream() + "_" + newMediaServerItem.getTranscodeSuffix()); + if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix()) && !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) { + streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix()); } wvpResult.setData(new StreamContent(streamInfo)); }else { @@ -145,10 +137,9 @@ public class PlayController { wvpResult.setCode(code); wvpResult.setMsg(msg); } - requestMessage.setData(wvpResult); - // 此处必须释放所有请求 - resultHolder.invokeAllResult(requestMessage); - }); + result.setResult(wvpResult); + }; + playService.play(device, channel, callback); return result; } @@ -207,16 +198,8 @@ public class PlayController { if (log.isDebugEnabled()) { 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); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlaybackController.java index 210b022f7..871085086 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PlaybackController.java @@ -156,7 +156,7 @@ public class PlaybackController { } DeviceChannel deviceChannel = channelService.getOneForSource(deviceId, channelId); if (deviceChannel == null) { - throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + deviceChannel + " 未找到"); + throw new ControllerException(ErrorCode.ERROR400.getCode(), "通道:" + channelId + " 未找到"); } playService.stop(InviteSessionType.PLAYBACK, device, deviceChannel, stream); } @@ -166,8 +166,7 @@ public class PlaybackController { @Parameter(name = "streamId", description = "回放流ID", required = true) @GetMapping("/pause/{streamId}") public void playPause(@PathVariable String streamId) { - log.info("playPause: "+streamId); - + log.info("[回放暂停] streamId: {}", streamId); try { playService.pauseRtp(streamId); } catch (ServiceException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PtzController.java b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PtzController.java index 061a9db13..2f3b3a950 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PtzController.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/controller/PtzController.java @@ -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.IPTZService; 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.WVPResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; 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 = "前端设备控制") @Slf4j @RestController @@ -225,40 +219,22 @@ public class PtzController { @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @GetMapping("/preset/query/{deviceId}/{channelId}") - public DeferredResult queryPreset(@PathVariable String deviceId, @PathVariable String channelId) { + public DeferredResult> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) { if (log.isDebugEnabled()) { log.debug("设备预置位查询API调用"); } Device device = deviceService.getDeviceByDeviceId(deviceId); - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); - DeferredResult result = new DeferredResult (3 * 1000L); - result.onTimeout(()->{ - log.warn(String.format("获取设备预置位超时")); - // 释放rtpserver - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("获取设备预置位超时"); - resultHolder.invokeResult(msg); + Assert.notNull(device, "设备不存在"); + DeferredResult> deferredResult = new DeferredResult<> (3 * 1000L); + deviceService.queryPreset(device, channelId, (code, msg, data) -> { + deferredResult.setResult(new WVPResult<>(code, msg, data)); }); - if (resultHolder.exist(key, null)) { - return result; - } - resultHolder.put(key, uuid, result); - try { - cmder.presetQuery(device, channelId, 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()); - } - return result; + + deferredResult.onTimeout(()->{ + log.warn("[获取设备预置位] 超时, {}", device.getDeviceId()); + deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时")); + }); + return deferredResult; } @Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER)) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/gb28181/dao/DeviceMapper.java index 145469b76..06a534821 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/dao/DeviceMapper.java @@ -43,6 +43,7 @@ public interface DeviceMapper { "as_message_channel," + "geo_coord_sys," + "on_line," + + "server_id,"+ "media_server_id," + "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 "+ @@ -80,6 +81,7 @@ public interface DeviceMapper { "as_message_channel,"+ "broadcast_push_after_ack,"+ "geo_coord_sys,"+ + "server_id,"+ "on_line"+ ") VALUES (" + "#{deviceId}," + @@ -112,6 +114,7 @@ public interface DeviceMapper { "#{asMessageChannel}," + "#{broadcastPushAfterAck}," + "#{geoCoordSys}," + + "#{serverId}," + "#{onLine}" + ")") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") @@ -136,6 +139,7 @@ public interface DeviceMapper { ", position_capability=#{positionCapability}" + ", heart_beat_count=#{heartBeatCount}" + ", expires=#{expires}" + + ", server_id=#{serverId}" + "WHERE device_id=#{deviceId}"+ " "}) int update(Device device); @@ -213,9 +217,43 @@ public interface DeviceMapper { "as_message_channel,"+ "broadcast_push_after_ack,"+ "geo_coord_sys,"+ + "server_id,"+ "on_line"+ " FROM wvp_device WHERE on_line = true") List 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 getOnlineDevicesByServerId(@Param("serverId") String serverId); @Select("SELECT " + "id,"+ @@ -274,6 +312,7 @@ public interface DeviceMapper { "geo_coord_sys,"+ "on_line,"+ "stream_mode," + + "server_id," + "media_server_id"+ ") VALUES (" + "#{deviceId}," + @@ -289,6 +328,7 @@ public interface DeviceMapper { "#{geoCoordSys}," + "#{onLine}," + "#{streamMode}," + + "#{serverId}," + "#{mediaServerId}" + ")") void addCustomDevice(Device device); @@ -331,6 +371,7 @@ public interface DeviceMapper { "geo_coord_sys,"+ "on_line,"+ "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 " + " FROM wvp_device de" + " where 1 = 1 "+ diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/dao/PlatformChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/gb28181/dao/PlatformChannelMapper.java index 9a565628b..c69a32d5c 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/dao/PlatformChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/dao/PlatformChannelMapper.java @@ -58,7 +58,10 @@ public interface PlatformChannelMapper { "where dc.channel_type = 0 and dc.channel_id = #{channelId} and pgc.platform_id=#{platformId}") List 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 queryParentPlatformByChannelId(@Param("channelId") String channelId); @Select("") List queryList(@Param("query") String query); - @Select("SELECT * FROM wvp_platform WHERE enable=#{enable} ") - List getEnableParentPlatformList(boolean enable); + @Select("SELECT * FROM wvp_platform WHERE server_id=#{serverId} and enable=#{enable} ") + List queryEnableParentPlatformList(@Param("serverId") String serverId, @Param("enable") boolean enable); @Select("SELECT * FROM wvp_platform WHERE enable=true and as_message_channel=true") List queryEnablePlatformListWithAsMessageChannel(); @@ -91,7 +92,9 @@ public interface PlatformMapper { @Update("UPDATE wvp_platform SET status=#{online} WHERE server_gb_id=#{platformGbID}" ) int updateStatus(@Param("platformGbID") String platformGbID, @Param("online") boolean online); - @Select("SELECT * FROM wvp_platform WHERE enable=true") - List queryEnablePlatformList(); + @Select("SELECT server_id FROM wvp_platform WHERE enable=true and server_id != #{serverId} group by server_id") + List queryServerIdsWithEnableAndNotInServer(@Param("serverId") String serverId); + @Select("SELECT * FROM wvp_platform WHERE server_id = #{serverId}") + List queryByServerId(@Param("serverId") String serverId); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java index 16e9d395b..aaea4309b 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -1,13 +1,19 @@ 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.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.mobilePosition.MobilePositionEvent; 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.MediaServerOnlineEvent; +import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; @@ -27,7 +33,13 @@ public class EventPublisher { @Autowired private ApplicationEventPublisher applicationEventPublisher; - + + @Autowired + private UserSetting userSetting; + + @Autowired + private IRedisRpcService redisRpcService; + /** * 设备报警事件 * @param deviceAlarm @@ -58,6 +70,18 @@ public class EventPublisher { } public void catalogEventPublish(Platform platform, List deviceChannels, String type) { + catalogEventPublish(platform, deviceChannels, type, true); + } + public void catalogEventPublish(Platform platform, List 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); List channels = new ArrayList<>(); if (deviceChannels.size() > 1) { @@ -76,6 +100,10 @@ public class EventPublisher { outEvent.setType(type); outEvent.setPlatform(platform); applicationEventPublisher.publishEvent(outEvent); + if (platform == null && share) { + // 如果没指定上级平台,则推送消息到所有在线的wvp处理自己含有的平台的目录更新 + redisRpcService.catalogEventPublish(null, outEvent); + } } public void mobilePositionEventPublish(MobilePosition mobilePosition) { @@ -84,9 +112,5 @@ public class EventPublisher { applicationEventPublisher.publishEvent(event); } - public void recordEndEventPush(RecordInfo recordInfo) { - RecordEndEvent outEvent = new RecordEndEvent(this); - outEvent.setRecordInfo(recordInfo); - applicationEventPublisher.publishEvent(outEvent); - } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/MessageSubscribe.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/MessageSubscribe.java new file mode 100755 index 000000000..f86c87867 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/MessageSubscribe.java @@ -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> subscribes = new ConcurrentHashMap<>(); + + private final DelayQueue> 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(); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java index a2034c726..027970038 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java @@ -29,24 +29,24 @@ public class SipSubscribe { private final DelayQueue delayQueue = new DelayQueue<>(); + @Scheduled(fixedDelay = 200) //每200毫秒执行 public void execute(){ - if (delayQueue.isEmpty()) { - return; - } - try { - SipEvent take = delayQueue.take(); - // 出现超时异常 - if(take.getErrorEvent() != null) { - EventResult eventResult = new EventResult<>(); - eventResult.type = EventResultType.timeout; - eventResult.msg = "消息超时未回复"; - eventResult.statusCode = -1024; - take.getErrorEvent().response(eventResult); + while (!delayQueue.isEmpty()) { + try { + SipEvent take = delayQueue.take(); + // 出现超时异常 + if(take.getErrorEvent() != null) { + EventResult eventResult = new EventResult<>(); + eventResult.type = EventResultType.timeout; + eventResult.msg = "消息超时未回复"; + 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, // 消息发送失败 - failedToGetPort + failedToGetPort, + // 收到失败的回复 + failedResult } public static class EventResult{ diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEndEvent.java similarity index 54% rename from src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java rename to src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEndEvent.java index cfd2985c5..4788eb622 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEndEvent.java @@ -1,7 +1,8 @@ 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 lombok.Getter; +import lombok.Setter; import org.springframework.context.ApplicationEvent; /** @@ -9,24 +10,18 @@ import org.springframework.context.ApplicationEvent; * @author: pan * @data: 2022-02-23 */ - -public class RecordEndEvent extends ApplicationEvent { +@Setter +@Getter +public class RecordInfoEndEvent extends ApplicationEvent { /** * */ private static final long serialVersionUID = 1L; - public RecordEndEvent(Object source) { + public RecordInfoEndEvent(Object source) { super(source); } private RecordInfo recordInfo; - public RecordInfo getRecordInfo() { - return recordInfo; - } - - public void setRecordInfo(RecordInfo recordInfo) { - this.recordInfo = recordInfo; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEvent.java new file mode 100755 index 000000000..d78a22b28 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEvent.java @@ -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; +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEventListener.java similarity index 85% rename from src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java rename to src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEventListener.java index 411b54d5c..f2a0986d6 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordInfoEventListener.java @@ -15,15 +15,15 @@ import java.util.concurrent.ConcurrentHashMap; */ @Slf4j @Component -public class RecordEndEventListener implements ApplicationListener { +public class RecordInfoEventListener implements ApplicationListener { - private Map handlerMap = new ConcurrentHashMap<>(); + private final Map handlerMap = new ConcurrentHashMap<>(); public interface RecordEndEventHandler{ void handler(RecordInfo recordInfo); } @Override - public void onApplicationEvent(RecordEndEvent event) { + public void onApplicationEvent(RecordInfoEvent event) { String deviceId = event.getRecordInfo().getDeviceId(); String channelId = event.getRecordInfo().getChannelId(); int count = event.getRecordInfo().getCount(); @@ -45,9 +45,6 @@ public class RecordEndEventListener implements ApplicationListener implements Delayed { + /** + * 超时时间(单位: 毫秒) + */ + private long delay; + + private String cmdType; + + private String sn; + + private String deviceId; + + private String result; + + private T t; + + private ErrorCallback 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 MessageEvent getInstance(String cmdType, String sn, String deviceId, Long delay, ErrorCallback callback){ + MessageEvent 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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/sip/SipEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/sip/SipEvent.java index e6af35caf..be20a54e2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/sip/SipEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/sip/SipEvent.java @@ -32,13 +32,13 @@ public class SipEvent implements Delayed { sipEvent.setKey(key); sipEvent.setOkEvent(okEvent); sipEvent.setErrorEvent(errorEvent); - sipEvent.setDelay(delay); + sipEvent.setDelay(System.currentTimeMillis() + delay); return sipEvent; } @Override public long getDelay(@NotNull TimeUnit unit) { - return unit.convert(delay, TimeUnit.MILLISECONDS); + return unit.convert(delay - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java index 6b64c05e5..08a329022 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java @@ -1,5 +1,6 @@ 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.Platform; 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.IPlatformService; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; @@ -15,10 +17,7 @@ import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import java.text.ParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * catalog事件 @@ -30,9 +29,6 @@ public class CatalogEventLister implements ApplicationListener { @Autowired private IPlatformChannelService platformChannelService; - @Autowired - private IPlatformService platformService; - @Autowired private ISIPCommanderForPlatform sipCommanderFroPlatform; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceChannelService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceChannelService.java index e9f137aa5..6cc39f760 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceChannelService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceChannelService.java @@ -1,5 +1,6 @@ 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.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; @@ -131,4 +132,9 @@ public interface IDeviceChannelService { List queryChaneIdListByDeviceDbIds(List deviceDbId); void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback callback); + + void queryRecordInfo(Device device, DeviceChannel channel, String startTime, String endTime, ErrorCallback object); + + void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback object); + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceService.java index 33f5e524d..45a46ff5a 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IDeviceService.java @@ -1,10 +1,10 @@ package com.genersoft.iot.vmp.gb28181.service; import com.genersoft.iot.vmp.common.CommonCallback; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; -import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; import java.util.List; @@ -86,7 +86,7 @@ public interface IDeviceService { * 获取所有在线设备 * @return 设备列表 */ - List getAllOnlineDevice(); + List getAllOnlineDevice(String serverId); List getAllByStatus(Boolean status); @@ -166,5 +166,35 @@ public interface IDeviceService { void subscribeMobilePosition(int id, int cycle, int interval); + WVPResult devicesSync(Device device); + + void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback callback); + + void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback callback); + + void teleboot(Device device); + + void record(Device device, String channelId, String recordCmdStr, ErrorCallback callback); + + void guard(Device device, String guardCmdStr, ErrorCallback callback); + + void resetAlarm(Device device, String channelId, String alarmMethod, String alarmType, ErrorCallback callback); + + void iFrame(Device device, String channelId); + + void homePosition(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback callback); + + void dragZoomIn(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback callback); + + void dragZoomOut(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback callback); + + void deviceStatus(Device device, ErrorCallback callback); + void updateDeviceHeartInfo(Device device); + + void alarm(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime, ErrorCallback callback); + + void deviceInfo(Device device, ErrorCallback callback); + + void queryPreset(Device device, String channelId, ErrorCallback callback); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelPlayService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelPlayService.java index ac58d28b9..1d6e1ebe8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelPlayService.java @@ -1,20 +1,33 @@ 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.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.service.bean.ErrorCallback; public interface IGbChannelPlayService { - void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback callback); + void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback callback); + + void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream); void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback callback); void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback callback); + void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream); + void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback callback); + void stopPlayProxy(CommonGBChannel channel); + void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback callback); + + void stopPlayPush(CommonGBChannel channel); + + void pauseRtp(String streamId); + + void resumeRtp(String streamId); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelService.java index 8dc67df20..e4706e618 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelService.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181.service; 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.github.pagehelper.PageInfo; @@ -87,4 +88,6 @@ public interface IGbChannelService { PageInfo queryList(int page, int count, String query, Boolean online, Boolean hasRecordPlan, Integer channelType); + void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback callback); + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java index d7c468052..c825c1cce 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java @@ -1,6 +1,7 @@ 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.Preset; @@ -18,4 +19,6 @@ public interface IPTZService { 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(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformChannelService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformChannelService.java index e03e0907e..0d97aa297 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformChannelService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformChannelService.java @@ -43,6 +43,8 @@ public interface IPlatformChannelService { CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId); + List queryChannelByPlatformIdAndChannelIds(Integer platformId, List channelIds); + void checkRegionAdd(List channelList); void checkRegionRemove(List channelList, List regionList); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformService.java index 36b6b63ae..a6c2b2466 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlatformService.java @@ -82,7 +82,7 @@ public interface IPlatformService { Platform queryOne(Integer platformId); - List queryEnablePlatformList(); + List queryEnablePlatformList(String serverId); void delete(Integer platformId, CommonCallback callback); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlayService.java index e208d3159..50c49776a 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/IPlayService.java @@ -25,6 +25,8 @@ public interface IPlayService { SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback callback); + void play(Device device, DeviceChannel channel, ErrorCallback callback); + StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, Device device, DeviceChannel channel); MediaServer getNewMediaServerItem(Device device); @@ -38,7 +40,7 @@ public interface IPlayService { 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; @@ -66,8 +68,12 @@ public interface IPlayService { void play(CommonGBChannel channel, Boolean record, ErrorCallback callback); + void stop(InviteSessionType inviteSessionType, CommonGBChannel channel, String stream); + void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback callback); void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback callback); + + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceAlarmServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceAlarmServiceImpl.java index a08111af1..9dd6e6410 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceAlarmServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceAlarmServiceImpl.java @@ -1,9 +1,8 @@ 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.service.IDeviceAlarmService; 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.PageInfo; import org.springframework.beans.factory.annotation.Autowired; @@ -12,7 +11,6 @@ import org.springframework.stereotype.Service; import java.util.List; @Service -@DS("master") public class DeviceAlarmServiceImpl implements IDeviceAlarmService { @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java index 2fcd0ab06..61162fa60 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.gb28181.service.impl; 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.InviteSessionType; 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.PlatformChannelMapper; 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.service.IDeviceChannelService; 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.utils.SipUtils; 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.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -32,18 +34,25 @@ import com.github.pagehelper.PageInfo; import lombok.extern.slf4j.Slf4j; import org.dom4j.Element; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import javax.sip.message.Response; import javax.validation.constraints.NotNull; import java.text.ParseException; 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; @@ -52,7 +61,6 @@ import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; */ @Slf4j @Service -@DS("master") public class DeviceChannelServiceImpl implements IDeviceChannelService { @Autowired @@ -82,6 +90,26 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @Autowired private IPlatformChannelService platformChannelService; + @Autowired + private IRedisRpcPlayService redisRpcPlayService; + + @Autowired + private ISIPCommander commander; + + // 记录录像查询的结果等待 + private final Map> topicSubscribers = new ConcurrentHashMap<>(); + + /** + * 监听录像查询结束事件 + */ + @Async("taskExecutor") + @org.springframework.context.event.EventListener + public void onApplicationEvent(RecordInfoEndEvent event) { + SynchronousQueue queue = topicSubscribers.get("record" + event.getRecordInfo().getSn()); + if (queue != null) { + queue.offer(event.getRecordInfo()); + } + } @Autowired private ISIPCommander cmder; @@ -179,10 +207,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @Override public ResourceBaseInfo getOverview() { - int online = channelMapper.getOnlineCount(); int total = channelMapper.getAllChannelCount(); - return new ResourceBaseInfo(total, online); } @@ -555,7 +581,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { List platformList = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getDeviceId()); if (!CollectionUtils.isEmpty(platformList)){ 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) { channelMapper.updateChannelForNotify(channel); } + + @Override + public void queryRecordInfo(Device device, DeviceChannel channel, String startTime, String endTime, ErrorCallback 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 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 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); + + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceServiceImpl.java index 19028c107..133468e06 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceServiceImpl.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.gb28181.service.impl; 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.VideoManagerConstants; 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.service.IMediaServerService; 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.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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.PageInfo; import lombok.extern.slf4j.Slf4j; @@ -49,7 +51,6 @@ import java.util.concurrent.TimeUnit; */ @Slf4j @Service -@DS("master") public class DeviceServiceImpl implements IDeviceService { @Autowired @@ -94,6 +95,9 @@ public class DeviceServiceImpl implements IDeviceService { @Autowired private AudioBroadcastManager audioBroadcastManager; + @Autowired + private IRedisRpcService redisRpcService; + private Device getDeviceByDeviceIdFromDb(String deviceId) { return deviceMapper.getDeviceByDeviceId(deviceId); } @@ -135,7 +139,7 @@ public class DeviceServiceImpl implements IDeviceService { deviceMapper.add(device); redisCatchStorage.updateDevice(device); try { - commander.deviceInfoQuery(device); + commander.deviceInfoQuery(device, null); commander.deviceConfigQuery(device, null, "BasicParam", null); } catch (InvalidArgumentException | SipException | ParseException e) { log.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); @@ -150,7 +154,7 @@ public class DeviceServiceImpl implements IDeviceService { if (userSetting.getSyncChannelOnDeviceOnline()) { log.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); try { - commander.deviceInfoQuery(device); + commander.deviceInfoQuery(device, null); } catch (InvalidArgumentException | SipException | ParseException e) { log.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); } @@ -214,7 +218,7 @@ public class DeviceServiceImpl implements IDeviceService { // deviceChannelMapper.offlineByDeviceId(deviceId); // 离线释放所有ssrc List ssrcTransactions = sessionManager.getSsrcTransactionByDeviceId(deviceId); - if (ssrcTransactions != null && ssrcTransactions.size() > 0) { + if (ssrcTransactions != null && !ssrcTransactions.isEmpty()) { for (SsrcTransaction ssrcTransaction : ssrcTransactions) { mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); @@ -338,6 +342,13 @@ public class DeviceServiceImpl implements IDeviceService { @Override 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); } @@ -381,8 +392,8 @@ public class DeviceServiceImpl implements IDeviceService { } @Override - public List getAllOnlineDevice() { - return deviceMapper.getOnlineDevices(); + public List getAllOnlineDevice(String serverId) { + return deviceMapper.getOnlineDevicesByServerId(serverId); } @Override @@ -470,9 +481,7 @@ public class DeviceServiceImpl implements IDeviceService { @Transactional public boolean delete(String deviceId) { Device device = getDeviceByDeviceIdFromDb(deviceId); - if (device == null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备:" + deviceId); - } + Assert.notNull(device, "未找到设备"); platformChannelMapper.delChannelForDeviceId(deviceId); deviceChannelMapper.cleanChannelsByDeviceId(device.getId()); deviceMapper.del(deviceId); @@ -523,10 +532,14 @@ public class DeviceServiceImpl implements IDeviceService { public void subscribeCatalog(int id, int cycle) { Device device = deviceMapper.query(id); Assert.notNull(device, "未找到设备"); + if (device.getSubscribeCycleForCatalog() == cycle) { return; } - + if (!userSetting.getServerId().equals(device.getServerId())) { + redisRpcService.subscribeCatalog(id, cycle); + return; + } // 目录订阅相关的信息 if (device.getSubscribeCycleForCatalog() > 0) { // 订阅周期不同,则先取消 @@ -556,7 +569,10 @@ public class DeviceServiceImpl implements IDeviceService { if (device.getSubscribeCycleForMobilePosition() == cycle) { return; } - + if (!userSetting.getServerId().equals(device.getServerId())) { + redisRpcService.subscribeMobilePosition(id, cycle, interval); + return; + } // 目录订阅相关的信息 if (device.getSubscribeCycleForMobilePosition() > 0) { // 订阅周期已经开启,则先取消 @@ -602,4 +618,297 @@ public class DeviceServiceImpl implements IDeviceService { updateDevice(deviceInDb); } } + + @Override + public WVPResult 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 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 wvpResult = new WVPResult<>(); + wvpResult.setCode(0); + wvpResult.setMsg("开始同步"); + return wvpResult; + } + + @Override + public void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 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("\r\n"); + cmdXml.append("" + length+ "\r\n"); + cmdXml.append("" + width+ "\r\n"); + cmdXml.append("" + midpointx+ "\r\n"); + cmdXml.append("" + midpointy+ "\r\n"); + cmdXml.append("" + lengthx+ "\r\n"); + cmdXml.append("" + lengthy+ "\r\n"); + cmdXml.append("\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 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("\r\n"); + cmdXml.append("" + length+ "\r\n"); + cmdXml.append("" + width+ "\r\n"); + cmdXml.append("" + midpointx+ "\r\n"); + cmdXml.append("" + midpointy+ "\r\n"); + cmdXml.append("" + lengthx+ "\r\n"); + cmdXml.append("" + lengthy+ "\r\n"); + cmdXml.append("\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 callback) { + + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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 callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + WVPResult 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()); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelPlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelPlayServiceImpl.java index 4b828a2f1..2e5b8e234 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelPlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelPlayServiceImpl.java @@ -1,10 +1,12 @@ 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.conf.exception.ServiceException; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.conf.UserSetting; 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.PlayException; 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.stereotype.Service; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; import javax.sip.message.Response; +import java.text.ParseException; @Slf4j @Service @@ -36,7 +41,7 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService { @Override - public void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback callback) { + public void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback callback) { if (channel == null || inviteInfo == null || callback == null || channel.getDataType() == null) { log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null); 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 public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback callback) { 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 public void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback 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 public void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback 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 callback){ try { 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, ErrorCallback callback){ try { @@ -171,4 +238,6 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService { callback.run(Response.BUSY_HERE, "busy here", null); } } + + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelServiceImpl.java index dc976b515..00cecf66a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelServiceImpl.java @@ -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.event.EventPublisher; 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.IPlatformChannelService; +import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.streamPush.bean.StreamPush; import com.genersoft.iot.vmp.utils.DateUtil; 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.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 @Service @@ -47,6 +53,9 @@ public class GbChannelServiceImpl implements IGbChannelService { @Autowired private GroupMapper groupMapper; + @Autowired + private IDeviceChannelService deviceChannelService; + @Override public CommonGBChannel queryByDeviceId(String gbDeviceId) { return commonGBChannelMapper.queryByDeviceId(gbDeviceId); @@ -722,4 +731,23 @@ public class GbChannelServiceImpl implements IGbChannelService { List all = commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType); return new PageInfo<>(all); } + + @Override + public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback 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"); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/InviteStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/InviteStreamServiceImpl.java index 4338bbfe5..c3c768072 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/InviteStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/InviteStreamServiceImpl.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.gb28181.service.impl; import com.alibaba.fastjson2.JSON; -import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -28,7 +27,6 @@ import java.util.concurrent.CopyOnWriteArrayList; @Slf4j @Service -@DS("master") public class InviteStreamServiceImpl implements IInviteStreamService { private final Map>> inviteErrorCallbackMap = new ConcurrentHashMap<>(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PTZServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PTZServiceImpl.java index 36f60510c..3fabadb2a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PTZServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PTZServiceImpl.java @@ -1,14 +1,22 @@ 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.gb28181.bean.CommonGBChannel; 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.service.IDeviceChannelService; +import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IPTZService; 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 lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.Assert; import javax.sip.InvalidArgumentException; import javax.sip.SipException; @@ -24,6 +32,18 @@ public class PTZServiceImpl implements IPTZService { @Autowired private SIPCommander cmder; + @Autowired + private UserSetting userSetting; + + @Autowired + private IRedisRpcPlayService redisRpcPlayService; + + @Autowired + private IDeviceChannelService deviceChannelService; + + @Autowired + private IDeviceService deviceService; + @Override 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 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 { cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2); } 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 public List queryPresetList(String deviceId, String channelDeviceId) { return Collections.emptyList(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformChannelServiceImpl.java index 1d4cf8d95..ff11f2ef7 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformChannelServiceImpl.java @@ -1,6 +1,5 @@ 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.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.dao.*; @@ -26,7 +25,6 @@ import java.util.*; */ @Slf4j @Service -@DS("master") public class PlatformChannelServiceImpl implements IPlatformChannelService { @Autowired @@ -598,4 +596,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { public CommonGBChannel queryChannelByPlatformIdAndChannelId(Integer platformId, Integer channelId) { return platformChannelMapper.queryShareChannel(platformId, channelId); } + + @Override + public List queryChannelByPlatformIdAndChannelIds(Integer platformId, List channelIds) { + return platformChannelMapper.queryShare(platformId, channelIds); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformServiceImpl.java index 3a1668d68..f76c0dc81 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlatformServiceImpl.java @@ -1,9 +1,9 @@ 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.*; 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.exception.SsrcTransactionNotFoundException; 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.service.ISendRtpServerService; 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.utils.DateUtil; import com.github.pagehelper.PageHelper; @@ -35,6 +36,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @@ -47,13 +49,13 @@ import java.text.ParseException; import java.util.List; import java.util.UUID; import java.util.Vector; +import java.util.concurrent.TimeUnit; /** * @author lin */ @Slf4j @Service -@DS("master") public class PlatformServiceImpl implements IPlatformService { private final static String REGISTER_KEY_PREFIX = "platform_register_"; @@ -67,6 +69,7 @@ public class PlatformServiceImpl implements IPlatformService { @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired private SSRCFactory ssrcFactory; @@ -85,6 +88,12 @@ public class PlatformServiceImpl implements IPlatformService { @Autowired private UserSetting userSetting; + @Autowired + private IRedisRpcService redisRpcService; + + @Autowired + private SipConfig sipConfig; + @Autowired private SipInviteSessionManager sessionManager; @@ -100,6 +109,85 @@ public class PlatformServiceImpl implements IPlatformService { @Autowired private ISendRtpServerService sendRtpServerService; + // 定时监听国标级联所进行的WVP服务是否正常, 如果异常则选择新的wvp执行 + @Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次 + public void execute(){ + if (!userSetting.isAutoRegisterPlatform()) { + return; + } + // 查找非平台的国标级联执行服务Id + List 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 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 platform.setCatalogGroup(1); } + platform.setServerId(userSetting.getServerId()); int result = platformMapper.add(platform); // 添加缓存 PlatformCatch platformCatch = new PlatformCatch(); @@ -201,6 +290,11 @@ public class PlatformServiceImpl implements IPlatformService { log.info("[国标级联] 更新平台 {}({})", platform.getName(), platform.getDeviceGBId()); platform.setCharacterSet(platform.getCharacterSet().toUpperCase()); 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()); platform.setUpdateTime(DateUtil.getNow()); @@ -782,8 +876,8 @@ public class PlatformServiceImpl implements IPlatformService { } @Override - public List queryEnablePlatformList() { - return platformMapper.queryEnablePlatformList(); + public List queryEnablePlatformList(String serverId) { + return platformMapper.queryEnableParentPlatformList(serverId,true); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlayServiceImpl.java index 2ef0851f4..e443f68bc 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/PlayServiceImpl.java @@ -1,6 +1,5 @@ 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.*; 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.ISendRtpServerService; 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.utils.CloudRecordUtils; import com.genersoft.iot.vmp.utils.DateUtil; @@ -64,8 +64,7 @@ import java.util.Vector; @SuppressWarnings(value = {"rawtypes", "unchecked"}) @Slf4j -@Service -@DS("master") +@Service("playService") public class PlayServiceImpl implements IPlayService { @Autowired @@ -125,6 +124,9 @@ public class PlayServiceImpl implements IPlayService { @Autowired 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 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 public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback callback) { @@ -736,6 +753,11 @@ public class PlayServiceImpl implements IPlayService { if (channel == null) { 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); if (newMediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的节点"); @@ -946,6 +968,11 @@ public class PlayServiceImpl implements IPlayService { @Override public void download(Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback callback) { + if (!userSetting.getServerId().equals(device.getServerId())) { + redisRpcPlayService.download(device.getServerId(), channel.getId(), startTime, endTime, downloadSpeed, callback); + return; + } + MediaServer newMediaServerItem = this.getNewMediaServerItem(device); if (newMediaServerItem == null) { callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), @@ -1075,6 +1102,8 @@ public class PlayServiceImpl implements IPlayService { @Override public StreamInfo getDownLoadInfo(Device device, DeviceChannel channel, String stream) { + + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channel.getId(), stream); if (inviteInfo == null) { String app = "rtp"; @@ -1216,10 +1245,19 @@ public class PlayServiceImpl implements IPlayService { } @Override - public AudioBroadcastResult audioBroadcast(Device device, DeviceChannel deviceChannel, Boolean broadcastMode) { - // TODO 必须多端口模式才支持语音喊话鹤语音对讲 - if (device == null || deviceChannel == null) { - return null; + public AudioBroadcastResult audioBroadcast(String deviceId, String channelDeviceId, Boolean broadcastMode) { + + Device device = deviceService.getDeviceByDeviceId(deviceId); + 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()); MediaServer mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); @@ -1351,11 +1389,20 @@ public class PlayServiceImpl implements IPlayService { @Override public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { - log.warn("streamId不存在!"); - throw new ServiceException("streamId不存在"); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "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); inviteStreamService.updateInviteInfo(inviteInfo); MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer(); @@ -1373,7 +1420,7 @@ public class PlayServiceImpl implements IPlayService { if (!result) { throw new ServiceException("暂停RTP接收失败"); } - Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId()); + DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId()); 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 { InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { - log.warn("streamId不存在!"); - throw new ServiceException("streamId不存在"); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "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); inviteStreamService.updateInviteInfo(inviteInfo); MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer(); @@ -1392,7 +1447,6 @@ public class PlayServiceImpl implements IPlayService { log.warn("mediaServer 不存在!"); throw new ServiceException("mediaServer不存在"); } - // zlm 暂停RTP超时检查 // 使用zlm中的流ID String streamKey = inviteInfo.getStream(); if (!mediaServerItem.isRtpEnable()) { @@ -1402,7 +1456,6 @@ public class PlayServiceImpl implements IPlayService { if (!result) { throw new ServiceException("继续RTP接收失败"); } - Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId()); DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId()); cmder.playResumeCmd(device, channel, inviteInfo.getStreamInfo()); } @@ -1598,30 +1651,34 @@ public class PlayServiceImpl implements IPlayService { @Override public void stop(InviteSessionType type, Device device, DeviceChannel channel, String stream) { - InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, channel.getId(), stream); - if (inviteInfo == null) { - if (type == InviteSessionType.PLAY) { + if (!userSetting.getServerId().equals(device.getServerId())) { + redisRpcPlayService.stop(device.getServerId(), type, channel.getId(), stream); + }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()); } - 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.getStreamInfo() != null) { + receiveRtpServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getSsrcInfo()); } } - - if (inviteInfo.getType() == InviteSessionType.PLAY) { - deviceChannelService.stopPlay(channel.getId()); - } - if (inviteInfo.getStreamInfo() != null) { - receiveRtpServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getSsrcInfo()); - } } @Override @@ -1662,13 +1719,19 @@ public class PlayServiceImpl implements IPlayService { log.warn("[点播] 未找到通道{}的设备信息", channel); throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error"); } - MediaServer mediaServer = getNewMediaServerItem(device); - if (mediaServer == null) { - log.warn("[点播] 未找到可用媒体节点"); + DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); + play(device, deviceChannel, callback); + } + + @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"); } DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); - play(mediaServer, device, deviceChannel, null, record, callback); + stop(inviteSessionType, device, deviceChannel, stream); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java deleted file mode 100755 index 3f24dbee4..000000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java +++ /dev/null @@ -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 data = new ConcurrentHashMap<>(); - - @Autowired - private DeferredResultHolder deferredResultHolder; - @Autowired - private RecordEndEventListener recordEndEventListener; - - - public int put(String deviceId,String channelId, String sn, int sumNum, List 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 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); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java index 102f9d0c9..56a649bc5 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java @@ -1,5 +1,6 @@ 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.Device; import com.genersoft.iot.vmp.gb28181.bean.Platform; @@ -60,9 +61,12 @@ public class SipRunner implements CommandLineRunner { @Autowired private ISendRtpServerService sendRtpServerService; + @Autowired + private UserSetting userSetting; + @Override public void run(String... args) throws Exception { - List deviceList = deviceService.getAllOnlineDevice(); + List deviceList = deviceService.getAllOnlineDevice(userSetting.getServerId()); for (Device device : deviceList) { if (deviceService.expire(device)){ @@ -86,7 +90,8 @@ public class SipRunner implements CommandLineRunner { deviceMapInDb.put(device.getDeviceId(), 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()); } }); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java index dfb7a5d82..b7892dbd3 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java @@ -94,7 +94,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult<>(responseEvent); 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 eventResult = new SipSubscribe.EventResult<>(responseEvent); sipEvent.getErrorEvent().response(eventResult); } - sipSubscribe.removeSubscribe(callIdHeader.getCallId()); + sipSubscribe.removeSubscribe(callIdHeader.getCallId() + cSeqHeader.getSeqNumber()); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java index f033f53ed..ba2a04432 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java @@ -75,12 +75,12 @@ public class SIPSender { CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME); String key = callIdHeader.getCallId() + cSeqHeader.getSeqNumber(); SipEvent sipEvent = SipEvent.getInstance(key, eventResult -> { - sipSubscribe.removeSubscribe(callIdHeader.getCallId()); + sipSubscribe.removeSubscribe(key); if(okEvent != null) { okEvent.response(eventResult); } }, (eventResult -> { - sipSubscribe.removeSubscribe(callIdHeader.getCallId()); + sipSubscribe.removeSubscribe(key); if (errorEvent != null) { errorEvent.response(eventResult); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java index 61aaac4a0..d39ce28e5 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -18,20 +18,6 @@ import java.util.concurrent.ConcurrentHashMap; @SuppressWarnings(value = {"rawtypes", "unchecked"}) @Component 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"; @@ -39,20 +25,11 @@ public class DeferredResultHolder { 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 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"; private Map> map = new ConcurrentHashMap<>(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index 60c639326..784a73c64 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -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.media.event.hook.HookSubscribe; 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 gov.nist.javax.sip.message.SIPRequest; @@ -142,7 +143,7 @@ public interface ISIPCommander { * @param channelId 预览通道 * @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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 远程启动控制命令 @@ -156,7 +157,7 @@ public interface ISIPCommander { * * @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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 报警复位命令 @@ -165,7 +166,7 @@ public interface ISIPCommander { * @param alarmMethod 报警方式(可选) * @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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 强制关键帧命令,设备收到此命令应立刻发送一个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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 设备配置命令 @@ -190,30 +191,24 @@ public interface ISIPCommander { /** * 设备配置命令: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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询设备状态 * * @param device 视频设备 */ - void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + void deviceStatusQuery(Device device, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询设备信息 - * - * @param device 视频设备 - * @return + * + * @param device 视频设备 + * @param callback + * @return */ - void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException; + void deviceInfoQuery(Device device, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询目录列表 @@ -245,7 +240,7 @@ public interface ISIPCommander { * @return true = 命令发送成功 */ 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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询设备配置 @@ -254,14 +249,14 @@ public interface ISIPCommander { * @param channelId 通道编码(可选) * @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 callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询设备预置位置 * * @param device 视频设备 */ - void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + void presetQuery(Device device, String channelId, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException; /** * 查询移动设备位置数据 @@ -304,7 +299,7 @@ public interface ISIPCommander { * @param channelId 通道id * @param cmdString 前端控制指令串 */ - void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException; + void dragZoomCmd(Device device, String channelId, String cmdString, ErrorCallback 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; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 905239dfd..8b0731131 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -7,7 +7,9 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.SipLayer; 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.sip.MessageEvent; import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 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.HookType; 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.utils.DateUtil; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import lombok.extern.slf4j.Slf4j; @@ -71,6 +75,9 @@ public class SIPCommander implements ISIPCommander { @Autowired private IMediaServerService mediaServerService; + @Autowired + private MessageSubscribe messageSubscribe; + /** @@ -671,13 +678,16 @@ public class SIPCommander implements ISIPCommander { * @param recordCmdStr 录像命令:Record / StopRecord */ @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 callback) throws InvalidArgumentException, SipException, ParseException { + final String cmdType = "DeviceControl"; + final int sn = (int) ((Math.random() * 9 + 1) * 100000); + StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); if (ObjectUtils.isEmpty(channelId)) { cmdXml.append("" + device.getDeviceId() + "\r\n"); } else { @@ -686,10 +696,14 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("" + recordCmdStr + "\r\n"); cmdXml.append("\r\n"); - + MessageEvent 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())); - 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" */ @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 callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceControl"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); cmdXml.append("" + device.getDeviceId() + "\r\n"); cmdXml.append("" + guardCmdStr + "\r\n"); cmdXml.append("\r\n"); - + MessageEvent 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())); - 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 视频设备 */ @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 callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceControl"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); cmdXml.append("" + device.getDeviceId() + "\r\n"); cmdXml.append("ResetAlarm\r\n"); if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { @@ -771,10 +795,14 @@ public class SIPCommander implements ISIPCommander { } cmdXml.append("\r\n"); - + MessageEvent 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())); - 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 */ @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 callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceControl"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("DeviceControl\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); if (ObjectUtils.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); + channelId = device.getDeviceId(); } + cmdXml.append("" + channelId + "\r\n"); cmdXml.append("\r\n"); if (enabled) { cmdXml.append("1\r\n"); @@ -840,10 +870,14 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("\r\n"); cmdXml.append("\r\n"); - + MessageEvent 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())); - 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 - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param name 设备/通道名称(可选) - * @param expiration 注册过期时间(可选) - * @param heartBeatInterval 心跳间隔时间(可选) - * @param heartBeatCount 心跳超时次数(可选) */ @Override - public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, - String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { + public void deviceBasicConfigCmd(Device device, BasicParam basicParam, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException { + int sn = (int) ((Math.random() * 9 + 1) * 100000); + String cmdType = "DeviceConfig"; StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("DeviceConfig\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); + String channelId = basicParam.getChannelId(); if (ObjectUtils.isEmpty(channelId)) { - cmdXml.append("" + device.getDeviceId() + "\r\n"); - } else { - cmdXml.append("" + channelId + "\r\n"); + channelId = device.getDeviceId(); } + cmdXml.append("" + channelId + "\r\n"); cmdXml.append("\r\n"); - if (!ObjectUtils.isEmpty(name)) { - cmdXml.append("" + name + "\r\n"); + if (!ObjectUtils.isEmpty(basicParam.getName())) { + cmdXml.append("" + basicParam.getName() + "\r\n"); } - if (NumericUtil.isInteger(expiration)) { - if (Integer.valueOf(expiration) > 0) { - cmdXml.append("" + expiration + "\r\n"); + if (NumericUtil.isInteger(basicParam.getExpiration())) { + if (Integer.parseInt(basicParam.getExpiration()) > 0) { + cmdXml.append("" + basicParam.getExpiration() + "\r\n"); } } - if (NumericUtil.isInteger(heartBeatInterval)) { - if (Integer.valueOf(heartBeatInterval) > 0) { - cmdXml.append("" + heartBeatInterval + "\r\n"); - } + if (basicParam.getHeartBeatInterval() != null && basicParam.getHeartBeatInterval() > 0) { + cmdXml.append("" + basicParam.getHeartBeatInterval() + "\r\n"); } - if (NumericUtil.isInteger(heartBeatCount)) { - if (Integer.valueOf(heartBeatCount) > 0) { - cmdXml.append("" + heartBeatCount + "\r\n"); - } + if (basicParam.getHeartBeatCount() != null && basicParam.getHeartBeatCount() > 0) { + cmdXml.append("" + basicParam.getHeartBeatCount() + "\r\n"); } cmdXml.append("\r\n"); cmdXml.append("\r\n"); + MessageEvent 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())); - 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 视频设备 */ @Override - public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { + public void deviceStatusQuery(Device device, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceStatus"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); String charset = device.getCharset(); StringBuffer catalogXml = new StringBuffer(200); catalogXml.append("\r\n"); catalogXml.append("\r\n"); - catalogXml.append("DeviceStatus\r\n"); - catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + cmdType + "\r\n"); + catalogXml.append("" + sn + "\r\n"); catalogXml.append("" + device.getDeviceId() + "\r\n"); catalogXml.append("\r\n"); - + MessageEvent 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())); - 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 - public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException { + public void deviceInfoQuery(Device device, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceInfo"; + String sn = (int) ((Math.random() * 9 + 1) * 100000) + ""; StringBuffer catalogXml = new StringBuffer(200); String charset = device.getCharset(); catalogXml.append("\r\n"); catalogXml.append("\r\n"); - catalogXml.append("DeviceInfo\r\n"); - catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + cmdType +"\r\n"); + catalogXml.append("" + sn + "\r\n"); catalogXml.append("" + device.getDeviceId() + "\r\n"); catalogXml.append("\r\n"); - + MessageEvent 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())); - 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 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 callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "Alarm"; + String sn = (int) ((Math.random() * 9 + 1) * 100000) + ""; StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("Alarm\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); cmdXml.append("" + device.getDeviceId() + "\r\n"); if (!ObjectUtils.isEmpty(startPriority)) { cmdXml.append("" + startPriority + "\r\n"); @@ -1069,10 +1118,14 @@ public class SIPCommander implements ISIPCommander { } cmdXml.append("\r\n"); - + MessageEvent 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())); - 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 配置类型: */ @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 callback) throws InvalidArgumentException, SipException, ParseException { + String cmdType = "ConfigDownload"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("ConfigDownload\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); if (ObjectUtils.isEmpty(channelId)) { cmdXml.append("" + device.getDeviceId() + "\r\n"); } else { @@ -1099,10 +1154,14 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("" + configType + "\r\n"); cmdXml.append("\r\n"); - + MessageEvent 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())); - 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 视频设备 */ @Override - public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { + public void presetQuery(Device device, String channelId, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "PresetQuery"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); cmdXml.append("\r\n"); cmdXml.append("\r\n"); - cmdXml.append("PresetQuery\r\n"); - cmdXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + cmdXml.append("" + cmdType + "\r\n"); + cmdXml.append("" + sn + "\r\n"); if (ObjectUtils.isEmpty(channelId)) { cmdXml.append("" + device.getDeviceId() + "\r\n"); } else { @@ -1126,9 +1188,14 @@ public class SIPCommander implements ISIPCommander { } cmdXml.append("\r\n"); + MessageEvent 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())); - 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 - public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException { + public void dragZoomCmd(Device device, String channelId, String cmdString, ErrorCallback callback) throws InvalidArgumentException, SipException, ParseException { + + String cmdType = "DeviceControl"; + int sn = (int) ((Math.random() * 9 + 1) * 100000); StringBuffer dragXml = new StringBuffer(200); String charset = device.getCharset(); dragXml.append("\r\n"); dragXml.append("\r\n"); - dragXml.append("DeviceControl\r\n"); - dragXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + dragXml.append("" + cmdType + "\r\n"); + dragXml.append("" + sn + "\r\n"); if (ObjectUtils.isEmpty(channelId)) { dragXml.append("" + device.getDeviceId() + "\r\n"); } else { @@ -1283,8 +1353,10 @@ public class SIPCommander implements ISIPCommander { dragXml.append(cmdString); dragXml.append("\r\n"); + MessageEvent 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())); - log.debug("拉框信令: " + request.toString()); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index 34545b7cc..4ddbc22be 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -121,7 +121,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements SIPRequest request = (SIPRequest)evt.getRequest(); try { - InviteInfo inviteInfo = decode(evt); + InviteMessageInfo inviteInfo = decode(evt); // 查询请求是否来自上级平台\设备 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(); 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); content.append("v=0\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) { log.warn("来自设备的Invite请求,无法从请求信息中确定请求来自的通道,已忽略,requesterId: {}", inviteInfo.getRequesterId()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index 05839f8a5..85eff4105 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -183,7 +183,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen device.setGeoCoordSys("WGS84"); } } - + device.setServerId(userSetting.getServerId()); device.setIp(remoteAddressInfo.getIp()); device.setPort(remoteAddressInfo.getPort()); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java index c4a8f2680..8f7e036af 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java @@ -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.impl.message.IMessageHandler; 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 lombok.extern.slf4j.Slf4j; import org.dom4j.Element; @@ -316,7 +317,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent private void handleDragZoom(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) { if (channel.getDataType() != ChannelDataType.GB28181.value) { // 只支持国标的云台控制 - log.warn("[INFO 消息] 只支持国标的拉框控制, 通道ID: {}", channel.getGbId()); + log.warn("[deviceControl-DragZoom] 只支持国标的拉框控制, 通道ID: {}", channel.getGbId()); try { responseAck(request, Response.FORBIDDEN, ""); } catch (SipException | InvalidArgumentException | ParseException e) { @@ -328,7 +329,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent Device device = deviceService.getDevice(channel.getDataDeviceId()); if (device == null) { // 不存在则回复404 - log.warn("[INFO 消息] 通道所属设备不存在, 通道ID: {}", channel.getGbId()); + log.warn("[deviceControl-DragZoom] 通道所属设备不存在, 通道ID: {}", channel.getGbId()); try { responseAck(request, Response.NOT_FOUND, "device not found"); } catch (SipException | InvalidArgumentException | ParseException e) { @@ -339,7 +340,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); if (deviceChannel == null) { - log.warn("[deviceControl] 未找到设备原始通道, 设备: {}({}),通道编号:{}", device.getName(), + log.warn("[deviceControl-DragZoom] 未找到设备原始通道, 设备: {}({}),通道编号:{}", device.getName(), device.getDeviceId(), channel.getGbId()); try { responseAck(request, Response.NOT_FOUND, "channel not found"); @@ -352,7 +353,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent deviceChannel.getName(), deviceChannel.getDeviceId()); try { DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class); - DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn(); + DragZoomParam dragZoom = dragZoomRequest.getDragZoomIn(); if (dragZoom == null) { dragZoom = dragZoomRequest.getDragZoomOut(); } @@ -365,7 +366,9 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent cmdXml.append("" + dragZoom.getLengthX() + "\r\n"); cmdXml.append("" + dragZoom.getLengthY() + "\r\n"); cmdXml.append("\r\n"); - cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString()); + cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString(), (code, msg, data) -> { + + }); responseAck(request, Response.OK); } catch (Exception e) { log.error("[命令发送失败] 拉框控制: {}", e.getMessage()); @@ -417,9 +420,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class); //获取整个消息主体,我们只需要修改请求头即可 HomePositionRequest.HomePosition info = homePosition.getHomePosition(); - cmder.homePositionCmd(device, deviceChannel.getDeviceId(), !"0".equals(info.getEnabled()), Integer.parseInt(info.getResetTime()), Integer.parseInt(info.getPresetIndex()), - errorResult -> onError(request, errorResult), - okResult -> onOk(request, okResult)); + cmder.homePositionCmd(device, deviceChannel.getDeviceId(), !"0".equals(info.getEnabled()), Integer.parseInt(info.getResetTime()), Integer.parseInt(info.getPresetIndex()), (code, msg, data) -> { + if (code == ErrorCode.SUCCESS.getCode()) { + onOk(request); + }else { + onError(request, code, msg); + } + }); } catch (Exception e) { log.error("[命令发送失败] 看守位设置: {}", e.getMessage()); } @@ -463,9 +470,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent } } try { - cmder.alarmCmd(device, alarmMethod, alarmType, - errorResult -> onError(request, errorResult), - okResult -> onOk(request, okResult)); + cmder.alarmResetCmd(device, alarmMethod, alarmType, (code, msg, data) -> { + if (code == ErrorCode.SUCCESS.getCode()) { + onOk(request); + }else { + onError(request, code, msg); + } + }); } catch (InvalidArgumentException | SipException | ParseException e) { log.error("[命令发送失败] 告警消息: {}", e.getMessage()); } @@ -515,9 +526,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent //获取整个消息主体,我们只需要修改请求头即可 String cmdString = getText(rootElement, type.getVal()); try { - cmder.recordCmd(device, deviceChannel.getDeviceId(), cmdString, - errorResult -> onError(request, errorResult), - okResult -> onOk(request, okResult)); + cmder.recordCmd(device, deviceChannel.getDeviceId(), cmdString, (code, msg, data) -> { + if (code == ErrorCode.SUCCESS.getCode()) { + onOk(request); + }else { + onError(request, code, msg); + } + }); } catch (InvalidArgumentException | SipException | ParseException e) { log.error("[命令发送失败] 录像控制: {}", e.getMessage()); } @@ -552,40 +567,47 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent //获取整个消息主体,我们只需要修改请求头即可 String cmdString = getText(rootElement, type.getVal()); try { - cmder.guardCmd(device, cmdString, - errorResult -> onError(request, errorResult), - okResult -> onOk(request, okResult)); + cmder.guardCmd(device, cmdString,(code, msg, data) -> { + if (code == ErrorCode.SUCCESS.getCode()) { + onOk(request); + }else { + onError(request, code, msg); + } + }); } catch (InvalidArgumentException | SipException | ParseException e) { 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 { - responseAck(request, eventResult.statusCode, eventResult.msg); + responseAck(request, code, msg); } catch (SipException | InvalidArgumentException | ParseException e) { log.error("[命令发送失败] 回复: {}", e.getMessage()); } } + private void onError(SIPRequest request, SipSubscribe.EventResult errorResult) { + onError(request, errorResult.statusCode, errorResult.msg); + } + /** * 成功响应处理 * * @param request 请求 - * @param eventResult 响应结构 */ - private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) { + private void onOk(SIPRequest request) { // 成功的回复 try { - responseAck(request, eventResult.statusCode); + responseAck(request, Response.OK); } catch (SipException | InvalidArgumentException | ParseException e) { log.error("[命令发送失败] 回复: {}", e.getMessage()); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java index f5cef7036..ecabdcb14 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java @@ -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.DeviceChannel; 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.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IGbChannelService; @@ -53,7 +53,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp private SIPCommander commander; @Autowired - private RecordEndEventListener recordEndEventListener; + private RecordInfoEventListener recordInfoEventListener; @Override public void afterPropertiesSet() throws Exception { @@ -127,7 +127,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp // 获取通道的原始信息 DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId()); // 接收录像数据 - recordEndEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{ + recordInfoEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{ try { log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId); cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java index 18da9cde9..6801622c8 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java @@ -1,11 +1,20 @@ 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.MessageRequestProcessor; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +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; + /** * 命令类型: 请求动作的应答 * 命令类型: 设备控制, 报警通知, 设备目录信息查询, 目录信息查询, 目录收到, 设备信息查询, 设备状态信息查询 ...... @@ -18,8 +27,32 @@ public class ResponseMessageHandler extends MessageHandlerAbstract implements In @Autowired private MessageRequestProcessor messageRequestProcessor; + @Autowired + private MessageSubscribe messageSubscribe; + @Override public void afterPropertiesSet() throws Exception { 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 subscribe = (MessageEvent)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); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java index 418534653..ffbe9075e 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java @@ -4,18 +4,22 @@ 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 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; @Slf4j @Component @@ -36,18 +40,18 @@ public class AlarmResponseMessageHandler extends SIPRequestProcessorParent imple @Override public void handForDevice(RequestEvent evt, Device device, Element rootElement) { - Element deviceIdElement = rootElement.element("DeviceID"); - String channelId = deviceIdElement.getText().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_ALARM + device.getDeviceId() + channelId; + // 回复200 OK + try { + responseAck((SIPRequest) evt.getRequest(), Response.OK); + } catch (SipException | InvalidArgumentException | ParseException e) { + log.error("[命令发送失败] 目录查询回复: {}", e.getMessage()); + } JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); if (log.isDebugEnabled()) { log.debug(json.toJSONString()); } - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(json); - deferredResultHolder.invokeAllResult(msg); + responseMessageHandler.handMessageEvent(rootElement, null); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java index d124f2369..6aa5cfa4d 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java @@ -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.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 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; @@ -23,8 +22,6 @@ 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 ConfigDownloadResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -48,13 +45,6 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar @Override 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 { // 回复200 OK responseAck((SIPRequest) evt.getRequest(), Response.OK); @@ -67,23 +57,33 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar if (log.isDebugEnabled()) { 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"); - Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval"); - Integer heartBeatCount = basicParam.getInteger("HeartBeatCount"); - Integer positionCapability = basicParam.getInteger("PositionCapability"); - device.setHeartBeatInterval(heartBeatInterval); - device.setHeartBeatCount(heartBeatCount); - device.setPositionCapability(positionCapability); - - deviceService.updateDeviceHeartInfo(device); - - - - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(json); - deferredResultHolder.invokeAllResult(msg); + if (basicParam != null) { + Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval"); + Integer heartBeatCount = basicParam.getInteger("HeartBeatCount"); + Integer positionCapability = basicParam.getInteger("PositionCapability"); + device.setHeartBeatInterval(heartBeatInterval); + device.setHeartBeatCount(heartBeatCount); + device.setPositionCapability(positionCapability); + deviceService.updateDeviceHeartInfo(device); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceConfigResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceConfigResponseMessageHandler.java deleted file mode 100755 index 453d8066f..000000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceConfigResponseMessageHandler.java +++ /dev/null @@ -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) { - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java deleted file mode 100755 index f3f489781..000000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java +++ /dev/null @@ -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) { - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java index 1de3ff7ab..24e7f5804 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java @@ -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.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.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; -import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import gov.nist.javax.sip.message.SIPRequest; import lombok.extern.slf4j.Slf4j; import org.dom4j.DocumentException; @@ -37,9 +35,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @Autowired private ResponseMessageHandler responseMessageHandler; - @Autowired - private DeferredResultHolder deferredResultHolder; - @Autowired private IDeviceService deviceService; @@ -70,9 +65,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent } 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.setManufacturer(getText(rootElement, "Manufacturer")); @@ -82,11 +74,8 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent device.setStreamMode("TCP-PASSIVE"); } deviceService.updateDevice(device); + responseMessageHandler.handMessageEvent(rootElement, device); - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(device); - deferredResultHolder.invokeAllResult(msg); } catch (DocumentException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java index c6e366445..a3c376aa3 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java @@ -3,14 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Platform; -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 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 lombok.extern.slf4j.Slf4j; import org.dom4j.Element; @@ -33,15 +30,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @Autowired private ResponseMessageHandler responseMessageHandler; - @Autowired - private DeferredResultHolder deferredResultHolder; - @Autowired private IDeviceService deviceService; - @Autowired - private IRedisCatchStorage redisCatchStorage; - @Override public void afterPropertiesSet() throws Exception { responseMessageHandler.addHandler(cmdType, this); @@ -60,9 +51,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen } catch (SipException | InvalidArgumentException | ParseException e) { log.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage()); } - Element deviceIdElement = element.element("DeviceID"); Element onlineElement = element.element("Online"); - String channelId = deviceIdElement.getText(); JSONObject json = new JSONObject(); XmlUtil.node2Json(element, json); if (log.isDebugEnabled()) { @@ -74,10 +63,8 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen }else { deviceService.offline(device.getDeviceId(), "设备状态查询结果:" + text.trim()); } - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId()); - msg.setData(json); - deferredResultHolder.invokeAllResult(msg); + responseMessageHandler.handMessageEvent(element, text); + } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java index 21626d8bf..5e154f6e7 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java @@ -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.Preset; 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; @@ -25,8 +24,6 @@ import java.util.ArrayList; import java.util.Iterator; 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 snElement = rootElement.element("SN"); //该字段可能为通道或则设备的id - String deviceId = getText(rootElement, "DeviceID"); - String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId; if (snElement == null || presetListNumElement == null) { try { responseAck(request, Response.BAD_REQUEST, "xml error"); @@ -98,10 +93,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent presetQuerySipReqList.add(presetQuerySipReq); } } - RequestMessage requestMessage = new RequestMessage(); - requestMessage.setKey(key); - requestMessage.setData(presetQuerySipReqList); - deferredResultHolder.invokeAllResult(requestMessage); + responseMessageHandler.handMessageEvent(rootElement, presetQuerySipReqList); try { responseAck(request, Response.OK); } catch (InvalidArgumentException | ParseException | SipException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java index 655c05511..0ab97e87f 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java @@ -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.RecordItem; 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.RequestMessage; 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.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; @@ -48,14 +51,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent private ResponseMessageHandler responseMessageHandler; @Autowired - private DeferredResultHolder deferredResultHolder; - - @Autowired - private EventPublisher eventPublisher; - - @Qualifier("taskExecutor") - @Autowired - private ThreadPoolTaskExecutor taskExecutor; + private ApplicationEventPublisher applicationEventPublisher; @Autowired private RedisTemplate redisTemplate; @@ -75,88 +71,89 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent }catch (SipException | InvalidArgumentException | ParseException e) { log.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage()); } - taskExecutor.execute(()->{ - try { - String sn = getText(rootElement, "SN"); - String channelId = getText(rootElement, "DeviceID"); - RecordInfo recordInfo = new RecordInfo(); - recordInfo.setChannelId(channelId); - recordInfo.setDeviceId(device.getDeviceId()); - recordInfo.setSn(sn); - recordInfo.setName(getText(rootElement, "Name")); - String sumNumStr = getText(rootElement, "SumNum"); - int sumNum = 0; - if (!ObjectUtils.isEmpty(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 recordListIterator = recordListElement.elementIterator(); - if (recordListIterator != null) { - List 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 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 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); + try { + String sn = getText(rootElement, "SN"); + String channelId = getText(rootElement, "DeviceID"); + RecordInfo recordInfo = new RecordInfo(); + recordInfo.setChannelId(channelId); + recordInfo.setDeviceId(device.getDeviceId()); + recordInfo.setSn(sn); + recordInfo.setName(getText(rootElement, "Name")); + String sumNumStr = getText(rootElement, "SumNum"); + int sumNum = 0; + if (!ObjectUtils.isEmpty(sumNumStr)) { + sumNum = Integer.parseInt(sumNumStr); } - }); + recordInfo.setSumNum(sumNum); + Element recordListElement = rootElement.element("RecordList"); + if (recordListElement == null || sumNum == 0) { + log.info("无录像数据"); + recordInfo.setCount(sumNum); + recordInfoEventPush(recordInfo); + recordInfoEndEventPush(recordInfo); + } else { + Iterator recordListIterator = recordListElement.elementIterator(); + if (recordListIterator != null) { + List 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 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 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 @@ -164,18 +161,31 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent } - public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){ - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; - // 对数据进行排序 - if(recordInfo!=null && recordInfo.getRecordList()!=null) { + private void recordInfoEventPush(RecordInfo recordInfo) { + if (recordInfo == null) { + return; + } + if(recordInfo.getRecordList() != null) { Collections.sort(recordInfo.getRecordList()); }else{ recordInfo.setRecordList(new ArrayList<>()); } + RecordInfoEvent outEvent = new RecordInfoEvent(this); + outEvent.setRecordInfo(recordInfo); + applicationEventPublisher.publishEvent(outEvent); + } - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(recordInfo); - deferredResultHolder.invokeAllResult(msg); + private void recordInfoEndEventPush(RecordInfo recordInfo) { + if (recordInfo == null) { + return; + } + if(recordInfo.getRecordList() != null) { + Collections.sort(recordInfo.getRecordList()); + }else{ + recordInfo.setRecordList(new ArrayList<>()); + } + RecordInfoEndEvent outEvent = new RecordInfoEndEvent(this); + outEvent.setRecordInfo(recordInfo); + applicationEventPublisher.publishEvent(outEvent); } } diff --git a/src/main/java/com/genersoft/iot/vmp/jt1078/util/ClassUtil.java b/src/main/java/com/genersoft/iot/vmp/jt1078/util/ClassUtil.java index 9c3fd2868..def0c0eb0 100644 --- a/src/main/java/com/genersoft/iot/vmp/jt1078/util/ClassUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/jt1078/util/ClassUtil.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.jt1078.util; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -12,6 +13,12 @@ import java.util.List; @Slf4j public class ClassUtil { + public static ConfigurableApplicationContext context; + + public static T getBean(String beanName, Class clazz) { + return context.getBean(beanName, clazz); + } + public static Object getBean(Class clazz) { if (clazz != null) { try { diff --git a/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java index b9f7c08ef..ba27fb350 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.media; 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.event.mediaServer.MediaServerChangeEvent; import com.genersoft.iot.vmp.media.service.IMediaServerService; @@ -30,6 +31,9 @@ public class MediaServerConfig implements CommandLineRunner { @Autowired private MediaConfig mediaConfig; + @Autowired + private UserSetting userSetting; + @Override public void run(String... strings) throws Exception { @@ -37,6 +41,7 @@ public class MediaServerConfig implements CommandLineRunner { mediaServerService.clearMediaServerForOnline(); MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer(); MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem(); + mediaSerItemInConfig.setServerId(userSetting.getServerId()); if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) { mediaServerService.update(mediaSerItemInConfig); }else { diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java index e6faac364..2660cb6a9 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java @@ -103,6 +103,9 @@ public class MediaServer { @Schema(description = "转码的前缀") private String transcodeSuffix; + @Schema(description = "服务Id") + private String serverId; + public MediaServer() { } @@ -388,4 +391,12 @@ public class MediaServer { public void setTranscodeSuffix(String transcodeSuffix) { this.transcodeSuffix = transcodeSuffix; } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java index a088366a7..11043c42f 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java @@ -1,6 +1,5 @@ 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.StreamInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -50,7 +49,6 @@ import java.util.*; */ @Slf4j @Service -@DS("master") public class MediaServerServiceImpl implements IMediaServerService { @Autowired @@ -305,7 +303,7 @@ public class MediaServerServiceImpl implements IMediaServerService { mediaServerMapper.update(mediaSerItem); MediaServer mediaServerInRedis = getOne(mediaSerItem.getId()); // 获取完整数据 - MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); + MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId(), userSetting.getServerId()); if (mediaServerInDataBase == null) { return; } @@ -352,7 +350,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public List getAll() { - List mediaServerList = mediaServerMapper.queryAll(); + List mediaServerList = mediaServerMapper.queryAll(userSetting.getServerId()); if (mediaServerList.isEmpty()) { return new ArrayList<>(); } @@ -368,7 +366,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public List getAllFromDatabase() { - return mediaServerMapper.queryAll(); + return mediaServerMapper.queryAll(userSetting.getServerId()); } @Override @@ -405,7 +403,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public MediaServer getDefaultMediaServer() { - return mediaServerMapper.queryDefault(); + return mediaServerMapper.queryDefault(userSetting.getServerId()); } @Override @@ -425,7 +423,7 @@ public class MediaServerServiceImpl implements IMediaServerService { log.info("[添加媒体节点] 失败, mediaServer的类型:为空"); return; } - if (mediaServerMapper.queryOne(mediaServer.getId()) != null) { + if (mediaServerMapper.queryOne(mediaServer.getId(), userSetting.getServerId()) != null) { log.info("[添加媒体节点] 失败, 媒体服务ID已存在,请修改媒体服务器配置, {}", mediaServer.getId()); throw new ControllerException(ErrorCode.ERROR100.getCode(),"保存失败,媒体服务ID [ " + mediaServer.getId() + " ] 已存在,请修改媒体服务器配置"); } @@ -523,7 +521,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override 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(), "此连接已存在"); } @@ -534,7 +532,7 @@ public class MediaServerServiceImpl implements IMediaServerService { } MediaServer mediaServer = mediaNodeServerService.checkMediaServer(ip, port, secret); 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() + " ] 已存在,请修改媒体服务器配置"); } } @@ -562,7 +560,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override 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()); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServer.getId(); redisTemplate.delete(key); @@ -574,13 +572,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public MediaServer getOneFromDatabase(String mediaServerId) { - return mediaServerMapper.queryOne(mediaServerId); + return mediaServerMapper.queryOne(mediaServerId, userSetting.getServerId()); } @Override public void syncCatchFromDatabase() { List allInCatch = getAllOnlineList(); - List allInDatabase = mediaServerMapper.queryAll(); + List allInDatabase = mediaServerMapper.queryAll(userSetting.getServerId()); Map mediaServerMap = new HashMap<>(); for (MediaServer mediaServer : allInDatabase) { @@ -608,7 +606,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public List getAllWithAssistPort() { - return mediaServerMapper.queryAllWithAssistPort(); + return mediaServerMapper.queryAllWithAssistPort(userSetting.getServerId()); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java index 8c7929dd8..e0df42dcc 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java @@ -89,6 +89,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService { @Override public MediaServer checkMediaServer(String ip, int port, String secret) { MediaServer mediaServer = new MediaServer(); + mediaServer.setServerId(userSetting.getServerId()); mediaServer.setIp(ip); mediaServer.setHttpPort(port); mediaServer.setFlvPort(port); diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java index 3716d73ee..33fd03648 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java @@ -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.utils.MediaServerUtils; +import lombok.Data; import java.util.Map; /** * 云端录像数据 */ +@Data public class CloudRecordItem { /** * 主键 @@ -79,6 +81,11 @@ public class CloudRecordItem { */ private long timeLen; + /** + * 所属服务ID + */ + private String serverId; + public static CloudRecordItem getInstance(MediaRecordMp4Event param) { CloudRecordItem cloudRecordItem = new CloudRecordItem(); cloudRecordItem.setApp(param.getApp()); @@ -98,115 +105,4 @@ public class 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; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java index 725115fcd..5523bd3c0 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.service.impl; import com.alibaba.fastjson2.JSONArray; 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.gb28181.service.ICloudRecordService; 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.service.bean.CloudRecordItem; 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.dao.CloudRecordServiceMapper; import com.genersoft.iot.vmp.utils.CloudRecordUtils; @@ -36,7 +37,6 @@ import java.util.Set; @Slf4j @Service -@DS("share") public class CloudRecordServiceImpl implements ICloudRecordService { @Autowired @@ -51,8 +51,15 @@ public class CloudRecordServiceImpl implements ICloudRecordService { @Autowired private AssistRESTfulUtils assistRESTfulUtils; + @Autowired + private UserSetting userSetting; + + @Autowired + private IRedisRpcPlayService redisRpcPlayService; + @Override - public PageInfo getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List mediaServerItems, String callId) { + public PageInfo getList(int page, int count, String query, String app, String stream, String startTime, + String endTime, List mediaServerItems, String callId) { // 开始时间和结束时间在数据库中都是以秒为单位的 Long startTimeStamp = null; Long endTimeStamp = null; @@ -109,6 +116,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { @EventListener public void onApplicationEvent(MediaRecordMp4Event event) { CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event); + cloudRecordItem.setServerId(userSetting.getServerId()); if (ObjectUtils.isEmpty(cloudRecordItem.getCallId())) { StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream()); if (streamAuthorityInfo != null) { @@ -237,6 +245,9 @@ public class CloudRecordServiceImpl implements ICloudRecordService { if (recordItem == null) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在"); } + if (!userSetting.getServerId().equals(recordItem.getServerId())) { + return redisRpcPlayService.getRecordPlayUrl(recordItem.getServerId(), recordId); + } String filePath = recordItem.getFilePath(); MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId()); return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java index f12c3cb8f..d31bbcefb 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java @@ -1,6 +1,5 @@ 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.storager.dao.RoleMapper; import com.genersoft.iot.vmp.storager.dao.dto.Role; @@ -10,7 +9,6 @@ import org.springframework.stereotype.Service; import java.util.List; @Service -@DS("master") public class RoleServerImpl implements IRoleService { @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/UserApiKeyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/UserApiKeyServiceImpl.java index 85ee4f0f5..8c552b10f 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/UserApiKeyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/UserApiKeyServiceImpl.java @@ -1,6 +1,5 @@ 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.storager.dao.UserApiKeyMapper; import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey; @@ -15,7 +14,6 @@ import org.springframework.stereotype.Service; import java.util.List; @Service -@DS("master") public class UserApiKeyServiceImpl implements IUserApiKeyService { @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java index fb97db939..cf0bea20f 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java @@ -1,6 +1,5 @@ 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.storager.dao.UserMapper; import com.genersoft.iot.vmp.storager.dao.dto.User; @@ -13,7 +12,6 @@ import org.springframework.util.DigestUtils; import java.util.List; @Service -@DS("master") public class UserServiceImpl implements IUserService { @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcPlayService.java new file mode 100644 index 000000000..174fa6b67 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcPlayService.java @@ -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 callback); + + void stop(String serverId, InviteSessionType type, int channelId, String stream); + + void playback(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback callback); + + void download(String serverId, Integer channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback callback); + + void queryRecordInfo(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback 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 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); +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcService.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcService.java index 7e23e2767..549af39b7 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/IRedisRpcService.java @@ -2,7 +2,8 @@ package com.genersoft.iot.vmp.service.redisMsg; import com.genersoft.iot.vmp.common.CommonCallback; 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; public interface IRedisRpcService { @@ -23,4 +24,44 @@ public interface IRedisRpcService { long onStreamOnlineEvent(String app, String stream, CommonCallback callback); 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 devicesSync(String serverId, String deviceId); + + SyncStatus getChannelSyncStatus(String serverId, String deviceId); + + WVPResult deviceBasicConfig(String serverId, Device device, BasicParam basicParam); + + WVPResult deviceConfigQuery(String serverId, Device device, String channelId, String configType); + + void teleboot(String serverId, Device device); + + WVPResult recordControl(String serverId, Device device, String channelId, String recordCmdStr); + + WVPResult guard(String serverId, Device device, String guardCmdStr); + + WVPResult resetAlarm(String serverId, Device device, String channelId, String alarmMethod, String alarmType); + + void iFrame(String serverId, Device device, String channelId); + + WVPResult 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 deviceStatus(String serverId, Device device); + + WVPResult alarm(String serverId, Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); + + WVPResult deviceInfo(String serverId, Device device); + + WVPResult queryPreset(String serverId, Device device, String channelId); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java index d4f65e138..886cd88eb 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java @@ -105,7 +105,7 @@ public class RedisAlarmMsgListener implements MessageListener { if (ObjectUtils.isEmpty(gbId)) { if (userSetting.getSendToPlatformsWhenIdLost()) { // 发送给所有的上级 - List parentPlatforms = platformService.queryEnablePlatformList(); + List parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId()); if (!parentPlatforms.isEmpty()) { for (Platform parentPlatform : parentPlatforms) { try { diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcChannelPlayController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcChannelPlayController.java new file mode 100644 index 000000000..84b444084 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcChannelPlayController.java @@ -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 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; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcCloudRecordController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcCloudRecordController.java new file mode 100644 index 000000000..516f5bfb4 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcCloudRecordController.java @@ -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 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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDeviceController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDeviceController.java new file mode 100644 index 000000000..a6d727e1f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDeviceController.java @@ -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 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 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; + } + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDevicePlayController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDevicePlayController.java new file mode 100644 index 000000000..2e83cc71f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcDevicePlayController.java @@ -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 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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcGbDeviceController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcGbDeviceController.java new file mode 100644 index 000000000..798c938c7 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcGbDeviceController.java @@ -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 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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcPlatformController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcPlatformController.java new file mode 100644 index 000000000..c5a9f4604 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcPlatformController.java @@ -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 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 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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcSendRtpController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcSendRtpController.java new file mode 100644 index 000000000..fa8180252 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcSendRtpController.java @@ -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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamProxyController.java new file mode 100644 index 000000000..55764c531 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamProxyController.java @@ -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 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; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamPushController.java similarity index 54% rename from src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcController.java rename to src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamPushController.java index b74df842f..d9fd90ed2 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcController.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/control/RedisRpcStreamPushController.java @@ -3,33 +3,32 @@ 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.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.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.event.hook.Hook; import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.event.hook.HookType; 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.streamPush.service.IStreamPushPlayService; 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; -/** - * 其他wvp发起的rpc调用,这里的方法被 RedisRpcConfig 通过反射寻找对应的方法名称调用 - */ -@Slf4j @Component -public class RedisRpcController { +@Slf4j +@RedisRpcController("streamPush") +public class RedisRpcStreamPushController extends RpcController { @Autowired private SSRCFactory ssrcFactory; @@ -49,52 +48,22 @@ public class RedisRpcController { @Autowired private RedisTemplate redisTemplate; + @Autowired + private IStreamPushPlayService streamPushPlayService; - /** - * 获取发流的信息 - */ - 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(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; + + 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("waitePushStreamOnline") public RedisRpcResponse waitePushStreamOnline(RedisRpcRequest request) { SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class); log.info("[redis-rpc] 监听流上线: {}/{}, 目标地址: {}:{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort()); @@ -115,7 +84,7 @@ public class RedisRpcController { sendRtpServerService.update(sendRtpItem); RedisRpcResponse response = request.getResponse(); response.setBody(sendRtpItem.getChannelId()); - response.setStatusCode(200); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); } // 监听流上线。 流上线直接发送sendRtpItem消息给实际的信令处理者 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); RedisRpcResponse response = request.getResponse(); response.setBody(sendRtpItem.getChannelId()); - response.setStatusCode(200); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); // 手动发送结果 sendResponse(response); hookSubscribe.removeSubscribe(hook); @@ -146,6 +115,7 @@ public class RedisRpcController { /** * 监听流上线 */ + @RedisRpcMapping("onStreamOnlineEvent") public RedisRpcResponse onStreamOnlineEvent(RedisRpcRequest request) { StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class); log.info("[redis-rpc] 监听流信息,等待流上线: {}/{}", streamInfo.getApp(), streamInfo.getStream()); @@ -155,7 +125,7 @@ public class RedisRpcController { log.info("[redis-rpc] 监听流上线时发现流已存在直接返回: {}/{}", streamInfo.getApp(), streamInfo.getStream()); RedisRpcResponse response = request.getResponse(); response.setBody(JSONObject.toJSONString(streamInfoInServer)); - response.setStatusCode(200); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); return response; } // 监听流上线。 流上线直接发送sendRtpItem消息给实际的信令处理者 @@ -168,7 +138,7 @@ public class RedisRpcController { streamInfo.getApp(), streamInfo.getStream(), hookData.getMediaInfo(), hookData.getMediaInfo() != null ? hookData.getMediaInfo().getCallId() : null); response.setBody(JSONObject.toJSONString(streamInfoByAppAndStream)); - response.setStatusCode(200); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); // 手动发送结果 sendResponse(response); hookSubscribe.removeSubscribe(hook); @@ -179,6 +149,7 @@ public class RedisRpcController { /** * 停止监听流上线 */ + @RedisRpcMapping("stopWaitePushStreamOnline") public RedisRpcResponse stopWaitePushStreamOnline(RedisRpcRequest request) { SendRtpInfo sendRtpItem = JSONObject.parseObject(request.getParam().toString(), SendRtpInfo.class); 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); hookSubscribe.removeSubscribe(hook); RedisRpcResponse response = request.getResponse(); - response.setStatusCode(200); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); return response; } /** * 停止监听流上线 */ + @RedisRpcMapping("unPushStreamOnlineEvent") public RedisRpcResponse unPushStreamOnlineEvent(RedisRpcRequest request) { StreamInfo streamInfo = JSONObject.parseObject(request.getParam().toString(), StreamInfo.class); 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); hookSubscribe.removeSubscribe(hook); RedisRpcResponse response = request.getResponse(); - response.setStatusCode(200); - 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); + response.setStatusCode(ErrorCode.SUCCESS.getCode()); return response; } /** - * 停止发流 + * 停止监听流上线 */ - public RedisRpcResponse stopSendRtp(RedisRpcRequest request) { - String callId = request.getParam().toString(); - SendRtpInfo sendRtpItem = sendRtpServerService.queryByCallId(callId); + @RedisRpcMapping("play") + public RedisRpcResponse play(RedisRpcRequest request) { + int id = Integer.parseInt(request.getParam().toString()); RedisRpcResponse response = request.getResponse(); - response.setStatusCode(200); - if (sendRtpItem == null) { - log.info("[redis-rpc] 停止推流, 未找到redis中的发流信息, key:{}", callId); - WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到redis中的发流信息"); - response.setBody(wvpResult); + if (id <= 0) { + response.setStatusCode(ErrorCode.ERROR400.getCode()); + response.setBody("param error"); 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; + streamPushPlayService.start(id, (code, msg, data) -> { + if (code == ErrorCode.SUCCESS.getCode()) { + response.setStatusCode(ErrorCode.SUCCESS.getCode()); + response.setBody(JSONObject.toJSONString(data)); + sendResponse(response); + } + }, null, null); + return null; } - 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); - } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcController.java new file mode 100644 index 000000000..f314b0c01 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcController.java @@ -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 ""; +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcMapping.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcMapping.java new file mode 100644 index 000000000..61f51bb68 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RedisRpcMapping.java @@ -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 ""; +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RpcController.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RpcController.java new file mode 100644 index 000000000..4544812f5 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/dto/RpcController.java @@ -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)); + } + } + + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcPlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcPlayServiceImpl.java new file mode 100644 index 000000000..4404a7205 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcPlayServiceImpl.java @@ -0,0 +1,257 @@ +package com.genersoft.iot.vmp.service.redisMsg.service; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.common.StreamInfo; +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.RedisRpcRequest; +import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse; +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.service.bean.InviteErrorCode; +import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService; +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.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +public class RedisRpcPlayServiceImpl implements IRedisRpcPlayService { + + + @Autowired + private RedisRpcConfig redisRpcConfig; + + @Autowired + private UserSetting userSetting; + + + private RedisRpcRequest buildRequest(String uri, Object param) { + RedisRpcRequest request = new RedisRpcRequest(); + request.setFromId(userSetting.getServerId()); + request.setParam(param); + request.setUri(uri); + return request; + } + + @Override + public void play(String serverId, Integer channelId, ErrorCallback callback) { + RedisRpcRequest request = buildRequest("channel/play", channelId); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.MILLISECONDS); + if (response == null) { + callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), null); + }else { + if (response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = JSON.parseObject(response.getBody().toString(), StreamInfo.class); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + }else { + callback.run(response.getStatusCode(), response.getBody().toString(), null); + } + } + } + + @Override + public void stop(String serverId, InviteSessionType type, int channelId, String stream) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channelId", channelId); + jsonObject.put("stream", stream); + jsonObject.put("inviteSessionType", type); + RedisRpcRequest request = buildRequest("channel/stop", jsonObject.toJSONString()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MICROSECONDS); + if (response == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg()); + }else { + if (response.getStatusCode() != ErrorCode.SUCCESS.getCode()) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg()); + } + } + } + + @Override + public void queryRecordInfo(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback callback) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channelId", channelId); + jsonObject.put("startTime", startTime); + jsonObject.put("endTime", endTime); + RedisRpcRequest request = buildRequest("channel/queryRecordInfo", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getRecordInfoTimeout(), TimeUnit.MILLISECONDS); + if (response == null) { + callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), null); + }else { + if (response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + RecordInfo recordInfo = JSON.parseObject(response.getBody().toString(), RecordInfo.class); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), recordInfo); + }else { + callback.run(response.getStatusCode(), response.getBody().toString(), null); + } + } + } + + @Override + public void playback(String serverId, Integer channelId, String startTime, String endTime, ErrorCallback callback) { + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channelId", channelId); + jsonObject.put("startTime", startTime); + jsonObject.put("endTime", endTime); + RedisRpcRequest request = buildRequest("channel/playback", jsonObject.toString()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.MILLISECONDS); + if (response == null) { + callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), null); + }else { + if (response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = JSON.parseObject(response.getBody().toString(), StreamInfo.class); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + }else { + callback.run(response.getStatusCode(), response.getBody().toString(), null); + } + } + } + + @Override + public void pauseRtp(String serverId, String streamId) { + RedisRpcRequest request = buildRequest("channel/pauseRtp", streamId); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 5, TimeUnit.SECONDS); + if (response == null) { + log.info("[RPC 暂停回放] 失败, streamId: {}", streamId); + }else { + if (response.getStatusCode() != ErrorCode.SUCCESS.getCode()) { + log.info("[RPC 暂停回放] 失败, {}, streamId: {}", response.getBody(), streamId); + } + } + } + + @Override + public void resumeRtp(String serverId, String streamId) { + RedisRpcRequest request = buildRequest("channel/resumeRtp", streamId); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 5, TimeUnit.SECONDS); + if (response == null) { + log.info("[RPC 恢复回放] 失败, streamId: {}", streamId); + }else { + if (response.getStatusCode() != ErrorCode.SUCCESS.getCode()) { + log.info("[RPC 恢复回放] 失败, {}, streamId: {}", response.getBody(), streamId); + } + } + } + + @Override + public void download(String serverId, Integer channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback callback) { + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channelId", channelId); + jsonObject.put("startTime", startTime); + jsonObject.put("endTime", endTime); + jsonObject.put("downloadSpeed", downloadSpeed); + RedisRpcRequest request = buildRequest("channel/download", jsonObject.toString()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.MILLISECONDS); + if (response == null) { + callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), null); + }else { + if (response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = JSON.parseObject(response.getBody().toString(), StreamInfo.class); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + }else { + callback.run(response.getStatusCode(), response.getBody().toString(), null); + } + } + } + + @Override + public String frontEndCommand(String serverId, Integer channelId, int cmdCode, int parameter1, int parameter2, int combindCode2) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channelId", channelId); + jsonObject.put("cmdCode", cmdCode); + jsonObject.put("parameter1", parameter1); + jsonObject.put("parameter2", parameter2); + jsonObject.put("combindCode2", combindCode2); + RedisRpcRequest request = buildRequest("channel/ptz/frontEndCommand", jsonObject.toString()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.MILLISECONDS); + if (response == null) { + return ErrorCode.ERROR100.getMsg(); + }else { + if (response.getStatusCode() != ErrorCode.SUCCESS.getCode()) { + return response.getBody().toString(); + } + } + return null; + } + + @Override + public void playPush(Integer id, ErrorCallback callback) { + RedisRpcRequest request = buildRequest("streamPush/play", id); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.SECONDS); + if (response == null) { + callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), null); + }else { + if (response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = JSON.parseObject(response.getBody().toString(), StreamInfo.class); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + }else { + callback.run(response.getStatusCode(), response.getBody().toString(), null); + } + } + } + + @Override + public StreamInfo playProxy(String serverId, int id) { + RedisRpcRequest request = buildRequest("streamProxy/play", id); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.SECONDS); + if (response != null && response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + return JSON.parseObject(response.getBody().toString(), StreamInfo.class); + } + return null; + } + + @Override + public void stopProxy(String serverId, int id) { + RedisRpcRequest request = buildRequest("streamProxy/stop", id); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.SECONDS); + if (response != null && response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + log.info("[rpc 拉流代理] 停止成功: id: {}", id); + }else { + log.info("[rpc 拉流代理] 停止失败 id: {}", id); + } + } + + @Override + public DownloadFileInfo getRecordPlayUrl(String serverId, Integer recordId) { + RedisRpcRequest request = buildRequest("cloudRecord/play", recordId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.SECONDS); + if (response != null && response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + return JSON.parseObject(response.getBody().toString(), DownloadFileInfo.class); + } + return null; + } + + @Override + public AudioBroadcastResult audioBroadcast(String serverId, String deviceId, String channelDeviceId, Boolean broadcastMode) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("deviceId", deviceId); + jsonObject.put("channelDeviceId", channelDeviceId); + jsonObject.put("broadcastMode", broadcastMode); + RedisRpcRequest request = buildRequest("devicePlay/audioBroadcast", jsonObject.toString()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, userSetting.getPlayTimeout(), TimeUnit.SECONDS); + if (response != null && response.getStatusCode() == ErrorCode.SUCCESS.getCode()) { + return JSON.parseObject(response.getBody().toString(), AudioBroadcastResult.class); + } + return null; + } +} + diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcServiceImpl.java index 861821353..b2d65963c 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/service/RedisRpcServiceImpl.java @@ -1,13 +1,16 @@ package com.genersoft.iot.vmp.service.redisMsg.service; import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.StreamInfo; 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.RedisRpcRequest; import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse; -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.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.media.event.hook.Hook; import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; @@ -22,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import java.util.concurrent.TimeUnit; + @Slf4j @Service public class RedisRpcServiceImpl implements IRedisRpcService { @@ -58,8 +63,8 @@ public class RedisRpcServiceImpl implements IRedisRpcService { @Override public SendRtpInfo getSendRtpItem(String callId) { - RedisRpcRequest request = buildRequest("getSendRtpItem", callId); - RedisRpcResponse response = redisRpcConfig.request(request, 10); + RedisRpcRequest request = buildRequest("sendRtp/getSendRtpItem", callId); + RedisRpcResponse response = redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); if (response.getBody() == null) { return null; } @@ -69,9 +74,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService { @Override public WVPResult startSendRtp(String callId, SendRtpInfo sendRtpItem) { log.info("[请求其他WVP] 开始推流,wvp:{}, {}/{}", sendRtpItem.getServerId(), sendRtpItem.getApp(), sendRtpItem.getStream()); - RedisRpcRequest request = buildRequest("startSendRtp", callId); + RedisRpcRequest request = buildRequest("sendRtp/startSendRtp", callId); request.setToId(sendRtpItem.getServerId()); - RedisRpcResponse response = redisRpcConfig.request(request, 10); + RedisRpcResponse response = redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); return JSON.parseObject(response.getBody().toString(), WVPResult.class); } @@ -83,9 +88,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService { return WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到发流信息"); } log.info("[请求其他WVP] 停止推流,wvp:{}, {}/{}", sendRtpItem.getServerId(), sendRtpItem.getApp(), sendRtpItem.getStream()); - RedisRpcRequest request = buildRequest("stopSendRtp", callId); + RedisRpcRequest request = buildRequest("sendRtp/stopSendRtp", callId); request.setToId(sendRtpItem.getServerId()); - RedisRpcResponse response = redisRpcConfig.request(request, 10); + RedisRpcResponse response = redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); return JSON.parseObject(response.getBody().toString(), WVPResult.class); } @@ -94,7 +99,7 @@ public class RedisRpcServiceImpl implements IRedisRpcService { log.info("[请求所有WVP监听流上线] {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream()); // 监听流上线。 流上线直接发送sendRtpItem消息给实际的信令处理者 Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null); - RedisRpcRequest request = buildRequest("waitePushStreamOnline", sendRtpItem); + RedisRpcRequest request = buildRequest("streamPush/waitePushStreamOnline", sendRtpItem); request.setToId(sendRtpItem.getServerId()); hookSubscribe.addSubscribe(hook, (hookData) -> { @@ -135,9 +140,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService { log.info("[停止WVP监听流上线] {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream()); Hook hook = Hook.getInstance(HookType.on_media_arrival, sendRtpItem.getApp(), sendRtpItem.getStream(), null); hookSubscribe.removeSubscribe(hook); - RedisRpcRequest request = buildRequest("stopWaitePushStreamOnline", sendRtpItem); + RedisRpcRequest request = buildRequest("streamPush/stopWaitePushStreamOnline", sendRtpItem); request.setToId(sendRtpItem.getServerId()); - redisRpcConfig.request(request, 10); + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); } @Override @@ -147,9 +152,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService { log.info("[停止WVP监听流上线] 未找到redis中的发流信息, key:{}", callId); return; } - RedisRpcRequest request = buildRequest("rtpSendStopped", callId); + RedisRpcRequest request = buildRequest("streamPush/rtpSendStopped", callId); request.setToId(sendRtpItem.getServerId()); - redisRpcConfig.request(request, 10); + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); } @Override @@ -166,7 +171,7 @@ public class RedisRpcServiceImpl implements IRedisRpcService { StreamInfo streamInfoParam = new StreamInfo(); streamInfoParam.setApp(app); streamInfoParam.setStream(stream); - RedisRpcRequest request = buildRequest("onStreamOnlineEvent", streamInfoParam); + RedisRpcRequest request = buildRequest("streamPush/onStreamOnlineEvent", streamInfoParam); hookSubscribe.addSubscribe(hook, (hookData) -> { log.info("[请求所有WVP监听流上线] 监听流上线 {}/{}", app, stream); if (callback != null) { @@ -198,7 +203,231 @@ public class RedisRpcServiceImpl implements IRedisRpcService { StreamInfo streamInfoParam = new StreamInfo(); streamInfoParam.setApp(app); streamInfoParam.setStream(stream); - RedisRpcRequest request = buildRequest("unPushStreamOnlineEvent", streamInfoParam); - redisRpcConfig.request(request, 10); + RedisRpcRequest request = buildRequest("streamPush/unPushStreamOnlineEvent", streamInfoParam); + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); + } + + @Override + public void subscribeCatalog(int id, int cycle) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id", id); + jsonObject.put("cycle", cycle); + RedisRpcRequest request = buildRequest("device/subscribeCatalog", jsonObject); + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); + } + + @Override + public void subscribeMobilePosition(int id, int cycle, int interval) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id", id); + jsonObject.put("cycle", cycle); + jsonObject.put("interval", cycle); + RedisRpcRequest request = buildRequest("device/subscribeMobilePosition", jsonObject); + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); + } + + @Override + public boolean updatePlatform(String serverId, Platform platform) { + RedisRpcRequest request = buildRequest("platform/update", platform); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 40, TimeUnit.MILLISECONDS); + return Boolean.parseBoolean(response.getBody().toString()); + } + + @Override + public void catalogEventPublish(String serverId, CatalogEvent event) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("platform", event.getPlatform()); + jsonObject.put("channels", event.getChannels()); + jsonObject.put("type", event.getType()); + RedisRpcRequest request = buildRequest("platform/catalogEventPublish", jsonObject); + if (serverId != null) { + request.setToId(serverId); + } + redisRpcConfig.request(request, 10, TimeUnit.MILLISECONDS); + } + + @Override + public WVPResult devicesSync(String serverId, String deviceId) { + RedisRpcRequest request = buildRequest("device/devicesSync", deviceId); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 100, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public SyncStatus getChannelSyncStatus(String serverId, String deviceId) { + RedisRpcRequest request = buildRequest("device/getChannelSyncStatus", deviceId); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 100, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), SyncStatus.class); + } + + @Override + public WVPResult deviceBasicConfig(String serverId, Device device, BasicParam basicParam) { + RedisRpcRequest request = buildRequest("device/deviceBasicConfig", JSONObject.toJSONString(basicParam)); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult deviceConfigQuery(String serverId, Device device, String channelId, String configType) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("configType", configType); + RedisRpcRequest request = buildRequest("device/deviceConfigQuery", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public void teleboot(String serverId, Device device) { + RedisRpcRequest request = buildRequest("device/teleboot", device.getDeviceId()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + if (response.getStatusCode() != ErrorCode.SUCCESS.getCode()) { + throw new ControllerException(response.getStatusCode(), response.getBody().toString()); + } + } + + @Override + public WVPResult recordControl(String serverId, Device device, String channelId, String recordCmdStr) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("recordCmdStr", recordCmdStr); + RedisRpcRequest request = buildRequest("device/record", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult guard(String serverId, Device device, String guardCmdStr) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("guardCmdStr", guardCmdStr); + RedisRpcRequest request = buildRequest("device/guard", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult resetAlarm(String serverId, Device device, String channelId, String alarmMethod, String alarmType) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("alarmMethod", alarmMethod); + jsonObject.put("alarmType", alarmType); + RedisRpcRequest request = buildRequest("device/resetAlarm", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public void iFrame(String serverId, Device device, String channelId) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + RedisRpcRequest request = buildRequest("device/iFrame", jsonObject); + request.setToId(serverId); + redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + } + + @Override + public WVPResult homePosition(String serverId, Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("enabled", enabled); + jsonObject.put("resetTime", resetTime); + jsonObject.put("presetIndex", presetIndex); + RedisRpcRequest request = buildRequest("device/homePosition", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public void dragZoomIn(String serverId, Device device, String channelId, int length, int width, int midpointx, + int midpointy, int lengthx, int lengthy) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("length", length); + jsonObject.put("width", width); + jsonObject.put("midpointx", midpointx); + jsonObject.put("midpointy", midpointy); + jsonObject.put("lengthx", lengthx); + jsonObject.put("lengthy", lengthy); + RedisRpcRequest request = buildRequest("device/dragZoomIn", jsonObject); + request.setToId(serverId); + redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + } + + @Override + public void dragZoomOut(String serverId, Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + jsonObject.put("length", length); + jsonObject.put("width", width); + jsonObject.put("midpointx", midpointx); + jsonObject.put("midpointy", midpointy); + jsonObject.put("lengthx", lengthx); + jsonObject.put("lengthy", lengthy); + RedisRpcRequest request = buildRequest("device/dragZoomOut", jsonObject); + request.setToId(serverId); + redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + } + + @Override + public WVPResult deviceStatus(String serverId, Device device) { + RedisRpcRequest request = buildRequest("device/deviceStatus", device.getDeviceId()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult deviceInfo(String serverId, Device device) { + RedisRpcRequest request = buildRequest("device/info", device.getDeviceId()); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult queryPreset(String serverId, Device device, String channelId) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); + jsonObject.put("channelId", channelId); + RedisRpcRequest request = buildRequest("device/queryPreset", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 60000, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); + } + + @Override + public WVPResult alarm(String serverId, Device device, String startPriority, String endPriority, + String alarmMethod, String alarmType, String startTime, String endTime) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("device", device.getDeviceId()); +// jsonObject.put("channelId", channelId); + jsonObject.put("startPriority", startPriority); + jsonObject.put("endPriority", endPriority); + jsonObject.put("alarmMethod", alarmMethod); + jsonObject.put("alarmType", alarmType); + jsonObject.put("startTime", startTime); + jsonObject.put("endTime", endTime); + RedisRpcRequest request = buildRequest("device/alarm", jsonObject); + request.setToId(serverId); + RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS); + return JSON.parseObject(response.getBody().toString(), WVPResult.class); } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 238134a9b..1f05a7b48 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.storager; import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.ServerInfo; import com.genersoft.iot.vmp.common.SystemAllInfo; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.media.bean.MediaInfo; @@ -37,7 +38,7 @@ public interface IRedisCatchStorage { /** * 在redis添加wvp的信息 */ - void updateWVPInfo(JSONObject jsonObject, int time); + void updateWVPInfo(ServerInfo serverInfo, int time); /** * 发送推流生成与推流消失消息 @@ -187,4 +188,10 @@ public interface IRedisCatchStorage { void sendStartSendRtp(SendRtpInfo sendRtpItem); void sendPushStreamOnline(SendRtpInfo sendRtpItem); + + ServerInfo queryServerInfo(String serverId); + + String chooseOneServer(String serverId); + + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java index 7e7ee54c3..f41c2e10c 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java @@ -21,6 +21,7 @@ public interface CloudRecordServiceMapper { " folder," + " file_path," + " file_size," + + " server_id," + " time_len ) " + "VALUES (" + " #{app}," + @@ -33,6 +34,7 @@ public interface CloudRecordServiceMapper { " #{folder}," + " #{filePath}," + " #{fileSize}," + + " #{serverId}," + " #{timeLen})" + " ") int add(CloudRecordItem cloudRecordItem); @@ -40,7 +42,7 @@ public interface CloudRecordServiceMapper { @Select(" "}) @@ -138,32 +141,27 @@ public interface MediaServerMapper { ", type=#{type}" + ", transcode_suffix=#{transcodeSuffix}" + ", hook_alive_interval=#{hookAliveInterval}" + + ", server_id=#{serverId}" + "WHERE ip=#{ip} and http_port=#{httpPort}"+ " "}) int updateByHostAndPort(MediaServer mediaServerItem); - @Select("SELECT * FROM wvp_media_server WHERE id=#{id}") - MediaServer queryOne(String id); + @Select("SELECT * FROM wvp_media_server WHERE id=#{id} and server_id = #{serverId}") + MediaServer queryOne(@Param("id") String id, @Param("serverId") String serverId); - @Select("SELECT * FROM wvp_media_server") - List queryAll(); + @Select("SELECT * FROM wvp_media_server where server_id = #{serverId}") + List queryAll(@Param("serverId") String serverId); - @Delete("DELETE FROM wvp_media_server WHERE id=#{id}") - void delOne(String id); + @Delete("DELETE FROM wvp_media_server WHERE id=#{id} and server_id = #{serverId}") + void delOne(String id, @Param("serverId") String serverId); - @Select("DELETE FROM wvp_media_server WHERE ip=#{host} and http_port=#{port}") - void delOneByIPAndPort(@Param("host") String host, @Param("port") int port); + @Select("SELECT * FROM wvp_media_server WHERE ip=#{host} and http_port=#{port} and server_id = #{serverId}") + MediaServer queryOneByHostAndPort(@Param("host") String host, @Param("port") int port, @Param("serverId") String serverId); - @Delete("DELETE FROM wvp_media_server WHERE default_server=true") - int delDefault(); + @Select("SELECT * FROM wvp_media_server WHERE default_server=true and server_id = #{serverId}") + MediaServer queryDefault(@Param("serverId") String serverId); - @Select("SELECT * FROM wvp_media_server WHERE ip=#{host} and http_port=#{port}") - MediaServer queryOneByHostAndPort(@Param("host") String host, @Param("port") int port); - - @Select("SELECT * FROM wvp_media_server WHERE default_server=true") - MediaServer queryDefault(); - - @Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0") - List queryAllWithAssistPort(); + @Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0 and server_id = #{serverId}") + List queryAllWithAssistPort(@Param("serverId") String serverId); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index b97c9cf06..4521b0b79 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.storager.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.ServerInfo; import com.genersoft.iot.vmp.common.SystemAllInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.dao.DeviceChannelMapper; @@ -110,10 +110,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override - public void updateWVPInfo(JSONObject jsonObject, int time) { + public void updateWVPInfo(ServerInfo serverInfo, int time) { String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); Duration duration = Duration.ofSeconds(time); - redisTemplate.opsForValue().set(key, jsonObject, duration); + redisTemplate.opsForValue().set(key, serverInfo, duration); + // 设置平台的分数值 + String setKey = VideoManagerConstants.WVP_SERVER_LIST; + // 首次设置就设置为0, 后续值越小说明越是最近启动的 + redisTemplate.opsForZSet().add(setKey, userSetting.getServerId(), System.currentTimeMillis()); } @Override @@ -533,4 +537,21 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { log.info("[redis发送通知] 流上线 {}: {}/{}->{}", key, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getTargetId()); redisTemplate.convertAndSend(key, JSON.toJSON(sendRtpItem)); } + + @Override + public ServerInfo queryServerInfo(String serverId) { + String key = VideoManagerConstants.WVP_SERVER_PREFIX + serverId; + return (ServerInfo)redisTemplate.opsForValue().get(key); + } + + @Override + public String chooseOneServer(String serverId) { + String key = VideoManagerConstants.WVP_SERVER_LIST; + redisTemplate.opsForZSet().remove(key, serverId); + Set range = redisTemplate.opsForZSet().range(key, 0, 0); + if (range == null || range.isEmpty()) { + return null; + } + return (String) range.iterator().next(); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxy.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxy.java index 7a531469c..61f6e6553 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxy.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxy.java @@ -36,6 +36,9 @@ public class StreamProxy extends CommonGBChannel { @Schema(description = "固定选择的流媒体服务ID") private String relatesMediaServerId; + @Schema(description = "服务ID") + private String serverId; + @Schema(description = "拉流地址") private String srcUrl; diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxyParam.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxyParam.java index 0497d2333..d791c3195 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxyParam.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/bean/StreamProxyParam.java @@ -53,11 +53,12 @@ public class StreamProxyParam { private boolean enableDisableNoneReader; - public StreamProxy buildStreamProxy() { + public StreamProxy buildStreamProxy(String serverId) { StreamProxy streamProxy = new StreamProxy(); streamProxy.setApp(app); streamProxy.setStream(stream); streamProxy.setRelatesMediaServerId(mediaServerId); + streamProxy.setServerId(serverId); streamProxy.setSrcUrl(url); streamProxy.setTimeout(timeoutMs/1000); streamProxy.setRtspType(rtpType); diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/controller/StreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/controller/StreamProxyController.java index d7f8d62b5..be4d91b33 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/controller/StreamProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/controller/StreamProxyController.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.streamProxy.controller; 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.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.media.bean.MediaServer; @@ -43,6 +44,9 @@ public class StreamProxyController { @Autowired private IStreamProxyPlayService streamProxyPlayService; + @Autowired + private UserSetting userSetting; + @Operation(summary = "分页查询流代理", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "page", description = "当前页") @@ -120,6 +124,7 @@ public class StreamProxyController { if (ObjectUtils.isEmpty(param.getGbId())) { param.setGbDeviceId(null); } + param.setServerId(userSetting.getServerId()); streamProxyService.add(param); return param; } diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/dao/StreamProxyMapper.java index f43f1096e..4258458b7 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/dao/StreamProxyMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/dao/StreamProxyMapper.java @@ -13,10 +13,10 @@ public interface StreamProxyMapper { @Insert("INSERT INTO wvp_stream_proxy (type, app, stream,relates_media_server_id, src_url, " + "timeout, ffmpeg_cmd_key, rtsp_type, enable_audio, enable_mp4, enable, pulling, " + - "enable_remove_none_reader, enable_disable_none_reader, create_time) VALUES" + + "enable_remove_none_reader, enable_disable_none_reader, server_id, create_time) VALUES" + "(#{type}, #{app}, #{stream}, #{relatesMediaServerId}, #{srcUrl}, " + "#{timeout}, #{ffmpegCmdKey}, #{rtspType}, #{enableAudio}, #{enableMp4}, #{enable}, #{pulling}, " + - "#{enableRemoveNoneReader}, #{enableDisableNoneReader}, #{createTime} )") + "#{enableRemoveNoneReader}, #{enableDisableNoneReader}, #{serverId}, #{createTime} )") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") int add(StreamProxy streamProxyDto); diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyPlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyPlayServiceImpl.java index f4ea79d0a..a6cffa93f 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyPlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyPlayServiceImpl.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.streamProxy.service.impl; -import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; @@ -12,6 +12,7 @@ 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.media.MediaArrivalEvent; import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService; import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy; @@ -36,7 +37,6 @@ import java.util.concurrent.ConcurrentHashMap; */ @Slf4j @Service -@DS("master") public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService { @Autowired @@ -54,6 +54,9 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService { @Autowired private UserSetting userSetting; + @Autowired + private IRedisRpcPlayService redisRpcPlayService; + private ConcurrentHashMap> callbackMap = new ConcurrentHashMap<>(); private ConcurrentHashMap streamInfoMap = new ConcurrentHashMap<>(); @@ -139,6 +142,13 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService { if (!streamProxy.isEnable()) { return null; } + if (streamProxy.getServerId() == null) { + streamProxy.setServerId(userSetting.getServerId()); + } + if (!userSetting.getServerId().equals(streamProxy.getServerId())) { + return redisRpcPlayService.playProxy(streamProxy.getServerId(), streamProxy.getId()); + } + MediaServer mediaServer; String mediaServerId = streamProxy.getRelatesMediaServerId(); if (mediaServerId == null) { @@ -163,6 +173,10 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService { if (streamProxy == null) { throw new ControllerException(ErrorCode.ERROR404.getCode(), "代理信息未找到"); } + if (!userSetting.getServerId().equals(streamProxy.getServerId())) { + redisRpcPlayService.stopProxy(streamProxy.getServerId(), streamProxy.getId()); + return; + } stopProxy(streamProxy); } diff --git a/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyServiceImpl.java index 612180e13..6c89b02d8 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/streamProxy/service/impl/StreamProxyServiceImpl.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.streamProxy.service.impl; import com.alibaba.fastjson2.JSONObject; -import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.enums.ChannelDataType; import com.genersoft.iot.vmp.conf.UserSetting; @@ -48,7 +47,6 @@ import java.util.Map; */ @Slf4j @Service -@DS("master") public class StreamProxyServiceImpl implements IStreamProxyService { @Autowired @@ -147,7 +145,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { if (param.getMediaServerId().equals("auto")) { param.setMediaServerId(null); } - StreamProxy streamProxy = param.buildStreamProxy(); + StreamProxy streamProxy = param.buildStreamProxy(userSetting.getServerId()); if (streamProxyInDb == null) { add(streamProxy); diff --git a/src/main/java/com/genersoft/iot/vmp/streamPush/controller/StreamPushController.java b/src/main/java/com/genersoft/iot/vmp/streamPush/controller/StreamPushController.java index ecaa92ee4..67fb1cfa1 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamPush/controller/StreamPushController.java +++ b/src/main/java/com/genersoft/iot/vmp/streamPush/controller/StreamPushController.java @@ -245,7 +245,7 @@ public class StreamPushController { @GetMapping(value = "/start") @ResponseBody @Operation(summary = "开始播放", security = @SecurityRequirement(name = JwtUtils.HEADER)) - public DeferredResult> batchStop(Integer id){ + public DeferredResult> start(Integer id){ Assert.notNull(id, "推流ID不可为NULL"); DeferredResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); result.onTimeout(()->{ @@ -260,4 +260,12 @@ public class StreamPushController { }, null, null); return result; } + + @GetMapping(value = "/forceClose") + @ResponseBody + @Operation(summary = "强制停止推流", security = @SecurityRequirement(name = JwtUtils.HEADER)) + public void stop(String app, String stream){ + + streamPushPlayService.stop(app, stream); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/streamPush/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/streamPush/dao/StreamPushMapper.java index dfdb34216..c77fa4194 100755 --- a/src/main/java/com/genersoft/iot/vmp/streamPush/dao/StreamPushMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/streamPush/dao/StreamPushMapper.java @@ -80,10 +80,9 @@ public interface StreamPushMapper { List selectAllByMediaServerIdWithOutGbID(String mediaServerId); @Update("UPDATE wvp_stream_push " + - "SET pushing=#{pushing} " + + "SET pushing=#{pushing}, server_id=#{serverId}, media_server_id=#{mediaServerId} " + "WHERE id=#{id}") - int updatePushStatus(@Param("id") int id, @Param("pushing") boolean pushing); - + int updatePushStatus(StreamPush streamPush); @Select("