liusuyi
2026-06-01 a2e7e8ff9cfaa69b001d483710bddbda50d55c91
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package com.ard.gb28181.transmit.event.request.impl.message.response.cmd;
 
import com.ard.gb28181.config.SipConfig;
import com.ard.gb28181.api.domain.Device;
import com.ard.gb28181.api.domain.DeviceChannel;
import com.ard.gb28181.api.domain.GbCode;
import com.ard.gb28181.api.domain.HandlerCatchData;
import com.ard.gb28181.service.IDeviceChannelService;
import com.ard.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.ard.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.ard.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.ard.gb28181.utils.Coordtransform;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
 
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
 
/**
 * 目录查询的回复
 */
@Slf4j
@Component
public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
    private final String cmdType = "Catalog";
 
    @Autowired
    private ResponseMessageHandler responseMessageHandler;
 
    @Autowired
    private SipConfig sipConfig;
 
    @Autowired
    private IDeviceChannelService deviceChannelService;
 
    private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
 
    @Override
    public void afterPropertiesSet() throws Exception {
        responseMessageHandler.addHandler(cmdType, this);
    }
 
    @Override
    public void handForDevice(RequestEvent evt, Device device, Element element) {
        taskQueue.offer(new HandlerCatchData(evt, device, element));
        // 回复200 OK
        try {
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            log.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
        }
    }
 
    @Scheduled(fixedDelay = 500)
    @Transactional
    public void executeTaskQueue() {
        if (taskQueue.isEmpty()) {
            return;
        }
        List<HandlerCatchData> handlerCatchDataList = new ArrayList<>();
        int size = taskQueue.size();
        for (int i = 0; i < size; i++) {
            HandlerCatchData poll = taskQueue.poll();
            if (poll != null) {
                handlerCatchDataList.add(poll);
            }
        }
        if (handlerCatchDataList.isEmpty()) {
            return;
        }
        for (HandlerCatchData take : handlerCatchDataList) {
            if (take == null) {
                continue;
            }
            RequestEvent evt = take.getEvt();
            int sn = 0;
            // 全局异常捕获,保证下一条可以得到处理
            try {
                Element rootElement = null;
                try {
                    rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
                } catch (DocumentException e) {
                    log.error("[xml解析] 失败: ", e);
                    continue;
                }
                if (rootElement == null) {
                    log.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
                    continue;
                }
                Element deviceListElement = rootElement.element("DeviceList");
                Element sumNumElement = rootElement.element("SumNum");
                Element snElement = rootElement.element("SN");
 
                sn = Integer.parseInt(snElement.getText());
                int sumNum = Integer.parseInt(sumNumElement.getText());
 
                if (sumNum == 0) {
                    log.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
                    // 数据已经完整接收
                    deviceChannelService.cleanChannelsForDevice(take.getDevice().getDeviceId());
                    return;
                } else {
                    Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
                    if (deviceListIterator != null) {
                        List<DeviceChannel> channelList = new ArrayList<>();
                        // 遍历DeviceList
                        while (deviceListIterator.hasNext()) {
                            Element itemDevice = deviceListIterator.next();
                            Element channelDeviceElement = itemDevice.element("DeviceID");
                            if (channelDeviceElement == null) {
                                // 总数减一, 避免最后总数不对 无法确定问题
                                continue;
                            }
                            // 从xml解析内容到 DeviceChannel 对象
                            DeviceChannel channel = DeviceChannel.decode(itemDevice);
                            if (channel.getDeviceId() == null) {
                                log.info("[收到目录订阅]:但是解析失败 {}", new String(evt.getRequest().getRawContent()));
                                continue;
                            }
                            channel.setDataDeviceId(take.getDevice().getId());
                            if (channel.getParentId() != null && channel.getParentId().equals(sipConfig.getId())) {
                                channel.setParentId(null);
                            }
 
                            // 解析通道类型
                            if (channel.getDeviceId().length() <= 8) {
                                // 行政区划
                                channel.setChannelType(1);
                            } else if (channel.getDeviceId().length() == 20) {
                                GbCode gbCode = GbCode.decode(channel.getDeviceId());
                                if (gbCode != null && ("215".equals(gbCode.getTypeCode()) || "216".equals(gbCode.getTypeCode()))) {
                                    // 业务分组/虚拟组织
                                    channel.setParental(1);
                                    channel.setChannelType(2);
                                }
                                // 坐标转换(所有20位编码通道,含普通摄像头和业务分组)
                                if (channel.getLongitude() != null && channel.getLatitude() != null && channel.getLongitude() > 0 && channel.getLatitude() > 0) {
                                    Double[] wgs84Position = Coordtransform.GCJ02ToWGS84(channel.getLongitude(), channel.getLatitude());
                                    channel.setGbLongitude(wgs84Position[0]);
                                    channel.setGbLatitude(wgs84Position[1]);
                                }
                            }
                            channelList.add(channel);
                        }
                        deviceChannelService.updateChannels(take.getDevice(), channelList);
//                        deviceChannelService.updateChannels(take.getDevice(), regionList);
//                        deviceChannelService.updateChannels(take.getDevice(), groupList);
                        log.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), sn, sumNum);
                    }
                }
            } catch (Exception e) {
                log.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest());
                log.error("[收到通道] 异常内容: ", e);
            }
        }
    }
}