|
|
@@ -0,0 +1,194 @@
|
|
|
+package cn.iocoder.yudao.module.pms.hik;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class HikIsapiService {
|
|
|
+
|
|
|
+ private final HikHttpClient httpClient;
|
|
|
+ private final HikvisionProperties properties;
|
|
|
+ private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ private final AlarmEventService alarmEventService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订阅事件通知
|
|
|
+ */
|
|
|
+ public String subscribeEvents(String deviceId) throws IOException {
|
|
|
+ HikvisionProperties.IsapiConfig.DeviceConfig device = getDeviceConfig(deviceId);
|
|
|
+ String url = device.getBaseUrl() + device.getPaths().getEventNotification();
|
|
|
+
|
|
|
+ // 构建JSON订阅请求
|
|
|
+ Map<String, Object> subscribeRequest = buildSubscribeRequest(deviceId);
|
|
|
+ String jsonRequest = objectMapper.writeValueAsString(subscribeRequest);
|
|
|
+
|
|
|
+ log.info("订阅事件通知: deviceId={}, url={}", deviceId, url);
|
|
|
+
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+
|
|
|
+ String response = httpClient.doPost(url, jsonRequest,
|
|
|
+ device.getUsername(), device.getPassword(),
|
|
|
+ device.getTimeout(), headers);
|
|
|
+
|
|
|
+ log.info("订阅成功: deviceId={}, response={}", deviceId, response);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建订阅JSON
|
|
|
+ */
|
|
|
+ private Map<String, Object> buildSubscribeRequest(String deviceId) {
|
|
|
+ Map<String, Object> request = new HashMap<>();
|
|
|
+ request.put("method", "Event.notification");
|
|
|
+ request.put("id", UUID.randomUUID().toString());
|
|
|
+
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
+ params.put("protocol", "json");
|
|
|
+
|
|
|
+ // 回调地址配置
|
|
|
+ HikvisionProperties.IsapiConfig.CallbackConfig callback =
|
|
|
+ properties.getIsapi().getCallback();
|
|
|
+
|
|
|
+ if (callback != null && callback.getEnabled()) {
|
|
|
+ Map<String, Object> httpHost = new HashMap<>();
|
|
|
+ httpHost.put("url", callback.getLocalUrl());
|
|
|
+ httpHost.put("method", "POST");
|
|
|
+ httpHost.put("timeout", 10);
|
|
|
+ httpHost.put("contentType", "application/json");
|
|
|
+
|
|
|
+ Map<String, Object> notification = new HashMap<>();
|
|
|
+ notification.put("httpHost", httpHost);
|
|
|
+ notification.put("heartbeatInterval",
|
|
|
+ properties.getIsapi().getDevices().stream()
|
|
|
+ .filter(d -> d.getId().equals(deviceId))
|
|
|
+ .findFirst()
|
|
|
+ .map(d -> d.getSubscription().getHeartbeatInterval())
|
|
|
+ .orElse(30));
|
|
|
+
|
|
|
+ params.put("notification", notification);
|
|
|
+ }
|
|
|
+
|
|
|
+ request.put("params", params);
|
|
|
+ return request;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取消订阅
|
|
|
+ */
|
|
|
+ public String unsubscribeEvents(String deviceId) throws IOException {
|
|
|
+ HikvisionProperties.IsapiConfig.DeviceConfig device = getDeviceConfig(deviceId);
|
|
|
+ String url = device.getBaseUrl() + device.getPaths().getEventNotification();
|
|
|
+
|
|
|
+ Map<String, Object> unsubscribeRequest = new HashMap<>();
|
|
|
+ unsubscribeRequest.put("method", "Event.unsubscribe");
|
|
|
+ unsubscribeRequest.put("id", UUID.randomUUID().toString());
|
|
|
+
|
|
|
+ String jsonRequest = objectMapper.writeValueAsString(unsubscribeRequest);
|
|
|
+
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+
|
|
|
+ return httpClient.doPost(url, jsonRequest,
|
|
|
+ device.getUsername(), device.getPassword(),
|
|
|
+ device.getTimeout(), headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取设备信息
|
|
|
+ */
|
|
|
+ public String getDeviceInfo(String deviceId) throws IOException {
|
|
|
+ HikvisionProperties.IsapiConfig.DeviceConfig device = getDeviceConfig(deviceId);
|
|
|
+ String url = device.getBaseUrl() + device.getPaths().getDeviceInfo();
|
|
|
+
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+
|
|
|
+ return httpClient.doGet(url,
|
|
|
+ device.getUsername(), device.getPassword(),
|
|
|
+ device.getTimeout(), headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理告警回调
|
|
|
+ */
|
|
|
+ public void handleAlarmCallback(String jsonPayload) {
|
|
|
+ try {
|
|
|
+ log.info("收到告警回调: {}", jsonPayload);
|
|
|
+
|
|
|
+ // 解析JSON
|
|
|
+ IsapiAlarmEvent alarmEvent = objectMapper.readValue(
|
|
|
+ jsonPayload, IsapiAlarmEvent.class);
|
|
|
+
|
|
|
+ // 转换为DTO
|
|
|
+// AlarmEventDTO dto = convertToDTO(alarmEvent);
|
|
|
+
|
|
|
+ // 保存到数据库
|
|
|
+// alarmEventService.saveAlarmEvent(dto);
|
|
|
+
|
|
|
+ // 触发告警处理流程
|
|
|
+// alarmEventService.processAlarmEvent(dto);
|
|
|
+
|
|
|
+
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ log.error("JSON解析失败: {}", jsonPayload, e);
|
|
|
+ throw new RuntimeException("JSON解析失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换告警事件
|
|
|
+ */
|
|
|
+// private AlarmEventDTO convertToDTO(IsapiAlarmEvent alarmEvent) {
|
|
|
+// AlarmEventDTO dto = new AlarmEventDTO();
|
|
|
+//
|
|
|
+// if (alarmEvent.getParams() != null) {
|
|
|
+// dto.setEventId(alarmEvent.getParams().getEventID());
|
|
|
+// dto.setDeviceId(alarmEvent.getParams().getDeviceID());
|
|
|
+// dto.setDeviceName(alarmEvent.getParams().getDeviceName());
|
|
|
+// dto.setChannelId(alarmEvent.getParams().getChannelID());
|
|
|
+// dto.setChannelName(alarmEvent.getParams().getChannelName());
|
|
|
+// dto.setEventType(alarmEvent.getParams().getEventType());
|
|
|
+// dto.setEventDescription(alarmEvent.getParams().getEventDescription());
|
|
|
+// dto.setEventTime(alarmEvent.getParams().getDateTime());
|
|
|
+// dto.setEventState(alarmEvent.getParams().getEventState());
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (alarmEvent.getParams() != null &&
|
|
|
+// alarmEvent.getParams().getData() != null &&
|
|
|
+// alarmEvent.getParams().getData().getAlarmEvent() != null &&
|
|
|
+// alarmEvent.getParams().getData().getAlarmEvent().getEventList() != null &&
|
|
|
+// alarmEvent.getParams().getData().getAlarmEvent().getEventList().getEvent() != null &&
|
|
|
+// !alarmEvent.getParams().getData().getAlarmEvent().getEventList().getEvent().isEmpty()) {
|
|
|
+//
|
|
|
+// IsapiAlarmEvent.EventData.AlarmEvent.EventList.Event event =
|
|
|
+// alarmEvent.getParams().getData().getAlarmEvent().getEventList().getEvent().get(0);
|
|
|
+//
|
|
|
+// dto.setConfidenceLevel(event.getConfidenceLevel());
|
|
|
+// dto.setRegionCoordinates(event.getRegionCoordinates());
|
|
|
+// dto.setTargetCoordinates(event.getTargetCoordinates());
|
|
|
+// dto.setImageUrl(event.getImageURL());
|
|
|
+// dto.setVideoUrl(event.getVideoURL());
|
|
|
+// }
|
|
|
+//
|
|
|
+// return dto;
|
|
|
+// }
|
|
|
+
|
|
|
+ private HikvisionProperties.IsapiConfig.DeviceConfig getDeviceConfig(String deviceId) {
|
|
|
+ return properties.getIsapi().getDevices().stream()
|
|
|
+ .filter(d -> d.getId().equals(deviceId))
|
|
|
+ .findFirst()
|
|
|
+ .orElseThrow(() -> new IllegalArgumentException("设备不存在: " + deviceId));
|
|
|
+ }
|
|
|
+}
|