PtzController.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. package com.genersoft.iot.vmp.gb28181.controller;
  2. import com.genersoft.iot.vmp.conf.exception.ControllerException;
  3. import com.genersoft.iot.vmp.conf.security.JwtUtils;
  4. import com.genersoft.iot.vmp.gb28181.bean.Device;
  5. import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
  6. import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  7. import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  8. import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  9. import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
  10. import io.swagger.v3.oas.annotations.Operation;
  11. import io.swagger.v3.oas.annotations.Parameter;
  12. import io.swagger.v3.oas.annotations.security.SecurityRequirement;
  13. import io.swagger.v3.oas.annotations.tags.Tag;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.util.ObjectUtils;
  17. import org.springframework.web.bind.annotation.*;
  18. import org.springframework.web.context.request.async.DeferredResult;
  19. import javax.sip.InvalidArgumentException;
  20. import javax.sip.SipException;
  21. import java.text.ParseException;
  22. import java.util.UUID;
  23. @Tag(name = "前端设备控制")
  24. @Slf4j
  25. @RestController
  26. @RequestMapping("/api/front-end")
  27. public class PtzController {
  28. @Autowired
  29. private SIPCommander cmder;
  30. @Autowired
  31. private IDeviceService deviceService;
  32. @Autowired
  33. private DeferredResultHolder resultHolder;
  34. @Operation(summary = "通用前端控制命令(参考国标文档A.3.1指令格式)", security = @SecurityRequirement(name = JwtUtils.HEADER))
  35. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  36. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  37. @Parameter(name = "cmdCode", description = "指令码(对应国标文档指令格式中的字节4)", required = true)
  38. @Parameter(name = "parameter1", description = "数据一(对应国标文档指令格式中的字节5, 范围0-255)", required = true)
  39. @Parameter(name = "parameter2", description = "数据二(对应国标文档指令格式中的字节6, 范围0-255)", required = true)
  40. @Parameter(name = "combindCode2", description = "组合码二(对应国标文档指令格式中的字节7, 范围0-16)", required = true)
  41. @GetMapping("/common/{deviceId}/{channelId}")
  42. public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2){
  43. if (log.isDebugEnabled()) {
  44. log.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d parameter1:%d parameter2:%d",deviceId, channelId, cmdCode, parameter1, parameter2));
  45. }
  46. Device device = deviceService.getDeviceByDeviceId(deviceId);
  47. if (parameter1 == null || parameter1 < 0 || parameter1 > 255) {
  48. throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
  49. }
  50. if (parameter2 == null || parameter2 < 0 || parameter2 > 255) {
  51. throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
  52. }
  53. if (combindCode2 == null || combindCode2 < 0 || combindCode2 > 16) {
  54. throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
  55. }
  56. try {
  57. cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
  58. } catch (SipException | InvalidArgumentException | ParseException e) {
  59. log.error("[命令发送失败] 前端控制: {}", e.getMessage());
  60. throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  61. }
  62. }
  63. @Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
  64. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  65. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  66. @Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
  67. @Parameter(name = "horizonSpeed", description = "水平速度(0-255)", required = true)
  68. @Parameter(name = "verticalSpeed", description = "垂直速度(0-255)", required = true)
  69. @Parameter(name = "zoomSpeed", description = "缩放速度(0-16)", required = true)
  70. @GetMapping("/ptz/{deviceId}/{channelId}")
  71. public void ptz(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed){
  72. if (log.isDebugEnabled()) {
  73. log.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,command:%s ,horizonSpeed:%d ,verticalSpeed:%d ,zoomSpeed:%d",deviceId, channelId, command, horizonSpeed, verticalSpeed, zoomSpeed));
  74. }
  75. if (horizonSpeed == null) {
  76. horizonSpeed = 100;
  77. }else if (horizonSpeed < 0 || horizonSpeed > 255) {
  78. throw new ControllerException(ErrorCode.ERROR100.getCode(), "horizonSpeed 为 1-255的数字");
  79. }
  80. if (verticalSpeed == null) {
  81. verticalSpeed = 100;
  82. }else if (verticalSpeed < 0 || verticalSpeed > 255) {
  83. throw new ControllerException(ErrorCode.ERROR100.getCode(), "verticalSpeed 为 1-255的数字");
  84. }
  85. if (zoomSpeed == null) {
  86. zoomSpeed = 16;
  87. }else if (zoomSpeed < 0 || zoomSpeed > 16) {
  88. throw new ControllerException(ErrorCode.ERROR100.getCode(), "zoomSpeed 为 1-255的数字");
  89. }
  90. int cmdCode = 0;
  91. switch (command){
  92. case "left":
  93. cmdCode = 2;
  94. break;
  95. case "right":
  96. cmdCode = 1;
  97. break;
  98. case "up":
  99. cmdCode = 8;
  100. break;
  101. case "down":
  102. cmdCode = 4;
  103. break;
  104. case "upleft":
  105. cmdCode = 10;
  106. break;
  107. case "upright":
  108. cmdCode = 9;
  109. break;
  110. case "downleft":
  111. cmdCode = 6;
  112. break;
  113. case "downright":
  114. cmdCode = 5;
  115. break;
  116. case "zoomin":
  117. cmdCode = 16;
  118. break;
  119. case "zoomout":
  120. cmdCode = 32;
  121. break;
  122. case "stop":
  123. horizonSpeed = 0;
  124. verticalSpeed = 0;
  125. zoomSpeed = 0;
  126. break;
  127. default:
  128. break;
  129. }
  130. frontEndCommand(deviceId, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
  131. }
  132. @Operation(summary = "光圈控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
  133. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  134. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  135. @Parameter(name = "command", description = "控制指令,允许值: in, out, stop", required = true)
  136. @Parameter(name = "speed", description = "光圈速度(0-255)", required = true)
  137. @GetMapping("/fi/iris/{deviceId}/{channelId}")
  138. public void iris(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer speed){
  139. if (log.isDebugEnabled()) {
  140. log.debug("设备光圈控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",deviceId, channelId, command, speed);
  141. }
  142. int cmdCode = 0x40;
  143. switch (command){
  144. case "in":
  145. cmdCode = 0x44;
  146. break;
  147. case "out":
  148. cmdCode = 0x48;
  149. break;
  150. case "stop":
  151. speed = 0;
  152. break;
  153. default:
  154. break;
  155. }
  156. frontEndCommand(deviceId, channelId, cmdCode, 0, speed, 0);
  157. }
  158. @Operation(summary = "聚焦控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
  159. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  160. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  161. @Parameter(name = "command", description = "控制指令,允许值: near, far, stop", required = true)
  162. @Parameter(name = "speed", description = "聚焦速度(0-255)", required = true)
  163. @GetMapping("/fi/focus/{deviceId}/{channelId}")
  164. public void focus(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer speed){
  165. if (log.isDebugEnabled()) {
  166. log.debug("设备聚焦控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",deviceId, channelId, command, speed);
  167. }
  168. if (speed == null) {
  169. speed = 100;
  170. }else if (speed < 0 || speed > 255) {
  171. throw new ControllerException(ErrorCode.ERROR100.getCode(), "verticalSpeed 为 1-255的数字");
  172. }
  173. int cmdCode = 0x40;
  174. switch (command){
  175. case "near":
  176. cmdCode = 0x42;
  177. break;
  178. case "far":
  179. cmdCode = 0x41;
  180. break;
  181. case "stop":
  182. speed = 0;
  183. break;
  184. default:
  185. break;
  186. }
  187. frontEndCommand(deviceId, channelId, cmdCode, speed, 0, 0);
  188. }
  189. @Operation(summary = "查询预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
  190. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  191. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  192. @GetMapping("/preset/query/{deviceId}/{channelId}")
  193. public DeferredResult<String> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) {
  194. if (log.isDebugEnabled()) {
  195. log.debug("设备预置位查询API调用");
  196. }
  197. Device device = deviceService.getDeviceByDeviceId(deviceId);
  198. String uuid = UUID.randomUUID().toString();
  199. String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
  200. DeferredResult<String> result = new DeferredResult<String> (3 * 1000L);
  201. result.onTimeout(()->{
  202. log.warn(String.format("获取设备预置位超时"));
  203. // 释放rtpserver
  204. RequestMessage msg = new RequestMessage();
  205. msg.setId(uuid);
  206. msg.setKey(key);
  207. msg.setData("获取设备预置位超时");
  208. resultHolder.invokeResult(msg);
  209. });
  210. if (resultHolder.exist(key, null)) {
  211. return result;
  212. }
  213. resultHolder.put(key, uuid, result);
  214. try {
  215. cmder.presetQuery(device, channelId, event -> {
  216. RequestMessage msg = new RequestMessage();
  217. msg.setId(uuid);
  218. msg.setKey(key);
  219. msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
  220. resultHolder.invokeResult(msg);
  221. });
  222. } catch (InvalidArgumentException | SipException | ParseException e) {
  223. log.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
  224. throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  225. }
  226. return result;
  227. }
  228. @Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
  229. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  230. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  231. @Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
  232. @GetMapping("/preset/add/{deviceId}/{channelId}")
  233. public void addPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
  234. if (presetId == null || presetId < 1 || presetId > 255) {
  235. throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
  236. }
  237. frontEndCommand(deviceId, channelId, 0x81, 1, presetId, 0);
  238. }
  239. @Operation(summary = "预置位指令-调用预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
  240. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  241. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  242. @Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
  243. @GetMapping("/preset/call/{deviceId}/{channelId}")
  244. public void callPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
  245. if (presetId == null || presetId < 1 || presetId > 255) {
  246. throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
  247. }
  248. frontEndCommand(deviceId, channelId, 0x82, 1, presetId, 0);
  249. }
  250. @Operation(summary = "预置位指令-删除预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
  251. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  252. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  253. @Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
  254. @GetMapping("/preset/delete/{deviceId}/{channelId}")
  255. public void deletePreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
  256. if (presetId == null || presetId < 1 || presetId > 255) {
  257. throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
  258. }
  259. frontEndCommand(deviceId, channelId, 0x83, 1, presetId, 0);
  260. }
  261. @Operation(summary = "巡航指令-加入巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
  262. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  263. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  264. @Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
  265. @Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
  266. @GetMapping("/cruise/point/add/{deviceId}/{channelId}")
  267. public void addCruisePoint(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer presetId) {
  268. if (presetId == null || cruiseId == null || presetId < 1 || presetId > 255 || cruiseId < 0 || cruiseId > 255) {
  269. throw new ControllerException(ErrorCode.ERROR100.getCode(), "编号必须为1-255之间的数字");
  270. }
  271. frontEndCommand(deviceId, channelId, 0x84, cruiseId, presetId, 0);
  272. }
  273. @Operation(summary = "巡航指令-删除一个巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
  274. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  275. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  276. @Parameter(name = "cruiseId", description = "巡航组号(1-255)", required = true)
  277. @Parameter(name = "presetId", description = "预置位编号(0-255, 为0时删除整个巡航)", required = true)
  278. @GetMapping("/cruise/point/delete/{deviceId}/{channelId}")
  279. public void deleteCruisePoint(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer presetId) {
  280. if (presetId == null || presetId < 0 || presetId > 255) {
  281. throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为0-255之间的数字, 为0时删除整个巡航");
  282. }
  283. if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
  284. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
  285. }
  286. frontEndCommand(deviceId, channelId, 0x85, cruiseId, presetId, 0);
  287. }
  288. @Operation(summary = "巡航指令-设置巡航速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
  289. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  290. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  291. @Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
  292. @Parameter(name = "speed", description = "巡航速度(1-4095)", required = true)
  293. @GetMapping("/cruise/speed/{deviceId}/{channelId}")
  294. public void setCruiseSpeed(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer speed) {
  295. if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
  296. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
  297. }
  298. if (speed == null || speed < 1 || speed > 4095) {
  299. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航速度必须为1-4095之间的数字");
  300. }
  301. int parameter2 = speed & 0xFF;
  302. int combindCode2 = speed >> 8;
  303. frontEndCommand(deviceId, channelId, 0x86, cruiseId, parameter2, combindCode2);
  304. }
  305. @Operation(summary = "巡航指令-设置巡航停留时间", security = @SecurityRequirement(name = JwtUtils.HEADER))
  306. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  307. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  308. @Parameter(name = "cruiseId", description = "巡航组号", required = true)
  309. @Parameter(name = "time", description = "巡航停留时间(1-4095)", required = true)
  310. @GetMapping("/cruise/time/{deviceId}/{channelId}")
  311. public void setCruiseTime(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer time) {
  312. if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
  313. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
  314. }
  315. if (time == null || time < 1 || time > 4095) {
  316. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航停留时间必须为1-4095之间的数字");
  317. }
  318. int parameter2 = time & 0xFF;
  319. int combindCode2 = time >> 8;
  320. frontEndCommand(deviceId, channelId, 0x87, cruiseId, parameter2, combindCode2);
  321. }
  322. @Operation(summary = "巡航指令-开始巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
  323. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  324. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  325. @Parameter(name = "cruiseId", description = "巡航组号)", required = true)
  326. @GetMapping("/cruise/start/{deviceId}/{channelId}")
  327. public void startCruise(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId) {
  328. if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
  329. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
  330. }
  331. frontEndCommand(deviceId, channelId, 0x88, cruiseId, 0, 0);
  332. }
  333. @Operation(summary = "巡航指令-停止巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
  334. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  335. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  336. @Parameter(name = "cruiseId", description = "巡航组号", required = true)
  337. @GetMapping("/cruise/stop/{deviceId}/{channelId}")
  338. public void stopCruise(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId) {
  339. if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
  340. throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
  341. }
  342. frontEndCommand(deviceId, channelId, 0, 0, 0, 0);
  343. }
  344. @Operation(summary = "扫描指令-开始自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
  345. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  346. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  347. @Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
  348. @GetMapping("/scan/start/{deviceId}/{channelId}")
  349. public void startScan(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
  350. if (scanId == null || scanId < 0 || scanId > 255 ) {
  351. throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
  352. }
  353. frontEndCommand(deviceId, channelId, 0x89, scanId, 0, 0);
  354. }
  355. @Operation(summary = "扫描指令-停止自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
  356. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  357. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  358. @Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
  359. @GetMapping("/scan/stop/{deviceId}/{channelId}")
  360. public void stopScan(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
  361. if (scanId == null || scanId < 0 || scanId > 255 ) {
  362. throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
  363. }
  364. frontEndCommand(deviceId, channelId, 0, 0, 0, 0);
  365. }
  366. @Operation(summary = "扫描指令-设置自动扫描左边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
  367. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  368. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  369. @Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
  370. @GetMapping("/scan/set/left/{deviceId}/{channelId}")
  371. public void setScanLeft(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
  372. if (scanId == null || scanId < 0 || scanId > 255 ) {
  373. throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
  374. }
  375. frontEndCommand(deviceId, channelId, 0x89, scanId, 1, 0);
  376. }
  377. @Operation(summary = "扫描指令-设置自动扫描右边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
  378. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  379. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  380. @Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
  381. @GetMapping("/scan/set/right/{deviceId}/{channelId}")
  382. public void setScanRight(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
  383. if (scanId == null || scanId < 0 || scanId > 255 ) {
  384. throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
  385. }
  386. frontEndCommand(deviceId, channelId, 0x89, scanId, 2, 0);
  387. }
  388. @Operation(summary = "扫描指令-设置自动扫描速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
  389. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  390. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  391. @Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
  392. @Parameter(name = "speed", description = "自动扫描速度(1-4095)", required = true)
  393. @GetMapping("/scan/set/speed/{deviceId}/{channelId}")
  394. public void setScanSpeed(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId, Integer speed) {
  395. if (scanId == null || scanId < 0 || scanId > 255 ) {
  396. throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
  397. }
  398. if (speed == null || speed < 1 || speed > 4095) {
  399. throw new ControllerException(ErrorCode.ERROR100.getCode(), "自动扫描速度必须为1-4095之间的数字");
  400. }
  401. int parameter2 = speed & 0xFF;
  402. int combindCode2 = speed >> 8;
  403. frontEndCommand(deviceId, channelId, 0x8A, scanId, parameter2, combindCode2);
  404. }
  405. @Operation(summary = "辅助开关控制指令-雨刷控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
  406. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  407. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  408. @Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
  409. @GetMapping("/wiper/{deviceId}/{channelId}")
  410. public void wiper(@PathVariable String deviceId,@PathVariable String channelId, String command){
  411. if (log.isDebugEnabled()) {
  412. log.debug("辅助开关控制指令-雨刷控制 API调用,deviceId:{} ,channelId:{} ,command:{}",deviceId, channelId, command);
  413. }
  414. int cmdCode = 0;
  415. switch (command){
  416. case "on":
  417. cmdCode = 0x8c;
  418. break;
  419. case "off":
  420. cmdCode = 0x8d;
  421. break;
  422. default:
  423. break;
  424. }
  425. frontEndCommand(deviceId, channelId, cmdCode, 1, 0, 0);
  426. }
  427. @Operation(summary = "辅助开关控制指令", security = @SecurityRequirement(name = JwtUtils.HEADER))
  428. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  429. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  430. @Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
  431. @Parameter(name = "switchId", description = "开关编号", required = true)
  432. @GetMapping("/auxiliary/{deviceId}/{channelId}")
  433. public void auxiliarySwitch(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer switchId){
  434. if (log.isDebugEnabled()) {
  435. log.debug("辅助开关控制指令-雨刷控制 API调用,deviceId:{} ,channelId:{} ,command:{}, switchId: {}",deviceId, channelId, command, switchId);
  436. }
  437. int cmdCode = 0;
  438. switch (command){
  439. case "on":
  440. cmdCode = 0x8c;
  441. break;
  442. case "off":
  443. cmdCode = 0x8d;
  444. break;
  445. default:
  446. break;
  447. }
  448. frontEndCommand(deviceId, channelId, cmdCode, switchId, 0, 0);
  449. }
  450. }