完成向上级联->通道推送
修复选择通道是查询的bug
| | |
| | | - [X] 注册 |
| | | - [X] 心跳保活 |
| | | - [X] 通道选择 |
| | | - [ ] 通道推送 |
| | | - [X] 通道推送 |
| | | - [ ] 点播 |
| | | - [ ] 云台控制 |
| | | - [ ] 添加RTSP视频 |
| | |
| | | */ |
| | | private boolean status; |
| | | |
| | | /** |
| | | * 在线状态 |
| | | */ |
| | | private int channelCount; |
| | | |
| | | |
| | | public boolean isEnable() { |
| | | return enable; |
| | |
| | | public void setStatus(boolean status) { |
| | | this.status = status; |
| | | } |
| | | |
| | | public int getChannelCount() { |
| | | return channelCount; |
| | | } |
| | | |
| | | public void setChannelCount(int channelCount) { |
| | | this.channelCount = channelCount; |
| | | } |
| | | } |
| | |
| | | import javax.sip.message.Request;
|
| | | import javax.sip.message.Response;
|
| | |
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | | import com.alibaba.fastjson.JSON;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
| | |
| | |
|
| | | @Autowired
|
| | | private SIPCommander cmder;
|
| | |
|
| | | @Autowired
|
| | | private SIPCommanderFroPlatform cmderFroPlatform;
|
| | |
|
| | | @Autowired
|
| | | private RedisUtil redis;
|
| | |
| | | processor.setDeferredResultHolder(deferredResultHolder);
|
| | | processor.setOffLineDetector(offLineDetector);
|
| | | processor.setCmder(cmder);
|
| | | processor.setCmderFroPlatform(cmderFroPlatform);
|
| | | processor.setStorager(storager);
|
| | | processor.setRedisCatchStorage(redisCatchStorage);
|
| | | return processor;
|
| | |
| | | package com.genersoft.iot.vmp.gb28181.transmit.cmd; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | | |
| | | import javax.sip.header.WWWAuthenticateHeader; |
| | | import java.nio.channels.Channel; |
| | | import java.util.List; |
| | | |
| | | public interface ISIPCommanderForPlatform { |
| | | |
| | |
| | | * @return callId(作为接受回复的判定) |
| | | */ |
| | | String keepalive(ParentPlatform parentPlatform); |
| | | |
| | | |
| | | /** |
| | | * 向上级回复通道信息 |
| | | * @param channel 通道信息 |
| | | * @param parentPlatform 平台信息 |
| | | * @param sn |
| | | * @param fromTag |
| | | * @param size |
| | | * @return |
| | | */ |
| | | boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size); |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | import com.genersoft.iot.vmp.gb28181.bean.Host; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.DigestUtils; |
| | | |
| | | import javax.sip.InvalidArgumentException; |
| | | import javax.sip.PeerUnavailableException; |
| | | import javax.sip.SipFactory; |
| | | import javax.sip.SipProvider; |
| | | import javax.sip.*; |
| | | import javax.sip.address.Address; |
| | | import javax.sip.address.SipURI; |
| | | import javax.sip.header.*; |
| | | import javax.sip.message.Request; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.nio.channels.Channel; |
| | | import java.text.ParseException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | |
| | | /** |
| | |
| | | return registerRequest; |
| | | } |
| | | |
| | | |
| | | public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag) throws PeerUnavailableException, ParseException, InvalidArgumentException { |
| | | Request request = null; |
| | | // sipuri |
| | | SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); |
| | | // via |
| | | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| | | ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), |
| | | parentPlatform.getTransport(), null); |
| | | viaHeader.setRPort(); |
| | | viaHeaders.add(viaHeader); |
| | | // from |
| | | SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), |
| | | parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); |
| | | Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); |
| | | FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); |
| | | // to |
| | | SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getServerGBDomain()); |
| | | Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); |
| | | ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null); |
| | | // callid |
| | | CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| | | : udpSipProvider.getNewCallId(); |
| | | // Forwards |
| | | MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); |
| | | // ceq |
| | | CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); |
| | | |
| | | request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, |
| | | toHeader, viaHeaders, maxForwards); |
| | | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); |
| | | request.setContent(content, contentTypeHeader); |
| | | return request; |
| | | } |
| | | } |
| | |
| | | |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | |
| | | import javax.sip.header.CallIdHeader; |
| | | import javax.sip.header.WWWAuthenticateHeader; |
| | | import javax.sip.message.Request; |
| | | import java.nio.channels.Channel; |
| | | import java.text.ParseException; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | |
| | | @Component |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 向上级回复通道信息 |
| | | * @param channel 通道信息 |
| | | * @param parentPlatform 平台信息 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) { |
| | | |
| | | if (channel == null || parentPlatform ==null) { |
| | | return false; |
| | | } |
| | | try { |
| | | StringBuffer catalogXml = new StringBuffer(600); |
| | | catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); |
| | | catalogXml.append("<Response>\r\n"); |
| | | catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); |
| | | catalogXml.append("<SN>" +sn + "</SN>\r\n"); |
| | | catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); |
| | | catalogXml.append("<SumNum>" + size + "</SumNum>\r\n"); |
| | | catalogXml.append("<DeviceList Num=\"1\">\r\n"); |
| | | catalogXml.append("<Item>\r\n"); |
| | | |
| | | catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); |
| | | catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); |
| | | catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n"); |
| | | catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n"); |
| | | catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n"); |
| | | catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); |
| | | catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); |
| | | catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");// TODO 当前不能添加分组, 所以暂时没有父节点 |
| | | catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); // TODO 当前不能添加分组, 所以暂时没有父节点 |
| | | catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); |
| | | catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); |
| | | catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n"); |
| | | catalogXml.append("<Info></Info>\r\n"); |
| | | |
| | | catalogXml.append("</Item>\r\n"); |
| | | catalogXml.append("</DeviceList>\r\n"); |
| | | catalogXml.append("</Response>\r\n"); |
| | | Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag); |
| | | transmitRequest(parentPlatform, request); |
| | | |
| | | } catch (SipException | ParseException | InvalidArgumentException e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | |
| | | 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.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.vmanager.platform.bean.ChannelReduce;
|
| | | import org.dom4j.Document;
|
| | | import org.dom4j.DocumentException;
|
| | | import org.dom4j.Element;
|
| | |
| | | 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;
|
| | |
| | | private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
| | |
|
| | | private SIPCommander cmder;
|
| | |
|
| | | private SIPCommanderFroPlatform cmderFroPlatform;
|
| | |
|
| | | private IVideoManagerStorager storager;
|
| | |
|
| | |
| | | Element deviceIdElement = rootElement.element("DeviceID");
|
| | | String deviceId = deviceIdElement.getText();
|
| | | Element deviceListElement = rootElement.element("DeviceList");
|
| | | if (deviceListElement == null) {
|
| | | if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
|
| | | // TODO 后续将代码拆分
|
| | | ParentPlatform parentPlatform = storager.queryParentPlatById(deviceId);
|
| | | if (parentPlatform == null) {
|
| | | response404Ack(evt);
|
| | | return;
|
| | | }else {
|
| | | // 回复200 OK
|
| | | responseAck(evt);
|
| | |
|
| | | Element snElement = rootElement.element("SN");
|
| | | String sn = snElement.getText();
|
| | | FromHeader fromHeader = (FromHeader)evt.getRequest().getHeader(FromHeader.NAME);
|
| | | // 准备回复通道信息
|
| | | List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getDeviceGBId());
|
| | | 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());
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | |
|
| | | }else {
|
| | | Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
| | | if (deviceListIterator != null) {
|
| | | Device device = storager.queryVideoDevice(deviceId);
|
| | |
| | | publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | |
| | | getServerTransaction(evt).sendResponse(response);
|
| | | }
|
| | |
|
| | | /***
|
| | | * 回复200 OK
|
| | | * @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);
|
| | | }
|
| | |
|
| | | private Element getRootElement(RequestEvent evt) throws DocumentException {
|
| | | Request request = evt.getRequest();
|
| | | SAXReader reader = new SAXReader();
|
| | |
| | | public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
| | | this.redisCatchStorage = redisCatchStorage;
|
| | | }
|
| | |
|
| | | public SIPCommanderFroPlatform getCmderFroPlatform() {
|
| | | return cmderFroPlatform;
|
| | | }
|
| | |
|
| | | public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
|
| | | this.cmderFroPlatform = cmderFroPlatform;
|
| | | }
|
| | | }
|
| | |
| | | */
|
| | | PageInfo<ChannelReduce> queryAllChannelList(int page, int count, String query, Boolean online, Boolean channelType, String platformId, Boolean inPlatform);
|
| | |
|
| | | /**
|
| | | * 查询设备的通道信息
|
| | | */
|
| | | List<ChannelReduce> queryChannelListInParentPlatform(String platformId);
|
| | |
|
| | |
|
| | | /**
|
| | | * 更新上级平台的通道信息
|
| | |
| | | "SELECT * FROM ( "+ |
| | | " SELECT dc.channelId, dc.deviceId, dc.name, de.manufacturer, de.hostAddress, " + |
| | | "(SELECT count(0) FROM device_channel WHERE parentId=dc.channelId) as subCount, " + |
| | | "pc.platformId " + |
| | | "(SELECT pc.platformId FROM platform_gb_channel pc WHERE pc.deviceId=dc.deviceId AND pc.channelId = dc.channelId ) as platformId " + |
| | | "FROM device_channel dc " + |
| | | "LEFT JOIN device de ON dc.deviceId = de.deviceId " + |
| | | "LEFT JOIN platform_gb_channel pc on pc.deviceId = dc.deviceId AND pc.channelId = dc.channelId " + |
| | | " WHERE 1=1 " + |
| | | " <if test=\"query != null\"> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + |
| | | " <if test=\"online == true\" > AND dc.status=1</if> " + |
| | | " <if test=\"online == false\" > AND dc.status=0</if> " + |
| | | " <if test=\"platformId != null and inPlatform == true\"> AND pc.platformId=#{platformId} </if> " + |
| | | ") dcr" + |
| | | " WHERE 1=1 " + |
| | | " <if test=\"hasSubChannel!= null and hasSubChannel == true\" > AND subCount >0</if> " + |
| | | " <if test=\"hasSubChannel!= null and hasSubChannel == false\" > AND subCount=0</if> " + |
| | | " <if test=\"platformId != null and inPlatform == true \" > AND platformId='${platformId}'</if> " + |
| | | " <if test=\"platformId != null and inPlatform == false \" > AND (platformId != '${platformId}' OR platformId is NULL ) </if> " + |
| | | " </script>"}) |
| | | |
| | | List<ChannelReduce> queryChannelListInAll(String query, Boolean online, Boolean hasSubChannel, String platformId, Boolean inPlatform); |
| | |
| | | @Delete("DELETE FROM parent_platform WHERE deviceGBId=#{deviceGBId}") |
| | | int delParentPlatform(ParentPlatform parentPlatform); |
| | | |
| | | @Select("SELECT * FROM parent_platform") |
| | | @Select("SELECT *,( SELECT count(0) FROM platform_gb_channel pc WHERE pc.platformId = pp.deviceGBId) as channelCount FROM parent_platform pp ") |
| | | List<ParentPlatform> getParentPlatformList(); |
| | | |
| | | @Select("SELECT * FROM parent_platform WHERE enable=#{enable}") |
| | |
| | | |
| | | |
| | | @Delete("<script> "+ |
| | | "DELETE FROM platform_gb_channel WHERE deviceAndChannelId in" + |
| | | "DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceAndChannelId in" + |
| | | "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.deviceId}_${item.channelId}'</foreach>" + |
| | | "</script>") |
| | | int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel); |
| | | |
| | | @Delete("<script> "+ |
| | | "DELETE FROM platform_gb_channel WHERE platformId='${platformId}'" + |
| | | "</script>") |
| | | int cleanChannelForGB(String platformId); |
| | | } |
| | |
| | | return result > 0; |
| | | } |
| | | |
| | | @Transactional |
| | | @Override |
| | | public boolean deleteParentPlatform(ParentPlatform parentPlatform) { |
| | | int result = platformMapper.delParentPlatform(parentPlatform); |
| | | // 删除关联的通道 |
| | | patformChannelMapper.cleanChannelForGB(parentPlatform.getDeviceGBId()); |
| | | return result > 0; |
| | | } |
| | | |
| | |
| | | return new PageInfo<>(all); |
| | | } |
| | | |
| | | @Override |
| | | public List<ChannelReduce> queryChannelListInParentPlatform(String platformId) { |
| | | |
| | | return deviceChannelMapper.queryChannelListInAll(null, null, null, platformId, true); |
| | | } |
| | | |
| | | @Override |
| | | public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces) { |
| | |
| | | <template> |
| | | <div id="chooseChannel" v-loading="isLoging"> |
| | | |
| | | <el-dialog title="选择通道" top="2rem" width="70%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()"> |
| | | <el-dialog title="选择通道" v-if="showDialog" top="2rem" width="70%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()"> |
| | | <el-tabs v-model="tabActiveName" > |
| | | <el-tab-pane label="国标通道" name="gbChannel"> |
| | | <el-container> |
| | |
| | | <el-table-column prop="manufacturer" label="厂家" align="center"> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination style="float: right;margin-top: 1rem;" @size-change="handleSizeChange" @current-change="currentChange" :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]" layout="total, sizes, prev, pager, next" :total="total"> |
| | | <el-pagination style="float: right;margin-top: 1rem;" @size-change="handleSizeChange" @current-change="currentChange" :current-page="currentPage" :page-size="count" :page-sizes="[10, 20, 30, 50]" layout="total, sizes, prev, pager, next" :total="total"> |
| | | </el-pagination> |
| | | </div> |
| | | </template> |