|
|
@@ -0,0 +1,206 @@
|
|
|
+package com.its.cctv.api.service;
|
|
|
+
|
|
|
+import com.its.app.utils.ByteUtils;
|
|
|
+import com.its.cctv.api.dto.CctvPresetControlDto;
|
|
|
+import com.its.cctv.api.dto.CctvPtzControlDto;
|
|
|
+import com.its.cctv.api.dto.CctvStatusDto;
|
|
|
+import com.its.cctv.domain.NET;
|
|
|
+import com.its.cctv.entity.TbCctvCtlr;
|
|
|
+import com.its.cctv.global.AppRepository;
|
|
|
+import com.its.cctv.xnettcp.cctv.protocol.CctvReqPresetMove;
|
|
|
+import com.its.cctv.xnettcp.cctv.protocol.CctvReqPresetQry;
|
|
|
+import com.its.cctv.xnettcp.cctv.protocol.CctvReqPtzCtrl;
|
|
|
+import lombok.Getter;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.Setter;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.nio.ByteBuffer;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.NoSuchElementException;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Service
|
|
|
+public class CctvControlService {
|
|
|
+
|
|
|
+ Map<String, ControlCmd> ptzControlMap = new HashMap<>();
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ void init() {
|
|
|
+ this.ptzControlMap.put("zoom-in", new ControlCmd((byte)0, (byte)0, (byte)1, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, "Zoom In"));
|
|
|
+ this.ptzControlMap.put("zoom-out", new ControlCmd((byte)0, (byte)0, (byte)2, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, "Zoom Out"));
|
|
|
+ this.ptzControlMap.put("focus-in", new ControlCmd((byte)0, (byte)0, (byte)0, (byte)1, (byte)0, (byte)0, (byte)0, (byte)0xFE, "Focus Near"));
|
|
|
+ this.ptzControlMap.put("focus-out", new ControlCmd((byte)0, (byte)0, (byte)0, (byte)2, (byte)0, (byte)0, (byte)0, (byte)0xFE, "Focus Far"));
|
|
|
+ this.ptzControlMap.put("pan-left", new ControlCmd((byte)1, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, (byte)0, (byte)0, "Pan Left"));
|
|
|
+ this.ptzControlMap.put("pan-right", new ControlCmd((byte)2, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, (byte)0, (byte)0, "Pan Right"));
|
|
|
+ this.ptzControlMap.put("tilt-up", new ControlCmd((byte)0, (byte)1, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, (byte)0, "Tilt Up"));
|
|
|
+ this.ptzControlMap.put("tilt-down", new ControlCmd((byte)0, (byte)2, (byte)0, (byte)0, (byte)0, (byte)0xFE, (byte)0, (byte)0, "Tilt Down"));
|
|
|
+ this.ptzControlMap.put("up-left", new ControlCmd((byte)1, (byte)1, (byte)0, (byte)0, (byte)0xFE, (byte)0xFE, (byte)0, (byte)0, "Pan Tilt Left Up"));
|
|
|
+ this.ptzControlMap.put("up-right", new ControlCmd((byte)2, (byte)1, (byte)0, (byte)0, (byte)0xFE, (byte)0xFE, (byte)0, (byte)0, "Pan Tilt Right Up"));
|
|
|
+ this.ptzControlMap.put("down-left", new ControlCmd((byte)1, (byte)2, (byte)0, (byte)0, (byte)0xFE, (byte)0xFE, (byte)0, (byte)0, "Pan Tilt Left Down"));
|
|
|
+ this.ptzControlMap.put("down-right", new ControlCmd((byte)2, (byte)2, (byte)0, (byte)0, (byte)0xFE, (byte)0xFE, (byte)0, (byte)0, "Pan Tilt Right Down"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ @Setter
|
|
|
+ public static class ControlCmd {
|
|
|
+ byte pan;
|
|
|
+ byte tilt;
|
|
|
+ byte zoom;
|
|
|
+ byte focus;
|
|
|
+ byte panSped;
|
|
|
+ byte tiltSped;
|
|
|
+ byte zoomSped;
|
|
|
+ byte focusSped;
|
|
|
+ String cmdDesc;
|
|
|
+ public ControlCmd(byte pan, byte tilt, byte zoom, byte focus, byte panSped, byte tiltSped, byte zoomSped, byte focusSped, String cmdDesc) {
|
|
|
+ this.pan = pan;
|
|
|
+ this.tilt = tilt;
|
|
|
+ this.zoom = zoom;
|
|
|
+ this.focus = focus;
|
|
|
+ this.panSped = panSped;
|
|
|
+ this.tiltSped = tiltSped;
|
|
|
+ this.zoomSped = zoomSped;
|
|
|
+ this.focusSped = focusSped;
|
|
|
+ this.cmdDesc = cmdDesc;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 데이터 1건 조회, 없으면 exception
|
|
|
+ private TbCctvCtlr requireOne(Long id) throws NoSuchElementException {
|
|
|
+ return AppRepository.getInstance().getCtlrMap().get(String.valueOf(id));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * CCTV 상태정보 요청 처리
|
|
|
+ * @param id
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public CctvStatusDto.CctvStatusDtoRes requestStatus(Long id) {
|
|
|
+ TbCctvCtlr cctv = this.requireOne(id);
|
|
|
+ if (cctv == null) {
|
|
|
+ return new CctvStatusDto.CctvStatusDtoRes(1, "알수없는 CCTV 관리번호 입니다.", null);
|
|
|
+ }
|
|
|
+ if (cctv.getNetState() != NET.LOGINED) {
|
|
|
+ return new CctvStatusDto.CctvStatusDtoRes(2, "CCTV 통신연결이 되어 있지 않습니다.", null);
|
|
|
+ }
|
|
|
+
|
|
|
+ CctvStatusDto.CctvStatusDtoRes result = new CctvStatusDto.CctvStatusDtoRes(0, "success", cctv.getStts().toDto());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * CCTV PTZ 컨트롤
|
|
|
+ * @param id
|
|
|
+ * @param req
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public CctvPtzControlDto.CctvPtzControlRes controlPtz(Long id, CctvPtzControlDto.CctvControlPtzReq req) {
|
|
|
+ log.info("{}", req);
|
|
|
+ TbCctvCtlr cctv = this.requireOne(id);
|
|
|
+ if (cctv == null) {
|
|
|
+ return new CctvPtzControlDto.CctvPtzControlRes(req.getCommand(), req.getAction(), 1, "알수없는 CCTV 관리번호 입니다.");
|
|
|
+ }
|
|
|
+ if (cctv.getNetState() != NET.LOGINED) {
|
|
|
+ return new CctvPtzControlDto.CctvPtzControlRes(req.getCommand(), req.getAction(), 2, "CCTV 통신연결이 되어 있지 않습니다.");
|
|
|
+ }
|
|
|
+
|
|
|
+ ControlCmd command = this.ptzControlMap.get(req.getCommand());
|
|
|
+ if (command == null) {
|
|
|
+ return new CctvPtzControlDto.CctvPtzControlRes(req.getCommand(), req.getAction(), 3, "CCTV PTZ 명령이 잘못 되었습니다.");
|
|
|
+ }
|
|
|
+
|
|
|
+ CctvPtzControlDto.CctvPtzControlRes result = new CctvPtzControlDto.CctvPtzControlRes(req.getCommand(), req.getAction(), 0, "success");
|
|
|
+ String cmdDesc = command.getCmdDesc();
|
|
|
+ if (StringUtils.equalsIgnoreCase("start", req.getAction())) {
|
|
|
+ byte speed = req.getSpeed().byteValue();
|
|
|
+ byte pan = command.getPan();
|
|
|
+ byte tilt = command.getTilt();
|
|
|
+ byte zoom = command.getZoom();
|
|
|
+ byte focus = command.getFocus();
|
|
|
+ byte panSped = (byte)Math.min(command.getPanSped(), speed);
|
|
|
+ byte tiltSped = (byte)Math.min(command.getTiltSped(), speed);
|
|
|
+ byte zoomSped = (byte)Math.min(command.getZoomSped(), speed);
|
|
|
+ byte focusSped = (byte)Math.min(command.getFocusSped(), speed);
|
|
|
+ CctvReqPtzCtrl pkt = new CctvReqPtzCtrl(cctv.getAddress());
|
|
|
+ byte ptz = pkt.setPtzValue((byte) pan, (byte) tilt, (byte) zoom, (byte) focus, (byte) panSped, (byte) tiltSped, (byte) zoomSped, (byte) focusSped);
|
|
|
+ log.info("PTZ Control: " + ByteUtils.byteToBitString(ptz));
|
|
|
+ ByteBuffer sendBuffer = pkt.getByteBuffer();
|
|
|
+ if (cctv.sendData(sendBuffer, 0, "cctv_StateReq")) {
|
|
|
+ log.info("{} send success.", cmdDesc);
|
|
|
+ } else {
|
|
|
+ result.setResult(4, "CCTV PTZ 시작 명령 전송이 실패하였습니다.");
|
|
|
+ log.error("{} send failed.", cmdDesc);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // stop
|
|
|
+ CctvReqPtzCtrl pkt = new CctvReqPtzCtrl(cctv.getAddress());
|
|
|
+ ByteBuffer sendBuffer = pkt.getByteBuffer();
|
|
|
+ if (cctv.sendData(sendBuffer, 0, "cctv_StateReq")) {
|
|
|
+ log.info("{} STOP send success.", cmdDesc);
|
|
|
+ } else {
|
|
|
+ result.setResult(4, "CCTV PTZ 정지 명령 전송이 실패하였습니다.");
|
|
|
+ log.error("{} STOP send failed.", cmdDesc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * CCTV Preset 컨트롤
|
|
|
+ * @param id
|
|
|
+ * @param req
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public CctvPresetControlDto.CctvPresetControlRes controlPreset(Long id, CctvPresetControlDto.CctvPresetControlReq req) {
|
|
|
+ log.info("{}", req);
|
|
|
+ TbCctvCtlr cctv = this.requireOne(id);
|
|
|
+ if (cctv == null) {
|
|
|
+ return new CctvPresetControlDto.CctvPresetControlRes(1, "unknown cctv type");
|
|
|
+ }
|
|
|
+ if (cctv.getNetState() != NET.LOGINED) {
|
|
|
+ return new CctvPresetControlDto.CctvPresetControlRes(2, "CCTV 통신연결이 되어 있지 않습니다.");
|
|
|
+ }
|
|
|
+
|
|
|
+ CctvPresetControlDto.CctvPresetControlRes result = new CctvPresetControlDto.CctvPresetControlRes(0, "success");
|
|
|
+ CctvReqPresetMove pkt = new CctvReqPresetMove(cctv.getAddress());
|
|
|
+ pkt.setValue(req.getPan().shortValue(), req.getTilt().shortValue(), req.getZoom().shortValue(), req.getFocus().shortValue());
|
|
|
+ ByteBuffer sendBuffer = pkt.getByteBuffer();
|
|
|
+ if (cctv.sendData(sendBuffer, 0, "cctv_PresetMove")) {
|
|
|
+ log.info("PRESET send success.");
|
|
|
+ } else {
|
|
|
+ result.setResult(4, "CCTV PRESET 명령 전송이 실패하였습니다.");
|
|
|
+ log.error("PRESET send failed.");
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CctvPresetControlDto.CctvPresetValueRes requestPresetValue(Long id) {
|
|
|
+ log.info("{}", id);
|
|
|
+ TbCctvCtlr cctv = this.requireOne(id);
|
|
|
+ if (cctv == null) {
|
|
|
+ return new CctvPresetControlDto.CctvPresetValueRes(1, "unknown cctv type");
|
|
|
+ }
|
|
|
+ if (cctv.getNetState() != NET.LOGINED) {
|
|
|
+ return new CctvPresetControlDto.CctvPresetValueRes(2, "CCTV 통신연결이 되어 있지 않습니다.");
|
|
|
+ }
|
|
|
+
|
|
|
+ CctvPresetControlDto.CctvPresetValueRes result = new CctvPresetControlDto.CctvPresetValueRes(0, "success");
|
|
|
+ CctvReqPresetQry pkt = new CctvReqPresetQry(cctv.getAddress());
|
|
|
+ pkt.setValue((byte)0x00);
|
|
|
+ ByteBuffer sendBuffer = pkt.getByteBuffer();
|
|
|
+ if (cctv.sendData(sendBuffer, 0, "cctv_PresetQry")) {
|
|
|
+ log.info("PRESET QRY send success.");
|
|
|
+ } else {
|
|
|
+ result.setResult(4, "CCTV PRESET 값조회 명령 전송이 실패하였습니다.");
|
|
|
+ log.error("PRESET QRY send failed.");
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|