Merge branch 'dev/数据库统合'

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

View File

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

View File

@ -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);
}
}

View File

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

View File

@ -10,6 +10,8 @@ public class VideoManagerConstants {
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
public static final String WVP_SERVER_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:";

View File

@ -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<String> 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;
}

View File

@ -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<Platform> parentPlatforms = platformService.queryEnablePlatformList();
List<Platform> parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId());
for (Platform platform : parentPlatforms) {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<Object, Object> redisTemplate;
@ -48,6 +49,40 @@ public class RedisRpcConfig implements MessageListener {
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
private final static Map<String, RedisRpcClassHandler> protocolHash = new HashMap<>();
public void addHandler(String path, RedisRpcClassHandler handler) {
protocolHash.put(path, handler);
}
// @Override
// public void run(String... args) throws Exception {
// List<Class<?>> classList = ClassUtil.getClassList("com.genersoft.iot.vmp.service.redisMsg.control", RedisRpcController.class);
// for (Class<?> handlerClass : classList) {
// String controllerPath = handlerClass.getAnnotation(RedisRpcController.class).value();
// Object bean = ClassUtil.getBean(controllerPath, handlerClass);
// // 扫描其下的方法
// Method[] methods = handlerClass.getDeclaredMethods();
// for (Method method : methods) {
// RedisRpcMapping annotation = method.getAnnotation(RedisRpcMapping.class);
// if (annotation != null) {
// String methodPath = annotation.value();
// if (methodPath != null) {
// protocolHash.put(controllerPath + "/" + methodPath, new RedisRpcClassHandler(bean, method));
// }
// }
//
// }
//
// }
// for (String s : protocolHash.keySet()) {
// System.out.println(s);
// }
// if (log.isDebugEnabled()) {
// log.debug("消息ID缓存表 protocolHash:{}", protocolHash);
// }
// }
@Override
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<Long, SynchronousQueue<RedisRpcResponse>> topicSubscribers = new ConcurrentHashMap<>();
private final Map<Long, CommonCallback<RedisRpcResponse>> callbacks = new ConcurrentHashMap<>();
public RedisRpcResponse request(RedisRpcRequest request, int timeOut) {
public RedisRpcResponse request(RedisRpcRequest request, long timeOut) {
return request(request, timeOut, TimeUnit.SECONDS);
}
public RedisRpcResponse request(RedisRpcRequest request, long timeOut, TimeUnit timeUnit) {
request.setSn((long) random.nextInt(1000) + 1);
SynchronousQueue<RedisRpcResponse> 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<RedisRpcResponse> 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());

View File

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

View File

@ -80,11 +80,12 @@ public class SipLayer implements CommandLineRunner {
monitorIps.add(sipConfig.getIp());
}
}
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());
}

View File

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

View File

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

View File

@ -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;
}
}

View File

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

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean;
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;
}
}

View File

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

View File

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

View File

@ -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<String> homePositionApi(@PathVariable String deviceId,
@RequestParam(required = false) String channelId,
@RequestParam(required = false) String name,
@RequestParam(required = false) String expiration,
@RequestParam(required = false) String heartBeatInterval,
@RequestParam(required = false) String heartBeatCount) {
@Parameter(name = "basicParam", description = "基础配置参数", required = true)
public DeferredResult<WVPResult<String>> 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<String> result = new DeferredResult<String>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
JSONObject json = new JSONObject();
json.put("DeviceID", deviceId);
json.put("Status", "Timeout");
json.put("Description", "设备配置操作超时, 设备未返回应答指令");
msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
resultHolder.invokeResult(msg);
Assert.notNull(basicParam.getDeviceId(), "设备ID必须存在");
Device device = deviceService.getDeviceByDeviceId(basicParam.getDeviceId());
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> 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<String> 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<WVPResult<Object>> 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<String> result = new DeferredResult<String > (3 * 1000L);
result.onTimeout(()->{
log.warn(String.format("获取设备配置超时"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData("Timeout. Device did not response to this command.");
resultHolder.invokeResult(msg);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<Object>> 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;
}
}

View File

@ -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<ResponseEntity<WVPResult<String>>> recordApi(@PathVariable String deviceId,
@PathVariable String recordCmdStr, String channelId) {
@GetMapping("/record")
public DeferredResult<WVPResult<String>> 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<ResponseEntity<WVPResult<String>>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeAllResult(msg);
});
if (resultHolder.exist(key, null)){
return result;
}
resultHolder.put(key, uuid, result);
try {
cmder.recordCmd(device, channelId, recordCmdStr, event -> {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg)));
resultHolder.invokeAllResult(msg);
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> 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<WVPResult<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
@GetMapping("/guard")
public DeferredResult<WVPResult<String>> 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<WVPResult<String>> result = new DeferredResult<>(3 * 1000L);
resultHolder.put(key, uuid, result);
result.onTimeout(() -> {
log.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> 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<ResponseEntity<WVPResult<String>>> 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<WVPResult<String>> 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<ResponseEntity<WVPResult<String>>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
resultHolder.invokeResult(msg);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> 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<WVPResult<String>> result = new DeferredResult<>(3 * 1000L);
result.onTimeout(() -> {
log.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答")); //("看守位控制操作超时, 设备未返回应答指令");
resultHolder.invokeResult(msg);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> 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<WVPResult<String>> 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("<DragZoomIn>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomIn>\r\n");
try {
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<WVPResult<String>> 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<WVPResult<String>> 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("<DragZoomOut>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomOut>\r\n");
try {
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<WVPResult<String>> 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;
}
}

View File

@ -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<SyncStatus> 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<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) {
public DeferredResult<WVPResult<String>> 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<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(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<WVPResult<String>> 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<ResponseEntity<String>> alarmApi(@PathVariable String deviceId,
@GetMapping("/alarm")
public DeferredResult<WVPResult<Object>> 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<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (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<WVPResult<Object>> 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<WVPResult<Object>> deviceInfo(String deviceId) {
if (log.isDebugEnabled()) {
log.debug("设备信息查询API调用");
}
Device device = deviceService.getDeviceByDeviceId(deviceId);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<Object>> 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;
}

View File

@ -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<WVPResult<RecordInfo>> result = new DeferredResult<>();
DeferredResult<WVPResult<RecordInfo>> 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<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}));
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
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<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(code);
wvpResult.setMsg(msg);
wvpResult.setData(data);
result.setResult(wvpResult);
});
result.onTimeout(()->{
msg.setData("timeout");
WVPResult<RecordInfo> 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))

View File

@ -19,6 +19,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.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<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
result.onTimeout(()->{
log.info("[点播等待超时] deviceId{}, channelId{}, ", deviceId, channelId);
// 释放rtpserver
WVPResult<StreamInfo> wvpResult = new WVPResult<>();
WVPResult<StreamContent> 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<StreamInfo> callback = (code, msg, streamInfo) -> {
WVPResult<StreamContent> 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);
}

View File

@ -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) {

View File

@ -7,9 +7,9 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.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<String> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) {
public DeferredResult<WVPResult<Object>> 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<String> result = new DeferredResult<String> (3 * 1000L);
result.onTimeout(()->{
log.warn(String.format("获取设备预置位超时"));
// 释放rtpserver
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
msg.setData("获取设备预置位超时");
resultHolder.invokeResult(msg);
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<Object>> 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))

View File

@ -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 {
"<if test=\"positionCapability != null\">, position_capability=#{positionCapability}</if>" +
"<if test=\"heartBeatCount != null\">, heart_beat_count=#{heartBeatCount}</if>" +
"<if test=\"expires != null\">, expires=#{expires}</if>" +
"<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
"WHERE device_id=#{deviceId}"+
" </script>"})
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<Device> getOnlineDevices();
@Select("SELECT " +
"id, " +
"device_id, " +
"coalesce(custom_name, name) as name, " +
"password, " +
"manufacturer, " +
"model, " +
"firmware, " +
"transport," +
"stream_mode," +
"ip," +
"sdp_ip,"+
"local_ip,"+
"port,"+
"host_address,"+
"expires,"+
"register_time,"+
"keepalive_time,"+
"create_time,"+
"update_time,"+
"charset,"+
"subscribe_cycle_for_catalog,"+
"subscribe_cycle_for_mobile_position,"+
"mobile_position_submission_interval,"+
"subscribe_cycle_for_alarm,"+
"ssrc_check,"+
"as_message_channel,"+
"broadcast_push_after_ack,"+
"geo_coord_sys,"+
"server_id,"+
"on_line"+
" FROM wvp_device WHERE on_line = true and server_id = #{serverId}")
List<Device> getOnlineDevicesByServerId(@Param("serverId") String serverId);
@Select("SELECT " +
"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 "+

View File

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

View File

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

View File

@ -1,13 +1,19 @@
package com.genersoft.iot.vmp.gb28181.event;
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<CommonGBChannel> deviceChannels, String type) {
catalogEventPublish(platform, deviceChannels, type, true);
}
public void catalogEventPublish(Platform platform, List<CommonGBChannel> deviceChannels, String type, boolean share) {
if (platform != null && !userSetting.getServerId().equals(platform.getServerId())) {
// 指定了上级平台的推送则发送到指定的设备未指定的则全部发送 接收后各自处理自己的
CatalogEvent outEvent = new CatalogEvent(this);
outEvent.setChannels(deviceChannels);
outEvent.setType(type);
outEvent.setPlatform(platform);
redisRpcService.catalogEventPublish(platform.getServerId(), outEvent);
return;
}
CatalogEvent outEvent = new CatalogEvent(this);
List<CommonGBChannel> 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);
}
}

View File

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

View File

@ -29,24 +29,24 @@ public class SipSubscribe {
private final DelayQueue<SipEvent> delayQueue = new DelayQueue<>();
@Scheduled(fixedDelay = 200) //每200毫秒执行
public void execute(){
if (delayQueue.isEmpty()) {
return;
}
try {
SipEvent take = delayQueue.take();
// 出现超时异常
if(take.getErrorEvent() != null) {
EventResult<Object> 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<Object> 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<EventObject>{

View File

@ -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;
}
}

View File

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

View File

@ -15,15 +15,15 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Slf4j
@Component
public class RecordEndEventListener implements ApplicationListener<RecordEndEvent> {
public class RecordInfoEventListener implements ApplicationListener<RecordInfoEvent> {
private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
private final Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
public interface RecordEndEventHandler{
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<RecordEndEven
/**
* 添加
* @param device
* @param channelId
* @param recordEndEventHandler
*/
public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) {
log.info("录像查询事件添加监听deviceId{}, channelId: {}", device, channelId);
@ -55,8 +52,6 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
}
/**
* 添加
* @param device
* @param channelId
*/
public void delEndEventHandler(String device, String channelId) {
log.info("录像查询事件移除监听deviceId{}, channelId: {}", device, channelId);

View File

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

View File

@ -32,13 +32,13 @@ public class SipEvent implements Delayed {
sipEvent.setKey(key);
sipEvent.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

View File

@ -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<CatalogEvent> {
@Autowired
private IPlatformChannelService platformChannelService;
@Autowired
private IPlatformService platformService;
@Autowired
private ISIPCommanderForPlatform sipCommanderFroPlatform;

View File

@ -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<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId);
void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback);
void queryRecordInfo(Device device, DeviceChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> object);
void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> object);
}

View File

@ -1,10 +1,10 @@
package com.genersoft.iot.vmp.gb28181.service;
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<Device> getAllOnlineDevice();
List<Device> getAllOnlineDevice(String serverId);
List<Device> getAllByStatus(Boolean status);
@ -166,5 +166,35 @@ public interface IDeviceService {
void subscribeMobilePosition(int id, int cycle, int interval);
WVPResult<SyncStatus> devicesSync(Device device);
void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback);
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback);
void teleboot(Device device);
void record(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback);
void guard(Device device, String guardCmdStr, ErrorCallback<String> callback);
void resetAlarm(Device device, String channelId, String alarmMethod, String alarmType, ErrorCallback<String> callback);
void iFrame(Device device, String channelId);
void homePosition(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback);
void dragZoomIn(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback);
void dragZoomOut(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback);
void deviceStatus(Device device, ErrorCallback<String> callback);
void updateDeviceHeartInfo(Device device);
void alarm(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime, ErrorCallback<Object> callback);
void deviceInfo(Device device, ErrorCallback<Object> callback);
void queryPreset(Device device, String channelId, ErrorCallback<Object> callback);
}

View File

@ -1,20 +1,33 @@
package com.genersoft.iot.vmp.gb28181.service;
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<StreamInfo> callback);
void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback);
void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream);
void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback);
void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream);
void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
void stopPlayProxy(CommonGBChannel channel);
void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback);
void stopPlayPush(CommonGBChannel channel);
void pauseRtp(String streamId);
void resumeRtp(String streamId);
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service;
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<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback);
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service;
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);
}

View File

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

View File

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

View File

@ -25,6 +25,8 @@ public interface IPlayService {
SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback);
void play(Device device, DeviceChannel channel, ErrorCallback<StreamInfo> 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<StreamInfo> callback);
void stop(InviteSessionType inviteSessionType, CommonGBChannel channel, String stream);
void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback);
void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback);
}

View File

@ -1,9 +1,8 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
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

View File

@ -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<String, SynchronousQueue<RecordInfo>> topicSubscribers = new ConcurrentHashMap<>();
/**
* 监听录像查询结束事件
*/
@Async("taskExecutor")
@org.springframework.context.event.EventListener
public void onApplicationEvent(RecordInfoEndEvent event) {
SynchronousQueue<RecordInfo> queue = topicSubscribers.get("record" + event.getRecordInfo().getSn());
if (queue != null) {
queue.offer(event.getRecordInfo());
}
}
@Autowired
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<Platform> 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<RecordInfo> callback) {
if (!userSetting.getServerId().equals(device.getServerId())){
redisRpcPlayService.queryRecordInfo(device.getServerId(), channel.getId(), startTime, endTime, callback);
return;
}
try {
int sn = (int)((Math.random()*9+1)*100000);
commander.recordInfoQuery(device, channel.getDeviceId(), startTime, endTime, sn, null, null, eventResult -> {
try {
// 消息发送成功, 监听等待数据到来
SynchronousQueue<RecordInfo> queue = new SynchronousQueue<>();
topicSubscribers.put("record" + sn, queue);
RecordInfo recordInfo = queue.poll(userSetting.getRecordInfoTimeout(), TimeUnit.MILLISECONDS);
if (recordInfo != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), recordInfo);
}else {
callback.run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), recordInfo);
}
} catch (InterruptedException e) {
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
} finally {
this.topicSubscribers.remove("record" + sn);
}
}, (eventResult -> {
callback.run(ErrorCode.ERROR100.getCode(), "查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg, null);
}));
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 查询录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
if (channel.getDataType() != ChannelDataType.GB28181.value){
// 只支持国标的语音喊话
log.warn("[INFO 消息] 非国标设备, 通道ID {}", channel.getGbId());
callback.run(ErrorCode.ERROR100.getCode(), "非国标设备", null);
return;
}
Device device = deviceMapper.query(channel.getDataDeviceId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
callback.run(ErrorCode.ERROR100.getCode(), "设备不存在", null);
return;
}
DeviceChannel deviceChannel = getOneForSourceById(channel.getGbId());
queryRecordInfo(device, deviceChannel, startTime, endTime, callback);
}
}

View File

@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
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<SsrcTransaction> 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<Device> getAllOnlineDevice() {
return deviceMapper.getOnlineDevices();
public List<Device> 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<SyncStatus> devicesSync(Device device) {
if (!userSetting.getServerId().equals(device.getServerId())) {
return redisRpcService.devicesSync(device.getServerId(), device.getDeviceId());
}
// 已存在则返回进度
if (isSyncRunning(device.getDeviceId())) {
SyncStatus channelSyncStatus = getChannelSyncStatus(device.getDeviceId());
WVPResult<SyncStatus> wvpResult = new WVPResult();
if (channelSyncStatus.getErrorMsg() != null) {
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(channelSyncStatus.getErrorMsg());
}else if (channelSyncStatus.getTotal() == null || channelSyncStatus.getTotal() == 0){
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg("等待通道信息...");
}else {
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(channelSyncStatus);
}
return wvpResult;
}
sync(device);
WVPResult<SyncStatus> wvpResult = new WVPResult<>();
wvpResult.setCode(0);
wvpResult.setMsg("开始同步");
return wvpResult;
}
@Override
public void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceBasicConfig(device.getServerId(), device, basicParam);
if (result.getCode() == ErrorCode.SUCCESS.getCode()) {
callback.run(result.getCode(), result.getMsg(), result.getData());
}
return;
}
try {
sipCommander.deviceBasicConfigCmd(device, basicParam, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 设备配置: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceConfigQuery(device.getServerId(), device, channelId, configType);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceConfigQuery(device, channelId, configType, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void teleboot(Device device) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.teleboot(device.getServerId(), device);
}
try {
sipCommander.teleBootCmd(device);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 远程启动: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void record(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.recordControl(device.getServerId(), device, channelId, recordCmdStr);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.recordCmd(device, channelId, recordCmdStr, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void guard(Device device, String guardCmdStr, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.guard(device.getServerId(), device, guardCmdStr);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.guardCmd(device, guardCmdStr, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void resetAlarm(Device device, String channelId, String alarmMethod, String alarmType, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.resetAlarm(device.getServerId(), device, channelId, alarmMethod, alarmType);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.alarmResetCmd(device, alarmMethod, alarmType, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void iFrame(Device device, String channelId) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.iFrame(device.getServerId(), device, channelId);
return;
}
try {
sipCommander.iFrameCmd(device, channelId);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 强制关键帧操作: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override
public void homePosition(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.homePosition(device.getServerId(), device, channelId, enabled, resetTime, presetIndex);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 看守位控制: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void dragZoomIn(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.dragZoomIn(device.getServerId(), device, channelId, length, width, midpointx, midpointy, lengthx, lengthy);
return;
}
StringBuffer cmdXml = new StringBuffer(200);
cmdXml.append("<DragZoomIn>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomIn>\r\n");
try {
sipCommander.dragZoomCmd(device, channelId, cmdXml.toString(), callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框放大: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void dragZoomOut(Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcService.dragZoomOut(device.getServerId(), device, channelId, length, width, midpointx, midpointy, lengthx, lengthy);
return;
}
StringBuffer cmdXml = new StringBuffer(200);
cmdXml.append("<DragZoomOut>\r\n");
cmdXml.append("<Length>" + length+ "</Length>\r\n");
cmdXml.append("<Width>" + width+ "</Width>\r\n");
cmdXml.append("<MidPointX>" + midpointx+ "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + midpointy+ "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomOut>\r\n");
try {
sipCommander.dragZoomCmd(device, channelId, cmdXml.toString(), callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 拉框放大: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void deviceStatus(Device device, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceStatus(device.getServerId(), device);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceStatusQuery(device, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void alarm(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.alarm(device.getServerId(), device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
String startAlarmTime = "";
if (startTime != null) {
startAlarmTime = DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime);
}
String endAlarmTime = "";
if (startTime != null) {
endAlarmTime = DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime);
}
try {
sipCommander.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startAlarmTime, endAlarmTime, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void deviceInfo(Device device, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<Object> result = redisRpcService.deviceInfo(device.getServerId(), device);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.deviceInfoQuery(device, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 获取设备信息: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void queryPreset(Device device, String channelId, ErrorCallback<Object> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<Object> result = redisRpcService.queryPreset(device.getServerId(), device, channelId);
callback.run(result.getCode(), result.getMsg(), result.getData());
return;
}
try {
sipCommander.presetQuery(device, channelId, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 预制位查询: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
}

View File

@ -1,10 +1,12 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
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<StreamInfo> callback) {
public void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> 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<StreamInfo> 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<StreamInfo> callback){
// 拉流代理通道
@ -138,6 +171,16 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
}
}
@Override
public void stopPlayProxy(CommonGBChannel channel) {
// 拉流代理通道
try {
streamProxyPlayService.stop(channel.getDataDeviceId());
}catch (Exception e) {
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
}
}
@Override
public void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback){
// 推流
@ -151,6 +194,16 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
}
}
@Override
public void stopPlayPush(CommonGBChannel channel) {
// 推流
try {
streamPushPlayService.stop(channel.getDataDeviceId());
}catch (Exception e) {
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
}
}
private void playbackGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback){
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<StreamInfo> callback){
try {
@ -171,4 +238,6 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
}

View File

@ -9,8 +9,10 @@ import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.gb28181.dao.RegionMapper;
import com.genersoft.iot.vmp.gb28181.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<CommonGBChannel> all = commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType);
return new PageInfo<>(all);
}
@Override
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
if (channel.getDataType() == ChannelDataType.GB28181.value) {
deviceChannelService.queryRecordInfo(channel, startTime, endTime, callback);
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
// 拉流代理
log.warn("[下载通用通道录像] 不支持下载拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
// 推流
log.warn("[下载通用通道录像] 不支持下载推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else {
// 通道数据异常
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}
}

View File

@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
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<String, List<ErrorCallback<StreamInfo>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();

View File

@ -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<Preset> queryPresetList(String deviceId, String channelDeviceId) {
return Collections.emptyList();

View File

@ -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<CommonGBChannel> queryChannelByPlatformIdAndChannelIds(Integer platformId, List<Integer> channelIds) {
return platformChannelMapper.queryShare(platformId, channelIds);
}
}

View File

@ -1,9 +1,9 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
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<String> serverIds = platformMapper.queryServerIdsWithEnableAndNotInServer(userSetting.getServerId());
if (serverIds == null || serverIds.isEmpty()) {
return;
}
serverIds.forEach(serverId -> {
// 检查每个是否存活
ServerInfo serverInfo = redisCatchStorage.queryServerInfo(serverId);
if (serverInfo != null) {
return;
}
log.info("[集群] 检测到 {} 已离线", serverId);
String chooseServerId = redisCatchStorage.chooseOneServer(serverId);
if (!userSetting.getServerId().equals(chooseServerId)){
return;
}
// 此平台需要选择新平台处理 确定由当前平台即开始处理
List<Platform> platformList = platformMapper.queryByServerId(serverId);
platformList.forEach(platform -> {
log.info("[集群] 由本平台开启上级平台{}({})的注册", platform.getName(), platform.getServerGBId());
// 设置平台使用当前平台的IP
platform.setAddress(getIpWithSameNetwork(platform.getAddress()));
platform.setServerId(userSetting.getServerId());
platformMapper.update(platform);
// 更新redis
redisCatchStorage.delPlatformCatchInfo(platform.getServerGBId());
PlatformCatch platformCatch = new PlatformCatch();
platformCatch.setPlatform(platform);
platformCatch.setId(platform.getServerGBId());
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
// 开始注册
// 注册成功时由程序直接调用了online方法
try {
commanderForPlatform.register(platform, eventResult -> {
log.info("[国标级联] {}{},添加向上级注册失败,请确定上级平台可用时重新保存", platform.getName(), platform.getServerGBId());
}, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
}
});
});
}
/**
* 获取同网段的IP
*/
private String getIpWithSameNetwork(String ip){
if (ip == null || sipConfig.getMonitorIps().size() == 1) {
return sipConfig.getMonitorIps().get(0);
}
String[] ipSplit = ip.split("\\.");
String ip1 = null, ip2 = null, ip3 = null;
for (String monitorIp : sipConfig.getMonitorIps()) {
String[] monitorIpSplit = monitorIp.split("\\.");
if (monitorIpSplit[0].equals(ipSplit[0]) && monitorIpSplit[1].equals(ipSplit[1]) && monitorIpSplit[2].equals(ipSplit[2])) {
ip3 = monitorIp;
}else if (monitorIpSplit[0].equals(ipSplit[0]) && monitorIpSplit[1].equals(ipSplit[1])) {
ip2 = monitorIp;
}else if (monitorIpSplit[0].equals(ipSplit[0])) {
ip1 = monitorIp;
}
}
if (ip3 != null) {
return ip3;
}else if (ip2 != null) {
return ip2;
}else if (ip1 != null) {
return ip1;
}else {
return sipConfig.getMonitorIps().get(0);
}
}
/**
* 流离开的处理
*/
@ -175,6 +263,7 @@ public class PlatformServiceImpl implements IPlatformService {
// 每次发送目录的数量默认为1
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<Platform> queryEnablePlatformList() {
return platformMapper.queryEnablePlatformList();
public List<Platform> queryEnablePlatformList(String serverId) {
return platformMapper.queryEnableParentPlatformList(serverId,true);
}
@Override

View File

@ -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<StreamInfo> callback) {
// 判断设备是否属于当前平台, 如果不属于则发起自动调用
if (!userSetting.getServerId().equals(device.getServerId())) {
redisRpcPlayService.play(device.getServerId(), channel.getId(), callback);
return;
}
MediaServer mediaServerItem = getNewMediaServerItem(device);
if (mediaServerItem == null) {
log.warn("[点播] 未找到可用的zlm deviceId: {},channelId:{}", device.getDeviceId(), channel.getDeviceId());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
}
play(mediaServerItem, device, channel, null, userSetting.getRecordSip(), callback);
}
@Override
public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback) {
@ -736,6 +753,11 @@ public class PlayServiceImpl implements IPlayService {
if (channel == null) {
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<StreamInfo> 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

View File

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

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.task;
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<Device> deviceList = deviceService.getAllOnlineDevice();
List<Device> 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());
}
});

View File

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

View File

@ -75,12 +75,12 @@ public class SIPSender {
CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME);
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);
}

View File

@ -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<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();

View File

@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.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<String> 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<String> 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<String> 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<String> 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<String> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备状态
*
* @param device 视频设备
*/
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void deviceStatusQuery(Device device, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备信息
*
* @param device 视频设备
* @return
*
* @param device 视频设备
* @param callback
* @return
*/
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
void deviceInfoQuery(Device device, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询目录列表
@ -245,7 +240,7 @@ public interface ISIPCommander {
* @return true = 命令发送成功
*/
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备配置
@ -254,14 +249,14 @@ public interface ISIPCommander {
* @param channelId 通道编码可选
* @param configType 配置类型
*/
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备预置位置
*
* @param device 视频设备
*/
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询移动设备位置数据
@ -304,7 +299,7 @@ public interface ISIPCommander {
* @param channelId 通道id
* @param cmdString 前端控制指令串
*/
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
void dragZoomCmd(Device device, String channelId, String cmdString, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
void playbackControlCmd(Device device, DeviceChannel channel, String stream, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;

View File

@ -7,7 +7,9 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
@ -686,10 +696,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
@ -771,10 +795,14 @@ public class SIPCommander implements ISIPCommander {
}
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
channelId = device.getDeviceId();
}
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
cmdXml.append("<HomePosition>\r\n");
if (enabled) {
cmdXml.append("<Enabled>1</Enabled>\r\n");
@ -840,10 +870,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("</HomePosition>\r\n");
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
String channelId = basicParam.getChannelId();
if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
channelId = device.getDeviceId();
}
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
cmdXml.append("<BasicParam>\r\n");
if (!ObjectUtils.isEmpty(name)) {
cmdXml.append("<Name>" + name + "</Name>\r\n");
if (!ObjectUtils.isEmpty(basicParam.getName())) {
cmdXml.append("<Name>" + basicParam.getName() + "</Name>\r\n");
}
if (NumericUtil.isInteger(expiration)) {
if (Integer.valueOf(expiration) > 0) {
cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
if (NumericUtil.isInteger(basicParam.getExpiration())) {
if (Integer.parseInt(basicParam.getExpiration()) > 0) {
cmdXml.append("<Expiration>" + basicParam.getExpiration() + "</Expiration>\r\n");
}
}
if (NumericUtil.isInteger(heartBeatInterval)) {
if (Integer.valueOf(heartBeatInterval) > 0) {
cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
}
if (basicParam.getHeartBeatInterval() != null && basicParam.getHeartBeatInterval() > 0) {
cmdXml.append("<HeartBeatInterval>" + basicParam.getHeartBeatInterval() + "</HeartBeatInterval>\r\n");
}
if (NumericUtil.isInteger(heartBeatCount)) {
if (Integer.valueOf(heartBeatCount) > 0) {
cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
}
if (basicParam.getHeartBeatCount() != null && basicParam.getHeartBeatCount() > 0) {
cmdXml.append("<HeartBeatCount>" + basicParam.getHeartBeatCount() + "</HeartBeatCount>\r\n");
}
cmdXml.append("</BasicParam>\r\n");
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
catalogXml.append("<Query>\r\n");
catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
catalogXml.append("<SN>" + sn + "</SN>\r\n");
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
catalogXml.append("</Query>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<Object> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
catalogXml.append("<Query>\r\n");
catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<CmdType>" + cmdType +"</CmdType>\r\n");
catalogXml.append("<SN>" + sn + "</SN>\r\n");
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
catalogXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn, device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<Object> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
if (!ObjectUtils.isEmpty(startPriority)) {
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
@ -1069,10 +1118,14 @@ public class SIPCommander implements ISIPCommander {
}
cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn, device.getDeviceId(), 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<Object> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
@ -1099,10 +1154,14 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<Object> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Query>\r\n");
cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
@ -1126,9 +1188,14 @@ public class SIPCommander implements ISIPCommander {
}
cmdXml.append("</Query>\r\n");
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
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<String> 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("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
dragXml.append("<Control>\r\n");
dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
dragXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
dragXml.append("<SN>" + sn + "</SN>\r\n");
if (ObjectUtils.isEmpty(channelId)) {
dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
} else {
@ -1283,8 +1353,10 @@ public class SIPCommander implements ISIPCommander {
dragXml.append(cmdString);
dragXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
log.debug("拉框信令: " + request.toString());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request);
}

View File

@ -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());

View File

@ -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())));

View File

@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.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("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n");
cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n");
cmdXml.append("</" + type.getVal() + ">\r\n");
cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString());
cmder.dragZoomCmd(device, deviceChannel.getDeviceId(), cmdXml.toString(), (code, msg, data) -> {
});
responseAck(request, Response.OK);
} 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());
}

View File

@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.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);

View File

@ -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<Object> subscribe = (MessageEvent<Object>)messageSubscribe.getSubscribe(cmd + sn);
if (subscribe != null) {
String result = getText(element, "Result");
if (result == null || "OK".equalsIgnoreCase(result) || data != null) {
subscribe.getCallback().run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data);
}else {
subscribe.getCallback().run(ErrorCode.ERROR100.getCode(), ErrorCode.ERROR100.getMsg(), result);
}
messageSubscribe.removeSubscribe(cmd + sn);
}
}
}

View File

@ -4,18 +4,22 @@ import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.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

View File

@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.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);
}
}

View File

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

View File

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

View File

@ -2,12 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.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);
}

View File

@ -3,14 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.alibaba.fastjson2.JSONObject;
import com.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

View File

@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.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) {

View File

@ -6,6 +6,8 @@ import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.bean.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<Object, Object> 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<Element> recordListIterator = recordListElement.elementIterator();
if (recordListIterator != null) {
List<RecordItem> recordList = new ArrayList<>();
// 遍历DeviceList
while (recordListIterator.hasNext()) {
Element itemRecord = recordListIterator.next();
Element recordElement = itemRecord.element("DeviceID");
if (recordElement == null) {
log.info("记录为空,下一个...");
continue;
}
RecordItem record = new RecordItem();
record.setDeviceId(getText(itemRecord, "DeviceID"));
record.setName(getText(itemRecord, "Name"));
record.setFilePath(getText(itemRecord, "FilePath"));
record.setFileSize(getText(itemRecord, "FileSize"));
record.setAddress(getText(itemRecord, "Address"));
String startTimeStr = getText(itemRecord, "StartTime");
record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
String endTimeStr = getText(itemRecord, "EndTime");
record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
: Integer.parseInt(getText(itemRecord, "Secrecy")));
record.setType(getText(itemRecord, "Type"));
record.setRecorderId(getText(itemRecord, "RecorderID"));
recordList.add(record);
}
Map<String, String> map = recordList.stream()
.filter(record -> record.getDeviceId() != null)
.collect(Collectors.toMap(record -> record.getStartTime()+ record.getEndTime(), UJson::writeJson));
// 获取任务结果数据
String resKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_PRE + channelId + sn;
redisTemplate.opsForHash().putAll(resKey, map);
redisTemplate.expire(resKey, recordInfoTtl, TimeUnit.SECONDS);
String resCountKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_COUNT_PRE + channelId + sn;
long incr = redisTemplate.opsForValue().increment(resCountKey, map.size());
redisTemplate.expire(resCountKey, recordInfoTtl, TimeUnit.SECONDS);
recordInfo.setRecordList(recordList);
recordInfo.setCount(Math.toIntExact(incr));
eventPublisher.recordEndEventPush(recordInfo);
if (incr < sumNum) {
return;
}
// 已接收完成
List<RecordItem> resList = redisTemplate.opsForHash().entries(resKey).values().stream().map(e -> UJson.readJson(e.toString(), RecordItem.class)).collect(Collectors.toList());
if (resList.size() < sumNum) {
return;
}
recordInfo.setRecordList(resList);
releaseRequest(device.getDeviceId(), sn,recordInfo);
}
}
} catch (Exception e) {
log.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest());
log.error("[国标录像] 异常内容: ", e);
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<Element> recordListIterator = recordListElement.elementIterator();
if (recordListIterator != null) {
List<RecordItem> recordList = new ArrayList<>();
// 遍历DeviceList
while (recordListIterator.hasNext()) {
Element itemRecord = recordListIterator.next();
Element recordElement = itemRecord.element("DeviceID");
if (recordElement == null) {
log.info("记录为空,下一个...");
continue;
}
RecordItem record = new RecordItem();
record.setDeviceId(getText(itemRecord, "DeviceID"));
record.setName(getText(itemRecord, "Name"));
record.setFilePath(getText(itemRecord, "FilePath"));
record.setFileSize(getText(itemRecord, "FileSize"));
record.setAddress(getText(itemRecord, "Address"));
String startTimeStr = getText(itemRecord, "StartTime");
record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
String endTimeStr = getText(itemRecord, "EndTime");
record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
: Integer.parseInt(getText(itemRecord, "Secrecy")));
record.setType(getText(itemRecord, "Type"));
record.setRecorderId(getText(itemRecord, "RecorderID"));
recordList.add(record);
}
Map<String, String> map = recordList.stream()
.filter(record -> record.getDeviceId() != null)
.collect(Collectors.toMap(record -> record.getStartTime()+ record.getEndTime(), UJson::writeJson));
// 获取任务结果数据
String resKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_PRE + channelId + sn;
redisTemplate.opsForHash().putAll(resKey, map);
redisTemplate.expire(resKey, recordInfoTtl, TimeUnit.SECONDS);
String resCountKey = VideoManagerConstants.REDIS_RECORD_INFO_RES_COUNT_PRE + channelId + sn;
Long incr = redisTemplate.opsForValue().increment(resCountKey, map.size());
if (incr == null) {
incr = 0L;
}
redisTemplate.expire(resCountKey, recordInfoTtl, TimeUnit.SECONDS);
recordInfo.setRecordList(recordList);
recordInfo.setCount(Math.toIntExact(incr));
recordInfoEventPush(recordInfo);
if (incr < sumNum) {
return;
}
// 已接收完成
List<RecordItem> resList = redisTemplate.opsForHash().entries(resKey).values().stream().map(e -> UJson.readJson(e.toString(), RecordItem.class)).collect(Collectors.toList());
if (resList.size() < sumNum) {
return;
}
recordInfo.setRecordList(resList);
recordInfoEndEventPush(recordInfo);
}
}
} catch (Exception e) {
log.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest());
log.error("[国标录像] 异常内容: ", e);
}
}
@Override
@ -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);
}
}

View File

@ -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> T getBean(String beanName, Class<T> clazz) {
return context.getBean(beanName, clazz);
}
public static Object getBean(Class<?> clazz) {
if (clazz != null) {
try {

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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<MediaServer> getAll() {
List<MediaServer> mediaServerList = mediaServerMapper.queryAll();
List<MediaServer> mediaServerList = mediaServerMapper.queryAll(userSetting.getServerId());
if (mediaServerList.isEmpty()) {
return new ArrayList<>();
}
@ -368,7 +366,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override
public List<MediaServer> 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<MediaServer> allInCatch = getAllOnlineList();
List<MediaServer> allInDatabase = mediaServerMapper.queryAll();
List<MediaServer> allInDatabase = mediaServerMapper.queryAll(userSetting.getServerId());
Map<String, MediaServer> mediaServerMap = new HashMap<>();
for (MediaServer mediaServer : allInDatabase) {
@ -608,7 +606,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override
public List<MediaServer> getAllWithAssistPort() {
return mediaServerMapper.queryAllWithAssistPort();
return mediaServerMapper.queryAllWithAssistPort(userSetting.getServerId());
}

View File

@ -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);

View File

@ -2,12 +2,14 @@ package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.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;
}
}

View File

@ -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<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId) {
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime,
String endTime, List<MediaServer> mediaServerItems, String callId) {
// 开始时间和结束时间在数据库中都是以秒为单位的
Long startTimeStamp = null;
Long 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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

@ -2,7 +2,8 @@ package com.genersoft.iot.vmp.service.redisMsg;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.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<StreamInfo> 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<SyncStatus> devicesSync(String serverId, String deviceId);
SyncStatus getChannelSyncStatus(String serverId, String deviceId);
WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam);
WVPResult<String> deviceConfigQuery(String serverId, Device device, String channelId, String configType);
void teleboot(String serverId, Device device);
WVPResult<String> recordControl(String serverId, Device device, String channelId, String recordCmdStr);
WVPResult<String> guard(String serverId, Device device, String guardCmdStr);
WVPResult<String> resetAlarm(String serverId, Device device, String channelId, String alarmMethod, String alarmType);
void iFrame(String serverId, Device device, String channelId);
WVPResult<String> homePosition(String serverId, Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex);
void dragZoomIn(String serverId, Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy);
void dragZoomOut(String serverId, Device device, String channelId, int length, int width, int midpointx, int midpointy, int lengthx, int lengthy);
WVPResult<String> deviceStatus(String serverId, Device device);
WVPResult<String> alarm(String serverId, Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
WVPResult<Object> deviceInfo(String serverId, Device device);
WVPResult<Object> queryPreset(String serverId, Device device, String channelId);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,33 +3,32 @@ package com.genersoft.iot.vmp.service.redisMsg.control;
import com.alibaba.fastjson2.JSONObject;
import com.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<Object, Object> 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);
}
}

View File

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

View File

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

View File

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

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