Commit 3227dcd082454a1bf85ee623b8d62bbd47d10420
1 parent
91bfbc36
添加兼容接口预置位添加调用删除,列表查询
Showing
3 changed files
with
144 additions
and
12 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -1137,7 +1137,6 @@ public class SIPCommander implements ISIPCommander { | @@ -1137,7 +1137,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 1137 | } | 1137 | } |
| 1138 | cmdXml.append("</Query>\r\n"); | 1138 | cmdXml.append("</Query>\r\n"); |
| 1139 | 1139 | ||
| 1140 | - | ||
| 1141 | 1140 | ||
| 1142 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | 1141 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1143 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | 1142 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java
| 1 | package com.genersoft.iot.vmp.web.gb28181; | 1 | package com.genersoft.iot.vmp.web.gb28181; |
| 2 | 2 | ||
| 3 | -import com.alibaba.fastjson2.JSONObject; | ||
| 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 3 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 4 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| @@ -9,7 +8,9 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | @@ -9,7 +8,9 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 9 | import org.slf4j.Logger; | 8 | import org.slf4j.Logger; |
| 10 | import org.slf4j.LoggerFactory; | 9 | import org.slf4j.LoggerFactory; |
| 11 | import org.springframework.beans.factory.annotation.Autowired; | 10 | import org.springframework.beans.factory.annotation.Autowired; |
| 12 | -import org.springframework.web.bind.annotation.*; | 11 | +import org.springframework.web.bind.annotation.RequestMapping; |
| 12 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 13 | +import org.springframework.web.bind.annotation.RestController; | ||
| 13 | 14 | ||
| 14 | import javax.sip.InvalidArgumentException; | 15 | import javax.sip.InvalidArgumentException; |
| 15 | import javax.sip.SipException; | 16 | import javax.sip.SipException; |
| @@ -102,4 +103,53 @@ public class ApiControlController { | @@ -102,4 +103,53 @@ public class ApiControlController { | ||
| 102 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | 103 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); |
| 103 | } | 104 | } |
| 104 | } | 105 | } |
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 设备控制 - 预置位控制 | ||
| 109 | + * @param serial 设备编号 | ||
| 110 | + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可 | ||
| 111 | + * @param channel 通道序号, 默认值: 1 | ||
| 112 | + * @param command 控制指令 允许值: set, goto, remove | ||
| 113 | + * @param preset 预置位编号(1~255) | ||
| 114 | + * @param name 预置位名称, command=set 时有效 | ||
| 115 | + * @return | ||
| 116 | + */ | ||
| 117 | + @RequestMapping(value = "/preset") | ||
| 118 | + private void list(String serial,String command, | ||
| 119 | + @RequestParam(required = false)Integer channel, | ||
| 120 | + @RequestParam(required = false)String code, | ||
| 121 | + @RequestParam(required = false)String name, | ||
| 122 | + @RequestParam(required = false)Integer preset){ | ||
| 123 | + | ||
| 124 | + if (logger.isDebugEnabled()) { | ||
| 125 | + logger.debug("模拟接口> 预置位控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,name:{} ,preset:{} ", | ||
| 126 | + serial, code, command, name, preset); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + if (channel == null) {channel = 0;} | ||
| 130 | + Device device = storager.queryVideoDevice(serial); | ||
| 131 | + if (device == null) { | ||
| 132 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到"); | ||
| 133 | + } | ||
| 134 | + int cmdCode = 0; | ||
| 135 | + switch (command){ | ||
| 136 | + case "set": | ||
| 137 | + cmdCode = 129; | ||
| 138 | + break; | ||
| 139 | + case "goto": | ||
| 140 | + cmdCode = 130; | ||
| 141 | + break; | ||
| 142 | + case "remove": | ||
| 143 | + cmdCode = 131; | ||
| 144 | + break; | ||
| 145 | + default: | ||
| 146 | + break; | ||
| 147 | + } | ||
| 148 | + try { | ||
| 149 | + cmder.frontEndCmd(device, code, cmdCode, 0, preset, 0); | ||
| 150 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 151 | + logger.error("[命令发送失败] 预置位控制: {}", e.getMessage()); | ||
| 152 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 153 | + } | ||
| 154 | + } | ||
| 105 | } | 155 | } |
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java
| @@ -2,21 +2,32 @@ package com.genersoft.iot.vmp.web.gb28181; | @@ -2,21 +2,32 @@ package com.genersoft.iot.vmp.web.gb28181; | ||
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONArray; | 3 | import com.alibaba.fastjson2.JSONArray; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 10 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 6 | import com.genersoft.iot.vmp.service.IDeviceService; | 11 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 7 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 13 | +import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; | ||
| 14 | +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 8 | import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; | 15 | import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; |
| 9 | import com.github.pagehelper.PageInfo; | 16 | import com.github.pagehelper.PageInfo; |
| 10 | import org.slf4j.Logger; | 17 | import org.slf4j.Logger; |
| 11 | import org.slf4j.LoggerFactory; | 18 | import org.slf4j.LoggerFactory; |
| 12 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
| 20 | +import org.springframework.util.ObjectUtils; | ||
| 13 | import org.springframework.util.StringUtils; | 21 | import org.springframework.util.StringUtils; |
| 14 | import org.springframework.web.bind.annotation.RequestMapping; | 22 | import org.springframework.web.bind.annotation.RequestMapping; |
| 15 | import org.springframework.web.bind.annotation.RequestParam; | 23 | import org.springframework.web.bind.annotation.RequestParam; |
| 16 | import org.springframework.web.bind.annotation.RestController; | 24 | import org.springframework.web.bind.annotation.RestController; |
| 25 | +import org.springframework.web.context.request.async.DeferredResult; | ||
| 17 | 26 | ||
| 18 | -import java.util.Arrays; | ||
| 19 | -import java.util.List; | 27 | +import javax.sip.InvalidArgumentException; |
| 28 | +import javax.sip.SipException; | ||
| 29 | +import java.text.ParseException; | ||
| 30 | +import java.util.*; | ||
| 20 | 31 | ||
| 21 | /** | 32 | /** |
| 22 | * API兼容:设备信息 | 33 | * API兼容:设备信息 |
| @@ -31,17 +42,15 @@ public class ApiDeviceController { | @@ -31,17 +42,15 @@ public class ApiDeviceController { | ||
| 31 | 42 | ||
| 32 | @Autowired | 43 | @Autowired |
| 33 | private IVideoManagerStorage storager; | 44 | private IVideoManagerStorage storager; |
| 45 | + | ||
| 46 | + @Autowired | ||
| 47 | + private SIPCommander cmder; | ||
| 34 | @Autowired | 48 | @Autowired |
| 35 | private IDeviceService deviceService; | 49 | private IDeviceService deviceService; |
| 36 | 50 | ||
| 37 | - // @Autowired | ||
| 38 | - // private SIPCommander cmder; | ||
| 39 | - | ||
| 40 | - // @Autowired | ||
| 41 | - // private DeferredResultHolder resultHolder; | 51 | + @Autowired |
| 52 | + private DeferredResultHolder resultHolder; | ||
| 42 | 53 | ||
| 43 | - // @Autowired | ||
| 44 | - // private DeviceOffLineDetector offLineDetector; | ||
| 45 | 54 | ||
| 46 | /** | 55 | /** |
| 47 | * 分页获取设备列表 现在直接返回,尚未实现分页 | 56 | * 分页获取设备列表 现在直接返回,尚未实现分页 |
| @@ -171,4 +180,78 @@ public class ApiDeviceController { | @@ -171,4 +180,78 @@ public class ApiDeviceController { | ||
| 171 | result.put("ChannelList", channleJSONList); | 180 | result.put("ChannelList", channleJSONList); |
| 172 | return result; | 181 | return result; |
| 173 | } | 182 | } |
| 183 | + | ||
| 184 | + /** | ||
| 185 | + * 设备信息 - 获取下级通道预置位 | ||
| 186 | + * @param serial 设备编号 | ||
| 187 | + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可 | ||
| 188 | + * @param channel 通道序号, 默认值: 1 | ||
| 189 | + * @param fill 是否填充空置预置位,当下级返回预置位,但不够255个时,自动填充空置预置位到255个, 默认值: true, 允许值: true, false | ||
| 190 | + * @param timeout 超时时间(秒) 默认值: 15 | ||
| 191 | + * @return | ||
| 192 | + */ | ||
| 193 | + @RequestMapping(value = "/fetchpreset") | ||
| 194 | + private DeferredResult<Object> list(String serial, | ||
| 195 | + @RequestParam(required = false)Integer channel, | ||
| 196 | + @RequestParam(required = false)String code, | ||
| 197 | + @RequestParam(required = false)Boolean fill, | ||
| 198 | + @RequestParam(required = false)Integer timeout){ | ||
| 199 | + | ||
| 200 | + if (logger.isDebugEnabled()) { | ||
| 201 | + logger.debug("<模拟接口> 获取下级通道预置位 API调用,deviceId:{} ,channel:{} ,code:{} ,fill:{} ,timeout:{} ", | ||
| 202 | + serial, channel, code, fill, timeout); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + Device device = storager.queryVideoDevice(serial); | ||
| 206 | + String uuid = UUID.randomUUID().toString(); | ||
| 207 | + String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(code) ? serial : code); | ||
| 208 | + DeferredResult<Object> result = new DeferredResult<> (timeout * 1000L); | ||
| 209 | + DeferredResultEx<Object> deferredResultEx = new DeferredResultEx<>(result); | ||
| 210 | + result.onTimeout(()->{ | ||
| 211 | + logger.warn("<模拟接口> 获取设备预置位超时"); | ||
| 212 | + // 释放rtpserver | ||
| 213 | + RequestMessage msg = new RequestMessage(); | ||
| 214 | + msg.setId(uuid); | ||
| 215 | + msg.setKey(key); | ||
| 216 | + msg.setData("wait for presetquery timeout["+timeout+"s]"); | ||
| 217 | + resultHolder.invokeResult(msg); | ||
| 218 | + }); | ||
| 219 | + if (resultHolder.exist(key, null)) { | ||
| 220 | + return result; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + deferredResultEx.setFilter(filterResult->{ | ||
| 224 | + List<PresetQuerySipReq> presetQuerySipReqList = (List<PresetQuerySipReq>)filterResult; | ||
| 225 | + HashMap<String, Object> resultMap = new HashMap<>(); | ||
| 226 | + resultMap.put("DeviceID", code); | ||
| 227 | + resultMap.put("Result", "OK"); | ||
| 228 | + resultMap.put("SumNum", presetQuerySipReqList.size()); | ||
| 229 | + ArrayList<Map<String, Object>> presetItemList = new ArrayList<>(presetQuerySipReqList.size()); | ||
| 230 | + for (PresetQuerySipReq presetQuerySipReq : presetQuerySipReqList) { | ||
| 231 | + Map<String, Object> item = new HashMap<>(); | ||
| 232 | + item.put("PresetID", presetQuerySipReq.getPresetId()); | ||
| 233 | + item.put("PresetName", presetQuerySipReq.getPresetName()); | ||
| 234 | + item.put("PresetEnable", true); | ||
| 235 | + presetItemList.add(item); | ||
| 236 | + } | ||
| 237 | + resultMap.put("PresetItemList",presetItemList ); | ||
| 238 | + return resultMap; | ||
| 239 | + }); | ||
| 240 | + | ||
| 241 | + resultHolder.put(key, uuid, deferredResultEx); | ||
| 242 | + | ||
| 243 | + try { | ||
| 244 | + cmder.presetQuery(device, code, event -> { | ||
| 245 | + RequestMessage msg = new RequestMessage(); | ||
| 246 | + msg.setId(uuid); | ||
| 247 | + msg.setKey(key); | ||
| 248 | + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg)); | ||
| 249 | + resultHolder.invokeResult(msg); | ||
| 250 | + }); | ||
| 251 | + } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 252 | + logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage()); | ||
| 253 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 254 | + } | ||
| 255 | + return result; | ||
| 256 | + } | ||
| 174 | } | 257 | } |