Merge remote-tracking branch 'origin/master'
commit
b6a6144bf2
|
@ -1,8 +1,5 @@
|
|||
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;
|
||||
|
||||
@Autowired
|
||||
private IPTZService iptzService;
|
||||
private IPTZService ptzService;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
@ -75,7 +75,7 @@ public class PtzController {
|
|||
|
||||
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))
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
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.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
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.web.gb28181.dto.DeviceChannelExtend;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -126,4 +130,5 @@ public interface IDeviceChannelService {
|
|||
|
||||
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.InviteSessionType;
|
||||
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.exception.ControllerException;
|
||||
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.IInviteStreamService;
|
||||
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.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
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.PageInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -34,8 +38,15 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
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 static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
|
@ -72,6 +83,10 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
|||
private IPlatformChannelService platformChannelService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ISIPCommander cmder;
|
||||
|
||||
|
||||
@Override
|
||||
public int updateChannels(Device device, List<DeviceChannel> channels) {
|
||||
List<DeviceChannel> addChannels = new ArrayList<>();
|
||||
|
@ -362,6 +377,39 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
|||
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
|
||||
public void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition) {
|
||||
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 ) {
|
||||
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) {
|
||||
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);
|
||||
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("</Control>\r\n");
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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.service.IDeviceChannelService;
|
||||
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.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
|
@ -42,6 +43,9 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
@Autowired
|
||||
private IGbChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private IGbChannelControlService channelControlService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
|
@ -135,49 +139,91 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
* 处理云台指令
|
||||
*/
|
||||
private void handlePtzCmd(CommonGBChannel channel, Element rootElement, SIPRequest request, DeviceControlType type) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181.value) {
|
||||
// 只支持国标的云台控制
|
||||
log.warn("[INFO 消息] 只支持国标的云台控制, 通道ID: {}", channel.getGbId());
|
||||
try {
|
||||
responseAck(request, Response.FORBIDDEN, "");
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 根据通道ID,获取所属设备
|
||||
Device device = deviceService.getDevice(channel.getDataDeviceId());
|
||||
if (device == null) {
|
||||
// 不存在则回复404
|
||||
log.warn("[INFO 消息] 通道所属设备不存在, 通道ID: {}", channel.getGbId());
|
||||
try {
|
||||
responseAck(request, Response.NOT_FOUND, "device not found");
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
|
||||
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
|
||||
if (deviceChannel == null) {
|
||||
log.warn("[deviceControl] 未找到设备原始通道, 设备: {}({}),通道编号:{}", device.getName(),
|
||||
device.getDeviceId(), channel.getGbId());
|
||||
try {
|
||||
responseAck(request, Response.NOT_FOUND, "channel not found");
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
||||
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 {
|
||||
responseAck(request, Response.FORBIDDEN, "");
|
||||
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (frontEndControlCode.getType()){
|
||||
case PTZ:
|
||||
channelControlService.ptz(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||
try {
|
||||
responseAck(request, code, msg);
|
||||
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||
}
|
||||
}));
|
||||
break;
|
||||
case FI:
|
||||
channelControlService.fi(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||
try {
|
||||
responseAck(request, code, msg);
|
||||
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||
log.error("[命令发送失败] 云台指令: {}", exception.getMessage());
|
||||
}
|
||||
}));
|
||||
break;
|
||||
case PRESET:
|
||||
channelControlService.preset(channel, (FrontEndControlCodeForPTZ)frontEndControlCode, ((code, msg, data) -> {
|
||||
try {
|
||||
responseAck(request, code, msg);
|
||||
} catch (InvalidArgumentException | SipException | ParseException exception) {
|
||||
log.error("[命令发送失败] 云台指令: {}", exception.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());
|
||||
}
|
||||
}
|
||||
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 -> onError(request, errorResult),
|
||||
okResult -> onOk(request, okResult));
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
log.error("[命令发送失败] 云台/前端: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,14 @@ package com.genersoft.iot.vmp.streamProxy.service.impl;
|
|||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
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.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
@ -23,6 +28,7 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
|
@ -39,6 +45,15 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
|
|||
@Autowired
|
||||
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, StreamInfo> streamInfoMap = new ConcurrentHashMap<>();
|
||||
|
@ -96,9 +111,25 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
|
|||
if (record != null) {
|
||||
streamProxy.setEnableMp4(record);
|
||||
}
|
||||
|
||||
StreamInfo streamInfo = startProxy(streamProxy);
|
||||
if (streamInfo != null && callback != null) {
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||
if (callback != null) {
|
||||
// 设置流超时的定时任务
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,164 +1,167 @@
|
|||
<template>
|
||||
<div id="channelList" style="width: 100%">
|
||||
<div v-if="!editId" class="page-header">
|
||||
<div class="page-title">
|
||||
<el-page-header @back="showDevice" content="通道列表"></el-page-header>
|
||||
</div>
|
||||
<div class="page-header-btn">
|
||||
<div v-if="!showTree" style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
通道类型:
|
||||
<el-select size="mini" @change="search" style="width: 8rem; margin-right: 1rem;" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="设备" value="false"></el-option>
|
||||
<el-option label="子目录" value="true"></el-option>
|
||||
</el-select>
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
码流类型重置:
|
||||
<el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream"
|
||||
placeholder="请选择码流类型" default-first-option >
|
||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
||||
</el-select>
|
||||
<div v-if="!editId">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<el-page-header @back="showDevice" content="通道列表"></el-page-header>
|
||||
</div>
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||
<el-table size="medium" ref="channelListTable" :data="deviceChannelList" :height="$tableHeght"
|
||||
header-row-class-name="table-header">
|
||||
<el-table-column prop="name" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="deviceId" label="编号" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column label="快照" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<el-image
|
||||
:src="getSnap(scope.row)"
|
||||
:preview-src-list="getBigSnap(scope.row)"
|
||||
@error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
|
||||
:fit="'contain'"
|
||||
style="width: 60px">
|
||||
<div slot="error" class="image-slot">
|
||||
<i class="el-icon-picture-outline"></i>
|
||||
</div>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="subCount" label="子节点数" min-width="100">-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="manufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="位置信息" min-width="120">
|
||||
<template v-slot:default="scope">
|
||||
<span size="medium" v-if="scope.row.longitude && scope.row.latitude">{{scope.row.longitude}}<br/>{{scope.row.latitude}}</span>
|
||||
<span size="medium" v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div >{{ scope.row.ptzTypeText }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开启音频" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="码流类型" min-width="180">
|
||||
<template v-slot:default="scope">
|
||||
<el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
|
||||
placeholder="请选择码流类型" default-first-option >
|
||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.status === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.status !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="340" fixed="right">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
|
||||
type="text" @click="sendDevicePush(scope.row)">播放
|
||||
</el-button>
|
||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0"
|
||||
icon="el-icon-switch-button"
|
||||
type="text" style="color: #f56c6c" v-if="!!scope.row.streamId"
|
||||
@click="stopDevicePush(scope.row)">停止
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button
|
||||
size="medium"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-s-open" type="text"
|
||||
v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8"
|
||||
@click="changeSubchannel(scope.row)">查看
|
||||
</el-button>
|
||||
<el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8" direction="vertical"></el-divider>
|
||||
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
|
||||
<el-button size="medium" type="text" >
|
||||
更多<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="records" v-bind:disabled="device == null || device.online === 0">
|
||||
设备录像</el-dropdown-item>
|
||||
<el-dropdown-item command="cloudRecords" v-bind:disabled="device == null || device.online === 0" >
|
||||
云端录像</el-dropdown-item>
|
||||
<el-dropdown-item command="record" v-bind:disabled="device == null || device.online === 0" >
|
||||
设备录像控制-开始</el-dropdown-item>
|
||||
<el-dropdown-item command="stopRecord" v-bind:disabled="device == null || device.online === 0" >
|
||||
设备录像控制-停止</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
<div class="page-header-btn">
|
||||
<div v-if="!showTree" style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
通道类型:
|
||||
<el-select size="mini" @change="search" style="width: 8rem; margin-right: 1rem;" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="设备" value="false"></el-option>
|
||||
<el-option label="子目录" value="true"></el-option>
|
||||
</el-select>
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
码流类型重置:
|
||||
<el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream"
|
||||
placeholder="请选择码流类型" default-first-option >
|
||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table size="medium" ref="channelListTable" :data="deviceChannelList" :height="$tableHeght"
|
||||
header-row-class-name="table-header">
|
||||
<el-table-column prop="name" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="deviceId" label="编号" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column label="快照" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<el-image
|
||||
:src="getSnap(scope.row)"
|
||||
:preview-src-list="getBigSnap(scope.row)"
|
||||
@error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
|
||||
:fit="'contain'"
|
||||
style="width: 60px">
|
||||
<div slot="error" class="image-slot">
|
||||
<i class="el-icon-picture-outline"></i>
|
||||
</div>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="subCount" label="子节点数" min-width="100">-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="manufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="位置信息" min-width="120">
|
||||
<template v-slot:default="scope">
|
||||
<span size="medium" v-if="scope.row.longitude && scope.row.latitude">{{scope.row.longitude}}<br/>{{scope.row.latitude}}</span>
|
||||
<span size="medium" v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div >{{ scope.row.ptzTypeText }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开启音频" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="码流类型" min-width="180">
|
||||
<template v-slot:default="scope">
|
||||
<el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
|
||||
placeholder="请选择码流类型" default-first-option >
|
||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.status === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.status !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="340" fixed="right">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
|
||||
type="text" @click="sendDevicePush(scope.row)">播放
|
||||
</el-button>
|
||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0"
|
||||
icon="el-icon-switch-button"
|
||||
type="text" style="color: #f56c6c" v-if="!!scope.row.streamId"
|
||||
@click="stopDevicePush(scope.row)">停止
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button
|
||||
size="medium"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-s-open" type="text"
|
||||
v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8"
|
||||
@click="changeSubchannel(scope.row)">查看
|
||||
</el-button>
|
||||
<el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8" direction="vertical"></el-divider>
|
||||
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
|
||||
<el-button size="medium" type="text" >
|
||||
更多<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="records" v-bind:disabled="device == null || device.online === 0">
|
||||
设备录像</el-dropdown-item>
|
||||
<el-dropdown-item command="cloudRecords" v-bind:disabled="device == null || device.online === 0" >
|
||||
云端录像</el-dropdown-item>
|
||||
<el-dropdown-item command="record" v-bind:disabled="device == null || device.online === 0" >
|
||||
设备录像控制-开始</el-dropdown-item>
|
||||
<el-dropdown-item command="stopRecord" v-bind:disabled="device == null || device.online === 0" >
|
||||
设备录像控制-停止</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||
<channel-edit v-if="editId" :id="editId" :closeEdit="closeEdit"></channel-edit>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -309,6 +309,7 @@ create table wvp_stream_proxy
|
|||
update_time character varying(50),
|
||||
stream_key character varying(255),
|
||||
enable_disable_none_reader bool default false,
|
||||
relates_media_server_id character varying(50),
|
||||
constraint uk_stream_proxy_app_stream unique (app, stream)
|
||||
);
|
||||
|
||||
|
|
|
@ -325,6 +325,7 @@ create table wvp_stream_proxy
|
|||
update_time character varying(50),
|
||||
stream_key character varying(255),
|
||||
enable_disable_none_reader bool default false,
|
||||
relates_media_server_id character varying(50),
|
||||
constraint uk_stream_proxy_app_stream unique (app, stream)
|
||||
);
|
||||
|
||||
|
@ -452,7 +453,7 @@ create table wvp_record_plan
|
|||
create table wvp_record_plan_item
|
||||
(
|
||||
id serial primary key,
|
||||
start int,
|
||||
"start" int,
|
||||
stop int,
|
||||
week_day int,
|
||||
plan_id int,
|
||||
|
|
Loading…
Reference in New Issue