mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-06-21 18:47:49 +08:00
支持相机基础信息配置
This commit is contained in:
parent
1fc8848cf9
commit
5a3b831717
@ -1,14 +1,16 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础配置
|
* 基础配置
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "基础配置")
|
@Schema(description = "基础配置")
|
||||||
public class BasicParam {
|
public class BasicParam implements DeviceConfigAware {
|
||||||
|
|
||||||
@Schema(description = "设备ID")
|
@Schema(description = "设备ID")
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
@ -46,4 +48,20 @@ public class BasicParam {
|
|||||||
basicParam.setHeartBeatCount(heartBeatCount);
|
basicParam.setHeartBeatCount(heartBeatCount);
|
||||||
return basicParam;
|
return basicParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String configType() {
|
||||||
|
return "BasicParam";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setName(XmlUtil.getText(element, "Name"));
|
||||||
|
setExpiration(XmlUtil.getText(element, "Expiration"));
|
||||||
|
setHeartBeatInterval(XmlUtil.getInteger(element, "HeartBeatInterval"));
|
||||||
|
setHeartBeatCount(XmlUtil.getInteger(element, "HeartBeatCount"));
|
||||||
|
setPositionCapability(XmlUtil.getInteger(element, "PositionCapability"));
|
||||||
|
setLongitude(XmlUtil.getDouble(element, "Longitude"));
|
||||||
|
setLatitude(XmlUtil.getDouble(element, "Latitude"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
public interface DeviceConfigAware {
|
||||||
|
|
||||||
|
String configType();
|
||||||
|
|
||||||
|
void fromXml(Element element);
|
||||||
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "SVAC解码配置")
|
||||||
|
public class SVACDecodeConfig implements DeviceConfigAware {
|
||||||
|
|
||||||
|
@Schema(description = "SVC参数")
|
||||||
|
private SVCParam svcParam;
|
||||||
|
|
||||||
|
@Schema(description = "监控专用信息参数")
|
||||||
|
private SurveillanceParam surveillanceParam;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String configType() {
|
||||||
|
return "SVACDecodeConfig";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
Element svcEl = element.element("SVCParam");
|
||||||
|
if (svcEl != null) {
|
||||||
|
SVCParam s = new SVCParam();
|
||||||
|
s.fromXml(svcEl);
|
||||||
|
setSvcParam(s);
|
||||||
|
}
|
||||||
|
Element survEl = element.element("SurveillanceParam");
|
||||||
|
if (survEl != null) {
|
||||||
|
SurveillanceParam s = new SurveillanceParam();
|
||||||
|
s.fromXml(survEl);
|
||||||
|
setSurveillanceParam(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SVCParam {
|
||||||
|
@Schema(description = "空域编码能力,0:不支持,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCSpaceSupportMode;
|
||||||
|
|
||||||
|
@Schema(description = "时域编码能力,0:不支持,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCTimeSupportMode;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setSVCSpaceSupportMode(XmlUtil.getInteger(element, "SVCSpaceSupportMode"));
|
||||||
|
setSVCTimeSupportMode(XmlUtil.getInteger(element, "SVCTimeSupportMode"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SurveillanceParam {
|
||||||
|
@Schema(description = "绝对时间信息显示开关,0:关闭,1:打开")
|
||||||
|
private Integer TimeShowFlag;
|
||||||
|
|
||||||
|
@Schema(description = "监控事件信息显示开关,0:关闭,1:打开")
|
||||||
|
private Integer EventShowFlag;
|
||||||
|
|
||||||
|
@Schema(description = "报警信息显示开关,0:关闭,1:打开")
|
||||||
|
private Integer AlerShowtFlag;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setTimeShowFlag(XmlUtil.getInteger(element, "TimeShowFlag"));
|
||||||
|
setEventShowFlag(XmlUtil.getInteger(element, "EventShowFlag"));
|
||||||
|
setAlerShowtFlag(XmlUtil.getInteger(element, "AlerShowtFlag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,167 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "SVAC编码配置")
|
||||||
|
public class SVACEncodeConfig implements DeviceConfigAware {
|
||||||
|
|
||||||
|
@Schema(description = "感兴趣区域参数")
|
||||||
|
private ROIParam roiParam;
|
||||||
|
|
||||||
|
@Schema(description = "SVC参数")
|
||||||
|
private SVCParam svcParam;
|
||||||
|
|
||||||
|
@Schema(description = "监控专用信息参数")
|
||||||
|
private SurveillanceParam surveillanceParam;
|
||||||
|
|
||||||
|
@Schema(description = "音频参数")
|
||||||
|
private AudioParam audioParam;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String configType() {
|
||||||
|
return "SVACEncodeConfig";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
Element roiEl = element.element("ROIParam");
|
||||||
|
if (roiEl != null) {
|
||||||
|
ROIParam r = new ROIParam();
|
||||||
|
r.fromXml(roiEl);
|
||||||
|
setRoiParam(r);
|
||||||
|
}
|
||||||
|
Element svcEl = element.element("SVCParam");
|
||||||
|
if (svcEl != null) {
|
||||||
|
SVCParam s = new SVCParam();
|
||||||
|
s.fromXml(svcEl);
|
||||||
|
setSvcParam(s);
|
||||||
|
}
|
||||||
|
Element survEl = element.element("SurveillanceParam");
|
||||||
|
if (survEl != null) {
|
||||||
|
SurveillanceParam s = new SurveillanceParam();
|
||||||
|
s.fromXml(survEl);
|
||||||
|
setSurveillanceParam(s);
|
||||||
|
}
|
||||||
|
Element audioEl = element.element("AudioParam");
|
||||||
|
if (audioEl != null) {
|
||||||
|
AudioParam a = new AudioParam();
|
||||||
|
a.fromXml(audioEl);
|
||||||
|
setAudioParam(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ROIParam {
|
||||||
|
@Schema(description = "感兴趣区域开关,0:关闭,1:打开")
|
||||||
|
private Integer ROIFlag;
|
||||||
|
|
||||||
|
@Schema(description = "感兴趣区域数量,取值范围0~16")
|
||||||
|
private Integer ROINumber;
|
||||||
|
|
||||||
|
@Schema(description = "感兴趣区域列表")
|
||||||
|
private List<ROIItem> Item;
|
||||||
|
|
||||||
|
@Schema(description = "背景区域编码质量等级,0:一般,1:较好,2:好,3:很好")
|
||||||
|
private Integer BackGroundQP;
|
||||||
|
|
||||||
|
@Schema(description = "背景跳过开关,0:关闭,1:打开")
|
||||||
|
private Integer BackGroundSkipFlag;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setROIFlag(XmlUtil.getInteger(element, "ROIFlag"));
|
||||||
|
setROINumber(XmlUtil.getInteger(element, "ROINumber"));
|
||||||
|
List<Element> itemElements = element.elements("Item");
|
||||||
|
if (!itemElements.isEmpty()) {
|
||||||
|
List<ROIItem> list = new ArrayList<>();
|
||||||
|
for (Element e : itemElements) {
|
||||||
|
ROIItem item = new ROIItem();
|
||||||
|
item.fromXml(e);
|
||||||
|
list.add(item);
|
||||||
|
}
|
||||||
|
setItem(list);
|
||||||
|
}
|
||||||
|
setBackGroundQP(XmlUtil.getInteger(element, "BackGroundQP"));
|
||||||
|
setBackGroundSkipFlag(XmlUtil.getInteger(element, "BackGroundSkipFlag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ROIItem {
|
||||||
|
@Schema(description = "感兴趣区域编号,取值范围1~16")
|
||||||
|
private Integer ROISeq;
|
||||||
|
|
||||||
|
@Schema(description = "感兴趣区域左上角坐标,取值范围0~19683")
|
||||||
|
private Integer TopLeft;
|
||||||
|
|
||||||
|
@Schema(description = "感兴趣区域右下角坐标,取值范围0~19683")
|
||||||
|
private Integer BottomRight;
|
||||||
|
|
||||||
|
@Schema(description = "ROI区域编码质量等级,0:一般,1:较好,2:好,3:很好")
|
||||||
|
private Integer ROIQP;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setROISeq(XmlUtil.getInteger(element, "ROISeq"));
|
||||||
|
setTopLeft(XmlUtil.getInteger(element, "TopLeft"));
|
||||||
|
setBottomRight(XmlUtil.getInteger(element, "BottomRight"));
|
||||||
|
setROIQP(XmlUtil.getInteger(element, "ROIQP"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SVCParam {
|
||||||
|
@Schema(description = "空域编码方式,0:基本层,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCSpaceDomainMode;
|
||||||
|
|
||||||
|
@Schema(description = "时域编码方式,0:基本层,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCTimeDomainMode;
|
||||||
|
|
||||||
|
@Schema(description = "空域编码能力,0:不支持,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCSpaceSupportMode;
|
||||||
|
|
||||||
|
@Schema(description = "时域编码能力,0:不支持,1:1级增强,2:2级增强,3:3级增强")
|
||||||
|
private Integer SVCTimeSupportMode;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setSVCSpaceDomainMode(XmlUtil.getInteger(element, "SVCSpaceDomainMode"));
|
||||||
|
setSVCTimeDomainMode(XmlUtil.getInteger(element, "SVCTimeDomainMode"));
|
||||||
|
setSVCSpaceSupportMode(XmlUtil.getInteger(element, "SVCSpaceSupportMode"));
|
||||||
|
setSVCTimeSupportMode(XmlUtil.getInteger(element, "SVCTimeSupportMode"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SurveillanceParam {
|
||||||
|
@Schema(description = "绝对时间信息开关,0:关闭,1:打开")
|
||||||
|
private Integer TimeFlag;
|
||||||
|
|
||||||
|
@Schema(description = "监控事件信息开关,0:关闭,1:打开")
|
||||||
|
private Integer EventFlag;
|
||||||
|
|
||||||
|
@Schema(description = "报警信息开关,0:关闭,1:打开")
|
||||||
|
private Integer AlertFlag;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setTimeFlag(XmlUtil.getInteger(element, "TimeFlag"));
|
||||||
|
setEventFlag(XmlUtil.getInteger(element, "EventFlag"));
|
||||||
|
setAlertFlag(XmlUtil.getInteger(element, "AlertFlag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class AudioParam {
|
||||||
|
@Schema(description = "声音识别特征参数开关,0:关闭,1:打开")
|
||||||
|
private Integer AudioRecognitionFlag;
|
||||||
|
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setAudioRecognitionFlag(XmlUtil.getInteger(element, "AudioRecognitionFlag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "视频参数范围")
|
||||||
|
public class VideoParamOpt implements DeviceConfigAware {
|
||||||
|
|
||||||
|
@Schema(description = "下载倍速范围,各可选参数以 '/' 分隔")
|
||||||
|
private String downloadSpeed;
|
||||||
|
|
||||||
|
@Schema(description = "摄像机支持的分辨率,多个分辨率值以 '/' 分隔")
|
||||||
|
private String resolution;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String configType() {
|
||||||
|
return "VideoParamOpt";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(Element element) {
|
||||||
|
setDownloadSpeed(XmlUtil.getText(element, "DownloadSpeed"));
|
||||||
|
setResolution(XmlUtil.getText(element, "Resolution"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +1,7 @@
|
|||||||
/**
|
|
||||||
* 设备设置命令API接口
|
|
||||||
*
|
|
||||||
* @author lawrencehj
|
|
||||||
* @date 2021年2月2日
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.genersoft.iot.vmp.gb28181.controller;
|
package com.genersoft.iot.vmp.gb28181.controller;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.BasicParam;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
@ -32,8 +24,8 @@ public class DeviceConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IDeviceService deviceService;
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
@GetMapping("/basicParam")
|
@GetMapping("/set/basicParam")
|
||||||
@Operation(summary = "基本配置设置命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "设置基本配置", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@Parameter(name = "basicParam", description = "基础配置参数", required = true)
|
@Parameter(name = "basicParam", description = "基础配置参数", required = true)
|
||||||
public DeferredResult<WVPResult<String>> homePositionApi(BasicParam basicParam) {
|
public DeferredResult<WVPResult<String>> homePositionApi(BasicParam basicParam) {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
@ -54,33 +46,79 @@ public class DeviceConfig {
|
|||||||
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
});
|
});
|
||||||
return deferredResult;
|
return deferredResult;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "设备配置查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "查询基本参数配置", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
@Parameter(name = "channelId", description = "通道国标编号")
|
||||||
@Parameter(name = "configType", description = "配置类型, 可选值," +
|
@GetMapping("/query/basicParam")
|
||||||
"基本参数配置:BasicParam," +
|
public DeferredResult<WVPResult<BasicParam>> queryBasicParam(String deviceId,
|
||||||
"视频参数范围:VideoParamOpt, " +
|
|
||||||
"SVAC编码配置:SVACEncodeConfig, " +
|
|
||||||
"SVAC解码配置:SVACDecodeConfig。" +
|
|
||||||
"可同时查询多个配置类型,各类型以“/”分隔,")
|
|
||||||
@GetMapping("/query")
|
|
||||||
public DeferredResult<WVPResult<Object>> configDownloadApi(String deviceId,String configType,
|
|
||||||
@RequestParam(required = false) String channelId) {
|
@RequestParam(required = false) String channelId) {
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("设备配置查询请求API调用");
|
|
||||||
}
|
|
||||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
Assert.notNull(device, "设备不存在");
|
Assert.notNull(device, "设备不存在");
|
||||||
|
DeferredResult<WVPResult<BasicParam>> deferredResult = new DeferredResult<>();
|
||||||
DeferredResult<WVPResult<Object>> deferredResult = new DeferredResult<>();
|
deviceService.deviceConfigQuery(device, channelId, BasicParam.class, (code, msg, data) -> {
|
||||||
|
data.setDeviceId(deviceId);
|
||||||
deviceService.deviceConfigQuery(device, channelId, configType, (code, msg, data) -> {
|
data.setChannelId(channelId);
|
||||||
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
||||||
});
|
});
|
||||||
|
deferredResult.onTimeout(() -> {
|
||||||
|
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
|
||||||
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
|
});
|
||||||
|
return deferredResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询视频参数范围", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||||
|
@Parameter(name = "channelId", description = "通道国标编号")
|
||||||
|
@GetMapping("/query/videoParamOpt")
|
||||||
|
public DeferredResult<WVPResult<VideoParamOpt>> queryVideoParamOpt(String deviceId,
|
||||||
|
@RequestParam(required = false) String channelId) {
|
||||||
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
|
Assert.notNull(device, "设备不存在");
|
||||||
|
DeferredResult<WVPResult<VideoParamOpt>> deferredResult = new DeferredResult<>();
|
||||||
|
deviceService.deviceConfigQuery(device, channelId, VideoParamOpt.class, (code, msg, data) -> {
|
||||||
|
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
||||||
|
});
|
||||||
|
deferredResult.onTimeout(() -> {
|
||||||
|
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
|
||||||
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
|
});
|
||||||
|
return deferredResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询SVAC编码配置", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||||
|
@Parameter(name = "channelId", description = "通道国标编号")
|
||||||
|
@GetMapping("/query/svacEncodeConfig")
|
||||||
|
public DeferredResult<WVPResult<SVACEncodeConfig>> querySVACEncodeConfig(String deviceId,
|
||||||
|
@RequestParam(required = false) String channelId) {
|
||||||
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
|
Assert.notNull(device, "设备不存在");
|
||||||
|
DeferredResult<WVPResult<SVACEncodeConfig>> deferredResult = new DeferredResult<>();
|
||||||
|
deviceService.deviceConfigQuery(device, channelId, SVACEncodeConfig.class, (code, msg, data) -> {
|
||||||
|
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
||||||
|
});
|
||||||
|
deferredResult.onTimeout(() -> {
|
||||||
|
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
|
||||||
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
|
});
|
||||||
|
return deferredResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询SVAC解码配置", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||||
|
@Parameter(name = "channelId", description = "通道国标编号")
|
||||||
|
@GetMapping("/query/svacDecodeConfig")
|
||||||
|
public DeferredResult<WVPResult<SVACDecodeConfig>> querySVACDecodeConfig(String deviceId,
|
||||||
|
@RequestParam(required = false) String channelId) {
|
||||||
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
|
Assert.notNull(device, "设备不存在");
|
||||||
|
DeferredResult<WVPResult<SVACDecodeConfig>> deferredResult = new DeferredResult<>();
|
||||||
|
deviceService.deviceConfigQuery(device, channelId, SVACDecodeConfig.class, (code, msg, data) -> {
|
||||||
|
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
||||||
|
});
|
||||||
deferredResult.onTimeout(() -> {
|
deferredResult.onTimeout(() -> {
|
||||||
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
|
log.warn("[获取设备配置] 超时, {}", device.getDeviceId());
|
||||||
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
|
|||||||
@ -171,7 +171,7 @@ public interface IDeviceService {
|
|||||||
|
|
||||||
void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback);
|
void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback);
|
||||||
|
|
||||||
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback);
|
<T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback);
|
||||||
|
|
||||||
void teleboot(Device device);
|
void teleboot(Device device);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
@ -331,7 +332,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
redisCatchStorage.updateDevice(device);
|
redisCatchStorage.updateDevice(device);
|
||||||
try {
|
try {
|
||||||
commander.deviceInfoQuery(device, null);
|
commander.deviceInfoQuery(device, null);
|
||||||
commander.deviceConfigQuery(device, null, "BasicParam", null);
|
commander.deviceConfigQuery(device, null, BasicParam.class, null);
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
|
log.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
@ -500,37 +501,37 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void catalogSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
private void catalogSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
||||||
log.info("[目录订阅] 到期, 编号: {}", deviceId);
|
|
||||||
Device device = getDeviceByDeviceId(deviceId);
|
Device device = getDeviceByDeviceId(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
log.info("[目录订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
log.info("[目录订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (device.isOnLine() && device.getSubscribeCycleForCatalog() > 0) {
|
if (device.isOnLine() && device.getSubscribeCycleForCatalog() > 0) {
|
||||||
|
log.info("[目录订阅] 到期, 编号: {}", deviceId);
|
||||||
addCatalogSubscribe(device, transactionInfo);
|
addCatalogSubscribe(device, transactionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mobilPositionSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
private void mobilPositionSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
||||||
log.info("[移动位置订阅] 到期, 编号: {}", deviceId);
|
|
||||||
Device device = getDeviceByDeviceId(deviceId);
|
Device device = getDeviceByDeviceId(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
log.info("[移动位置订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
log.info("[移动位置订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (device.isOnLine() && device.getSubscribeCycleForMobilePosition() > 0) {
|
if (device.isOnLine() && device.getSubscribeCycleForMobilePosition() > 0) {
|
||||||
|
log.info("[移动位置订阅] 到期, 编号: {}", deviceId);
|
||||||
addMobilePositionSubscribe(device, transactionInfo);
|
addMobilePositionSubscribe(device, transactionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void alarmSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
private void alarmSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
||||||
log.info("[报警订阅] 到期, 编号: {}", deviceId);
|
|
||||||
Device device = getDeviceByDeviceId(deviceId);
|
Device device = getDeviceByDeviceId(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
log.info("[移报警订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
log.info("[移报警订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (device.isOnLine() && device.getSubscribeCycleForAlarm() > 0) {
|
if (device.isOnLine() && device.getSubscribeCycleForAlarm() > 0) {
|
||||||
|
log.info("[报警订阅] 到期, 编号: {}", deviceId);
|
||||||
addAlarmSubscribe(device, transactionInfo);
|
addAlarmSubscribe(device, transactionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1160,16 +1161,21 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) {
|
public <T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback) {
|
||||||
|
|
||||||
if (!userSetting.getServerId().equals(device.getServerId())) {
|
if (!userSetting.getServerId().equals(device.getServerId())) {
|
||||||
WVPResult<String> result = redisRpcService.deviceConfigQuery(device.getServerId(), device, channelId, configType);
|
WVPResult<Object> result = redisRpcService.deviceConfigQuery(device.getServerId(), device, channelId, configClass.getName());
|
||||||
callback.run(result.getCode(), result.getMsg(), result.getData());
|
if (result.getData() instanceof JSONObject) {
|
||||||
|
T obj = ((JSONObject) result.getData()).toJavaObject(configClass);
|
||||||
|
callback.run(result.getCode(), result.getMsg(), obj);
|
||||||
|
} else {
|
||||||
|
callback.run(result.getCode(), result.getMsg(), null);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sipCommander.deviceConfigQuery(device, channelId, configType, callback);
|
sipCommander.deviceConfigQuery(device, channelId, configClass, callback);
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
|
log.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
|
||||||
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
|
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
|
||||||
|
|||||||
@ -248,9 +248,9 @@ public interface ISIPCommander {
|
|||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 通道编码(可选)
|
* @param channelId 通道编码(可选)
|
||||||
* @param configType 配置类型:
|
* @param configClass 配置类型:
|
||||||
*/
|
*/
|
||||||
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
<T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备预置位置
|
* 查询设备预置位置
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
|||||||
import gov.nist.javax.sip.message.SIPRequest;
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
import gov.nist.javax.sip.message.SIPResponse;
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dom4j.Element;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -846,11 +847,13 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
cmdXml.append("<Control>\r\n");
|
cmdXml.append("<Control>\r\n");
|
||||||
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
|
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
|
||||||
cmdXml.append("<SN>" + sn + "</SN>\r\n");
|
cmdXml.append("<SN>" + sn + "</SN>\r\n");
|
||||||
String channelId = basicParam.getChannelId();
|
// String channelId = basicParam.getChannelId();
|
||||||
if (ObjectUtils.isEmpty(channelId)) {
|
// if (ObjectUtils.isEmpty(channelId)) {
|
||||||
channelId = device.getDeviceId();
|
// channelId = device.getDeviceId();
|
||||||
}
|
// }
|
||||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
// 此处经过详细测试 对于这里使用通道ID还是设备ID,海康两者都支持 大华必须是设备ID,宇视都支持,但是不回复消息直接自己就注销重启,
|
||||||
|
// 所以这里取值 device.getDeviceId()
|
||||||
|
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||||
cmdXml.append("<BasicParam>\r\n");
|
cmdXml.append("<BasicParam>\r\n");
|
||||||
if (!ObjectUtils.isEmpty(basicParam.getName())) {
|
if (!ObjectUtils.isEmpty(basicParam.getName())) {
|
||||||
cmdXml.append("<Name>" + basicParam.getName() + "</Name>\r\n");
|
cmdXml.append("<Name>" + basicParam.getName() + "</Name>\r\n");
|
||||||
@ -870,7 +873,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
cmdXml.append("</Control>\r\n");
|
cmdXml.append("</Control>\r\n");
|
||||||
|
|
||||||
|
|
||||||
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
|
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 2000L, callback);
|
||||||
messageSubscribe.addSubscribe(messageEvent);
|
messageSubscribe.addSubscribe(messageEvent);
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||||
@ -1075,10 +1078,10 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 通道编码(可选)
|
* @param channelId 通道编码(可选)
|
||||||
* @param configType 配置类型:
|
* @param configClass 配置类型
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
|
public <T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
String cmdType = "ConfigDownload";
|
String cmdType = "ConfigDownload";
|
||||||
int sn = (int) ((Math.random() * 9 + 1) * 100000);
|
int sn = (int) ((Math.random() * 9 + 1) * 100000);
|
||||||
@ -1093,10 +1096,42 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
} else {
|
} else {
|
||||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T sample;
|
||||||
|
try {
|
||||||
|
sample = configClass.getDeclaredConstructor().newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[命令发送失败] 实例化配置类: {}", e.getMessage());
|
||||||
|
if (callback != null) {
|
||||||
|
callback.run(ErrorCode.ERROR100.getCode(), "实例化失败: " + e.getMessage(), null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String configType = sample.configType();
|
||||||
cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
|
cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
|
||||||
cmdXml.append("</Query>\r\n");
|
cmdXml.append("</Query>\r\n");
|
||||||
|
|
||||||
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
|
ErrorCallback<Object> wrappedCallback = (code, msg, data) -> {
|
||||||
|
if (callback != null) {
|
||||||
|
if (code == ErrorCode.SUCCESS.getCode() && data instanceof Element) {
|
||||||
|
Element responseElement = (Element) data;
|
||||||
|
Element configElement = responseElement.element(configType);
|
||||||
|
if (configElement != null) {
|
||||||
|
try {
|
||||||
|
T result = configClass.getDeclaredConstructor().newInstance();
|
||||||
|
result.fromXml(configElement);
|
||||||
|
callback.run(code, msg, result);
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[设备配置查询] 创建实例失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback.run(code, msg, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, wrappedCallback);
|
||||||
messageSubscribe.addSubscribe(messageEvent);
|
messageSubscribe.addSubscribe(messageEvent);
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import javax.sip.RequestEvent;
|
|||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
import javax.sip.header.AuthorizationHeader;
|
import javax.sip.header.AuthorizationHeader;
|
||||||
import javax.sip.header.ContactHeader;
|
import javax.sip.header.ContactHeader;
|
||||||
|
import javax.sip.header.ExpiresHeader;
|
||||||
import javax.sip.header.FromHeader;
|
import javax.sip.header.FromHeader;
|
||||||
import javax.sip.header.ViaHeader;
|
import javax.sip.header.ViaHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
@ -75,177 +76,45 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
|||||||
sipProcessorObserver.addRequestProcessor(method, this);
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 收到注册请求 处理
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt) {
|
public void process(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||||
Response response = null;
|
|
||||||
boolean passwordCorrect = false;
|
|
||||||
// 注册标志
|
|
||||||
boolean registerFlag = request.getExpires().getExpires() != 0;
|
|
||||||
// 注销成功
|
|
||||||
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
|
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
|
||||||
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
||||||
SipUri uri = (SipUri) address.getURI();
|
SipUri uri = (SipUri) address.getURI();
|
||||||
String deviceId = uri.getUser();
|
String deviceId = uri.getUser();
|
||||||
|
|
||||||
if (userSetting.isDeviceIdStrict()) {
|
if (userSetting.isDeviceIdStrict()) {
|
||||||
// 严格模式下,非20位设备ID不予处理
|
|
||||||
GbCode decode = GbCode.decode(deviceId);
|
GbCode decode = GbCode.decode(deviceId);
|
||||||
if (decode == null) {
|
if (decode == null) {
|
||||||
// 注册失败
|
Response response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 调整逻辑,如果为设置公共密码,那么就必须要预设用户信息,否则无法注册。
|
|
||||||
|
ExpiresHeader expiresHeader = request.getExpires();
|
||||||
|
if (expiresHeader == null) {
|
||||||
|
Response response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean registerFlag = expiresHeader.getExpires() != 0;
|
||||||
|
|
||||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
|
|
||||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
|
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
|
||||||
userSetting.getSipUseSourceIpAsRemoteAddress());
|
userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||||
String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
|
String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
|
||||||
String title = registerFlag ? "[注册请求]" : "[注销请求]";
|
|
||||||
log.info("{} 设备:{}, 开始处理: {}", title, deviceId, requestAddress);
|
|
||||||
String password = null;
|
|
||||||
if (device != null) {
|
|
||||||
if (device.getSipTransactionInfo() != null &&
|
|
||||||
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
|
||||||
log.info("{} 设备:{}, 注册续订: {}", title, device.getDeviceId(), device.getDeviceId());
|
|
||||||
if (registerFlag) {
|
if (registerFlag) {
|
||||||
device.setExpires(request.getExpires().getExpires());
|
registerHandler(device, request, remoteAddressInfo, deviceId, requestAddress);
|
||||||
device.setIp(remoteAddressInfo.getIp());
|
|
||||||
device.setPort(remoteAddressInfo.getPort());
|
|
||||||
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
|
|
||||||
|
|
||||||
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
|
||||||
Response registerOkResponse = getRegisterOkResponse(request);
|
|
||||||
// 判断TCP还是UDP
|
|
||||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String transport = reqViaHeader.getTransport();
|
|
||||||
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
|
|
||||||
device.setRegisterTimeStamp(System.currentTimeMillis());
|
|
||||||
deviceService.online(device);
|
|
||||||
} else {
|
} else {
|
||||||
deviceService.offline(device);
|
cancellationHandler(device, request, remoteAddressInfo, deviceId, requestAddress);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}else {
|
|
||||||
// 正常注册, 用户信息未设置密码,并且公共密码也未设置,则关闭鉴权
|
|
||||||
if (!ObjectUtils.isEmpty(device.getPassword()) || !ObjectUtils.isEmpty(sipConfig.getPassword())) {
|
|
||||||
password = (!ObjectUtils.isEmpty(device.getPassword())) ? device.getPassword() : sipConfig.getPassword();
|
|
||||||
}
|
|
||||||
// 如果设置了一个无密码的设备,那么这里就会自动跳动,后续会直接注册成功
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if (ObjectUtils.isEmpty(sipConfig.getPassword())) {
|
|
||||||
log.info("{} 设备:{}, 地址: {}, 公共密码已经禁用,请添加用户信息后注册", title, deviceId, requestAddress);
|
|
||||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
|
||||||
return;
|
|
||||||
}else {
|
|
||||||
password = sipConfig.getPassword();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
|
||||||
if (authHead == null && !ObjectUtils.isEmpty(password)) {
|
|
||||||
log.info(title + " 设备:{}, 回复401: {}", deviceId, requestAddress);
|
|
||||||
response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
|
|
||||||
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验密码是否正确
|
|
||||||
passwordCorrect = ObjectUtils.isEmpty(password) ||
|
|
||||||
new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, password);
|
|
||||||
|
|
||||||
if (!passwordCorrect) {
|
|
||||||
// 注册失败
|
|
||||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
|
||||||
response.setReasonPhrase("wrong password");
|
|
||||||
log.info("{} 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", title, deviceId, requestAddress);
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 携带授权头并且密码正确
|
|
||||||
response = getMessageFactory().createResponse(Response.OK, request);
|
|
||||||
// 如果主动禁用了Date头,则不添加
|
|
||||||
if (!userSetting.isDisableDateHeader()) {
|
|
||||||
// 添加 date头
|
|
||||||
SIPDateHeader dateHeader = new SIPDateHeader();
|
|
||||||
// 使用自己修改的
|
|
||||||
GbSipDate gbSipDate = new GbSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
|
|
||||||
dateHeader.setDate(gbSipDate);
|
|
||||||
response.addHeader(dateHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.getExpires() == null) {
|
|
||||||
response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 添加 Contact头
|
|
||||||
response.addHeader(request.getHeader(ContactHeader.NAME));
|
|
||||||
// 添加 Expires头
|
|
||||||
response.addHeader(request.getExpires());
|
|
||||||
|
|
||||||
if (device == null) {
|
|
||||||
device = new Device();
|
|
||||||
device.setStreamMode("TCP-PASSIVE");
|
|
||||||
device.setCharset("GB2312");
|
|
||||||
device.setGeoCoordSys("WGS84");
|
|
||||||
device.setMediaServerId("auto");
|
|
||||||
device.setDeviceId(deviceId);
|
|
||||||
device.setOnLine(false);
|
|
||||||
} else {
|
|
||||||
if (ObjectUtils.isEmpty(device.getStreamMode())) {
|
|
||||||
device.setStreamMode("TCP-PASSIVE");
|
|
||||||
}
|
|
||||||
if (ObjectUtils.isEmpty(device.getCharset())) {
|
|
||||||
device.setCharset("GB2312");
|
|
||||||
}
|
|
||||||
if (ObjectUtils.isEmpty(device.getGeoCoordSys())) {
|
|
||||||
device.setGeoCoordSys("WGS84");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
device.setServerId(userSetting.getServerId());
|
|
||||||
device.setIp(remoteAddressInfo.getIp());
|
|
||||||
device.setPort(remoteAddressInfo.getPort());
|
|
||||||
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
|
|
||||||
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
|
||||||
if (request.getExpires().getExpires() == 0) {
|
|
||||||
// 注销成功
|
|
||||||
registerFlag = false;
|
|
||||||
} else {
|
|
||||||
// 注册成功
|
|
||||||
device.setExpires(request.getExpires().getExpires());
|
|
||||||
registerFlag = true;
|
|
||||||
// 判断 TCP/UDP
|
|
||||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String transport = reqViaHeader.getTransport();
|
|
||||||
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
|
||||||
}
|
|
||||||
|
|
||||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
|
||||||
// 注册成功
|
|
||||||
device.setRegisterTimeStamp(System.currentTimeMillis());
|
|
||||||
// 保存到 redis
|
|
||||||
if (registerFlag) {
|
|
||||||
log.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
|
|
||||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse) response);
|
|
||||||
device.setSipTransactionInfo(sipTransactionInfo);
|
|
||||||
deviceService.online(device);
|
|
||||||
} else {
|
|
||||||
log.info("[注销成功] deviceId: {}->{}", deviceId, requestAddress);
|
|
||||||
deviceService.offline(device);
|
|
||||||
}
|
|
||||||
redisCatchStorage.updateDeviceRegisterTimeStamp(List.of(device));
|
|
||||||
} catch (SipException | NoSuchAlgorithmException | ParseException e) {
|
} catch (SipException | NoSuchAlgorithmException | ParseException e) {
|
||||||
log.error("未处理的异常 ", e);
|
log.error("未处理的异常 ", e);
|
||||||
}
|
}
|
||||||
@ -273,4 +142,149 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerHandler(Device device, SIPRequest request, RemoteAddressInfo remoteAddressInfo,
|
||||||
|
String deviceId, String requestAddress) throws SipException, NoSuchAlgorithmException, ParseException {
|
||||||
|
if (device != null && device.getSipTransactionInfo() != null &&
|
||||||
|
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
||||||
|
log.info("[注册续订] 设备:{}", device.getDeviceId());
|
||||||
|
device.setExpires(request.getExpires().getExpires());
|
||||||
|
device.setIp(remoteAddressInfo.getIp());
|
||||||
|
device.setPort(remoteAddressInfo.getPort());
|
||||||
|
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
|
||||||
|
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
||||||
|
|
||||||
|
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||||
|
String transport = reqViaHeader.getTransport();
|
||||||
|
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
||||||
|
|
||||||
|
Response okResponse = getRegisterOkResponse(request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), okResponse);
|
||||||
|
device.setRegisterTimeStamp(System.currentTimeMillis());
|
||||||
|
deviceService.online(device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device == null && ObjectUtils.isEmpty(sipConfig.getPassword())) {
|
||||||
|
log.info("[注册请求] 设备:{}, 地址: {}, 公共密码已经禁用,请添加用户信息后注册", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String password = device != null && !ObjectUtils.isEmpty(device.getPassword()) ? device.getPassword() : sipConfig.getPassword();
|
||||||
|
|
||||||
|
AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||||
|
if (!ObjectUtils.isEmpty(password) && authHead == null) {
|
||||||
|
log.info("[注册请求] 设备:{}, 回复401: {}", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
|
||||||
|
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ObjectUtils.isEmpty(password) && !new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, password)) {
|
||||||
|
log.info("[注册请求] 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
|
response.setReasonPhrase("wrong password");
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response response = getMessageFactory().createResponse(Response.OK, request);
|
||||||
|
if (!userSetting.isDisableDateHeader()) {
|
||||||
|
SIPDateHeader dateHeader = new SIPDateHeader();
|
||||||
|
GbSipDate gbSipDate = new GbSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
|
||||||
|
dateHeader.setDate(gbSipDate);
|
||||||
|
response.addHeader(dateHeader);
|
||||||
|
}
|
||||||
|
response.addHeader(request.getHeader(ContactHeader.NAME));
|
||||||
|
response.addHeader(request.getExpires());
|
||||||
|
|
||||||
|
if (device == null) {
|
||||||
|
device = new Device();
|
||||||
|
device.setStreamMode("TCP-PASSIVE");
|
||||||
|
device.setCharset("GB2312");
|
||||||
|
device.setGeoCoordSys("WGS84");
|
||||||
|
device.setMediaServerId("auto");
|
||||||
|
device.setDeviceId(deviceId);
|
||||||
|
device.setOnLine(false);
|
||||||
|
} else {
|
||||||
|
if (ObjectUtils.isEmpty(device.getStreamMode())) {
|
||||||
|
device.setStreamMode("TCP-PASSIVE");
|
||||||
|
}
|
||||||
|
if (ObjectUtils.isEmpty(device.getCharset())) {
|
||||||
|
device.setCharset("GB2312");
|
||||||
|
}
|
||||||
|
if (ObjectUtils.isEmpty(device.getGeoCoordSys())) {
|
||||||
|
device.setGeoCoordSys("WGS84");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device.setServerId(userSetting.getServerId());
|
||||||
|
device.setIp(remoteAddressInfo.getIp());
|
||||||
|
device.setPort(remoteAddressInfo.getPort());
|
||||||
|
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
|
||||||
|
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
||||||
|
device.setExpires(request.getExpires().getExpires());
|
||||||
|
|
||||||
|
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||||
|
String transport = reqViaHeader.getTransport();
|
||||||
|
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
||||||
|
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
|
||||||
|
device.setRegisterTimeStamp(System.currentTimeMillis());
|
||||||
|
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse) response);
|
||||||
|
device.setSipTransactionInfo(sipTransactionInfo);
|
||||||
|
deviceService.online(device);
|
||||||
|
redisCatchStorage.updateDeviceRegisterTimeStamp(List.of(device));
|
||||||
|
|
||||||
|
log.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancellationHandler(Device device, SIPRequest request, RemoteAddressInfo remoteAddressInfo,
|
||||||
|
String deviceId, String requestAddress) throws SipException, NoSuchAlgorithmException, ParseException {
|
||||||
|
if (device != null && device.getSipTransactionInfo() != null &&
|
||||||
|
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
||||||
|
Response response = getRegisterOkResponse(request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
deviceService.offline(device);
|
||||||
|
log.info("[注销成功] deviceId: {}->{}", deviceId, requestAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device == null && ObjectUtils.isEmpty(sipConfig.getPassword())) {
|
||||||
|
log.info("[注销请求] 设备:{}, 地址: {}, 公共密码已经禁用,请添加用户信息后注销", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String password = device != null && !ObjectUtils.isEmpty(device.getPassword()) ? device.getPassword() : sipConfig.getPassword();
|
||||||
|
|
||||||
|
AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||||
|
if (!ObjectUtils.isEmpty(password) && authHead == null) {
|
||||||
|
log.info("[注销请求] 设备:{}, 回复401: {}", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
|
||||||
|
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ObjectUtils.isEmpty(password) && !new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, password)) {
|
||||||
|
log.info("[注销请求] 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress);
|
||||||
|
Response response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
|
response.setReasonPhrase("wrong password");
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response response = getRegisterOkResponse(request);
|
||||||
|
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||||
|
|
||||||
|
if (device != null) {
|
||||||
|
deviceService.offline(device);
|
||||||
|
redisCatchStorage.updateDeviceRegisterTimeStamp(List.of(device));
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[注销成功] deviceId: {}->{}", deviceId, requestAddress);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,6 +119,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
|||||||
}else { // 由于上面已经判断都为null则直接返回,所以这里device和parentPlatform必有一个不为null
|
}else { // 由于上面已经判断都为null则直接返回,所以这里device和parentPlatform必有一个不为null
|
||||||
messageHandler.handForPlatform(evt, parentPlatform, rootElement);
|
messageHandler.handForPlatform(evt, parentPlatform, rootElement);
|
||||||
}
|
}
|
||||||
|
responseAck(request, Response.OK);
|
||||||
}else {
|
}else {
|
||||||
// 不支持的message
|
// 不支持的message
|
||||||
// 不存在则回复415
|
// 不存在则回复415
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
@ -31,9 +29,6 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ResponseMessageHandler responseMessageHandler;
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeferredResultHolder deferredResultHolder;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IDeviceService deviceService;
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
@ -42,54 +37,29 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
|
|||||||
responseMessageHandler.addHandler(cmdType, this);
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
try {
|
try {
|
||||||
// 回复200 OK
|
|
||||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
log.error("[命令发送失败] 设备配置查询: {}", e.getMessage());
|
log.error("[命令发送失败] 设备配置查询: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
// 此处是对本平台发出DeviceControl指令的应答
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
XmlUtil.node2Json(element, json);
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug(json.toJSONString());
|
|
||||||
}
|
|
||||||
JSONObject jsonObject = new JSONObject();
|
|
||||||
if (json.get("BasicParam") != null) {
|
|
||||||
jsonObject.put("BasicParam", json.getJSONObject("BasicParam"));
|
|
||||||
}
|
|
||||||
if (json.get("VideoParamOpt") != null) {
|
|
||||||
jsonObject.put("VideoParamOpt", json.getJSONObject("VideoParamOpt"));
|
|
||||||
}
|
|
||||||
if (json.get("SVACEncodeConfig") != null) {
|
|
||||||
jsonObject.put("SVACEncodeConfig", json.getJSONObject("SVACEncodeConfig"));
|
|
||||||
}
|
|
||||||
if (json.get("SVACDecodeConfig") != null) {
|
|
||||||
jsonObject.put("SVACDecodeConfig", json.getJSONObject("SVACDecodeConfig"));
|
|
||||||
}
|
|
||||||
|
|
||||||
responseMessageHandler.handMessageEvent(element, jsonObject);
|
responseMessageHandler.handMessageEvent(element, element);
|
||||||
|
|
||||||
JSONObject basicParam = json.getJSONObject("BasicParam");
|
Element basicParam = element.element("BasicParam");
|
||||||
if (basicParam != null) {
|
if (basicParam != null) {
|
||||||
Integer heartBeatInterval = basicParam.getInteger("HeartBeatInterval");
|
Integer heartBeatInterval = XmlUtil.getInteger(basicParam, "HeartBeatInterval");
|
||||||
Integer heartBeatCount = basicParam.getInteger("HeartBeatCount");
|
Integer heartBeatCount = XmlUtil.getInteger(basicParam, "HeartBeatCount");
|
||||||
Integer positionCapability = basicParam.getInteger("PositionCapability");
|
Integer positionCapability = XmlUtil.getInteger(basicParam, "PositionCapability");
|
||||||
device.setHeartBeatInterval(heartBeatInterval);
|
device.setHeartBeatInterval(heartBeatInterval);
|
||||||
device.setHeartBeatCount(heartBeatCount);
|
device.setHeartBeatCount(heartBeatCount);
|
||||||
device.setPositionCapability(positionCapability);
|
device.setPositionCapability(positionCapability);
|
||||||
|
|
||||||
deviceService.updateDeviceHeartInfo(device);
|
deviceService.updateDeviceHeartInfo(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handForPlatform(RequestEvent evt, Platform parentPlatform, Element element) {
|
public void handForPlatform(RequestEvent evt, Platform parentPlatform, Element element) {
|
||||||
// 不会收到上级平台的心跳信息
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@ public interface IRedisRpcService {
|
|||||||
|
|
||||||
WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam);
|
WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam);
|
||||||
|
|
||||||
WVPResult<String> deviceConfigQuery(String serverId, Device device, String channelId, String configType);
|
WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType);
|
||||||
|
|
||||||
void teleboot(String serverId, Device device);
|
void teleboot(String serverId, Device device);
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
|
|||||||
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
|
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.BasicParam;
|
import com.genersoft.iot.vmp.gb28181.bean.BasicParam;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceConfigAware;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
|
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
|
import com.genersoft.iot.vmp.service.redisMsg.dto.RedisRpcController;
|
||||||
@ -121,7 +122,7 @@ public class RedisRpcDeviceController extends RpcController {
|
|||||||
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
|
JSONObject paramJson = JSONObject.parseObject(request.getParam().toString());
|
||||||
String deviceId = paramJson.getString("deviceId");
|
String deviceId = paramJson.getString("deviceId");
|
||||||
String channelId = paramJson.getString("channelId");
|
String channelId = paramJson.getString("channelId");
|
||||||
String configType = paramJson.getString("configType");
|
String className = paramJson.getString("configType");
|
||||||
|
|
||||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||||
|
|
||||||
@ -131,12 +132,24 @@ public class RedisRpcDeviceController extends RpcController {
|
|||||||
response.setBody("param error");
|
response.setBody("param error");
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
deviceService.deviceConfigQuery(device, channelId, configType, (code, msg, data) -> {
|
try {
|
||||||
|
Class<?> rawClass = Class.forName(className);
|
||||||
|
if (!DeviceConfigAware.class.isAssignableFrom(rawClass)) {
|
||||||
|
response.setStatusCode(ErrorCode.ERROR400.getCode());
|
||||||
|
response.setBody("invalid config type: " + className);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
Class<? extends DeviceConfigAware> configClass = rawClass.asSubclass(DeviceConfigAware.class);
|
||||||
|
deviceService.deviceConfigQuery(device, channelId, configClass, (code, msg, data) -> {
|
||||||
response.setStatusCode(code);
|
response.setStatusCode(code);
|
||||||
response.setBody(new WVPResult<>(code, msg, data));
|
response.setBody(new WVPResult<>(code, msg, data));
|
||||||
// 手动发送结果
|
|
||||||
sendResponse(response);
|
sendResponse(response);
|
||||||
});
|
});
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
response.setStatusCode(ErrorCode.ERROR400.getCode());
|
||||||
|
response.setBody("unknown config type: " + className);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -351,9 +351,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WVPResult<String> deviceConfigQuery(String serverId, Device device, String channelId, String configType) {
|
public WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType) {
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put("device", device.getDeviceId());
|
jsonObject.put("deviceId", device.getDeviceId());
|
||||||
jsonObject.put("channelId", channelId);
|
jsonObject.put("channelId", channelId);
|
||||||
jsonObject.put("configType", configType);
|
jsonObject.put("configType", configType);
|
||||||
RedisRpcRequest request = buildRequest("device/deviceConfigQuery", jsonObject);
|
RedisRpcRequest request = buildRequest("device/deviceConfigQuery", jsonObject);
|
||||||
|
|||||||
@ -113,10 +113,19 @@ export function subscribeForAlarm(params) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryBasicParam(deviceId) {
|
export function queryBasicParam(params) {
|
||||||
return request({
|
return request({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `/api/device/config/query/${deviceId}/BasicParam`
|
url: '/api/device/config/query/basicParam',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setBasicParam(params) {
|
||||||
|
return request({
|
||||||
|
method: 'get',
|
||||||
|
url: '/api/device/config/set/basicParam',
|
||||||
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
queryDeviceTree,
|
queryDeviceTree,
|
||||||
queryHasStreamChannels,
|
queryHasStreamChannels,
|
||||||
resetGuard,
|
resetGuard,
|
||||||
|
setBasicParam,
|
||||||
setGuard,
|
setGuard,
|
||||||
subscribeCatalog, subscribeForAlarm,
|
subscribeCatalog, subscribeForAlarm,
|
||||||
subscribeMobilePosition,
|
subscribeMobilePosition,
|
||||||
@ -124,9 +125,19 @@ const actions = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
queryBasicParam({ commit }, deviceId) {
|
queryBasicParam({ commit }, params) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
queryBasicParam(deviceId).then(response => {
|
queryBasicParam(params).then(response => {
|
||||||
|
const { data } = response
|
||||||
|
resolve(data)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setBasicParam({ commit }, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setBasicParam(params).then(response => {
|
||||||
const { data } = response
|
const { data } = response
|
||||||
resolve(data)
|
resolve(data)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|||||||
132
web/src/views/device/channel/basicPropertyConfig.vue
Normal file
132
web/src/views/device/channel/basicPropertyConfig.vue
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<template>
|
||||||
|
<div id="dhBasicPropertyPage">
|
||||||
|
<div class="basic-property-body">
|
||||||
|
<div class="config-section">
|
||||||
|
<el-form ref="formRef" :model="form" label-width="140px">
|
||||||
|
<el-form-item label="设备名称" prop="name">
|
||||||
|
<el-input v-model="form.name" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="注册过期时间(秒)" prop="expiration">
|
||||||
|
<el-input-number v-model="form.expiration" :min="60" :max="86400" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="心跳间隔(秒)" prop="heartBeatInterval">
|
||||||
|
<el-input-number v-model="form.heartBeatInterval" :min="5" :max="3600" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="心跳超时次数" prop="heartBeatCount">
|
||||||
|
<el-input-number v-model="form.heartBeatCount" :min="1" :max="60" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="定位功能" prop="positionCapability">
|
||||||
|
<el-select v-model="form.positionCapability">
|
||||||
|
<el-option :value="0" label="不支持" />
|
||||||
|
<el-option :value="1" label="GPS定位" />
|
||||||
|
<el-option :value="2" label="北斗定位" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="经度" v-if="form.longitude !== null">
|
||||||
|
<span class="readonly-field">{{ form.longitude }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="纬度" v-if="form.latitude !== null">
|
||||||
|
<span class="readonly-field">{{ form.latitude }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
|
||||||
|
<el-button :loading="loading" @click="handleRefresh">刷新</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'BasicPropertyPage',
|
||||||
|
props: {
|
||||||
|
deviceId: { type: String, default: null },
|
||||||
|
channelDeviceId: { type: String, default: null }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
saving: false,
|
||||||
|
form: {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelDeviceId,
|
||||||
|
name: '',
|
||||||
|
expiration: 3600,
|
||||||
|
heartBeatInterval: 60,
|
||||||
|
heartBeatCount: 3,
|
||||||
|
positionCapability: 0,
|
||||||
|
longitude: null,
|
||||||
|
latitude: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadConfig()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadConfig() {
|
||||||
|
this.loading = true
|
||||||
|
this.$store.dispatch('device/queryBasicParam', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelDeviceId
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
this.form = { ...this.form, ...data }
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
|
this.saving = true
|
||||||
|
this.$store.dispatch('device/setBasicParam', this.form)
|
||||||
|
.then(() => {
|
||||||
|
this.$message({ showClose: true, message: '保存成功', type: 'success' })
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.$message({ showClose: true, message: error, type: 'error' })
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.saving = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleRefresh() {
|
||||||
|
this.loadConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#dhBasicPropertyPage {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-property-body {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
min-height: 30vw;
|
||||||
|
flex: 1;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-section {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-section .el-input,
|
||||||
|
.config-section .el-input-number,
|
||||||
|
.config-section .el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readonly-field {
|
||||||
|
color: #606266;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
93
web/src/views/device/channel/cameraConfig.vue
Normal file
93
web/src/views/device/channel/cameraConfig.vue
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<div id="dhCameraConfigPage">
|
||||||
|
<el-page-header content="相机配置" @back="$emit('close')" />
|
||||||
|
<div class="camera-config-body">
|
||||||
|
<div class="config-sidebar">
|
||||||
|
<el-menu :default-active="activeTab" @select="handleMenuSelect">
|
||||||
|
<el-menu-item index="base">
|
||||||
|
<i class="iconfont icon-wxbzhuye" style="margin-right: 10px" />
|
||||||
|
<span>基础属性</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="image">
|
||||||
|
<i class="iconfont icon-shishiyulan" style="margin-right: 10px" />
|
||||||
|
<span>图像属性</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="encode">
|
||||||
|
<i class="iconfont icon-shipin" style="margin-right: 10px" />
|
||||||
|
<span>编码设置</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="alarm">
|
||||||
|
<i class="iconfont icon-baojing" style="margin-right: 10px" />
|
||||||
|
<span>报警配置</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
<div class="config-content">
|
||||||
|
<basicPropertyConfig v-if="activeTab === 'base'" :device-id="deviceId" :channel-device-id="channelDeviceId" />
|
||||||
|
<imagePropertyConfig v-if="activeTab === 'image'" :device-id="deviceId" :channel-device-id="channelDeviceId" />
|
||||||
|
<div v-if="activeTab === 'osd'" class="placeholder-tab">OSD配置(开发中)</div>
|
||||||
|
<div v-if="activeTab === 'encode'" class="placeholder-tab">编码设置(开发中)</div>
|
||||||
|
<div v-if="activeTab === 'alarm'" class="placeholder-tab">报警配置(开发中)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import basicPropertyConfig from './basicPropertyConfig.vue'
|
||||||
|
import imagePropertyConfig from './imagePropertyConfig.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CameraConfigPage',
|
||||||
|
components: { basicPropertyConfig, imagePropertyConfig },
|
||||||
|
props: {
|
||||||
|
deviceId: { type: String, default: null },
|
||||||
|
channelDeviceId: { type: String, default: null }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeTab: 'base'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleMenuSelect(index) {
|
||||||
|
this.activeTab = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#dhCameraConfigPage {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.camera-config-body {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
.config-sidebar {
|
||||||
|
width: 160px;
|
||||||
|
flex: none;
|
||||||
|
border-right: 1px solid #e6e6e6;
|
||||||
|
}
|
||||||
|
.config-sidebar .el-menu {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
.config-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.placeholder-tab {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 200px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
84
web/src/views/device/channel/imagePropertyConfig.vue
Normal file
84
web/src/views/device/channel/imagePropertyConfig.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div id="dhImagePropertyPage">
|
||||||
|
<div class="image-property-body">
|
||||||
|
<div class="player-section">
|
||||||
|
<playerPtzPanel :device-id="deviceId" :channel-device-id="channelDeviceId" />
|
||||||
|
</div>
|
||||||
|
<div class="config-section">
|
||||||
|
<el-tabs v-model="activeTab" tab-position="left" class="config-tabs">
|
||||||
|
<el-tab-pane label="OSD配置" name="osd">
|
||||||
|
<div class="placeholder-tab">OSD配置(开发中)</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="视角" name="control">
|
||||||
|
<div class="placeholder-tab">视角(开发中)</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="画面遮挡" name="pictureMask">
|
||||||
|
<div class="placeholder-tab">画面遮挡(开发中)</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import playerPtzPanel from '../common/playerPtzPanel.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ImagePropertyPage',
|
||||||
|
components: { playerPtzPanel },
|
||||||
|
props: {
|
||||||
|
deviceId: { type: String, default: null },
|
||||||
|
channelDeviceId: { type: String, default: null }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeTab: 'osd'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#dhImagePropertyPage {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-property-body {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
min-height: 30vw;
|
||||||
|
flex: 1;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-section {
|
||||||
|
width: 520px;
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-section {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-tabs {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder-tab {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 200px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="channelList" style="height: calc(100vh - 124px);">
|
<div id="channelList" style="height: calc(100vh - 124px);">
|
||||||
<div v-if="!editId && !ptzConfigChannelDeviceId" style="height: 100%">
|
<div v-if="!editId && !ptzConfigChannelDeviceId && !cameraConfigDeviceId" style="height: 100%">
|
||||||
<el-form :inline="true" size="mini">
|
<el-form :inline="true" size="mini">
|
||||||
<el-form-item style="margin-right: 2rem">
|
<el-form-item style="margin-right: 2rem">
|
||||||
<el-page-header content="通道列表" @back="showDevice" />
|
<el-page-header content="通道列表" @back="showDevice" />
|
||||||
@ -193,6 +193,8 @@
|
|||||||
云台配置</el-dropdown-item>
|
云台配置</el-dropdown-item>
|
||||||
<el-dropdown-item command="audioTalk" :disabled="device == null || device.online === 0">
|
<el-dropdown-item command="audioTalk" :disabled="device == null || device.online === 0">
|
||||||
语音对讲</el-dropdown-item>
|
语音对讲</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="cameraConfig" :disabled="device == null || device.online === 0" divided>
|
||||||
|
相机配置</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
|
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@ -214,6 +216,7 @@
|
|||||||
<devicePlayer ref="devicePlayer" />
|
<devicePlayer ref="devicePlayer" />
|
||||||
<channel-edit v-if="editId" :id="editId" :close-edit="closeEdit" />
|
<channel-edit v-if="editId" :id="editId" :close-edit="closeEdit" />
|
||||||
<ptzConfig v-if="ptzConfigChannelDeviceId" :device-id="ptzConfigDeviceId" :channel-device-id="ptzConfigChannelDeviceId" @close="closePtzConfig" />
|
<ptzConfig v-if="ptzConfigChannelDeviceId" :device-id="ptzConfigDeviceId" :channel-device-id="ptzConfigChannelDeviceId" @close="closePtzConfig" />
|
||||||
|
<cameraConfig v-if="cameraConfigDeviceId" :device-id="deviceId" :channel-device-id="cameraConfigDeviceId" @close="cameraConfigDeviceId = null" />
|
||||||
<audioTalk ref="audioTalk" />
|
<audioTalk ref="audioTalk" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -224,6 +227,7 @@ import devicePlayer from '../dialog/devicePlayer.vue'
|
|||||||
import audioTalk from '../dialog/audioTalk.vue'
|
import audioTalk from '../dialog/audioTalk.vue'
|
||||||
import Edit from './edit.vue'
|
import Edit from './edit.vue'
|
||||||
import ptzConfig from '@/views/device/channel/ptzConfig.vue'
|
import ptzConfig from '@/views/device/channel/ptzConfig.vue'
|
||||||
|
import cameraConfig from './cameraConfig.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ChannelList',
|
name: 'ChannelList',
|
||||||
@ -231,7 +235,8 @@ export default {
|
|||||||
devicePlayer,
|
devicePlayer,
|
||||||
audioTalk,
|
audioTalk,
|
||||||
ChannelEdit: Edit,
|
ChannelEdit: Edit,
|
||||||
ptzConfig
|
ptzConfig,
|
||||||
|
cameraConfig
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
defaultPage: {
|
defaultPage: {
|
||||||
@ -270,6 +275,7 @@ export default {
|
|||||||
editId: null,
|
editId: null,
|
||||||
ptzConfigDeviceId: null,
|
ptzConfigDeviceId: null,
|
||||||
ptzConfigChannelDeviceId: null,
|
ptzConfigChannelDeviceId: null,
|
||||||
|
cameraConfigDeviceId: null,
|
||||||
loadSnap: {},
|
loadSnap: {},
|
||||||
ptzTypes: {
|
ptzTypes: {
|
||||||
0: '未知',
|
0: '未知',
|
||||||
@ -402,6 +408,8 @@ export default {
|
|||||||
this.ptzConfigChannelDeviceId = itemData.deviceId
|
this.ptzConfigChannelDeviceId = itemData.deviceId
|
||||||
} else if (command === 'audioTalk') {
|
} else if (command === 'audioTalk') {
|
||||||
this.$refs.audioTalk.openDialog(this.deviceId, itemData.deviceId)
|
this.$refs.audioTalk.openDialog(this.deviceId, itemData.deviceId)
|
||||||
|
} else if (command === 'cameraConfig') {
|
||||||
|
this.cameraConfigDeviceId = itemData.deviceId
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryRecords: function(itemData) {
|
queryRecords: function(itemData) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user