Merge remote-tracking branch 'origin/master'
commit
b6a6144bf2
|
@ -1,8 +1,5 @@
|
||||||
package com.genersoft.iot.vmp.common.enums;
|
package com.genersoft.iot.vmp.common.enums;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持的通道数据类型
|
* 支持的通道数据类型
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析收到的前端控制指令
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FrontEndCode {
|
||||||
|
|
||||||
|
|
||||||
|
public static String encode(IFrontEndControlCode frontEndControlCode){
|
||||||
|
return frontEndControlCode.encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFrontEndControlCode decode(@NotNull String cmdStr) {
|
||||||
|
if (cmdStr.length() != 16) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String cmdCodeStr = cmdStr.substring(6, 8);
|
||||||
|
int cmdCode = Integer.parseInt(cmdCodeStr, 16);
|
||||||
|
if (cmdCode < 39) {
|
||||||
|
// PTZ指令
|
||||||
|
FrontEndControlCodeForPTZ codeForPTZ = new FrontEndControlCodeForPTZ();
|
||||||
|
int zoomOut = cmdCode >> 5 & 1;
|
||||||
|
if (zoomOut == 1) {
|
||||||
|
codeForPTZ.setZoom(0);
|
||||||
|
}
|
||||||
|
int zoomIn = cmdCode >> 4 & 1;
|
||||||
|
if (zoomIn == 1) {
|
||||||
|
codeForPTZ.setZoom(1);
|
||||||
|
}
|
||||||
|
int tiltUp = cmdCode >> 3 & 1;
|
||||||
|
if (tiltUp == 1) {
|
||||||
|
codeForPTZ.setTilt(0);
|
||||||
|
}
|
||||||
|
int tiltDown = cmdCode >> 2 & 1;
|
||||||
|
if (tiltDown == 1) {
|
||||||
|
codeForPTZ.setTilt(1);
|
||||||
|
}
|
||||||
|
int panLeft = cmdCode >> 1 & 1;
|
||||||
|
if (panLeft == 1) {
|
||||||
|
codeForPTZ.setPan(0);
|
||||||
|
}
|
||||||
|
int panRight = cmdCode & 1;
|
||||||
|
if (panRight == 1) {
|
||||||
|
codeForPTZ.setPan(1);
|
||||||
|
}
|
||||||
|
String param1Str = cmdStr.substring(8, 10);
|
||||||
|
codeForPTZ.setPanSpeed(Integer.parseInt(param1Str, 16));
|
||||||
|
String param2Str = cmdStr.substring(10, 12);
|
||||||
|
codeForPTZ.setTiltSpeed(Integer.parseInt(param2Str, 16));
|
||||||
|
String param3Str = cmdStr.substring(12, 13);
|
||||||
|
codeForPTZ.setZoomSpeed(Integer.parseInt(param3Str, 16));
|
||||||
|
return codeForPTZ;
|
||||||
|
}else if (cmdCode < 74) {
|
||||||
|
// FI指令
|
||||||
|
FrontEndControlCodeForFI codeForFI = new FrontEndControlCodeForFI();
|
||||||
|
int irisOut = cmdCode >> 3 & 1;
|
||||||
|
if (irisOut == 1) {
|
||||||
|
codeForFI.setIris(0);
|
||||||
|
}
|
||||||
|
int irisIn = cmdCode >> 2 & 1;
|
||||||
|
if (irisIn == 1) {
|
||||||
|
codeForFI.setIris(1);
|
||||||
|
}
|
||||||
|
int focusNear = cmdCode >> 1 & 1;
|
||||||
|
if (focusNear == 1) {
|
||||||
|
codeForFI.setFocus(0);
|
||||||
|
}
|
||||||
|
int focusFar = cmdCode & 1;
|
||||||
|
if (focusFar == 1) {
|
||||||
|
codeForFI.setFocus(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String param1Str = cmdStr.substring(8, 10);
|
||||||
|
codeForFI.setFocusSpeed(Integer.parseInt(param1Str, 16));
|
||||||
|
String param2Str = cmdStr.substring(10, 12);
|
||||||
|
codeForFI.setIrisSpeed(Integer.parseInt(param2Str, 16));
|
||||||
|
return codeForFI;
|
||||||
|
}else if (cmdCode < 131) {
|
||||||
|
// 预置位指令
|
||||||
|
FrontEndControlCodeForPreset codeForPreset = new FrontEndControlCodeForPreset();
|
||||||
|
switch (cmdCode) {
|
||||||
|
case 0x81: // 设置预置位
|
||||||
|
codeForPreset.setCode(1);
|
||||||
|
break;
|
||||||
|
case 0x82: // 调用预置位
|
||||||
|
codeForPreset.setCode(2);
|
||||||
|
break;
|
||||||
|
case 0x83: // 删除预置位
|
||||||
|
codeForPreset.setCode(3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 预置位编号
|
||||||
|
String param2Str = cmdStr.substring(10, 12);
|
||||||
|
codeForPreset.setPresetId(Integer.parseInt(param2Str, 16));
|
||||||
|
return codeForPreset;
|
||||||
|
}else if (cmdCode < 136) {
|
||||||
|
// 巡航指令
|
||||||
|
FrontEndControlCodeForTour codeForTour = new FrontEndControlCodeForTour();
|
||||||
|
String param3Str = cmdStr.substring(12, 13);
|
||||||
|
switch (cmdCode) {
|
||||||
|
case 0x84: // 加入巡航点
|
||||||
|
codeForTour.setCode(1);
|
||||||
|
break;
|
||||||
|
case 0x85: // 删除一个巡航点
|
||||||
|
codeForTour.setCode(2);
|
||||||
|
break;
|
||||||
|
case 0x86: // 设置巡航速度
|
||||||
|
codeForTour.setCode(3);
|
||||||
|
codeForTour.setTourSpeed(Integer.parseInt(param3Str, 16));
|
||||||
|
break;
|
||||||
|
case 0x87: // 设置巡航停留时间
|
||||||
|
codeForTour.setCode(4);
|
||||||
|
codeForTour.setTourTime(Integer.parseInt(param3Str, 16));
|
||||||
|
break;
|
||||||
|
case 0x88: // 开始巡航
|
||||||
|
codeForTour.setCode(5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String param1Str = cmdStr.substring(8, 10);
|
||||||
|
codeForTour.setTourId(Integer.parseInt(param1Str, 16));
|
||||||
|
String param2Str = cmdStr.substring(10, 12);
|
||||||
|
codeForTour.setPresetId(Integer.parseInt(param2Str, 16));
|
||||||
|
return codeForTour;
|
||||||
|
}else if (cmdCode < 138) {
|
||||||
|
// 扫描指令
|
||||||
|
FrontEndControlCodeForScan controlCodeForScan = new FrontEndControlCodeForScan();
|
||||||
|
String param2Str = cmdStr.substring(10, 11);
|
||||||
|
int param2Code = Integer.parseInt(param2Str, 16);
|
||||||
|
switch (cmdCode) {
|
||||||
|
case 0x89:
|
||||||
|
switch (param2Code) {
|
||||||
|
case 0x00: // 开始自动扫描
|
||||||
|
controlCodeForScan.setCode(1);
|
||||||
|
break;
|
||||||
|
case 0x01: // 设置自动扫描左边界
|
||||||
|
controlCodeForScan.setCode(2);
|
||||||
|
break;
|
||||||
|
case 0x02: // 设置自动扫描右边界
|
||||||
|
controlCodeForScan.setCode(3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x8A: // 删除一个巡航点
|
||||||
|
controlCodeForScan.setCode(4);
|
||||||
|
String param3Str = cmdStr.substring(12, 13);
|
||||||
|
controlCodeForScan.setScanSpeed(Integer.parseInt(param3Str, 16));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String param1Str = cmdStr.substring(8, 10);
|
||||||
|
controlCodeForScan.setScanId(Integer.parseInt(param1Str, 16));
|
||||||
|
return controlCodeForScan;
|
||||||
|
}else if (cmdCode < 141) {
|
||||||
|
// 辅助开关
|
||||||
|
FrontEndControlCodeForAuxiliary codeForAuxiliary = new FrontEndControlCodeForAuxiliary();
|
||||||
|
switch (cmdCode) {
|
||||||
|
case 0x8C: // 开
|
||||||
|
codeForAuxiliary.setCode(1);
|
||||||
|
break;
|
||||||
|
case 0x8D: // 关
|
||||||
|
codeForAuxiliary.setCode(2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 预置位编号
|
||||||
|
String param2Str = cmdStr.substring(10, 12);
|
||||||
|
codeForAuxiliary.setAuxiliaryId(Integer.parseInt(param2Str, 16));
|
||||||
|
return codeForAuxiliary;
|
||||||
|
}else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForAuxiliary implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.AUXILIARY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 辅助开关控制指令: 1为开, 2为关, 3为设置自动扫描右边界, 4为设置自动扫描速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 辅助开关编号
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer auxiliaryId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForFI implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.FI;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 光圈,0为缩小 1为放大
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer iris;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚焦 0 近, 1远
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer focus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚焦速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer focusSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 光圈速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer irisSpeed;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForPTZ implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.PTZ;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 镜头变倍,0为缩小 1为放大
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer zoom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 云台垂直方向控制 0 为上, 1为下
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer tilt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 云台水平方向控制 0 为左, 1为右
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer pan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水平控制速度相对值
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer panSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 垂直控制速度相对值
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer tiltSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 变倍控制速度相对值
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer zoomSpeed;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForPreset implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.PRESET;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预置位指令: 1为设置预置位, 2为调用预置位, 3为删除预置位
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预置位编号
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer presetId;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForScan implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.SCAN;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预置位指令: 1为开始自动扫描, 2为设置自动扫描左边界, 3为设置自动扫描右边界, 4为设置自动扫描速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动扫描速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer scanSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扫描组号
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer scanId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class FrontEndControlCodeForTour implements IFrontEndControlCode {
|
||||||
|
|
||||||
|
private final FrontEndControlType type = FrontEndControlType.TOUR;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FrontEndControlType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 巡航指令: 1为加入巡航点, 2为删除一个巡航点, 3为设置巡航速度, 4为设置巡航停留时间, 5为开始巡航
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 巡航点
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer tourId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 巡航停留时间
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer tourTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 巡航速度
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer tourSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预置位编号
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Integer presetId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
public enum FrontEndControlType {
|
||||||
|
|
||||||
|
PTZ,FI,PRESET,TOUR,SCAN,AUXILIARY
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
public interface IFrontEndControlCode {
|
||||||
|
|
||||||
|
FrontEndControlType getType();
|
||||||
|
String encode();
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ public class PtzController {
|
||||||
private IDeviceService deviceService;
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPTZService iptzService;
|
private IPTZService ptzService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
@ -75,7 +75,7 @@ public class PtzController {
|
||||||
|
|
||||||
Assert.notNull(device, "设备[" + deviceId + "]不存在");
|
Assert.notNull(device, "设备[" + deviceId + "]不存在");
|
||||||
|
|
||||||
iptzService.frontEndCommand(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
ptzService.frontEndCommand(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.service;
|
package com.genersoft.iot.vmp.gb28181.service;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
||||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,4 +130,5 @@ public interface IDeviceChannelService {
|
||||||
|
|
||||||
List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId);
|
List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId);
|
||||||
|
|
||||||
|
void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.service;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.FrontEndControlCodeForPTZ;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
|
|
||||||
|
public interface IGbChannelControlService {
|
||||||
|
|
||||||
|
|
||||||
|
void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
void fi(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
void preset(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
void tour(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
void scan(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
void auxiliary(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||||
|
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
|
@ -18,7 +19,9 @@ import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
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.gb28181.utils.SipUtils;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
|
@ -27,6 +30,7 @@ import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dom4j.Element;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -34,8 +38,15 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lin
|
* @author lin
|
||||||
*/
|
*/
|
||||||
|
@ -72,6 +83,10 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||||
private IPlatformChannelService platformChannelService;
|
private IPlatformChannelService platformChannelService;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISIPCommander cmder;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateChannels(Device device, List<DeviceChannel> channels) {
|
public int updateChannels(Device device, List<DeviceChannel> channels) {
|
||||||
List<DeviceChannel> addChannels = new ArrayList<>();
|
List<DeviceChannel> addChannels = new ArrayList<>();
|
||||||
|
@ -362,6 +377,39 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||||
return channelMapper.queryChaneIdListByDeviceDbIds(deviceDbIds);
|
return channelMapper.queryChaneIdListByDeviceDbIds(deviceDbIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback) {
|
||||||
|
|
||||||
|
// 根据通道ID,获取所属设备
|
||||||
|
Device device = deviceMapper.query(dataDeviceId);
|
||||||
|
if (device == null) {
|
||||||
|
// 不存在则回复404
|
||||||
|
log.warn("[INFO 消息] 通道所属设备不存在, 设备ID: {}", dataDeviceId);
|
||||||
|
callback.run(Response.NOT_FOUND, "device not found", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceChannel deviceChannel = channelMapper.getOneForSource(gbId);
|
||||||
|
if (deviceChannel == null) {
|
||||||
|
log.warn("[deviceControl] 未找到设备原始通道, 设备: {}({}),通道编号:{}", device.getName(),
|
||||||
|
device.getDeviceId(), gbId);
|
||||||
|
callback.run(Response.NOT_FOUND, "channel not found", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("[deviceControl] 命令: {}, 设备: {}({}), 通道{}({}", type, device.getName(), device.getDeviceId(),
|
||||||
|
deviceChannel.getName(), deviceChannel.getDeviceId());
|
||||||
|
String cmdString = getText(rootElement, type.getVal());
|
||||||
|
try {
|
||||||
|
cmder.fronEndCmd(device, deviceChannel.getDeviceId(), cmdString, errorResult->{
|
||||||
|
callback.run(errorResult.statusCode, errorResult.msg, null);
|
||||||
|
}, errorResult->{
|
||||||
|
callback.run(errorResult.statusCode, errorResult.msg, null);
|
||||||
|
});
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
|
log.error("[命令发送失败] 云台/前端: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition) {
|
public void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition) {
|
||||||
if (userSetting.getSavePositionHistory()) {
|
if (userSetting.getSavePositionHistory()) {
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.FrontEndControlCodeForPTZ;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelControlService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class GbChannelControlServiceImpl implements IGbChannelControlService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
log.info("[通用通道] 云台控制, 通道: {}", channel.getGbId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preset(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
log.info("[通用通道] 预置位, 通道: {}", channel.getGbId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fi(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
log.info("[通用通道] FI指令, 通道: {}", channel.getGbId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tour(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scan(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void auxiliary(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ public class SipInviteSessionManager {
|
||||||
if (ssrcTransaction == null ) {
|
if (ssrcTransaction == null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_STREAM + userSetting.getServerId(), stream);
|
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_STREAM + userSetting.getServerId(), app + stream);
|
||||||
if (ssrcTransaction.getCallId() != null) {
|
if (ssrcTransaction.getCallId() != null) {
|
||||||
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_CALL_ID + userSetting.getServerId(), ssrcTransaction.getCallId());
|
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_CALL_ID + userSetting.getServerId(), ssrcTransaction.getCallId());
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class SipInviteSessionManager {
|
||||||
}
|
}
|
||||||
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_CALL_ID + userSetting.getServerId(), callId);
|
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_CALL_ID + userSetting.getServerId(), callId);
|
||||||
if (ssrcTransaction.getStream() != null) {
|
if (ssrcTransaction.getStream() != null) {
|
||||||
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_STREAM + userSetting.getServerId(), ssrcTransaction.getStream());
|
redisTemplate.opsForHash().delete(VideoManagerConstants.SIP_INVITE_SESSION_STREAM + userSetting.getServerId(), ssrcTransaction.getApp() + ssrcTransaction.getStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,9 +211,6 @@ public class SIPCommander implements ISIPCommander {
|
||||||
ptzXml.append("</Info>\r\n");
|
ptzXml.append("</Info>\r\n");
|
||||||
ptzXml.append("</Control>\r\n");
|
ptzXml.append("</Control>\r\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.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);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelControlService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
@ -42,6 +43,9 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||||
@Autowired
|
@Autowired
|
||||||
private IGbChannelService channelService;
|
private IGbChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IGbChannelControlService channelControlService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IDeviceService deviceService;
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
|
@ -135,49 +139,91 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||||
* 处理云台指令
|
* 处理云台指令
|
||||||
*/
|
*/
|
||||||
private void handlePtzCmd(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) {
|
private void handlePtzCmd(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) {
|
||||||
if (channel.getDataType() != ChannelDataType.GB28181.value) {
|
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||||
// 只支持国标的云台控制
|
|
||||||
log.warn("[INFO 消息] 只支持国标的云台控制, 通道ID: {}", channel.getGbId());
|
deviceChannelService.handlePtzCmd(channel.getDataDeviceId(), channel.getGbId(), rootElement, type, ((code, msg, data) -> {
|
||||||
|
try {
|
||||||
|
responseAck(request, code, msg);
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}else {
|
||||||
|
// 解析云台控制参数
|
||||||
|
String cmdString = getText(rootElement, type.getVal());
|
||||||
|
IFrontEndControlCode frontEndControlCode = FrontEndCode.decode(cmdString);
|
||||||
|
if (frontEndControlCode == null) {
|
||||||
|
log.info("[INFO 消息] 不支持的控制方式");
|
||||||
try {
|
try {
|
||||||
responseAck(request, Response.FORBIDDEN, "");
|
responseAck(request, Response.FORBIDDEN, "");
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 根据通道ID,获取所属设备
|
switch (frontEndControlCode.getType()){
|
||||||
Device device = deviceService.getDevice(channel.getDataDeviceId());
|
case PTZ:
|
||||||
if (device == null) {
|
channelControlService.ptz(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
// 不存在则回复404
|
|
||||||
log.warn("[INFO 消息] 通道所属设备不存在, 通道ID: {}", channel.getGbId());
|
|
||||||
try {
|
try {
|
||||||
responseAck(request, Response.NOT_FOUND, "device not found");
|
responseAck(request, code, msg);
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
}
|
}
|
||||||
return;
|
}));
|
||||||
}
|
break;
|
||||||
|
case FI:
|
||||||
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
|
channelControlService.fi(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
if (deviceChannel == null) {
|
|
||||||
log.warn("[deviceControl] 未找到设备原始通道, 设备: {}({}),通道编号:{}", device.getName(),
|
|
||||||
device.getDeviceId(), channel.getGbId());
|
|
||||||
try {
|
try {
|
||||||
responseAck(request, Response.NOT_FOUND, "channel not found");
|
responseAck(request, code, msg);
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
}
|
}
|
||||||
return;
|
}));
|
||||||
}
|
break;
|
||||||
log.info("[deviceControl] 命令: {}, 设备: {}({}), 通道{}({}", type, device.getName(), device.getDeviceId(),
|
case PRESET:
|
||||||
deviceChannel.getName(), deviceChannel.getDeviceId());
|
channelControlService.preset(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
String cmdString = getText(rootElement, type.getVal());
|
|
||||||
try {
|
try {
|
||||||
cmder.fronEndCmd(device, deviceChannel.getDeviceId(), cmdString,
|
responseAck(request, code, msg);
|
||||||
errorResult -> onError(request, errorResult),
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
okResult -> onOk(request, okResult));
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
}
|
||||||
log.error("[命令发送失败] 云台/前端: {}", e.getMessage());
|
}));
|
||||||
|
break;
|
||||||
|
case TOUR:
|
||||||
|
channelControlService.tour(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
|
try {
|
||||||
|
responseAck(request, code, msg);
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case SCAN:
|
||||||
|
channelControlService.scan(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
|
try {
|
||||||
|
responseAck(request, code, msg);
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case AUXILIARY:
|
||||||
|
channelControlService.auxiliary(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||||
|
try {
|
||||||
|
responseAck(request, code, msg);
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.info("[INFO 消息] 设备不支持的控制方式");
|
||||||
|
try {
|
||||||
|
responseAck(request, Response.FORBIDDEN, "");
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||||
|
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,14 @@ package com.genersoft.iot.vmp.streamProxy.service.impl;
|
||||||
|
|
||||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||||
|
import com.genersoft.iot.vmp.media.event.hook.Hook;
|
||||||
|
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.media.event.hook.HookType;
|
||||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
|
@ -23,6 +28,7 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +45,15 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HookSubscribe subscribe;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DynamicTask dynamicTask;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetting userSetting;
|
||||||
|
|
||||||
private ConcurrentHashMap<Integer, ErrorCallback<StreamInfo>> callbackMap = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<Integer, ErrorCallback<StreamInfo>> callbackMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private ConcurrentHashMap<Integer, StreamInfo> streamInfoMap = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<Integer, StreamInfo> streamInfoMap = new ConcurrentHashMap<>();
|
||||||
|
@ -96,9 +111,25 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
streamProxy.setEnableMp4(record);
|
streamProxy.setEnableMp4(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamInfo streamInfo = startProxy(streamProxy);
|
StreamInfo streamInfo = startProxy(streamProxy);
|
||||||
if (streamInfo != null && callback != null) {
|
if (callback != null) {
|
||||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
|
// 设置流超时的定时任务
|
||||||
|
String timeOutTaskKey = UUID.randomUUID().toString();
|
||||||
|
Hook rtpHook = Hook.getInstance(HookType.on_media_arrival, streamProxy.getApp(), streamProxy.getStream(), streamInfo.getMediaServer().getId());
|
||||||
|
dynamicTask.startDelay(timeOutTaskKey, () -> {
|
||||||
|
// 收流超时
|
||||||
|
subscribe.removeSubscribe(rtpHook);
|
||||||
|
callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), streamInfo);
|
||||||
|
}, userSetting.getPlayTimeout());
|
||||||
|
|
||||||
|
// 开启流到来的监听
|
||||||
|
subscribe.addSubscribe(rtpHook, (hookData) -> {
|
||||||
|
dynamicTask.stop(timeOutTaskKey);
|
||||||
|
// hook响应
|
||||||
|
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||||
|
subscribe.removeSubscribe(rtpHook);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return streamInfo;
|
return streamInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="channelList" style="width: 100%">
|
<div id="channelList" style="width: 100%">
|
||||||
<div v-if="!editId" class="page-header">
|
<div v-if="!editId">
|
||||||
|
<div class="page-header">
|
||||||
<div class="page-title">
|
<div class="page-title">
|
||||||
<el-page-header @back="showDevice" content="通道列表"></el-page-header>
|
<el-page-header @back="showDevice" content="通道列表"></el-page-header>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,7 +41,6 @@
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
|
||||||
<el-table size="medium" ref="channelListTable" :data="deviceChannelList" :height="$tableHeght"
|
<el-table size="medium" ref="channelListTable" :data="deviceChannelList" :height="$tableHeght"
|
||||||
header-row-class-name="table-header">
|
header-row-class-name="table-header">
|
||||||
<el-table-column prop="name" label="名称" min-width="180">
|
<el-table-column prop="name" label="名称" min-width="180">
|
||||||
|
@ -159,6 +159,9 @@
|
||||||
layout="total, sizes, prev, pager, next"
|
layout="total, sizes, prev, pager, next"
|
||||||
:total="total">
|
:total="total">
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||||
<channel-edit v-if="editId" :id="editId" :closeEdit="closeEdit"></channel-edit>
|
<channel-edit v-if="editId" :id="editId" :closeEdit="closeEdit"></channel-edit>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -309,6 +309,7 @@ create table wvp_stream_proxy
|
||||||
update_time character varying(50),
|
update_time character varying(50),
|
||||||
stream_key character varying(255),
|
stream_key character varying(255),
|
||||||
enable_disable_none_reader bool default false,
|
enable_disable_none_reader bool default false,
|
||||||
|
relates_media_server_id character varying(50),
|
||||||
constraint uk_stream_proxy_app_stream unique (app, stream)
|
constraint uk_stream_proxy_app_stream unique (app, stream)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,7 @@ create table wvp_stream_proxy
|
||||||
update_time character varying(50),
|
update_time character varying(50),
|
||||||
stream_key character varying(255),
|
stream_key character varying(255),
|
||||||
enable_disable_none_reader bool default false,
|
enable_disable_none_reader bool default false,
|
||||||
|
relates_media_server_id character varying(50),
|
||||||
constraint uk_stream_proxy_app_stream unique (app, stream)
|
constraint uk_stream_proxy_app_stream unique (app, stream)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -452,7 +453,7 @@ create table wvp_record_plan
|
||||||
create table wvp_record_plan_item
|
create table wvp_record_plan_item
|
||||||
(
|
(
|
||||||
id serial primary key,
|
id serial primary key,
|
||||||
start int,
|
"start" int,
|
||||||
stop int,
|
stop int,
|
||||||
week_day int,
|
week_day int,
|
||||||
plan_id int,
|
plan_id int,
|
||||||
|
|
Loading…
Reference in New Issue