panlinlin
2021-02-25 0f58218badea86a5209ae7f1ccd60b7cb4b26eee
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -7,59 +7,53 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.header.FromHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import com.alibaba.fastjson.JSONObject;
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.gb28181.bean.BaiduPoint;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
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 gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.springframework.util.StringUtils;
import com.genersoft.iot.vmp.common.StreamInfo;
/**
 * @Description:MESSAGE请求处理器
 * @author: swwheihei
 * @date: 2020年5月3日 下午5:32:41
 */
@SuppressWarnings(value={"unchecked", "rawtypes"})
public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
   public static volatile List<String> threadNameList = new ArrayList();
   private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
   private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
   private SIPCommander cmder;
   private SIPCommanderFroPlatform cmderFroPlatform;
   private IVideoManagerStorager storager;
@@ -407,40 +401,69 @@
   private void processMessageCatalogList(RequestEvent evt) {
      try {
         Element rootElement = getRootElement(evt);
         String name = rootElement.getName();
         Element deviceIdElement = rootElement.element("DeviceID");
         String deviceId = deviceIdElement.getText();
         Element deviceListElement = rootElement.element("DeviceList");
         if (deviceListElement == null) {
            return;
         }
         Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
         if (deviceListIterator != null) {
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
         FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
         AddressImpl address = (AddressImpl) fromHeader.getAddress();
         SipUri uri = (SipUri) address.getURI();
         String platformId = uri.getUser();
         // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
         if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
               // TODO 后续将代码拆分
            ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
            if (parentPlatform == null) {
               response404Ack(evt);
               return;
            }else {
               // 回复200 OK
               responseAck(evt);
               Element snElement = rootElement.element("SN");
               String sn = snElement.getText();
               // 准备回复通道信息
               List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
               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());
                  }
               }
            }
            // 遍历DeviceList
            while (deviceListIterator.hasNext()) {
               Element itemDevice = deviceListIterator.next();
               Element channelDeviceElement = itemDevice.element("DeviceID");
               if (channelDeviceElement == null) {
                  continue;
         }else {
            Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
            if (deviceListIterator != null) {
               Device device = storager.queryVideoDevice(deviceId);
               if (device == null) {
                  return;
               }
               String channelDeviceId = channelDeviceElement.getTextTrim();
               Element channdelNameElement = itemDevice.element("Name");
               String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
               Element statusElement = itemDevice.element("Status");
               String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
               DeviceChannel deviceChannel = new DeviceChannel();
               deviceChannel.setName(channelName);
               deviceChannel.setChannelId(channelDeviceId);
               // ONLINE OFFLINE  HIKVISION DS-7716N-E4 NVR的兼容性处理
               if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
                  deviceChannel.setStatus(1);
               }
               if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
                  deviceChannel.setStatus(0);
               }
               // 遍历DeviceList
               while (deviceListIterator.hasNext()) {
                  Element itemDevice = deviceListIterator.next();
                  Element channelDeviceElement = itemDevice.element("DeviceID");
                  if (channelDeviceElement == null) {
                     continue;
                  }
                  String channelDeviceId = channelDeviceElement.getText();
                  Element channdelNameElement = itemDevice.element("Name");
                  String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
                  Element statusElement = itemDevice.element("Status");
                  String status = statusElement != null ? statusElement.getText().toString() : "ON";
                  DeviceChannel deviceChannel = new DeviceChannel();
                  deviceChannel.setName(channelName);
                  deviceChannel.setChannelId(channelDeviceId);
                  // ONLINE OFFLINE  HIKVISION DS-7716N-E4 NVR的兼容性处理
                  if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
                     deviceChannel.setStatus(1);
                  }
                  if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
                     deviceChannel.setStatus(0);
                  }
               deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
               deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
@@ -484,15 +507,15 @@
                  deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
               }
               deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
               if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
                  deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
               } else {
               if (XmlUtil.getText(itemDevice, "Longitude") == null || XmlUtil.getText(itemDevice, "Longitude") == "") {
                  deviceChannel.setLongitude(0.00);
               }
               if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
                  deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
               } else {
                  deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
               }
               if (XmlUtil.getText(itemDevice, "Latitude") == null || XmlUtil.getText(itemDevice, "Latitude") =="") {
                  deviceChannel.setLatitude(0.00);
               } else {
                  deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
               }
               if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
                  deviceChannel.setPTZType(0);
@@ -520,7 +543,8 @@
   }
   /***
    * alarm设备报警信息处理
    * 收到alarm设备报警信息 处理
    *
    * @param evt
    */
   private void processMessageAlarm(RequestEvent evt) {
@@ -528,72 +552,26 @@
         Element rootElement = getRootElement(evt);
         Element deviceIdElement = rootElement.element("DeviceID");
         String deviceId = deviceIdElement.getText().toString();
         // 回复200 OK
         responseAck(evt);
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
            // TODO 也可能是通道
            // storager.queryChannel(deviceId)
            return;
         }
         if (rootElement.getName().equals("Notify")) {   // 处理报警通知
            DeviceAlarm deviceAlarm = new DeviceAlarm();
            deviceAlarm.setDeviceId(deviceId);
            deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
            deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
            deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime"));
            if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
               deviceAlarm.setAlarmDescription("");
            } else {
               deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
            }
            if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) {
               deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
            } else {
               deviceAlarm.setLongitude(0.00);
            }
            if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) {
               deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
            } else {
               deviceAlarm.setLatitude(0.00);
            }
            if (!XmlUtil.isEmpty(deviceAlarm.getAlarmMethod())) {
               if ( deviceAlarm.getAlarmMethod().equals("4")) {
                  MobilePosition mobilePosition = new MobilePosition();
                  mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
                  mobilePosition.setTime(deviceAlarm.getAlarmTime());
                  mobilePosition.setLongitude(deviceAlarm.getLongitude());
                  mobilePosition.setLatitude(deviceAlarm.getLatitude());
                  mobilePosition.setReportSource("GPS Alarm");
                  BaiduPoint bp = new BaiduPoint();
                  bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
                  logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
                  mobilePosition.setGeodeticSystem("BD-09");
                  mobilePosition.setCnLng(bp.getBdLng());
                  mobilePosition.setCnLat(bp.getBdLat());
                  if (!userSetup.getSavePositionHistory()) {
                     storager.clearMobilePositionsByDeviceId(deviceId);
                  }
                  storager.insertMobilePosition(mobilePosition);
               }
            }
            // TODO: 需要实现存储报警信息、报警分类
            if (offLineDetector.isOnline(deviceId)) {
               publisher.deviceAlarmEventPublish(deviceAlarm);
            }
         } else if (rootElement.getName().equals("Response")) {   // 处理报警查询响应
            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_ALARM);
            msg.setData(json);
            deferredResultHolder.invokeResult(msg);
         device.setName(XmlUtil.getText(rootElement, "DeviceName"));
         device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
         device.setModel(XmlUtil.getText(rootElement, "Model"));
         device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
         if (StringUtils.isEmpty(device.getStreamMode())) {
            device.setStreamMode("UDP");
         }
         storager.updateDevice(device);
         //cmder.catalogQuery(device, null);
         // 回复200 OK
         responseAck(evt);
         if (offLineDetector.isOnline(deviceId)) {
            publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
         }
      } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
         // } catch (DocumentException e) {
@@ -705,7 +683,7 @@
                  logger.debug("Thread " + cacheKey + " already started.");
               }
            }
            // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回
            // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) {
            //    // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分
@@ -747,7 +725,7 @@
   /**
    * 收到MediaStatus消息处理
     *
     *
     * @param evt
     */
   private void processMessageMediaStatus(RequestEvent evt){
@@ -780,6 +758,18 @@
    */
   private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
      Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
      getServerTransaction(evt).sendResponse(response);
   }
   /***
    * 回复404
    * @param evt
    * @throws SipException
    * @throws InvalidArgumentException
    * @throws ParseException
    */
   private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
      Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
      getServerTransaction(evt).sendResponse(response);
   }
@@ -822,4 +812,12 @@
   public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
      this.redisCatchStorage = redisCatchStorage;
   }
}
   public SIPCommanderFroPlatform getCmderFroPlatform() {
      return cmderFroPlatform;
   }
   public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
      this.cmderFroPlatform = cmderFroPlatform;
   }
}