|  |  | 
 |  |  | import java.text.ParseException;
 | 
 |  |  | import java.util.*;
 | 
 |  |  | 
 | 
 |  |  | import javax.sip.address.SipURI;
 | 
 |  |  | 
 | 
 |  |  | import javax.sip.header.FromHeader;
 | 
 |  |  | import javax.sip.header.HeaderAddress;
 | 
 |  |  | import javax.sip.header.ToHeader;
 | 
 |  |  | import javax.sip.InvalidArgumentException;
 | 
 |  |  | import javax.sip.ListeningPoint;
 | 
 |  |  | import javax.sip.ObjectInUseException;
 | 
 |  |  | import javax.sip.RequestEvent;
 | 
 |  |  | import javax.sip.SipException;
 | 
 |  |  | import javax.sip.SipProvider;
 | 
 |  |  | import javax.sip.message.Request;
 | 
 |  |  | import javax.sip.message.Response;
 | 
 |  |  | 
 | 
 |  |  | import com.alibaba.fastjson.JSONObject;
 | 
 |  |  | import com.genersoft.iot.vmp.VManageBootstrap;
 | 
 |  |  | import com.genersoft.iot.vmp.common.StreamInfo;
 | 
 |  |  | import com.genersoft.iot.vmp.common.VideoManagerConstants;
 | 
 |  |  | import com.genersoft.iot.vmp.conf.UserSetup;
 | 
 |  |  | 
 |  |  | import com.genersoft.iot.vmp.utils.GpsUtil;
 | 
 |  |  | import com.genersoft.iot.vmp.utils.SpringBeanFactory;
 | 
 |  |  | import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 | 
 |  |  | import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
 | 
 |  |  | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
 | 
 |  |  | 
 | 
 |  |  | import gov.nist.javax.sip.SipStackImpl;
 | 
 |  |  | import gov.nist.javax.sip.address.AddressImpl;
 | 
 |  |  | import gov.nist.javax.sip.address.SipUri;
 | 
 |  |  | 
 | 
 |  |  | 
 |  |  |    private static final String MESSAGE_ALARM = "Alarm";
 | 
 |  |  |    private static final String MESSAGE_RECORD_INFO = "RecordInfo";
 | 
 |  |  |    private static final String MESSAGE_MEDIA_STATUS = "MediaStatus";
 | 
 |  |  |    // private static final String MESSAGE_BROADCAST = "Broadcast";
 | 
 |  |  |    private static final String MESSAGE_BROADCAST = "Broadcast";
 | 
 |  |  |    private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
 | 
 |  |  |    private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl";
 | 
 |  |  |    private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig";
 | 
 |  |  | 
 |  |  |             logger.info("接收到Catalog消息");
 | 
 |  |  |             processMessageCatalogList(evt);
 | 
 |  |  |          } else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
 | 
 |  |  |             logger.info("接收到DeviceInfo消息");
 | 
 |  |  |             // DeviceInfo消息处理
 | 
 |  |  |             processMessageDeviceInfo(evt);
 | 
 |  |  |          } else if (MESSAGE_DEVICE_STATUS.equals(cmd)) {
 | 
 |  |  |             logger.info("接收到DeviceStatus消息");
 | 
 |  |  |             // DeviceStatus消息处理
 | 
 |  |  |             processMessageDeviceStatus(evt);
 | 
 |  |  |          } else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) {
 | 
 |  |  |             logger.info("接收到DeviceControl消息");
 | 
 |  |  | 
 |  |  |          } else if (MESSAGE_PRESET_QUERY.equals(cmd)) {
 | 
 |  |  |             logger.info("接收到PresetQuery消息");
 | 
 |  |  |             processMessagePresetQuery(evt);
 | 
 |  |  |          } else if (MESSAGE_BROADCAST.equals(cmd)) {
 | 
 |  |  |             // Broadcast消息处理
 | 
 |  |  |             processMessageBroadcast(evt);
 | 
 |  |  |          } else {
 | 
 |  |  |             logger.info("接收到消息:" + cmd);
 | 
 |  |  |             responseAck(evt);
 | 
 |  |  | 
 |  |  |    private void processMessageDeviceStatus(RequestEvent evt) {
 | 
 |  |  |       try {
 | 
 |  |  |          Element rootElement = getRootElement(evt);
 | 
 |  |  |          String deviceId = XmlUtil.getText(rootElement, "DeviceID");
 | 
 |  |  |          // 检查设备是否存在, 不存在则不回复
 | 
 |  |  |          if (storager.exists(deviceId)) {
 | 
 |  |  |             // 回复200 OK
 | 
 |  |  |             responseAck(evt);
 | 
 |  |  |             JSONObject json = new JSONObject();
 | 
 |  |  |             XmlUtil.node2Json(rootElement, json);
 | 
 |  |  |             if (logger.isDebugEnabled()) {
 | 
 |  |  |                logger.debug(json.toJSONString());
 | 
 |  |  |             }
 | 
 |  |  |             RequestMessage msg = new RequestMessage();
 | 
 |  |  |             msg.setDeviceId(deviceId);
 | 
 |  |  |             msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
 | 
 |  |  |             msg.setData(json);
 | 
 |  |  |             deferredResultHolder.invokeResult(msg);
 | 
 |  |  |          String name = rootElement.getName();
 | 
 |  |  |          Element deviceIdElement = rootElement.element("DeviceID");
 | 
 |  |  |          String deviceId = deviceIdElement.getText();
 | 
 |  |  | 
 | 
 |  |  |             if (offLineDetector.isOnline(deviceId)) {
 | 
 |  |  |                publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
 | 
 |  |  |          if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
 | 
 |  |  |             logger.info("接收到DeviceStatus查询消息");
 | 
 |  |  |             FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
 | 
 |  |  |             String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
 | 
 |  |  |                if (platformId == null) {
 | 
 |  |  |                response404Ack(evt);
 | 
 |  |  |                return;
 | 
 |  |  |             } else {
 | 
 |  |  |                // 回复200 OK
 | 
 |  |  |                responseAck(evt);
 | 
 |  |  |                String sn = rootElement.element("SN").getText();
 | 
 |  |  |                ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
 | 
 |  |  |                cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
 | 
 |  |  |             }
 | 
 |  |  |          } else {
 | 
 |  |  |             logger.info("接收到DeviceStatus应答消息");
 | 
 |  |  |             // 检查设备是否存在, 不存在则不回复
 | 
 |  |  |             if (storager.exists(deviceId)) {
 | 
 |  |  |                // 回复200 OK
 | 
 |  |  |                responseAck(evt);
 | 
 |  |  |                JSONObject json = new JSONObject();
 | 
 |  |  |                XmlUtil.node2Json(rootElement, json);
 | 
 |  |  |                if (logger.isDebugEnabled()) {
 | 
 |  |  |                   logger.debug(json.toJSONString());
 | 
 |  |  |                }
 | 
 |  |  |                RequestMessage msg = new RequestMessage();
 | 
 |  |  |                msg.setDeviceId(deviceId);
 | 
 |  |  |                msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
 | 
 |  |  |                msg.setData(json);
 | 
 |  |  |                deferredResultHolder.invokeResult(msg);
 | 
 |  |  | 
 | 
 |  |  |                if (offLineDetector.isOnline(deviceId)) {
 | 
 |  |  |                   publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
 | 
 |  |  |                } else {
 | 
 |  |  |                }
 | 
 |  |  |             }
 | 
 |  |  |          }
 | 
 |  |  | 
 | 
 |  |  |       } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
 | 
 |  |  |          e.printStackTrace();
 | 
 |  |  |       }
 | 
 |  |  | 
 |  |  |             deferredResultHolder.invokeResult(msg);
 | 
 |  |  |          } else {
 | 
 |  |  |             // 此处是上级发出的DeviceControl指令
 | 
 |  |  |             String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
 | 
 |  |  |             String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
 | 
 |  |  |             // 远程启动功能
 | 
 |  |  |             if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) {
 | 
 |  |  |                if (deviceId.equals(targetGBId)) {
 | 
 |  |  |                   // 远程启动本平台:需要在重新启动程序后先对SipStack解绑
 | 
 |  |  |                   logger.info("执行远程启动本平台命令");
 | 
 |  |  |                   ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
 | 
 |  |  |                   cmderFroPlatform.unregister(parentPlatform, null, null);
 | 
 |  |  | 	 | 
 |  |  |                   Thread restartThread = new Thread(new Runnable() {
 | 
 |  |  |                      @Override
 | 
 |  |  |                      public void run() {
 | 
 |  |  |                         try {
 | 
 |  |  |                            Thread.sleep(3000);
 | 
 |  |  |                            SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
 | 
 |  |  |                            SipStackImpl stack = (SipStackImpl)up.getSipStack();
 | 
 |  |  |                            stack.stop();
 | 
 |  |  |                            Iterator listener = stack.getListeningPoints();
 | 
 |  |  |                            while (listener.hasNext()) {
 | 
 |  |  |                               stack.deleteListeningPoint((ListeningPoint) listener.next());
 | 
 |  |  |                            }
 | 
 |  |  |                            Iterator providers = stack.getSipProviders();
 | 
 |  |  |                            while (providers.hasNext()) {
 | 
 |  |  |                               stack.deleteSipProvider((SipProvider) providers.next());
 | 
 |  |  |                            }
 | 
 |  |  |                            VManageBootstrap.restart();
 | 
 |  |  |                         } catch (InterruptedException ignored) {
 | 
 |  |  |                         } catch (ObjectInUseException e) {
 | 
 |  |  |                            e.printStackTrace();
 | 
 |  |  |                         }
 | 
 |  |  |                      }
 | 
 |  |  |                   });
 | 
 |  |  | 			 | 
 |  |  |                   restartThread.setDaemon(false);
 | 
 |  |  |                   restartThread.start();
 | 
 |  |  |                } else {
 | 
 |  |  |                   // 远程启动指定设备
 | 
 |  |  |                }
 | 
 |  |  |             }
 | 
 |  |  |             // 云台/前端控制命令
 | 
 |  |  |             if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
 | 
 |  |  |                String cmdString = XmlUtil.getText(rootElement,"PTZCmd");
 | 
 |  |  |                Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
 | 
 |  |  |                cmder.fronEndCmd(device, deviceId, cmdString);
 | 
 |  |  |             }
 | 
 |  |  |          }
 | 
 |  |  |       } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
 | 
 |  |  |          e.printStackTrace();
 | 
 |  |  | 
 |  |  |          Element deviceIdElement = rootElement.element("DeviceID");
 | 
 |  |  |          String deviceId = deviceIdElement.getTextTrim().toString();
 | 
 |  |  |          if (requestName.equals("Query")) {
 | 
 |  |  |             // 回复200 OK
 | 
 |  |  |             responseAck(evt);
 | 
 |  |  |             logger.info("接收到DeviceInfo查询消息");
 | 
 |  |  |             FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
 | 
 |  |  |             String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
 | 
 |  |  |                if (platformId == null) {
 | 
 |  |  |                response404Ack(evt);
 | 
 |  |  |                return;
 | 
 |  |  |             } else {
 | 
 |  |  |                // 回复200 OK
 | 
 |  |  |                responseAck(evt);
 | 
 |  |  |                String sn = rootElement.element("SN").getText();
 | 
 |  |  |                ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
 | 
 |  |  |                cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
 | 
 |  |  |             }
 | 
 |  |  |          } else {
 | 
 |  |  |             logger.info("接收到DeviceInfo应答消息");
 | 
 |  |  |             Device device = storager.queryVideoDevice(deviceId);
 | 
 |  |  |             if (device == null) {
 | 
 |  |  |                return;
 | 
 |  |  | 
 |  |  |                String sn = snElement.getText();
 | 
 |  |  |                // 准备回复通道信息
 | 
 |  |  |                List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
 | 
 |  |  |                // 查询关联的直播通道
 | 
 |  |  |                List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
 | 
 |  |  |                int size = channelReduces.size() + gbStreams.size();
 | 
 |  |  |                // 回复级联的通道
 | 
 |  |  |                if (channelReduces.size() > 0) {
 | 
 |  |  |                   for (ChannelReduce channelReduce : channelReduces) {
 | 
 |  |  |                      DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
 | 
 |  |  |                      cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), channelReduces.size());
 | 
 |  |  |                      cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
 | 
 |  |  |                   }
 | 
 |  |  |                }
 | 
 |  |  |                // 回复直播的通道
 | 
 |  |  |                if (gbStreams.size() > 0) {
 | 
 |  |  |                   for (GbStream gbStream : gbStreams) {
 | 
 |  |  |                      DeviceChannel deviceChannel = new DeviceChannel();
 | 
 |  |  |                      deviceChannel.setChannelId(gbStream.getGbId());
 | 
 |  |  |                      deviceChannel.setName(gbStream.getName());
 | 
 |  |  |                      deviceChannel.setLongitude(gbStream.getLongitude());
 | 
 |  |  |                      deviceChannel.setLatitude(gbStream.getLatitude());
 | 
 |  |  |                      deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
 | 
 |  |  |                      deviceChannel.setManufacture("wvp-pro");
 | 
 |  |  |                      deviceChannel.setStatus(gbStream.isStatus()?1:0);
 | 
 |  |  | //                     deviceChannel.setParentId(parentPlatform.getDeviceGBId());
 | 
 |  |  |                      deviceChannel.setRegisterWay(1);
 | 
 |  |  |                      deviceChannel.setCivilCode(cmder.getSipConfig().getSipDomain());
 | 
 |  |  |                      deviceChannel.setModel("live");
 | 
 |  |  |                      deviceChannel.setOwner("wvp-pro");
 | 
 |  |  | //                     deviceChannel.setAddress("test");
 | 
 |  |  |                      deviceChannel.setParental(0);
 | 
 |  |  |                      deviceChannel.setSecrecy("0");
 | 
 |  |  |                      deviceChannel.setSecrecy("0");
 | 
 |  |  | 
 | 
 |  |  |                      cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
 | 
 |  |  |                   }
 | 
 |  |  |                }
 | 
 |  |  |                if (size == 0) {
 | 
 |  |  |                   // 回复无通道
 | 
 |  |  |                   cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size);
 | 
 |  |  |                }
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  | 
 | 
 |  |  | 
 |  |  |       }
 | 
 |  |  |    }
 | 
 |  |  | 
 | 
 |  |  |    /**
 | 
 |  |  |     * 处理AudioBroadcast语音广播Message
 | 
 |  |  |     *  | 
 |  |  |     * @param evt
 | 
 |  |  |     */
 | 
 |  |  |    private void processMessageBroadcast(RequestEvent evt) {
 | 
 |  |  |       try {
 | 
 |  |  |          Element rootElement = getRootElement(evt);
 | 
 |  |  |          String deviceId = XmlUtil.getText(rootElement, "DeviceID");
 | 
 |  |  |          // 回复200 OK
 | 
 |  |  |          responseAck(evt);
 | 
 |  |  |          if (rootElement.getName().equals("Response")) {
 | 
 |  |  |                // 此处是对本平台发出Broadcast指令的应答
 | 
 |  |  |             JSONObject json = new JSONObject();
 | 
 |  |  |             XmlUtil.node2Json(rootElement, json);
 | 
 |  |  |             if (logger.isDebugEnabled()) {
 | 
 |  |  |                logger.debug(json.toJSONString());
 | 
 |  |  |             }
 | 
 |  |  |             RequestMessage msg = new RequestMessage();
 | 
 |  |  |             msg.setDeviceId(deviceId);
 | 
 |  |  |             msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST);
 | 
 |  |  |             msg.setData(json);
 | 
 |  |  |             deferredResultHolder.invokeResult(msg);
 | 
 |  |  |          } else {
 | 
 |  |  |             // 此处是上级发出的Broadcast指令
 | 
 |  |  |          }
 | 
 |  |  |       } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
 | 
 |  |  |          e.printStackTrace();
 | 
 |  |  |       }
 | 
 |  |  |    }
 | 
 |  |  | 
 | 
 |  |  | 
 | 
 |  |  |    /***
 | 
 |  |  |     * 回复200 OK
 |