Commit 7083f30fc4ffd7af893e612c9c8cb1bf612faa6c
1 parent
ca1719da
康宝
Showing
5 changed files
with
580 additions
and
551 deletions
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| @@ -26,7 +26,9 @@ import io.swagger.v3.oas.annotations.Operation; | @@ -26,7 +26,9 @@ import io.swagger.v3.oas.annotations.Operation; | ||
| 26 | import io.swagger.v3.oas.annotations.Parameter; | 26 | import io.swagger.v3.oas.annotations.Parameter; |
| 27 | import io.swagger.v3.oas.annotations.security.SecurityRequirement; | 27 | import io.swagger.v3.oas.annotations.security.SecurityRequirement; |
| 28 | import io.swagger.v3.oas.annotations.tags.Tag; | 28 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 29 | +import org.apache.commons.collections4.CollectionUtils; | ||
| 29 | import org.apache.commons.compress.utils.IOUtils; | 30 | import org.apache.commons.compress.utils.IOUtils; |
| 31 | +import org.apache.commons.lang3.StringUtils; | ||
| 30 | import org.apache.ibatis.annotations.Options; | 32 | import org.apache.ibatis.annotations.Options; |
| 31 | import org.slf4j.Logger; | 33 | import org.slf4j.Logger; |
| 32 | import org.slf4j.LoggerFactory; | 34 | import org.slf4j.LoggerFactory; |
| @@ -48,539 +50,568 @@ import java.io.InputStream; | @@ -48,539 +50,568 @@ import java.io.InputStream; | ||
| 48 | import java.nio.file.Files; | 50 | import java.nio.file.Files; |
| 49 | import java.text.ParseException; | 51 | import java.text.ParseException; |
| 50 | import java.util.*; | 52 | import java.util.*; |
| 53 | +import java.util.stream.Collectors; | ||
| 51 | 54 | ||
| 52 | -@Tag(name = "国标设备查询", description = "国标设备查询") | 55 | +@Tag(name = "国标设备查询", description = "国标设备查询") |
| 53 | @SuppressWarnings("rawtypes") | 56 | @SuppressWarnings("rawtypes") |
| 54 | 57 | ||
| 55 | @RestController | 58 | @RestController |
| 56 | @RequestMapping("/api/device/query") | 59 | @RequestMapping("/api/device/query") |
| 57 | public class DeviceQuery { | 60 | public class DeviceQuery { |
| 58 | - | ||
| 59 | - private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class); | ||
| 60 | - | ||
| 61 | - @Autowired | ||
| 62 | - private IVideoManagerStorage storager; | ||
| 63 | - | ||
| 64 | - @Autowired | ||
| 65 | - private IDeviceChannelService deviceChannelService; | ||
| 66 | - | ||
| 67 | - @Autowired | ||
| 68 | - private IRedisCatchStorage redisCatchStorage; | ||
| 69 | - | ||
| 70 | - @Autowired | ||
| 71 | - private IInviteStreamService inviteStreamService; | ||
| 72 | - | ||
| 73 | - @Autowired | ||
| 74 | - private SIPCommander cmder; | ||
| 75 | - | ||
| 76 | - @Autowired | ||
| 77 | - private DeferredResultHolder resultHolder; | ||
| 78 | - | ||
| 79 | - @Autowired | ||
| 80 | - private IDeviceService deviceService; | ||
| 81 | - | ||
| 82 | - @Autowired | ||
| 83 | - private DynamicTask dynamicTask; | ||
| 84 | - | ||
| 85 | - /** | ||
| 86 | - * 使用ID查询国标设备 | ||
| 87 | - * @param deviceId 国标ID | ||
| 88 | - * @return 国标设备 | ||
| 89 | - */ | ||
| 90 | - @Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 91 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 92 | - @GetMapping("/devices/{deviceId}") | ||
| 93 | - public Device devices(@PathVariable String deviceId){ | ||
| 94 | - | ||
| 95 | - return storager.queryVideoDevice(deviceId); | ||
| 96 | - } | ||
| 97 | - | ||
| 98 | - /** | ||
| 99 | - * 分页查询国标设备 | ||
| 100 | - * @param page 当前页 | ||
| 101 | - * @param count 每页查询数量 | ||
| 102 | - * @return 分页国标列表 | ||
| 103 | - */ | ||
| 104 | - @Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 105 | - @Parameter(name = "page", description = "当前页", required = true) | ||
| 106 | - @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 107 | - @GetMapping("/devices") | ||
| 108 | - @Options() | ||
| 109 | - public PageInfo<Device> devices(int page, int count){ | 61 | + |
| 62 | + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class); | ||
| 63 | + | ||
| 64 | + @Autowired | ||
| 65 | + private IVideoManagerStorage storager; | ||
| 66 | + | ||
| 67 | + @Autowired | ||
| 68 | + private IDeviceChannelService deviceChannelService; | ||
| 69 | + | ||
| 70 | + @Autowired | ||
| 71 | + private IRedisCatchStorage redisCatchStorage; | ||
| 72 | + | ||
| 73 | + @Autowired | ||
| 74 | + private IInviteStreamService inviteStreamService; | ||
| 75 | + | ||
| 76 | + @Autowired | ||
| 77 | + private SIPCommander cmder; | ||
| 78 | + | ||
| 79 | + @Autowired | ||
| 80 | + private DeferredResultHolder resultHolder; | ||
| 81 | + | ||
| 82 | + @Autowired | ||
| 83 | + private IDeviceService deviceService; | ||
| 84 | + | ||
| 85 | + @Autowired | ||
| 86 | + private DynamicTask dynamicTask; | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * 使用ID查询国标设备 | ||
| 90 | + * | ||
| 91 | + * @param deviceId 国标ID | ||
| 92 | + * @return 国标设备 | ||
| 93 | + */ | ||
| 94 | + @Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 95 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 96 | + @GetMapping("/devices/{deviceId}") | ||
| 97 | + public Device devices(@PathVariable String deviceId) { | ||
| 98 | + | ||
| 99 | + return storager.queryVideoDevice(deviceId); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + /** | ||
| 103 | + * 分页查询国标设备 | ||
| 104 | + * | ||
| 105 | + * @param page 当前页 | ||
| 106 | + * @param count 每页查询数量 | ||
| 107 | + * @return 分页国标列表 | ||
| 108 | + */ | ||
| 109 | + @Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 110 | + @Parameter(name = "page", description = "当前页", required = true) | ||
| 111 | + @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 112 | + @GetMapping("/devices") | ||
| 113 | + @Options() | ||
| 114 | + public PageInfo<Device> devices(int page, int count) { | ||
| 110 | // if (page == null) page = 0; | 115 | // if (page == null) page = 0; |
| 111 | // if (count == null) count = 20; | 116 | // if (count == null) count = 20; |
| 112 | - return storager.queryVideoDeviceList(page, count,null); | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - /** | ||
| 116 | - * 分页查询通道数 | ||
| 117 | - * | ||
| 118 | - * @param deviceId 设备id | ||
| 119 | - * @param page 当前页 | ||
| 120 | - * @param count 每页条数 | ||
| 121 | - * @param query 查询内容 | ||
| 122 | - * @param online 是否在线 在线 true / 离线 false | ||
| 123 | - * @param channelType 设备 false/子目录 true | ||
| 124 | - * @param catalogUnderDevice 是否直属与设备的目录 | ||
| 125 | - * @return 通道列表 | ||
| 126 | - */ | ||
| 127 | - @GetMapping("/devices/{deviceId}/channels") | ||
| 128 | - @Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 129 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 130 | - @Parameter(name = "page", description = "当前页", required = true) | ||
| 131 | - @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 132 | - @Parameter(name = "query", description = "查询内容") | ||
| 133 | - @Parameter(name = "online", description = "是否在线") | ||
| 134 | - @Parameter(name = "channelType", description = "设备/子目录-> false/true") | ||
| 135 | - @Parameter(name = "catalogUnderDevice", description = "是否直属与设备的目录") | ||
| 136 | - public PageInfo<DeviceChannel> channels(@PathVariable String deviceId, | ||
| 137 | - int page, int count, | ||
| 138 | - @RequestParam(required = false) String query, | ||
| 139 | - @RequestParam(required = false) Boolean online, | ||
| 140 | - @RequestParam(required = false) Boolean channelType, | ||
| 141 | - @RequestParam(required = false) Boolean catalogUnderDevice) { | ||
| 142 | - if (ObjectUtils.isEmpty(query)) { | ||
| 143 | - query = null; | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - return storager.queryChannelsByDeviceId(deviceId, query, channelType, online, catalogUnderDevice, page, count); | ||
| 147 | - } | ||
| 148 | - | ||
| 149 | - /** | ||
| 150 | - * 同步设备通道 | ||
| 151 | - * @param deviceId 设备id | ||
| 152 | - * @return | ||
| 153 | - */ | ||
| 154 | - @Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 155 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 156 | - @GetMapping("/devices/{deviceId}/sync") | ||
| 157 | - public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId){ | ||
| 158 | - | ||
| 159 | - if (logger.isDebugEnabled()) { | ||
| 160 | - logger.debug("设备通道信息同步API调用,deviceId:" + deviceId); | ||
| 161 | - } | ||
| 162 | - Device device = storager.queryVideoDevice(deviceId); | ||
| 163 | - boolean status = deviceService.isSyncRunning(deviceId); | ||
| 164 | - // 已存在则返回进度 | ||
| 165 | - if (status) { | ||
| 166 | - SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId); | ||
| 167 | - return WVPResult.success(channelSyncStatus); | ||
| 168 | - } | ||
| 169 | - deviceService.sync(device); | ||
| 170 | - | ||
| 171 | - WVPResult<SyncStatus> wvpResult = new WVPResult<>(); | ||
| 172 | - wvpResult.setCode(0); | ||
| 173 | - wvpResult.setMsg("开始同步"); | ||
| 174 | - return wvpResult; | ||
| 175 | - } | ||
| 176 | - | ||
| 177 | - /** | ||
| 178 | - * 移除设备 | ||
| 179 | - * @param deviceId 设备id | ||
| 180 | - * @return | ||
| 181 | - */ | ||
| 182 | - @Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 183 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 184 | - @DeleteMapping("/devices/{deviceId}/delete") | ||
| 185 | - public String delete(@PathVariable String deviceId){ | ||
| 186 | - | ||
| 187 | - if (logger.isDebugEnabled()) { | ||
| 188 | - logger.debug("设备信息删除API调用,deviceId:" + deviceId); | ||
| 189 | - } | ||
| 190 | - | ||
| 191 | - // 清除redis记录 | ||
| 192 | - boolean isSuccess = deviceService.delete(deviceId); | ||
| 193 | - if (isSuccess) { | ||
| 194 | - inviteStreamService.clearInviteInfo(deviceId); | ||
| 195 | - // 停止此设备的订阅更新 | ||
| 196 | - Set<String> allKeys = dynamicTask.getAllKeys(); | ||
| 197 | - for (String key : allKeys) { | ||
| 198 | - if (key.startsWith(deviceId)) { | ||
| 199 | - Runnable runnable = dynamicTask.get(key); | ||
| 200 | - if (runnable instanceof ISubscribeTask) { | ||
| 201 | - ISubscribeTask subscribeTask = (ISubscribeTask) runnable; | ||
| 202 | - subscribeTask.stop(null); | ||
| 203 | - } | ||
| 204 | - dynamicTask.stop(key); | ||
| 205 | - } | ||
| 206 | - } | ||
| 207 | - JSONObject json = new JSONObject(); | ||
| 208 | - json.put("deviceId", deviceId); | ||
| 209 | - return json.toString(); | ||
| 210 | - } else { | ||
| 211 | - logger.warn("设备信息删除API调用失败!"); | ||
| 212 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备信息删除API调用失败!"); | ||
| 213 | - } | ||
| 214 | - } | ||
| 215 | - | ||
| 216 | - /** | ||
| 217 | - * 分页查询子目录通道 | ||
| 218 | - * @param deviceId 通道id | ||
| 219 | - * @param channelId 通道id | ||
| 220 | - * @param page 当前页 | ||
| 221 | - * @param count 每页条数 | ||
| 222 | - * @param query 查询内容 | ||
| 223 | - * @param online 是否在线 | ||
| 224 | - * @param channelType 通道类型 | ||
| 225 | - * @return 子通道列表 | ||
| 226 | - */ | ||
| 227 | - @Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 228 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 229 | - @Parameter(name = "channelId", description = "通道国标编号", required = true) | ||
| 230 | - @Parameter(name = "page", description = "当前页", required = true) | ||
| 231 | - @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 232 | - @Parameter(name = "query", description = "查询内容") | ||
| 233 | - @Parameter(name = "online", description = "是否在线") | ||
| 234 | - @Parameter(name = "channelType", description = "设备/子目录-> false/true") | ||
| 235 | - @GetMapping("/sub_channels/{deviceId}/{channelId}/channels") | ||
| 236 | - public PageInfo<DeviceChannel> subChannels(@PathVariable String deviceId, | ||
| 237 | - @PathVariable String channelId, | ||
| 238 | - int page, | ||
| 239 | - int count, | ||
| 240 | - @RequestParam(required = false) String query, | ||
| 241 | - @RequestParam(required = false) Boolean online, | ||
| 242 | - @RequestParam(required = false) Boolean channelType){ | ||
| 243 | - | ||
| 244 | - DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId); | ||
| 245 | - if (deviceChannel == null) { | ||
| 246 | - PageInfo<DeviceChannel> deviceChannelPageResult = new PageInfo<>(); | ||
| 247 | - return deviceChannelPageResult; | ||
| 248 | - } | ||
| 249 | - | ||
| 250 | - return storager.querySubChannels(deviceId, channelId, query, channelType, online, page, count); | ||
| 251 | - } | ||
| 252 | - | ||
| 253 | - /** | ||
| 254 | - * 更新通道信息 | ||
| 255 | - * @param deviceId 设备id | ||
| 256 | - * @param channel 通道 | ||
| 257 | - * @return | ||
| 258 | - */ | ||
| 259 | - @Operation(summary = "更新通道信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 260 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 261 | - @Parameter(name = "channel", description = "通道信息", required = true) | ||
| 262 | - @PostMapping("/channel/update/{deviceId}") | ||
| 263 | - public void updateChannel(@PathVariable String deviceId,DeviceChannel channel){ | ||
| 264 | - deviceChannelService.updateChannel(deviceId, channel); | ||
| 265 | - } | ||
| 266 | - | ||
| 267 | - @Operation(summary = "修改通道的码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 268 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 269 | - @Parameter(name = "channel", description = "通道信息", required = true) | ||
| 270 | - @PostMapping("/channel/stream/identification/update/") | ||
| 271 | - public void updateChannelStreamIdentification(DeviceChannel channel){ | ||
| 272 | - deviceChannelService.updateChannelStreamIdentification(channel); | ||
| 273 | - } | ||
| 274 | - | ||
| 275 | - /** | ||
| 276 | - * 修改数据流传输模式 | ||
| 277 | - * @param deviceId 设备id | ||
| 278 | - * @param streamMode 数据流传输模式 | ||
| 279 | - * @return | ||
| 280 | - */ | ||
| 281 | - @Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 282 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 283 | - @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" + | ||
| 284 | - "UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", required = true) | ||
| 285 | - @PostMapping("/transport/{deviceId}/{streamMode}") | ||
| 286 | - public void updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){ | ||
| 287 | - Device device = deviceService.getDevice(deviceId); | ||
| 288 | - device.setStreamMode(streamMode); | ||
| 289 | - deviceService.updateCustomDevice(device); | ||
| 290 | - } | ||
| 291 | - | ||
| 292 | - /** | ||
| 293 | - * 添加设备信息 | ||
| 294 | - * @param device 设备信息 | ||
| 295 | - * @return | ||
| 296 | - */ | ||
| 297 | - @Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 298 | - @Parameter(name = "device", description = "设备", required = true) | ||
| 299 | - @PostMapping("/device/add/") | ||
| 300 | - public void addDevice(Device device){ | ||
| 301 | - | ||
| 302 | - if (device == null || device.getDeviceId() == null) { | ||
| 303 | - throw new ControllerException(ErrorCode.ERROR400); | ||
| 304 | - } | ||
| 305 | - | ||
| 306 | - // 查看deviceId是否存在 | ||
| 307 | - boolean exist = deviceService.isExist(device.getDeviceId()); | ||
| 308 | - if (exist) { | ||
| 309 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备编号已存在"); | ||
| 310 | - } | ||
| 311 | - deviceService.addDevice(device); | ||
| 312 | - } | ||
| 313 | - | ||
| 314 | - /** | ||
| 315 | - * 更新设备信息 | ||
| 316 | - * @param device 设备信息 | ||
| 317 | - * @return | ||
| 318 | - */ | ||
| 319 | - @Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 320 | - @Parameter(name = "device", description = "设备", required = true) | ||
| 321 | - @PostMapping("/device/update/") | ||
| 322 | - public void updateDevice(Device device){ | ||
| 323 | - | ||
| 324 | - if (device != null && device.getDeviceId() != null) { | ||
| 325 | - deviceService.updateCustomDevice(device); | ||
| 326 | - } | ||
| 327 | - } | ||
| 328 | - | ||
| 329 | - /** | ||
| 330 | - * 设备状态查询请求API接口 | ||
| 331 | - * | ||
| 332 | - * @param deviceId 设备id | ||
| 333 | - */ | ||
| 334 | - @Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 335 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 336 | - @GetMapping("/devices/{deviceId}/status") | ||
| 337 | - public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) { | ||
| 338 | - if (logger.isDebugEnabled()) { | ||
| 339 | - logger.debug("设备状态查询API调用"); | ||
| 340 | - } | ||
| 341 | - Device device = storager.queryVideoDevice(deviceId); | ||
| 342 | - String uuid = UUID.randomUUID().toString(); | ||
| 343 | - String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId; | ||
| 344 | - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L); | ||
| 345 | - if(device == null) { | ||
| 346 | - result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK)); | ||
| 347 | - return result; | ||
| 348 | - } | ||
| 349 | - try { | ||
| 350 | - cmder.deviceStatusQuery(device, event -> { | ||
| 351 | - RequestMessage msg = new RequestMessage(); | ||
| 352 | - msg.setId(uuid); | ||
| 353 | - msg.setKey(key); | ||
| 354 | - msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg)); | ||
| 355 | - resultHolder.invokeResult(msg); | ||
| 356 | - }); | ||
| 357 | - } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 358 | - logger.error("[命令发送失败] 获取设备状态: {}", e.getMessage()); | ||
| 359 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 360 | - } | ||
| 361 | - result.onTimeout(()->{ | ||
| 362 | - logger.warn(String.format("获取设备状态超时")); | ||
| 363 | - // 释放rtpserver | ||
| 364 | - RequestMessage msg = new RequestMessage(); | ||
| 365 | - msg.setId(uuid); | ||
| 366 | - msg.setKey(key); | ||
| 367 | - msg.setData("Timeout. Device did not response to this command."); | ||
| 368 | - resultHolder.invokeResult(msg); | ||
| 369 | - }); | ||
| 370 | - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, uuid, result); | ||
| 371 | - return result; | ||
| 372 | - } | ||
| 373 | - | ||
| 374 | - /** | ||
| 375 | - * 设备报警查询请求API接口 | ||
| 376 | - * @param deviceId 设备id | ||
| 377 | - * @param startPriority 报警起始级别(可选) | ||
| 378 | - * @param endPriority 报警终止级别(可选) | ||
| 379 | - * @param alarmMethod 报警方式条件(可选) | ||
| 380 | - * @param alarmType 报警类型 | ||
| 381 | - * @param startTime 报警发生起始时间(可选) | ||
| 382 | - * @param endTime 报警发生终止时间(可选) | ||
| 383 | - * @return true = 命令发送成功 | ||
| 384 | - */ | ||
| 385 | - @Operation(summary = "设备报警查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 386 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 387 | - @Parameter(name = "startPriority", description = "报警起始级别") | ||
| 388 | - @Parameter(name = "endPriority", description = "报警终止级别") | ||
| 389 | - @Parameter(name = "alarmMethod", description = "报警方式条件") | ||
| 390 | - @Parameter(name = "alarmType", description = "报警类型") | ||
| 391 | - @Parameter(name = "startTime", description = "报警发生起始时间") | ||
| 392 | - @Parameter(name = "endTime", description = "报警发生终止时间") | ||
| 393 | - @GetMapping("/alarm/{deviceId}") | ||
| 394 | - public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId, | ||
| 395 | - @RequestParam(required = false) String startPriority, | ||
| 396 | - @RequestParam(required = false) String endPriority, | ||
| 397 | - @RequestParam(required = false) String alarmMethod, | ||
| 398 | - @RequestParam(required = false) String alarmType, | ||
| 399 | - @RequestParam(required = false) String startTime, | ||
| 400 | - @RequestParam(required = false) String endTime) { | ||
| 401 | - if (logger.isDebugEnabled()) { | ||
| 402 | - logger.debug("设备报警查询API调用"); | ||
| 403 | - } | ||
| 404 | - Device device = storager.queryVideoDevice(deviceId); | ||
| 405 | - String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; | ||
| 406 | - String uuid = UUID.randomUUID().toString(); | ||
| 407 | - try { | ||
| 408 | - cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> { | ||
| 409 | - RequestMessage msg = new RequestMessage(); | ||
| 410 | - msg.setId(uuid); | ||
| 411 | - msg.setKey(key); | ||
| 412 | - msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg)); | ||
| 413 | - resultHolder.invokeResult(msg); | ||
| 414 | - }); | ||
| 415 | - } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 416 | - logger.error("[命令发送失败] 设备报警查询: {}", e.getMessage()); | ||
| 417 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 418 | - } | ||
| 419 | - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L); | ||
| 420 | - result.onTimeout(()->{ | ||
| 421 | - logger.warn(String.format("设备报警查询超时")); | ||
| 422 | - // 释放rtpserver | ||
| 423 | - RequestMessage msg = new RequestMessage(); | ||
| 424 | - msg.setId(uuid); | ||
| 425 | - msg.setKey(key); | ||
| 426 | - msg.setData("设备报警查询超时"); | ||
| 427 | - resultHolder.invokeResult(msg); | ||
| 428 | - }); | ||
| 429 | - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, uuid, result); | ||
| 430 | - return result; | ||
| 431 | - } | ||
| 432 | - | ||
| 433 | - | ||
| 434 | - @GetMapping("/{deviceId}/sync_status") | ||
| 435 | - @Operation(summary = "获取通道同步进度", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 436 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 437 | - public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) { | ||
| 438 | - SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId); | ||
| 439 | - WVPResult<SyncStatus> wvpResult = new WVPResult<>(); | ||
| 440 | - if (channelSyncStatus == null) { | ||
| 441 | - wvpResult.setCode(-1); | ||
| 442 | - wvpResult.setMsg("同步尚未开始"); | ||
| 443 | - }else { | ||
| 444 | - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 445 | - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 446 | - wvpResult.setData(channelSyncStatus); | ||
| 447 | - if (channelSyncStatus.getErrorMsg() != null) { | ||
| 448 | - wvpResult.setMsg(channelSyncStatus.getErrorMsg()); | ||
| 449 | - } | ||
| 450 | - } | ||
| 451 | - return wvpResult; | ||
| 452 | - } | ||
| 453 | - | ||
| 454 | - @GetMapping("/{deviceId}/subscribe_info") | ||
| 455 | - @Operation(summary = "获取设备的订阅状态", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 456 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 457 | - public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) { | ||
| 458 | - Set<String> allKeys = dynamicTask.getAllKeys(); | ||
| 459 | - Map<String, Integer> dialogStateMap = new HashMap<>(); | ||
| 460 | - for (String key : allKeys) { | ||
| 461 | - if (key.startsWith(deviceId)) { | ||
| 462 | - ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key); | ||
| 463 | - if (subscribeTask instanceof CatalogSubscribeTask) { | ||
| 464 | - dialogStateMap.put("catalog", 1); | ||
| 465 | - }else if (subscribeTask instanceof MobilePositionSubscribeTask) { | ||
| 466 | - dialogStateMap.put("mobilePosition", 1); | ||
| 467 | - } | ||
| 468 | - } | ||
| 469 | - } | ||
| 470 | - WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>(); | ||
| 471 | - wvpResult.setCode(0); | ||
| 472 | - wvpResult.setData(dialogStateMap); | ||
| 473 | - return wvpResult; | ||
| 474 | - } | ||
| 475 | - | ||
| 476 | - @GetMapping("/snap/{deviceId}/{channelId}") | ||
| 477 | - @Operation(summary = "请求截图") | ||
| 478 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 479 | - @Parameter(name = "channelId", description = "通道国标编号", required = true) | ||
| 480 | - @Parameter(name = "mark", description = "标识", required = false) | ||
| 481 | - public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId, @RequestParam(required = false) String mark) { | ||
| 482 | - | ||
| 483 | - try { | ||
| 484 | - final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + (mark == null? ".jpg": ("_" + mark + ".jpg"))).toPath()); | ||
| 485 | - resp.setContentType(MediaType.IMAGE_PNG_VALUE); | ||
| 486 | - ServletOutputStream outputStream = resp.getOutputStream(); | ||
| 487 | - IOUtils.copy(in, resp.getOutputStream()); | ||
| 488 | - in.close(); | ||
| 489 | - outputStream.close(); | ||
| 490 | - } catch (IOException e) { | ||
| 491 | - resp.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||
| 492 | - } | ||
| 493 | - } | ||
| 494 | - | ||
| 495 | - /** | ||
| 496 | - * 查询国标树 | ||
| 497 | - * @param deviceId 设备ID | ||
| 498 | - * @param parentId 父ID | ||
| 499 | - * @param page 当前页 | ||
| 500 | - * @param count 每页条数 | ||
| 501 | - * @return 国标设备 | ||
| 502 | - */ | ||
| 503 | - @Operation(summary = "查询国标树") | ||
| 504 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 505 | - @Parameter(name = "parentId", description = "父级国标编号") | ||
| 506 | - @Parameter(name = "onlyCatalog", description = "只获取目录") | ||
| 507 | - @Parameter(name = "page", description = "当前页", required = true) | ||
| 508 | - @Parameter(name = "count", description = "每页条数", required = true) | ||
| 509 | - @GetMapping("/tree/{deviceId}") | ||
| 510 | - public ResponseEntity<PageInfo> getTree(@PathVariable String deviceId, | ||
| 511 | - @RequestParam(required = false) String parentId, | ||
| 512 | - @RequestParam(required = false) Boolean onlyCatalog, | ||
| 513 | - int page, int count){ | ||
| 514 | - | ||
| 515 | - | ||
| 516 | - if (page <= 0) { | ||
| 517 | - page = 1; | ||
| 518 | - } | ||
| 519 | - if (onlyCatalog == null) { | ||
| 520 | - onlyCatalog = false; | ||
| 521 | - } | ||
| 522 | - | ||
| 523 | - List<BaseTree<DeviceChannel>> treeData = deviceService.queryVideoDeviceTree(deviceId, parentId, onlyCatalog); | ||
| 524 | - if (treeData == null || (page - 1) * count > treeData.size()) { | ||
| 525 | - PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 526 | - pageInfo.setPageNum(page); | ||
| 527 | - pageInfo.setTotal(treeData == null? 0 : treeData.size()); | ||
| 528 | - pageInfo.setSize(0); | ||
| 529 | - pageInfo.setList(new ArrayList<>()); | ||
| 530 | - return new ResponseEntity<>(pageInfo,HttpStatus.OK); | ||
| 531 | - } | ||
| 532 | - | ||
| 533 | - int toIndex = Math.min(page * count, treeData.size()); | ||
| 534 | - // 处理分页 | ||
| 535 | - List<BaseTree<DeviceChannel>> trees = treeData.subList((page - 1) * count, toIndex); | ||
| 536 | - PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 537 | - pageInfo.setPageNum(page); | ||
| 538 | - pageInfo.setTotal(treeData.size()); | ||
| 539 | - pageInfo.setSize(trees.size()); | ||
| 540 | - pageInfo.setList(trees); | ||
| 541 | - | ||
| 542 | - return new ResponseEntity<>(pageInfo,HttpStatus.OK); | ||
| 543 | - } | ||
| 544 | - | ||
| 545 | - /** | ||
| 546 | - * 查询国标树下的通道 | ||
| 547 | - * @param deviceId 设备ID | ||
| 548 | - * @param parentId 父ID | ||
| 549 | - * @param page 当前页 | ||
| 550 | - * @param count 每页条数 | ||
| 551 | - * @return 国标设备 | ||
| 552 | - */ | ||
| 553 | - @Operation(summary = "查询国标树下的通道") | ||
| 554 | - @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 555 | - @Parameter(name = "parentId", description = "父级国标编号") | ||
| 556 | - @Parameter(name = "page", description = "当前页", required = true) | ||
| 557 | - @Parameter(name = "count", description = "每页条数", required = true) | ||
| 558 | - @GetMapping("/tree/channel/{deviceId}") | ||
| 559 | - public ResponseEntity<PageInfo> getChannelInTreeNode(@PathVariable String deviceId, @RequestParam(required = false) String parentId, int page, int count){ | ||
| 560 | - | ||
| 561 | - if (page <= 0) { | ||
| 562 | - page = 1; | ||
| 563 | - } | ||
| 564 | - | ||
| 565 | - List<DeviceChannel> treeData = deviceService.queryVideoDeviceInTreeNode(deviceId, parentId); | ||
| 566 | - if (treeData == null || (page - 1) * count > treeData.size()) { | ||
| 567 | - PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 568 | - pageInfo.setPageNum(page); | ||
| 569 | - pageInfo.setTotal(treeData == null? 0 : treeData.size()); | ||
| 570 | - pageInfo.setSize(0); | ||
| 571 | - pageInfo.setList(new ArrayList<>()); | ||
| 572 | - return new ResponseEntity<>(pageInfo,HttpStatus.OK); | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - int toIndex = Math.min(page * count, treeData.size()); | ||
| 576 | - // 处理分页 | ||
| 577 | - List<DeviceChannel> trees = treeData.subList((page - 1) * count, toIndex); | ||
| 578 | - PageInfo<DeviceChannel> pageInfo = new PageInfo<>(); | ||
| 579 | - pageInfo.setPageNum(page); | ||
| 580 | - pageInfo.setTotal(treeData.size()); | ||
| 581 | - pageInfo.setSize(trees.size()); | ||
| 582 | - pageInfo.setList(trees); | ||
| 583 | - | ||
| 584 | - return new ResponseEntity<>(pageInfo,HttpStatus.OK); | ||
| 585 | - } | 117 | + return storager.queryVideoDeviceList(page, count, null); |
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 分页查询通道数 | ||
| 122 | + * | ||
| 123 | + * @param deviceId 设备id | ||
| 124 | + * @param page 当前页 | ||
| 125 | + * @param count 每页条数 | ||
| 126 | + * @param query 查询内容 | ||
| 127 | + * @param online 是否在线 在线 true / 离线 false | ||
| 128 | + * @param channelType 设备 false/子目录 true | ||
| 129 | + * @param catalogUnderDevice 是否直属与设备的目录 | ||
| 130 | + * @return 通道列表 | ||
| 131 | + */ | ||
| 132 | + @GetMapping("/devices/{deviceId}/channels") | ||
| 133 | + @Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 134 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 135 | + @Parameter(name = "page", description = "当前页", required = true) | ||
| 136 | + @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 137 | + @Parameter(name = "query", description = "查询内容") | ||
| 138 | + @Parameter(name = "online", description = "是否在线") | ||
| 139 | + @Parameter(name = "channelType", description = "设备/子目录-> false/true") | ||
| 140 | + @Parameter(name = "catalogUnderDevice", description = "是否直属与设备的目录") | ||
| 141 | + public PageInfo<DeviceChannel> channels(@PathVariable String deviceId, | ||
| 142 | + int page, int count, | ||
| 143 | + @RequestParam(required = false) String query, | ||
| 144 | + @RequestParam(required = false) String online, | ||
| 145 | + @RequestParam(required = false) Boolean channelType, | ||
| 146 | + @RequestParam(required = false) Boolean catalogUnderDevice) { | ||
| 147 | + if (ObjectUtils.isEmpty(query)) { | ||
| 148 | + query = null; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + Boolean onlineBoolean = null; | ||
| 152 | + if (StringUtils.equalsAnyIgnoreCase("true", online)) { | ||
| 153 | + onlineBoolean = true; | ||
| 154 | + } else if (StringUtils.equalsAnyIgnoreCase("false", online)) { | ||
| 155 | + onlineBoolean = false; | ||
| 156 | + } else if (StringUtils.equalsAnyIgnoreCase("the", online)) { | ||
| 157 | + page = 1; | ||
| 158 | + count = 10000; | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + PageInfo<DeviceChannel> pageInfo = storager.queryChannelsByDeviceId(deviceId, query, channelType, onlineBoolean, catalogUnderDevice, page, count); | ||
| 162 | + if (StringUtils.equalsAnyIgnoreCase("the", online) && Objects.nonNull(pageInfo) && CollectionUtils.isNotEmpty(pageInfo.getList())) { | ||
| 163 | + List<DeviceChannel> channels = pageInfo.getList().stream().filter(ch -> Objects.equals(ch.getChannelId(), "34020000001310000001") | ||
| 164 | + || Objects.equals(ch.getChannelId(), "34020000001310000002")).collect(Collectors.toList()); | ||
| 165 | + pageInfo.setList(channels); | ||
| 166 | + } | ||
| 167 | + return pageInfo; | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + /** | ||
| 171 | + * 同步设备通道 | ||
| 172 | + * | ||
| 173 | + * @param deviceId 设备id | ||
| 174 | + * @return | ||
| 175 | + */ | ||
| 176 | + @Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 177 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 178 | + @GetMapping("/devices/{deviceId}/sync") | ||
| 179 | + public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId) { | ||
| 180 | + | ||
| 181 | + if (logger.isDebugEnabled()) { | ||
| 182 | + logger.debug("设备通道信息同步API调用,deviceId:" + deviceId); | ||
| 183 | + } | ||
| 184 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 185 | + boolean status = deviceService.isSyncRunning(deviceId); | ||
| 186 | + // 已存在则返回进度 | ||
| 187 | + if (status) { | ||
| 188 | + SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId); | ||
| 189 | + return WVPResult.success(channelSyncStatus); | ||
| 190 | + } | ||
| 191 | + deviceService.sync(device); | ||
| 192 | + | ||
| 193 | + WVPResult<SyncStatus> wvpResult = new WVPResult<>(); | ||
| 194 | + wvpResult.setCode(0); | ||
| 195 | + wvpResult.setMsg("开始同步"); | ||
| 196 | + return wvpResult; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * 移除设备 | ||
| 201 | + * | ||
| 202 | + * @param deviceId 设备id | ||
| 203 | + * @return | ||
| 204 | + */ | ||
| 205 | + @Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 206 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 207 | + @DeleteMapping("/devices/{deviceId}/delete") | ||
| 208 | + public String delete(@PathVariable String deviceId) { | ||
| 209 | + | ||
| 210 | + if (logger.isDebugEnabled()) { | ||
| 211 | + logger.debug("设备信息删除API调用,deviceId:" + deviceId); | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + // 清除redis记录 | ||
| 215 | + boolean isSuccess = deviceService.delete(deviceId); | ||
| 216 | + if (isSuccess) { | ||
| 217 | + inviteStreamService.clearInviteInfo(deviceId); | ||
| 218 | + // 停止此设备的订阅更新 | ||
| 219 | + Set<String> allKeys = dynamicTask.getAllKeys(); | ||
| 220 | + for (String key : allKeys) { | ||
| 221 | + if (key.startsWith(deviceId)) { | ||
| 222 | + Runnable runnable = dynamicTask.get(key); | ||
| 223 | + if (runnable instanceof ISubscribeTask) { | ||
| 224 | + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; | ||
| 225 | + subscribeTask.stop(null); | ||
| 226 | + } | ||
| 227 | + dynamicTask.stop(key); | ||
| 228 | + } | ||
| 229 | + } | ||
| 230 | + JSONObject json = new JSONObject(); | ||
| 231 | + json.put("deviceId", deviceId); | ||
| 232 | + return json.toString(); | ||
| 233 | + } else { | ||
| 234 | + logger.warn("设备信息删除API调用失败!"); | ||
| 235 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备信息删除API调用失败!"); | ||
| 236 | + } | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + /** | ||
| 240 | + * 分页查询子目录通道 | ||
| 241 | + * | ||
| 242 | + * @param deviceId 通道id | ||
| 243 | + * @param channelId 通道id | ||
| 244 | + * @param page 当前页 | ||
| 245 | + * @param count 每页条数 | ||
| 246 | + * @param query 查询内容 | ||
| 247 | + * @param online 是否在线 | ||
| 248 | + * @param channelType 通道类型 | ||
| 249 | + * @return 子通道列表 | ||
| 250 | + */ | ||
| 251 | + @Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 252 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 253 | + @Parameter(name = "channelId", description = "通道国标编号", required = true) | ||
| 254 | + @Parameter(name = "page", description = "当前页", required = true) | ||
| 255 | + @Parameter(name = "count", description = "每页查询数量", required = true) | ||
| 256 | + @Parameter(name = "query", description = "查询内容") | ||
| 257 | + @Parameter(name = "online", description = "是否在线") | ||
| 258 | + @Parameter(name = "channelType", description = "设备/子目录-> false/true") | ||
| 259 | + @GetMapping("/sub_channels/{deviceId}/{channelId}/channels") | ||
| 260 | + public PageInfo<DeviceChannel> subChannels(@PathVariable String deviceId, | ||
| 261 | + @PathVariable String channelId, | ||
| 262 | + int page, | ||
| 263 | + int count, | ||
| 264 | + @RequestParam(required = false) String query, | ||
| 265 | + @RequestParam(required = false) Boolean online, | ||
| 266 | + @RequestParam(required = false) Boolean channelType) { | ||
| 267 | + | ||
| 268 | + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | ||
| 269 | + if (deviceChannel == null) { | ||
| 270 | + PageInfo<DeviceChannel> deviceChannelPageResult = new PageInfo<>(); | ||
| 271 | + return deviceChannelPageResult; | ||
| 272 | + } | ||
| 273 | + | ||
| 274 | + return storager.querySubChannels(deviceId, channelId, query, channelType, online, page, count); | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + /** | ||
| 278 | + * 更新通道信息 | ||
| 279 | + * | ||
| 280 | + * @param deviceId 设备id | ||
| 281 | + * @param channel 通道 | ||
| 282 | + * @return | ||
| 283 | + */ | ||
| 284 | + @Operation(summary = "更新通道信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 285 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 286 | + @Parameter(name = "channel", description = "通道信息", required = true) | ||
| 287 | + @PostMapping("/channel/update/{deviceId}") | ||
| 288 | + public void updateChannel(@PathVariable String deviceId, DeviceChannel channel) { | ||
| 289 | + deviceChannelService.updateChannel(deviceId, channel); | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + @Operation(summary = "修改通道的码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 293 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 294 | + @Parameter(name = "channel", description = "通道信息", required = true) | ||
| 295 | + @PostMapping("/channel/stream/identification/update/") | ||
| 296 | + public void updateChannelStreamIdentification(DeviceChannel channel) { | ||
| 297 | + deviceChannelService.updateChannelStreamIdentification(channel); | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + /** | ||
| 301 | + * 修改数据流传输模式 | ||
| 302 | + * | ||
| 303 | + * @param deviceId 设备id | ||
| 304 | + * @param streamMode 数据流传输模式 | ||
| 305 | + * @return | ||
| 306 | + */ | ||
| 307 | + @Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 308 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 309 | + @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" + | ||
| 310 | + "UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", required = true) | ||
| 311 | + @PostMapping("/transport/{deviceId}/{streamMode}") | ||
| 312 | + public void updateTransport(@PathVariable String deviceId, @PathVariable String streamMode) { | ||
| 313 | + Device device = deviceService.getDevice(deviceId); | ||
| 314 | + device.setStreamMode(streamMode); | ||
| 315 | + deviceService.updateCustomDevice(device); | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + /** | ||
| 319 | + * 添加设备信息 | ||
| 320 | + * | ||
| 321 | + * @param device 设备信息 | ||
| 322 | + * @return | ||
| 323 | + */ | ||
| 324 | + @Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 325 | + @Parameter(name = "device", description = "设备", required = true) | ||
| 326 | + @PostMapping("/device/add/") | ||
| 327 | + public void addDevice(Device device) { | ||
| 328 | + | ||
| 329 | + if (device == null || device.getDeviceId() == null) { | ||
| 330 | + throw new ControllerException(ErrorCode.ERROR400); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + // 查看deviceId是否存在 | ||
| 334 | + boolean exist = deviceService.isExist(device.getDeviceId()); | ||
| 335 | + if (exist) { | ||
| 336 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备编号已存在"); | ||
| 337 | + } | ||
| 338 | + deviceService.addDevice(device); | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + /** | ||
| 342 | + * 更新设备信息 | ||
| 343 | + * | ||
| 344 | + * @param device 设备信息 | ||
| 345 | + * @return | ||
| 346 | + */ | ||
| 347 | + @Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 348 | + @Parameter(name = "device", description = "设备", required = true) | ||
| 349 | + @PostMapping("/device/update/") | ||
| 350 | + public void updateDevice(Device device) { | ||
| 351 | + | ||
| 352 | + if (device != null && device.getDeviceId() != null) { | ||
| 353 | + deviceService.updateCustomDevice(device); | ||
| 354 | + } | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + /** | ||
| 358 | + * 设备状态查询请求API接口 | ||
| 359 | + * | ||
| 360 | + * @param deviceId 设备id | ||
| 361 | + */ | ||
| 362 | + @Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 363 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 364 | + @GetMapping("/devices/{deviceId}/status") | ||
| 365 | + public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) { | ||
| 366 | + if (logger.isDebugEnabled()) { | ||
| 367 | + logger.debug("设备状态查询API调用"); | ||
| 368 | + } | ||
| 369 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 370 | + String uuid = UUID.randomUUID().toString(); | ||
| 371 | + String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId; | ||
| 372 | + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2 * 1000L); | ||
| 373 | + if (device == null) { | ||
| 374 | + result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId), HttpStatus.OK)); | ||
| 375 | + return result; | ||
| 376 | + } | ||
| 377 | + try { | ||
| 378 | + cmder.deviceStatusQuery(device, event -> { | ||
| 379 | + RequestMessage msg = new RequestMessage(); | ||
| 380 | + msg.setId(uuid); | ||
| 381 | + msg.setKey(key); | ||
| 382 | + msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg)); | ||
| 383 | + resultHolder.invokeResult(msg); | ||
| 384 | + }); | ||
| 385 | + } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 386 | + logger.error("[命令发送失败] 获取设备状态: {}", e.getMessage()); | ||
| 387 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 388 | + } | ||
| 389 | + result.onTimeout(() -> { | ||
| 390 | + logger.warn(String.format("获取设备状态超时")); | ||
| 391 | + // 释放rtpserver | ||
| 392 | + RequestMessage msg = new RequestMessage(); | ||
| 393 | + msg.setId(uuid); | ||
| 394 | + msg.setKey(key); | ||
| 395 | + msg.setData("Timeout. Device did not response to this command."); | ||
| 396 | + resultHolder.invokeResult(msg); | ||
| 397 | + }); | ||
| 398 | + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, uuid, result); | ||
| 399 | + return result; | ||
| 400 | + } | ||
| 401 | + | ||
| 402 | + /** | ||
| 403 | + * 设备报警查询请求API接口 | ||
| 404 | + * | ||
| 405 | + * @param deviceId 设备id | ||
| 406 | + * @param startPriority 报警起始级别(可选) | ||
| 407 | + * @param endPriority 报警终止级别(可选) | ||
| 408 | + * @param alarmMethod 报警方式条件(可选) | ||
| 409 | + * @param alarmType 报警类型 | ||
| 410 | + * @param startTime 报警发生起始时间(可选) | ||
| 411 | + * @param endTime 报警发生终止时间(可选) | ||
| 412 | + * @return true = 命令发送成功 | ||
| 413 | + */ | ||
| 414 | + @Operation(summary = "设备报警查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 415 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 416 | + @Parameter(name = "startPriority", description = "报警起始级别") | ||
| 417 | + @Parameter(name = "endPriority", description = "报警终止级别") | ||
| 418 | + @Parameter(name = "alarmMethod", description = "报警方式条件") | ||
| 419 | + @Parameter(name = "alarmType", description = "报警类型") | ||
| 420 | + @Parameter(name = "startTime", description = "报警发生起始时间") | ||
| 421 | + @Parameter(name = "endTime", description = "报警发生终止时间") | ||
| 422 | + @GetMapping("/alarm/{deviceId}") | ||
| 423 | + public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId, | ||
| 424 | + @RequestParam(required = false) String startPriority, | ||
| 425 | + @RequestParam(required = false) String endPriority, | ||
| 426 | + @RequestParam(required = false) String alarmMethod, | ||
| 427 | + @RequestParam(required = false) String alarmType, | ||
| 428 | + @RequestParam(required = false) String startTime, | ||
| 429 | + @RequestParam(required = false) String endTime) { | ||
| 430 | + if (logger.isDebugEnabled()) { | ||
| 431 | + logger.debug("设备报警查询API调用"); | ||
| 432 | + } | ||
| 433 | + Device device = storager.queryVideoDevice(deviceId); | ||
| 434 | + String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; | ||
| 435 | + String uuid = UUID.randomUUID().toString(); | ||
| 436 | + try { | ||
| 437 | + cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> { | ||
| 438 | + RequestMessage msg = new RequestMessage(); | ||
| 439 | + msg.setId(uuid); | ||
| 440 | + msg.setKey(key); | ||
| 441 | + msg.setData(String.format("设备报警查询失败,错误码: %s, %s", event.statusCode, event.msg)); | ||
| 442 | + resultHolder.invokeResult(msg); | ||
| 443 | + }); | ||
| 444 | + } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 445 | + logger.error("[命令发送失败] 设备报警查询: {}", e.getMessage()); | ||
| 446 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 447 | + } | ||
| 448 | + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L); | ||
| 449 | + result.onTimeout(() -> { | ||
| 450 | + logger.warn(String.format("设备报警查询超时")); | ||
| 451 | + // 释放rtpserver | ||
| 452 | + RequestMessage msg = new RequestMessage(); | ||
| 453 | + msg.setId(uuid); | ||
| 454 | + msg.setKey(key); | ||
| 455 | + msg.setData("设备报警查询超时"); | ||
| 456 | + resultHolder.invokeResult(msg); | ||
| 457 | + }); | ||
| 458 | + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, uuid, result); | ||
| 459 | + return result; | ||
| 460 | + } | ||
| 461 | + | ||
| 462 | + | ||
| 463 | + @GetMapping("/{deviceId}/sync_status") | ||
| 464 | + @Operation(summary = "获取通道同步进度", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 465 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 466 | + public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) { | ||
| 467 | + SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId); | ||
| 468 | + WVPResult<SyncStatus> wvpResult = new WVPResult<>(); | ||
| 469 | + if (channelSyncStatus == null) { | ||
| 470 | + wvpResult.setCode(-1); | ||
| 471 | + wvpResult.setMsg("同步尚未开始"); | ||
| 472 | + } else { | ||
| 473 | + wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 474 | + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 475 | + wvpResult.setData(channelSyncStatus); | ||
| 476 | + if (channelSyncStatus.getErrorMsg() != null) { | ||
| 477 | + wvpResult.setMsg(channelSyncStatus.getErrorMsg()); | ||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + return wvpResult; | ||
| 481 | + } | ||
| 482 | + | ||
| 483 | + @GetMapping("/{deviceId}/subscribe_info") | ||
| 484 | + @Operation(summary = "获取设备的订阅状态", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ||
| 485 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 486 | + public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) { | ||
| 487 | + Set<String> allKeys = dynamicTask.getAllKeys(); | ||
| 488 | + Map<String, Integer> dialogStateMap = new HashMap<>(); | ||
| 489 | + for (String key : allKeys) { | ||
| 490 | + if (key.startsWith(deviceId)) { | ||
| 491 | + ISubscribeTask subscribeTask = (ISubscribeTask) dynamicTask.get(key); | ||
| 492 | + if (subscribeTask instanceof CatalogSubscribeTask) { | ||
| 493 | + dialogStateMap.put("catalog", 1); | ||
| 494 | + } else if (subscribeTask instanceof MobilePositionSubscribeTask) { | ||
| 495 | + dialogStateMap.put("mobilePosition", 1); | ||
| 496 | + } | ||
| 497 | + } | ||
| 498 | + } | ||
| 499 | + WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>(); | ||
| 500 | + wvpResult.setCode(0); | ||
| 501 | + wvpResult.setData(dialogStateMap); | ||
| 502 | + return wvpResult; | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + @GetMapping("/snap/{deviceId}/{channelId}") | ||
| 506 | + @Operation(summary = "请求截图") | ||
| 507 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 508 | + @Parameter(name = "channelId", description = "通道国标编号", required = true) | ||
| 509 | + @Parameter(name = "mark", description = "标识", required = false) | ||
| 510 | + public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId, @RequestParam(required = false) String mark) { | ||
| 511 | + | ||
| 512 | + try { | ||
| 513 | + final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + (mark == null ? ".jpg" : ("_" + mark + ".jpg"))).toPath()); | ||
| 514 | + resp.setContentType(MediaType.IMAGE_PNG_VALUE); | ||
| 515 | + ServletOutputStream outputStream = resp.getOutputStream(); | ||
| 516 | + IOUtils.copy(in, resp.getOutputStream()); | ||
| 517 | + in.close(); | ||
| 518 | + outputStream.close(); | ||
| 519 | + } catch (IOException e) { | ||
| 520 | + resp.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||
| 521 | + } | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + /** | ||
| 525 | + * 查询国标树 | ||
| 526 | + * | ||
| 527 | + * @param deviceId 设备ID | ||
| 528 | + * @param parentId 父ID | ||
| 529 | + * @param page 当前页 | ||
| 530 | + * @param count 每页条数 | ||
| 531 | + * @return 国标设备 | ||
| 532 | + */ | ||
| 533 | + @Operation(summary = "查询国标树") | ||
| 534 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 535 | + @Parameter(name = "parentId", description = "父级国标编号") | ||
| 536 | + @Parameter(name = "onlyCatalog", description = "只获取目录") | ||
| 537 | + @Parameter(name = "page", description = "当前页", required = true) | ||
| 538 | + @Parameter(name = "count", description = "每页条数", required = true) | ||
| 539 | + @GetMapping("/tree/{deviceId}") | ||
| 540 | + public ResponseEntity<PageInfo> getTree(@PathVariable String deviceId, | ||
| 541 | + @RequestParam(required = false) String parentId, | ||
| 542 | + @RequestParam(required = false) Boolean onlyCatalog, | ||
| 543 | + int page, int count) { | ||
| 544 | + | ||
| 545 | + | ||
| 546 | + if (page <= 0) { | ||
| 547 | + page = 1; | ||
| 548 | + } | ||
| 549 | + if (onlyCatalog == null) { | ||
| 550 | + onlyCatalog = false; | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + List<BaseTree<DeviceChannel>> treeData = deviceService.queryVideoDeviceTree(deviceId, parentId, onlyCatalog); | ||
| 554 | + if (treeData == null || (page - 1) * count > treeData.size()) { | ||
| 555 | + PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 556 | + pageInfo.setPageNum(page); | ||
| 557 | + pageInfo.setTotal(treeData == null ? 0 : treeData.size()); | ||
| 558 | + pageInfo.setSize(0); | ||
| 559 | + pageInfo.setList(new ArrayList<>()); | ||
| 560 | + return new ResponseEntity<>(pageInfo, HttpStatus.OK); | ||
| 561 | + } | ||
| 562 | + | ||
| 563 | + int toIndex = Math.min(page * count, treeData.size()); | ||
| 564 | + // 处理分页 | ||
| 565 | + List<BaseTree<DeviceChannel>> trees = treeData.subList((page - 1) * count, toIndex); | ||
| 566 | + PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 567 | + pageInfo.setPageNum(page); | ||
| 568 | + pageInfo.setTotal(treeData.size()); | ||
| 569 | + pageInfo.setSize(trees.size()); | ||
| 570 | + pageInfo.setList(trees); | ||
| 571 | + | ||
| 572 | + return new ResponseEntity<>(pageInfo, HttpStatus.OK); | ||
| 573 | + } | ||
| 574 | + | ||
| 575 | + /** | ||
| 576 | + * 查询国标树下的通道 | ||
| 577 | + * | ||
| 578 | + * @param deviceId 设备ID | ||
| 579 | + * @param parentId 父ID | ||
| 580 | + * @param page 当前页 | ||
| 581 | + * @param count 每页条数 | ||
| 582 | + * @return 国标设备 | ||
| 583 | + */ | ||
| 584 | + @Operation(summary = "查询国标树下的通道") | ||
| 585 | + @Parameter(name = "deviceId", description = "设备国标编号", required = true) | ||
| 586 | + @Parameter(name = "parentId", description = "父级国标编号") | ||
| 587 | + @Parameter(name = "page", description = "当前页", required = true) | ||
| 588 | + @Parameter(name = "count", description = "每页条数", required = true) | ||
| 589 | + @GetMapping("/tree/channel/{deviceId}") | ||
| 590 | + public ResponseEntity<PageInfo> getChannelInTreeNode(@PathVariable String deviceId, @RequestParam(required = false) String parentId, int page, int count) { | ||
| 591 | + | ||
| 592 | + if (page <= 0) { | ||
| 593 | + page = 1; | ||
| 594 | + } | ||
| 595 | + | ||
| 596 | + List<DeviceChannel> treeData = deviceService.queryVideoDeviceInTreeNode(deviceId, parentId); | ||
| 597 | + if (treeData == null || (page - 1) * count > treeData.size()) { | ||
| 598 | + PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>(); | ||
| 599 | + pageInfo.setPageNum(page); | ||
| 600 | + pageInfo.setTotal(treeData == null ? 0 : treeData.size()); | ||
| 601 | + pageInfo.setSize(0); | ||
| 602 | + pageInfo.setList(new ArrayList<>()); | ||
| 603 | + return new ResponseEntity<>(pageInfo, HttpStatus.OK); | ||
| 604 | + } | ||
| 605 | + | ||
| 606 | + int toIndex = Math.min(page * count, treeData.size()); | ||
| 607 | + // 处理分页 | ||
| 608 | + List<DeviceChannel> trees = treeData.subList((page - 1) * count, toIndex); | ||
| 609 | + PageInfo<DeviceChannel> pageInfo = new PageInfo<>(); | ||
| 610 | + pageInfo.setPageNum(page); | ||
| 611 | + pageInfo.setTotal(treeData.size()); | ||
| 612 | + pageInfo.setSize(trees.size()); | ||
| 613 | + pageInfo.setList(trees); | ||
| 614 | + | ||
| 615 | + return new ResponseEntity<>(pageInfo, HttpStatus.OK); | ||
| 616 | + } | ||
| 586 | } | 617 | } |
src/main/resources/application-local.yml
| @@ -17,9 +17,9 @@ spring: | @@ -17,9 +17,9 @@ spring: | ||
| 17 | # [必须修改] 端口号 | 17 | # [必须修改] 端口号 |
| 18 | port: 6379 | 18 | port: 6379 |
| 19 | # [可选] 数据库 DB | 19 | # [可选] 数据库 DB |
| 20 | - database: 7 | 20 | + database: 8 |
| 21 | # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 | 21 | # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 |
| 22 | -# password: guzijian | 22 | + # password: guzijian |
| 23 | # [可选] 超时时间 | 23 | # [可选] 超时时间 |
| 24 | timeout: 10000 | 24 | timeout: 10000 |
| 25 | # mysql数据源 | 25 | # mysql数据源 |
| @@ -30,7 +30,7 @@ spring: | @@ -30,7 +30,7 @@ spring: | ||
| 30 | master: | 30 | master: |
| 31 | type: com.zaxxer.hikari.HikariDataSource | 31 | type: com.zaxxer.hikari.HikariDataSource |
| 32 | driver-class-name: com.mysql.cj.jdbc.Driver | 32 | driver-class-name: com.mysql.cj.jdbc.Driver |
| 33 | - url: jdbc:mysql://127.0.0.1:3306/latest_wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true | 33 | + url: jdbc:mysql://192.168.169.100:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true |
| 34 | username: root | 34 | username: root |
| 35 | password: guzijian | 35 | password: guzijian |
| 36 | hikari: | 36 | hikari: |
| @@ -60,9 +60,10 @@ sip: | @@ -60,9 +60,10 @@ sip: | ||
| 60 | # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | 60 | # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 |
| 61 | # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | 61 | # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 |
| 62 | # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | 62 | # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 |
| 63 | - ip: 192.169.1.31 | 63 | + ip: 0.0.0.0 |
| 64 | # [可选] 28181服务监听的端口 | 64 | # [可选] 28181服务监听的端口 |
| 65 | port: 5060 | 65 | port: 5060 |
| 66 | + | ||
| 66 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) | 67 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) |
| 67 | # 后两位为行业编码,定义参照附录D.3 | 68 | # 后两位为行业编码,定义参照附录D.3 |
| 68 | # 3701020049标识山东济南历下区 信息行业接入 | 69 | # 3701020049标识山东济南历下区 信息行业接入 |
| @@ -77,29 +78,29 @@ sip: | @@ -77,29 +78,29 @@ sip: | ||
| 77 | 78 | ||
| 78 | #zlm 默认服务器配置 | 79 | #zlm 默认服务器配置 |
| 79 | media: | 80 | media: |
| 80 | - id: cQ5byeSBKP2INt6l | 81 | + id: guzijian1 |
| 81 | # [必须修改] zlm服务器的内网IP | 82 | # [必须修改] zlm服务器的内网IP |
| 82 | - ip: 192.169.1.31 | 83 | + ip: 192.168.169.100 |
| 83 | # [必须修改] zlm服务器的http.port | 84 | # [必须修改] zlm服务器的http.port |
| 84 | - http-port: 80 | 85 | + http-port: 1091 |
| 85 | # [可选] 返回流地址时的ip,置空使用 media.ip | 86 | # [可选] 返回流地址时的ip,置空使用 media.ip |
| 86 | - stream-ip: 192.169.1.31 | 87 | + stream-ip: 192.168.169.100 |
| 87 | # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip | 88 | # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip |
| 88 | - sdp-ip: 192.169.1.31 | 89 | + sdp-ip: 192.168.169.100 |
| 89 | # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip | 90 | # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip |
| 90 | - hook-ip: 192.169.1.31 | 91 | + hook-ip: 192.168.169.100 |
| 91 | # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置 | 92 | # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置 |
| 92 | http-ssl-port: 443 | 93 | http-ssl-port: 443 |
| 93 | # [可选] zlm服务器的hook.admin_params=secret | 94 | # [可选] zlm服务器的hook.admin_params=secret |
| 94 | - secret: ZLh24VioqaKqxiihBJ80ny60NuWpVe62 | 95 | + secret: RPorcBlIw26uHGnEHYGesIYyFDXpgjkP1 |
| 95 | # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 | 96 | # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 |
| 96 | rtp: | 97 | rtp: |
| 97 | # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 | 98 | # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 |
| 98 | enable: true | 99 | enable: true |
| 99 | # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 | 100 | # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 |
| 100 | - port-range: 50000,50300 # 端口范围 | 101 | + port-range: 60000,60300 # 端口范围 |
| 101 | # [可选] 国标级联在此范围内选择端口发送媒体流, | 102 | # [可选] 国标级联在此范围内选择端口发送媒体流, |
| 102 | - send-port-range: 50000,50300 # 端口范围 | 103 | + send-port-range: 60000,60300 # 端口范围 |
| 103 | # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 | 104 | # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 |
| 104 | record-assist-port: 18081 | 105 | record-assist-port: 18081 |
| 105 | # [根据业务需求配置] | 106 | # [根据业务需求配置] |
| @@ -111,17 +112,13 @@ user-settings: | @@ -111,17 +112,13 @@ user-settings: | ||
| 111 | # 设备/通道状态变化时发送消息 | 112 | # 设备/通道状态变化时发送消息 |
| 112 | device-status-notify: true | 113 | device-status-notify: true |
| 113 | # 推流直播是否录制 | 114 | # 推流直播是否录制 |
| 114 | -# record-push-live: true | 115 | + # record-push-live: true |
| 115 | # 是否开启接口鉴权 | 116 | # 是否开启接口鉴权 |
| 116 | -# interface-authentication: false | 117 | + # interface-authentication: false |
| 117 | # 国标是否录制 | 118 | # 国标是否录制 |
| 118 | -# record-sip: true | 119 | + # record-sip: true |
| 119 | # 等待音视频编码信息再返回, true: 可以根据编码选择合适的播放器,false: 可以更快点播 | 120 | # 等待音视频编码信息再返回, true: 可以根据编码选择合适的播放器,false: 可以更快点播 |
| 120 | # wait-track: true | 121 | # wait-track: true |
| 121 | # [可选] 日志配置, 一般不需要改 | 122 | # [可选] 日志配置, 一般不需要改 |
| 122 | logging: | 123 | logging: |
| 123 | - config: classpath:logback-spring.xml | ||
| 124 | -#mybatis: | ||
| 125 | -# configuration: | ||
| 126 | -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | ||
| 127 | - | 124 | + config: classpath:logback-spring.xml |
| 128 | \ No newline at end of file | 125 | \ No newline at end of file |
web_src/config/index.js
| @@ -11,7 +11,7 @@ module.exports = { | @@ -11,7 +11,7 @@ module.exports = { | ||
| 11 | assetsPublicPath: "/", | 11 | assetsPublicPath: "/", |
| 12 | proxyTable: { | 12 | proxyTable: { |
| 13 | "/debug": { | 13 | "/debug": { |
| 14 | - target: "http://61.169.120.202:18089", | 14 | + target: "http://127.0.0.1:18080", |
| 15 | changeOrigin: true, | 15 | changeOrigin: true, |
| 16 | pathRewrite: { | 16 | pathRewrite: { |
| 17 | "^/debug": "/", | 17 | "^/debug": "/", |
web_src/src/components/channelList.vue
| @@ -25,6 +25,7 @@ | @@ -25,6 +25,7 @@ | ||
| 25 | <el-option label="全部" value=""></el-option> | 25 | <el-option label="全部" value=""></el-option> |
| 26 | <el-option label="在线" value="true"></el-option> | 26 | <el-option label="在线" value="true"></el-option> |
| 27 | <el-option label="离线" value="false"></el-option> | 27 | <el-option label="离线" value="false"></el-option> |
| 28 | + <el-option label="特定通道" value="the"></el-option> | ||
| 28 | </el-select> | 29 | </el-select> |
| 29 | 码流类型重置: | 30 | 码流类型重置: |
| 30 | <el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream" | 31 | <el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream" |
| @@ -242,7 +243,7 @@ export default { | @@ -242,7 +243,7 @@ export default { | ||
| 242 | updateLooper: 0, //数据刷新轮训标志 | 243 | updateLooper: 0, //数据刷新轮训标志 |
| 243 | searchSrt: "", | 244 | searchSrt: "", |
| 244 | channelType: "", | 245 | channelType: "", |
| 245 | - online: "", | 246 | + online: "the", |
| 246 | subStream: "", | 247 | subStream: "", |
| 247 | winHeight: window.innerHeight - 200, | 248 | winHeight: window.innerHeight - 200, |
| 248 | currentPage: 1, | 249 | currentPage: 1, |