|
|
@@ -1,22 +1,23 @@
|
|
|
package cn.iocoder.yudao.module.pms.hik;
|
|
|
|
|
|
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
|
-import cn.iocoder.yudao.module.pms.controller.admin.alarm.vo.IotVideoAlarmRespVO;
|
|
|
import cn.iocoder.yudao.module.pms.controller.admin.alarm.vo.IotVideoAlarmSaveReqVO;
|
|
|
-import cn.iocoder.yudao.module.pms.dal.dataobject.alarm.IotVideoAlarmDO;
|
|
|
+import cn.iocoder.yudao.module.pms.controller.admin.yanfan.utils.XmlUtil;
|
|
|
import cn.iocoder.yudao.module.pms.service.alarm.IotVideoAlarmService;
|
|
|
-import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import lombok.Data;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.dom4j.Document;
|
|
|
+import org.dom4j.Element;
|
|
|
+import org.dom4j.QName;
|
|
|
+import org.dom4j.io.SAXReader;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
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;
|
|
|
+import java.io.StringReader;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -51,7 +52,25 @@ public class HikIsapiService {
|
|
|
log.info("订阅成功: deviceId={}, response={}", deviceId, response);
|
|
|
return response;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取sip信息
|
|
|
+ * @param deviceId
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public String getSipInfo(String deviceId) throws IOException {
|
|
|
+ HikvisionProperties.IsapiConfig.DeviceConfig device = getDeviceConfig(deviceId);
|
|
|
+ String url = device.getBaseUrl() + device.getPaths().getSipInfo();
|
|
|
+
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+
|
|
|
+ String response = httpClient.doGet(url, device.getUsername(), device.getPassword(),
|
|
|
+ device.getTimeout(), headers);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 构建订阅JSON
|
|
|
*/
|
|
|
@@ -139,12 +158,22 @@ public class HikIsapiService {
|
|
|
jsonPayload, IotVideoAlarmSaveReqVO.class);
|
|
|
//安全帽检测与抽烟打电话
|
|
|
if ("safetyHelmetDetection".equals(alarmEvent.getEventType()) || "抽烟打电话".equals(alarmEvent.getMpName())) {
|
|
|
+ //调用sip获取是哪个业务通道
|
|
|
+ String sipInfo = getSipInfo("nvr-001");
|
|
|
+ List<VideoInput> videoInputs = parseVideoInputList(sipInfo);
|
|
|
+ AtomicReference<String> businessChannelId = new AtomicReference<>();
|
|
|
+ videoInputs.stream().filter(e -> String.valueOf(e.getId()).equals(alarmEvent.getChannelId())).findFirst().ifPresent(e -> {
|
|
|
+ businessChannelId.set(e.getVideoInputID());
|
|
|
+ });
|
|
|
+ if (businessChannelId.get() != null) {
|
|
|
+ alarmEvent.setBusinessChannel(businessChannelId.get());
|
|
|
+ }
|
|
|
// 保存到数据库
|
|
|
iotVideoAlarmService.createIotVideoAlarm(alarmEvent);
|
|
|
// 触发告警处理流程
|
|
|
alarmEventService.processAlarmEvent(alarmEvent);
|
|
|
}
|
|
|
- } catch (JsonProcessingException e) {
|
|
|
+ } catch (Exception e) {
|
|
|
log.error("JSON解析失败: {}", jsonPayload, e);
|
|
|
throw new RuntimeException("JSON解析失败", e);
|
|
|
}
|
|
|
@@ -194,4 +223,48 @@ public class HikIsapiService {
|
|
|
.findFirst()
|
|
|
.orElseThrow(() -> new IllegalArgumentException("设备不存在: " + deviceId));
|
|
|
}
|
|
|
+
|
|
|
+ private List<VideoInput> parseVideoInputList(String xmlStr) {
|
|
|
+ List<VideoInput> videoInputList = new ArrayList<>();
|
|
|
+ SAXReader reader = new SAXReader();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 读取 XML 字符串为 Document 对象
|
|
|
+ Document document = reader.read(new StringReader(xmlStr));
|
|
|
+ // 获取根节点(SIPInfo)
|
|
|
+ Element root = document.getRootElement();
|
|
|
+
|
|
|
+ // 1. 找到 VideoInputList 节点(带命名空间)
|
|
|
+ Element videoInputListElement = root.element(QName.get("VideoInputList", "http://www.isapi.org/ver20/XMLSchema"));
|
|
|
+ if (videoInputListElement == null) {
|
|
|
+ return videoInputList;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 遍历所有 VideoInput 子节点
|
|
|
+ Iterator<Element> videoInputIter = videoInputListElement.elementIterator(QName.get("VideoInput", "http://www.isapi.org/ver20/XMLSchema"));
|
|
|
+ while (videoInputIter.hasNext()) {
|
|
|
+ Element videoInputElement = videoInputIter.next();
|
|
|
+
|
|
|
+ // 3. 提取 id 和 videoInputID
|
|
|
+ Integer id = Integer.parseInt(videoInputElement.elementText(QName.get("id", "http://www.isapi.org/ver20/XMLSchema")));
|
|
|
+ // 空标签(<videoInputID/>)会返回空字符串,需处理
|
|
|
+ String videoInputID = videoInputElement.elementText(QName.get("videoInputID", "http://www.isapi.org/ver20/XMLSchema")).trim();
|
|
|
+
|
|
|
+ // 4. 封装为 VideoInput 对象(可直接用 Map 替代,无需实体类)
|
|
|
+ VideoInput input = new VideoInput();
|
|
|
+ input.setId(id);
|
|
|
+ input.setVideoInputID(videoInputID.isEmpty() ? null : videoInputID);
|
|
|
+
|
|
|
+ videoInputList.add(input);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("XML解析失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ return videoInputList;
|
|
|
+ }
|
|
|
+ @Data
|
|
|
+ public static class VideoInput {
|
|
|
+ private Integer id;
|
|
|
+ private String videoInputID;
|
|
|
+ }
|
|
|
}
|