From 3227dcd082454a1bf85ee623b8d62bbd47d10420 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 28 Mar 2023 17:56:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=BC=E5=AE=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E9=A2=84=E7=BD=AE=E4=BD=8D=E6=B7=BB=E5=8A=A0=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E5=88=A0=E9=99=A4=EF=BC=8C=E5=88=97=E8=A1=A8=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transmit/cmd/impl/SIPCommander.java | 1 - .../vmp/web/gb28181/ApiControlController.java | 54 +++++++++- .../vmp/web/gb28181/ApiDeviceController.java | 101 ++++++++++++++++-- 3 files changed, 144 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 6b777827..03050169 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -1137,7 +1137,6 @@ public class SIPCommander implements ISIPCommander { } cmdXml.append("\r\n"); - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java index 6f2fe544..286c8d57 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.web.gb28181; -import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; @@ -9,7 +8,9 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import javax.sip.InvalidArgumentException; import javax.sip.SipException; @@ -102,4 +103,53 @@ public class ApiControlController { throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); } } + + /** + * 设备控制 - 预置位控制 + * @param serial 设备编号 + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可 + * @param channel 通道序号, 默认值: 1 + * @param command 控制指令 允许值: set, goto, remove + * @param preset 预置位编号(1~255) + * @param name 预置位名称, command=set 时有效 + * @return + */ + @RequestMapping(value = "/preset") + private void list(String serial,String command, + @RequestParam(required = false)Integer channel, + @RequestParam(required = false)String code, + @RequestParam(required = false)String name, + @RequestParam(required = false)Integer preset){ + + if (logger.isDebugEnabled()) { + logger.debug("模拟接口> 预置位控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,name:{} ,preset:{} ", + serial, code, command, name, preset); + } + + if (channel == null) {channel = 0;} + Device device = storager.queryVideoDevice(serial); + if (device == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到"); + } + int cmdCode = 0; + switch (command){ + case "set": + cmdCode = 129; + break; + case "goto": + cmdCode = 130; + break; + case "remove": + cmdCode = 131; + break; + default: + break; + } + try { + cmder.frontEndCmd(device, code, cmdCode, 0, preset, 0); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[命令发送失败] 预置位控制: {}", e.getMessage()); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java index 99989608..08f79bf4 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java @@ -2,21 +2,32 @@ package com.genersoft.iot.vmp.web.gb28181; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; import com.github.pagehelper.PageInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.async.DeferredResult; -import java.util.Arrays; -import java.util.List; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; +import java.util.*; /** * API兼容:设备信息 @@ -31,17 +42,15 @@ public class ApiDeviceController { @Autowired private IVideoManagerStorage storager; + + @Autowired + private SIPCommander cmder; @Autowired private IDeviceService deviceService; - // @Autowired - // private SIPCommander cmder; + @Autowired + private DeferredResultHolder resultHolder; - // @Autowired - // private DeferredResultHolder resultHolder; - - // @Autowired - // private DeviceOffLineDetector offLineDetector; /** * 分页获取设备列表 现在直接返回,尚未实现分页 @@ -171,4 +180,78 @@ public class ApiDeviceController { result.put("ChannelList", channleJSONList); return result; } + + /** + * 设备信息 - 获取下级通道预置位 + * @param serial 设备编号 + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可 + * @param channel 通道序号, 默认值: 1 + * @param fill 是否填充空置预置位,当下级返回预置位,但不够255个时,自动填充空置预置位到255个, 默认值: true, 允许值: true, false + * @param timeout 超时时间(秒) 默认值: 15 + * @return + */ + @RequestMapping(value = "/fetchpreset") + private DeferredResult list(String serial, + @RequestParam(required = false)Integer channel, + @RequestParam(required = false)String code, + @RequestParam(required = false)Boolean fill, + @RequestParam(required = false)Integer timeout){ + + if (logger.isDebugEnabled()) { + logger.debug("<模拟接口> 获取下级通道预置位 API调用,deviceId:{} ,channel:{} ,code:{} ,fill:{} ,timeout:{} ", + serial, channel, code, fill, timeout); + } + + Device device = storager.queryVideoDevice(serial); + String uuid = UUID.randomUUID().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(code) ? serial : code); + DeferredResult result = new DeferredResult<> (timeout * 1000L); + DeferredResultEx deferredResultEx = new DeferredResultEx<>(result); + result.onTimeout(()->{ + logger.warn("<模拟接口> 获取设备预置位超时"); + // 释放rtpserver + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + msg.setData("wait for presetquery timeout["+timeout+"s]"); + resultHolder.invokeResult(msg); + }); + if (resultHolder.exist(key, null)) { + return result; + } + + deferredResultEx.setFilter(filterResult->{ + List presetQuerySipReqList = (List)filterResult; + HashMap resultMap = new HashMap<>(); + resultMap.put("DeviceID", code); + resultMap.put("Result", "OK"); + resultMap.put("SumNum", presetQuerySipReqList.size()); + ArrayList> presetItemList = new ArrayList<>(presetQuerySipReqList.size()); + for (PresetQuerySipReq presetQuerySipReq : presetQuerySipReqList) { + Map item = new HashMap<>(); + item.put("PresetID", presetQuerySipReq.getPresetId()); + item.put("PresetName", presetQuerySipReq.getPresetName()); + item.put("PresetEnable", true); + presetItemList.add(item); + } + resultMap.put("PresetItemList",presetItemList ); + return resultMap; + }); + + resultHolder.put(key, uuid, deferredResultEx); + + try { + cmder.presetQuery(device, code, event -> { + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg)); + resultHolder.invokeResult(msg); + }); + } catch (InvalidArgumentException | SipException | ParseException e) { + logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage()); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); + } + return result; + } }