commit
6070af1fae
@ -42,6 +42,14 @@ https://gitee.com/18010473990/wvp-GB28181.git
|
||||
12. 支持播放h265, g.711格式的流
|
||||
13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD))
|
||||
14. 报警信息处理,支持向前端推送报警信息
|
||||
15. 支持订阅与通知方法
|
||||
- [X] 移动位置订阅
|
||||
- [X] 移动位置通知处理
|
||||
- [ ] 报警事件订阅
|
||||
- [X] 报警事件通知处理
|
||||
- [ ] 设备目录订阅
|
||||
- [X] 设备目录通知处理
|
||||
16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储
|
||||
|
||||
# 待实现:
|
||||
上级级联
|
||||
|
18
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java
Normal file
18
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration("userSetup")
|
||||
public class UserSetup {
|
||||
@Value("${userSettings.savePositionHistory}")
|
||||
boolean savePositionHistory;
|
||||
|
||||
public boolean getSavePositionHistory() {
|
||||
return savePositionHistory;
|
||||
}
|
||||
|
||||
public void setSavePositionHistory(boolean savePositionHistory) {
|
||||
this.savePositionHistory = savePositionHistory;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public class BaiduPoint {
|
||||
|
||||
String bdLng;
|
||||
|
||||
String bdLat;
|
||||
|
||||
public String getBdLng() {
|
||||
return bdLng;
|
||||
}
|
||||
|
||||
public void setBdLng(String bdLng) {
|
||||
this.bdLng = bdLng;
|
||||
}
|
||||
|
||||
public String getBdLat() {
|
||||
return bdLat;
|
||||
}
|
||||
|
||||
public void setBdLat(String bdLat) {
|
||||
this.bdLat = bdLat;
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
/**
|
||||
* @Description: 移动位置bean
|
||||
* @author: lawrencehj
|
||||
* @date: 2021年1月23日
|
||||
*/
|
||||
|
||||
public class MobilePosition {
|
||||
/**
|
||||
* 设备Id
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 通知时间
|
||||
*/
|
||||
private String time;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private double longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private double latitude;
|
||||
|
||||
/**
|
||||
* 海拔高度
|
||||
*/
|
||||
private double altitude;
|
||||
|
||||
/**
|
||||
* 速度
|
||||
*/
|
||||
private double speed;
|
||||
|
||||
/**
|
||||
* 方向
|
||||
*/
|
||||
private double direction;
|
||||
|
||||
/**
|
||||
* 位置信息上报来源(Mobile Position、GPS Alarm)
|
||||
*/
|
||||
private String reportSource;
|
||||
|
||||
/**
|
||||
* 国内地理坐标系(GCJ-02 / BD-09)
|
||||
*/
|
||||
private String GeodeticSystem;
|
||||
|
||||
/**
|
||||
* 国内坐标系:经度坐标
|
||||
*/
|
||||
private String cnLng;
|
||||
|
||||
/**
|
||||
* 国内坐标系:纬度坐标
|
||||
*/
|
||||
private String cnLat;
|
||||
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public void setDeviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getAltitude() {
|
||||
return altitude;
|
||||
}
|
||||
|
||||
public void setAltitude(double altitude) {
|
||||
this.altitude = altitude;
|
||||
}
|
||||
|
||||
public double getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setSpeed(double speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public double getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(double direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public String getReportSource() {
|
||||
return reportSource;
|
||||
}
|
||||
|
||||
public void setReportSource(String reportSource) {
|
||||
this.reportSource = reportSource;
|
||||
}
|
||||
|
||||
public String getGeodeticSystem() {
|
||||
return GeodeticSystem;
|
||||
}
|
||||
|
||||
public void setGeodeticSystem(String geodeticSystem) {
|
||||
GeodeticSystem = geodeticSystem;
|
||||
}
|
||||
|
||||
public String getCnLng() {
|
||||
return cnLng;
|
||||
}
|
||||
|
||||
public void setCnLng(String cnLng) {
|
||||
this.cnLng = cnLng;
|
||||
}
|
||||
|
||||
public String getCnLat() {
|
||||
return cnLat;
|
||||
}
|
||||
|
||||
public void setCnLat(String cnLat) {
|
||||
this.cnLat = cnLat;
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor;
|
||||
@ -132,7 +133,6 @@ public class SIPProcessorFactory {
|
||||
processor.setRequestEvent(evt);
|
||||
return processor;
|
||||
} else if (Request.MESSAGE.equals(method)) {
|
||||
|
||||
MessageRequestProcessor processor = new MessageRequestProcessor();
|
||||
processor.setRequestEvent(evt);
|
||||
processor.setTcpSipProvider(getTcpSipProvider());
|
||||
@ -145,13 +145,27 @@ public class SIPProcessorFactory {
|
||||
processor.setStorager(storager);
|
||||
processor.setRedisCatchStorage(redisCatchStorage);
|
||||
return processor;
|
||||
} else if (Request.NOTIFY.equalsIgnoreCase(method)) {
|
||||
NotifyRequestProcessor processor = new NotifyRequestProcessor();
|
||||
processor.setRequestEvent(evt);
|
||||
processor.setTcpSipProvider(getTcpSipProvider());
|
||||
processor.setUdpSipProvider(getUdpSipProvider());
|
||||
processor.setPublisher(publisher);
|
||||
processor.setRedis(redis);
|
||||
processor.setDeferredResultHolder(deferredResultHolder);
|
||||
processor.setOffLineDetector(offLineDetector);
|
||||
processor.setCmder(cmder);
|
||||
processor.setStorager(storager);
|
||||
processor.setRedisCatchStorage(redisCatchStorage);
|
||||
return processor;
|
||||
} else {
|
||||
return new OtherRequestProcessor();
|
||||
OtherRequestProcessor processor = new OtherRequestProcessor();
|
||||
processor.setRequestEvent(evt);
|
||||
return processor;
|
||||
}
|
||||
}
|
||||
|
||||
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
|
||||
|
||||
Response response = evt.getResponse();
|
||||
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||
String method = cseqHeader.getMethod();
|
||||
|
@ -17,8 +17,16 @@ import org.springframework.web.context.request.async.DeferredResult;
|
||||
@Component
|
||||
public class DeferredResultHolder {
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
|
||||
|
||||
public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
|
||||
|
||||
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
|
||||
|
||||
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
|
||||
@ -27,6 +35,12 @@ public class DeferredResultHolder {
|
||||
|
||||
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
||||
|
||||
public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
|
||||
|
||||
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
|
||||
|
||||
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
|
||||
|
||||
private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
|
||||
|
||||
public void put(String key, DeferredResult result) {
|
||||
|
@ -115,24 +115,35 @@ public interface ISIPCommander {
|
||||
/**
|
||||
* 音视频录像控制
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||
*/
|
||||
boolean recordCmd(Device device,String channelId);
|
||||
boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 远程启动控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean teleBootCmd(Device device);
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param setGuard true: SetGuard, false: ResetGuard
|
||||
*/
|
||||
boolean guardCmd(Device device);
|
||||
boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 报警复位命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param alarmMethod 报警方式(可选)
|
||||
* @param alarmType 报警类型(可选)
|
||||
*/
|
||||
boolean alarmCmd(Device device);
|
||||
boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
||||
@ -140,14 +151,17 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
boolean iFameCmd(Device device,String channelId);
|
||||
boolean iFrameCmd(Device device, String channelId);
|
||||
|
||||
/**
|
||||
* 看守位控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param enabled 看守位使能:1 = 开启,0 = 关闭
|
||||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
boolean homePositionCmd(Device device);
|
||||
boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 设备配置命令
|
||||
@ -156,13 +170,24 @@ public interface ISIPCommander {
|
||||
*/
|
||||
boolean deviceConfigCmd(Device device);
|
||||
|
||||
/**
|
||||
* 设备配置命令:basicParam
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param name 设备/通道名称(可选)
|
||||
* @param expiration 注册过期时间(可选)
|
||||
* @param heartBeatInterval 心跳间隔时间(可选)
|
||||
* @param heartBeatCount 心跳超时次数(可选)
|
||||
*/
|
||||
boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 查询设备状态
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean deviceStatusQuery(Device device);
|
||||
boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 查询设备信息
|
||||
@ -191,30 +216,65 @@ public interface ISIPCommander {
|
||||
/**
|
||||
* 查询报警信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethod 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean alarmInfoQuery(Device device);
|
||||
boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 查询设备配置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param configType 配置类型:
|
||||
*/
|
||||
boolean configQuery(Device device);
|
||||
boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 查询设备预置位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean presetQuery(Device device);
|
||||
boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 查询移动设备位置数据
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean mobilePostitionQuery(Device device);
|
||||
boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅移动位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅超时时间(值=0时为取消订阅)
|
||||
* @param interval 上报时间间隔
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean mobilePositionSubscribe(Device device, int expires, int interval);
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅报警信息
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅过期时间(0 = 取消订阅)
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethods 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
||||
|
||||
|
||||
/**
|
||||
* 释放rtpserver
|
||||
|
@ -164,4 +164,51 @@ public class SIPRequestHeaderProvider {
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
|
||||
device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
// from
|
||||
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),
|
||||
sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
|
||||
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
|
||||
// to
|
||||
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain());
|
||||
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
|
||||
// callid
|
||||
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||
: udpSipProvider.getNewCallId();
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
|
||||
// ceq
|
||||
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE);
|
||||
|
||||
request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
|
||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
// Expires
|
||||
ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(expires);
|
||||
request.addHeader(expireHeader);
|
||||
|
||||
// Event
|
||||
EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
|
||||
request.addHeader(eventHeader);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
|
||||
/**
|
||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@ -235,7 +237,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
ptzXml.append("</Info>\r\n");
|
||||
ptzXml.append("</Control>\r\n");
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
|
||||
|
||||
transmitRequest(device, request);
|
||||
return true;
|
||||
@ -271,7 +274,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
ptzXml.append("</Info>\r\n");
|
||||
ptzXml.append("</Control>\r\n");
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
|
||||
transmitRequest(device, request);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
@ -383,7 +387,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
|
||||
content.append("y="+ssrc+"\r\n");//ssrc
|
||||
|
||||
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc);
|
||||
|
||||
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||
streamSession.put(streamId, transaction);
|
||||
@ -482,7 +487,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
|
||||
content.append("y="+ssrc+"\r\n");//ssrc
|
||||
|
||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null);
|
||||
|
||||
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||
streamSession.put(streamId, transaction);
|
||||
@ -573,24 +579,89 @@ public class SIPCommander implements ISIPCommander {
|
||||
/**
|
||||
* 音视频录像控制
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||
*/
|
||||
@Override
|
||||
public boolean recordCmd(Device device, String channelId) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程启动控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public boolean teleBootCmd(Device device) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null);
|
||||
transmitRequest(device, request);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param guardCmdStr "SetGuard"/"ResetGuard"
|
||||
*/
|
||||
@Override
|
||||
public boolean guardCmd(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -599,9 +670,37 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public boolean alarmCmd(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
|
||||
if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
|
||||
cmdXml.append("<Info>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
|
||||
cmdXml.append("</Info>\r\n");
|
||||
}
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -611,20 +710,79 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
@Override
|
||||
public boolean iFameCmd(Device device, String channelId) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean iFrameCmd(Device device, String channelId) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null);
|
||||
transmitRequest(device, request);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 看守位控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param enabled 看守位使能:1 = 开启,0 = 关闭
|
||||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
@Override
|
||||
public boolean homePositionCmd(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<HomePosition>\r\n");
|
||||
if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
|
||||
cmdXml.append("<Enabled>1</Enabled>\r\n");
|
||||
if (NumericUtil.isInteger(resetTime)) {
|
||||
cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<ResetTime>0</ResetTime>\r\n");
|
||||
}
|
||||
if (NumericUtil.isInteger(presetIndex)) {
|
||||
cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
|
||||
}
|
||||
} else {
|
||||
cmdXml.append("<Enabled>0</Enabled>\r\n");
|
||||
}
|
||||
cmdXml.append("</HomePosition>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -638,15 +796,88 @@ public class SIPCommander implements ISIPCommander {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备配置命令:basicParam
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param name 设备/通道名称(可选)
|
||||
* @param expiration 注册过期时间(可选)
|
||||
* @param heartBeatInterval 心跳间隔时间(可选)
|
||||
* @param heartBeatCount 心跳超时次数(可选)
|
||||
*/
|
||||
@Override
|
||||
public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,
|
||||
String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<BasicParam>\r\n");
|
||||
if (!XmlUtil.isEmpty(name)) {
|
||||
cmdXml.append("<Name>" + name + "</Name>\r\n");
|
||||
}
|
||||
if (NumericUtil.isInteger(expiration)) {
|
||||
if (Integer.valueOf(expiration) > 0) {
|
||||
cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
|
||||
}
|
||||
}
|
||||
if (NumericUtil.isInteger(heartBeatInterval)) {
|
||||
if (Integer.valueOf(heartBeatInterval) > 0) {
|
||||
cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
|
||||
}
|
||||
}
|
||||
if (NumericUtil.isInteger(heartBeatCount)) {
|
||||
if (Integer.valueOf(heartBeatCount) > 0) {
|
||||
cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
|
||||
}
|
||||
}
|
||||
cmdXml.append("</BasicParam>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备状态
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public boolean deviceStatusQuery(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer catalogXml = new StringBuffer(200);
|
||||
catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||
catalogXml.append("<Query>\r\n");
|
||||
catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
|
||||
catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
catalogXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null);
|
||||
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -665,7 +896,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
catalogXml.append("</Query>\r\n");
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDev" + tm, null);
|
||||
|
||||
transmitRequest(device, request);
|
||||
|
||||
@ -694,7 +926,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
catalogXml.append("</Query>\r\n");
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCat" + tm, null);
|
||||
|
||||
transmitRequest(device, request, errorEvent);
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
@ -728,7 +961,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
recordInfoXml.append("<Type>all</Type>\r\n");
|
||||
recordInfoXml.append("</Query>\r\n");
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", null);
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "fromRec" + tm, null);
|
||||
|
||||
transmitRequest(device, request);
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
@ -741,23 +975,86 @@ public class SIPCommander implements ISIPCommander {
|
||||
/**
|
||||
* 查询报警信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethods 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
@Override
|
||||
public boolean alarmInfoQuery(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
|
||||
String startTime, String endTime, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
if (!XmlUtil.isEmpty(startPriority)) {
|
||||
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endPriority)) {
|
||||
cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(startTime)) {
|
||||
cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endTime)) {
|
||||
cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备配置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param configType 配置类型:
|
||||
*/
|
||||
@Override
|
||||
public boolean configQuery(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
|
||||
cmdXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -766,9 +1063,28 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public boolean presetQuery(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
|
||||
transmitRequest(device, request, errorEvent);
|
||||
return true;
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -777,11 +1093,116 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public boolean mobilePostitionQuery(Device device) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
StringBuffer mobilePostitionXml = new StringBuffer(200);
|
||||
mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||
mobilePostitionXml.append("<Query>\r\n");
|
||||
mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
|
||||
mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
mobilePostitionXml.append("<Interval>60</Interval>\r\n");
|
||||
mobilePostitionXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null);
|
||||
|
||||
transmitRequest(device, request, errorEvent);
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅移动位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅超时时间
|
||||
* @param interval 上报时间间隔
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
public boolean mobilePositionSubscribe(Device device, int expires, int interval) {
|
||||
try {
|
||||
StringBuffer subscribePostitionXml = new StringBuffer(200);
|
||||
subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||
subscribePostitionXml.append("<Query>\r\n");
|
||||
subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
|
||||
subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
if (expires > 0) {
|
||||
subscribePostitionXml.append("<Interval>" + String.valueOf(interval) + "</Interval>\r\n");
|
||||
}
|
||||
subscribePostitionXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4));
|
||||
transmitRequest(device, request);
|
||||
|
||||
return true;
|
||||
|
||||
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅报警信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅过期时间(0 = 取消订阅)
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethod 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
|
||||
try {
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
if (!XmlUtil.isEmpty(startPriority)) {
|
||||
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endPriority)) {
|
||||
cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(startTime)) {
|
||||
cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endTime)) {
|
||||
cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
|
||||
String tm = Long.toString(System.currentTimeMillis());
|
||||
Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" );
|
||||
transmitRequest(device, request);
|
||||
|
||||
return true;
|
||||
|
||||
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
||||
return transmitRequest(device, request, null, null);
|
||||
}
|
||||
|
@ -10,19 +10,15 @@ import javax.sip.SipException;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
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.beans.factory.annotation.Autowired;
|
||||
|
||||
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;
|
||||
@ -32,18 +28,31 @@ 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.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 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 com.genersoft.iot.vmp.common.StreamInfo;
|
||||
/**
|
||||
* @Description:MESSAGE请求处理器
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月3日 下午5:32:41
|
||||
*/
|
||||
|
||||
public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
|
||||
private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
||||
|
||||
private SIPCommander cmder;
|
||||
@ -70,9 +79,12 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
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_DEVICE_STATUS = "DeviceStatus";
|
||||
// private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
|
||||
private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
|
||||
private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl";
|
||||
private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig";
|
||||
private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
|
||||
// private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
|
||||
private static final String MESSAGE_PRESET_QUERY = "PresetQuery";
|
||||
|
||||
/**
|
||||
* 处理MESSAGE请求
|
||||
@ -91,12 +103,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
processMessageKeepAlive(evt);
|
||||
} else if (MESSAGE_CONFIG_DOWNLOAD.equals(cmd)) {
|
||||
logger.info("接收到ConfigDownload消息");
|
||||
processMessageConfigDownload(evt);
|
||||
} else if (MESSAGE_CATALOG.equals(cmd)) {
|
||||
logger.info("接收到Catalog消息");
|
||||
processMessageCatalogList(evt);
|
||||
} else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
|
||||
logger.info("接收到DeviceInfo消息");
|
||||
processMessageDeviceInfo(evt);
|
||||
} else if (MESSAGE_DEVICE_STATUS.equals(cmd)) {
|
||||
logger.info("接收到DeviceStatus消息");
|
||||
processMessageDeviceStatus(evt);
|
||||
} else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) {
|
||||
logger.info("接收到DeviceControl消息");
|
||||
processMessageDeviceControl(evt);
|
||||
} else if (MESSAGE_DEVICE_CONFIG.equals(cmd)) {
|
||||
logger.info("接收到DeviceConfig消息");
|
||||
processMessageDeviceConfig(evt);
|
||||
} else if (MESSAGE_ALARM.equals(cmd)) {
|
||||
logger.info("接收到Alarm消息");
|
||||
processMessageAlarm(evt);
|
||||
@ -106,16 +128,239 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}else if (MESSAGE_MEDIA_STATUS.equals(cmd)) {
|
||||
logger.info("接收到MediaStatus消息");
|
||||
processMessageMediaStatus(evt);
|
||||
} else if (MESSAGE_MOBILE_POSITION.equals(cmd)) {
|
||||
logger.info("接收到MobilePosition消息");
|
||||
processMessageMobilePosition(evt);
|
||||
} else if (MESSAGE_PRESET_QUERY.equals(cmd)) {
|
||||
logger.info("接收到PresetQuery消息");
|
||||
processMessagePresetQuery(evt);
|
||||
} else {
|
||||
logger.info("接收到消息:" + cmd);
|
||||
responseAck(evt);
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
} catch (DocumentException | SipException |InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到deviceInfo设备信息请求 处理
|
||||
* 处理MobilePosition移动位置消息
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageMobilePosition(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
MobilePosition mobilePosition = new MobilePosition();
|
||||
Element deviceIdElement = rootElement.element("DeviceID");
|
||||
String deviceId = deviceIdElement.getTextTrim().toString();
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device != null) {
|
||||
if (!StringUtils.isEmpty(device.getName())) {
|
||||
mobilePosition.setDeviceName(device.getName());
|
||||
}
|
||||
}
|
||||
mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID"));
|
||||
mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
|
||||
mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
||||
mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
|
||||
mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
|
||||
} else {
|
||||
mobilePosition.setSpeed(0.0);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
|
||||
mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
|
||||
} else {
|
||||
mobilePosition.setDirection(0.0);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
|
||||
mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
|
||||
} else {
|
||||
mobilePosition.setAltitude(0.0);
|
||||
}
|
||||
mobilePosition.setReportSource("Mobile Position");
|
||||
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);
|
||||
//回复 200 OK
|
||||
responseAck(evt);
|
||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理DeviceStatus设备状态Message
|
||||
*
|
||||
* @param 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);
|
||||
|
||||
if (offLineDetector.isOnline(deviceId)) {
|
||||
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理DeviceControl设备状态Message
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageDeviceControl(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||
String result = XmlUtil.getText(rootElement, "Result");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
if (!XmlUtil.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
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_DEVICECONTROL);
|
||||
msg.setData(json);
|
||||
deferredResultHolder.invokeResult(msg);
|
||||
} else {
|
||||
// 此处是上级发出的DeviceControl指令
|
||||
}
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理DeviceConfig设备状态Message
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageDeviceConfig(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||
String result = XmlUtil.getText(rootElement, "Result");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
//if (!XmlUtil.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
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_DEVICECONFIG);
|
||||
msg.setData(json);
|
||||
deferredResultHolder.invokeResult(msg);
|
||||
// } else {
|
||||
// // 此处是上级发出的DeviceConfig指令
|
||||
//}
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理ConfigDownload设备状态Message
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageConfigDownload(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||
String result = XmlUtil.getText(rootElement, "Result");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
//if (!XmlUtil.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
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_CONFIGDOWNLOAD);
|
||||
msg.setData(json);
|
||||
deferredResultHolder.invokeResult(msg);
|
||||
// } else {
|
||||
// // 此处是上级发出的DeviceConfig指令
|
||||
//}
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理PresetQuery预置位列表Message
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessagePresetQuery(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||
String result = XmlUtil.getText(rootElement, "Result");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
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_PRESETQUERY);
|
||||
msg.setData(json);
|
||||
deferredResultHolder.invokeResult(msg);
|
||||
} else {
|
||||
// 此处是上级发出的DeviceControl指令
|
||||
}
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理DeviceInfo设备信息Message
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
@ -123,7 +368,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
Element deviceIdElement = rootElement.element("DeviceID");
|
||||
String deviceId = deviceIdElement.getText().toString();
|
||||
String deviceId = deviceIdElement.getTextTrim().toString();
|
||||
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device == null) {
|
||||
@ -180,11 +425,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
if (channelDeviceElement == null) {
|
||||
continue;
|
||||
}
|
||||
String channelDeviceId = channelDeviceElement.getText();
|
||||
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.getText().toString() : "ON";
|
||||
String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
|
||||
DeviceChannel deviceChannel = new DeviceChannel();
|
||||
deviceChannel.setName(channelName);
|
||||
deviceChannel.setChannelId(channelDeviceId);
|
||||
@ -238,15 +483,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
|
||||
}
|
||||
deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
|
||||
if (XmlUtil.getText(itemDevice, "Longitude") == null || XmlUtil.getText(itemDevice, "Longitude") == "") {
|
||||
deviceChannel.setLongitude(0.00);
|
||||
} else {
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
|
||||
deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
|
||||
}
|
||||
if (XmlUtil.getText(itemDevice, "Latitude") == null || XmlUtil.getText(itemDevice, "Latitude") =="") {
|
||||
deviceChannel.setLatitude(0.00);
|
||||
} else {
|
||||
deviceChannel.setLongitude(0.00);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
|
||||
deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
|
||||
} else {
|
||||
deviceChannel.setLatitude(0.00);
|
||||
}
|
||||
if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
|
||||
deviceChannel.setPTZType(0);
|
||||
@ -274,8 +519,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}
|
||||
|
||||
/***
|
||||
* 收到alarm设备报警信息 处理
|
||||
*
|
||||
* alarm设备报警信息处理
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageAlarm(RequestEvent evt) {
|
||||
@ -283,48 +527,72 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
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;
|
||||
}
|
||||
|
||||
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 (XmlUtil.getText(rootElement, "Longitude") == null || XmlUtil.getText(rootElement, "Longitude") == "") {
|
||||
deviceAlarm.setLongitude(0.00);
|
||||
} else {
|
||||
deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
||||
}
|
||||
if (XmlUtil.getText(rootElement, "Latitude") == null || XmlUtil.getText(rootElement, "Latitude") =="") {
|
||||
deviceAlarm.setLatitude(0.00);
|
||||
} else {
|
||||
deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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.deviceAlarmEventPublish(deviceAlarm);
|
||||
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);
|
||||
}
|
||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||
// } catch (DocumentException e) {
|
||||
@ -350,14 +618,13 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* 收到catalog设备目录列表请求 处理 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致
|
||||
* 处理RecordInfo设备录像列表Message请求 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
@ -444,12 +711,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
// 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作
|
||||
// 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据
|
||||
|
||||
// 对记录进行排序
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setDeviceId(deviceId);
|
||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
|
||||
// // 自然顺序排序, 元素进行升序排列
|
||||
// recordInfo.getRecordList().sort(Comparator.naturalOrder());
|
||||
msg.setData(recordInfo);
|
||||
deferredResultHolder.invokeResult(msg);
|
||||
logger.info("处理完成,返回结果");
|
||||
@ -458,7 +722,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 收到MediaStatus消息处理
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processMessageMediaStatus(RequestEvent evt){
|
||||
try {
|
||||
// 回复200 OK
|
||||
|
@ -0,0 +1,385 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.text.ParseException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
|
||||
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.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.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* @Description: Notify请求处理器
|
||||
* @author: lawrencehj
|
||||
* @date: 2021年1月27日
|
||||
*/
|
||||
|
||||
public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
|
||||
private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
||||
|
||||
private SIPCommander cmder;
|
||||
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
private EventPublisher publisher;
|
||||
|
||||
private RedisUtil redis;
|
||||
|
||||
private DeferredResultHolder deferredResultHolder;
|
||||
|
||||
private DeviceOffLineDetector offLineDetector;
|
||||
|
||||
private static final String NOTIFY_CATALOG = "Catalog";
|
||||
private static final String NOTIFY_ALARM = "Alarm";
|
||||
private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
|
||||
|
||||
@Override
|
||||
public void process(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
String cmd = XmlUtil.getText(rootElement, "CmdType");
|
||||
|
||||
if (NOTIFY_CATALOG.equals(cmd)) {
|
||||
logger.info("接收到Catalog通知");
|
||||
processNotifyCatalogList(evt);
|
||||
} else if (NOTIFY_ALARM.equals(cmd)) {
|
||||
logger.info("接收到Alarm通知");
|
||||
processNotifyAlarm(evt);
|
||||
} else if (NOTIFY_MOBILE_POSITION.equals(cmd)) {
|
||||
logger.info("接收到MobilePosition通知");
|
||||
processNotifyMobilePosition(evt);
|
||||
} else {
|
||||
logger.info("接收到消息:" + cmd);
|
||||
response200Ok(evt);
|
||||
}
|
||||
} catch (DocumentException | SipException |InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理MobilePosition移动位置Notify
|
||||
* @param evt
|
||||
*/
|
||||
private void processNotifyMobilePosition(RequestEvent evt) {
|
||||
try {
|
||||
//回复 200 OK
|
||||
Element rootElement = getRootElement(evt);
|
||||
MobilePosition mobilePosition = new MobilePosition();
|
||||
Element deviceIdElement = rootElement.element("DeviceID");
|
||||
String deviceId = deviceIdElement.getTextTrim().toString();
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device != null) {
|
||||
if (!StringUtils.isEmpty(device.getName())) {
|
||||
mobilePosition.setDeviceName(device.getName());
|
||||
}
|
||||
}
|
||||
mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID"));
|
||||
mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
|
||||
mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
||||
mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
|
||||
mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
|
||||
} else {
|
||||
mobilePosition.setSpeed(0.0);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
|
||||
mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
|
||||
} else {
|
||||
mobilePosition.setDirection(0.0);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
|
||||
mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
|
||||
} else {
|
||||
mobilePosition.setAltitude(0.0);
|
||||
}
|
||||
mobilePosition.setReportSource("Mobile Position");
|
||||
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);
|
||||
response200Ok(evt);
|
||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* 处理alarm设备报警Notify
|
||||
* @param evt
|
||||
*/
|
||||
private void processNotifyAlarm(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
Element deviceIdElement = rootElement.element("DeviceID");
|
||||
String deviceId = deviceIdElement.getText().toString();
|
||||
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
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 ( 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: 需要实现存储报警信息、报警分类
|
||||
|
||||
// 回复200 OK
|
||||
response200Ok(evt);
|
||||
if (offLineDetector.isOnline(deviceId)) {
|
||||
publisher.deviceAlarmEventPublish(deviceAlarm);
|
||||
}
|
||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* 处理catalog设备目录列表Notify
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
private void processNotifyCatalogList(RequestEvent evt) {
|
||||
try {
|
||||
Element rootElement = getRootElement(evt);
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
// 遍历DeviceList
|
||||
while (deviceListIterator.hasNext()) {
|
||||
Element itemDevice = deviceListIterator.next();
|
||||
Element channelDeviceElement = itemDevice.element("DeviceID");
|
||||
if (channelDeviceElement == null) {
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
|
||||
deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
|
||||
deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
|
||||
deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
|
||||
deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
|
||||
deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
|
||||
if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") {
|
||||
deviceChannel.setParental(0);
|
||||
} else {
|
||||
deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
|
||||
}
|
||||
deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
|
||||
if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay")== "") {
|
||||
deviceChannel.setSafetyWay(0);
|
||||
} else {
|
||||
deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
|
||||
}
|
||||
if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") =="") {
|
||||
deviceChannel.setRegisterWay(1);
|
||||
} else {
|
||||
deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
|
||||
}
|
||||
deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
|
||||
if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") {
|
||||
deviceChannel.setCertifiable(0);
|
||||
} else {
|
||||
deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
|
||||
}
|
||||
if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") {
|
||||
deviceChannel.setErrCode(0);
|
||||
} else {
|
||||
deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
|
||||
}
|
||||
deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
|
||||
deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
|
||||
deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
|
||||
if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") =="") {
|
||||
deviceChannel.setPort(0);
|
||||
} else {
|
||||
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 {
|
||||
deviceChannel.setLongitude(0.00);
|
||||
}
|
||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
|
||||
deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
|
||||
} else {
|
||||
deviceChannel.setLatitude(0.00);
|
||||
}
|
||||
if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
|
||||
deviceChannel.setPTZType(0);
|
||||
} else {
|
||||
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
|
||||
}
|
||||
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
||||
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
||||
}
|
||||
|
||||
// RequestMessage msg = new RequestMessage();
|
||||
// msg.setDeviceId(deviceId);
|
||||
// msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
||||
// msg.setData(device);
|
||||
// deferredResultHolder.invokeResult(msg);
|
||||
// 回复200 OK
|
||||
response200Ok(evt);
|
||||
if (offLineDetector.isOnline(deviceId)) {
|
||||
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||
}
|
||||
}
|
||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* 回复200 OK
|
||||
* @param evt
|
||||
* @throws SipException
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ParseException
|
||||
*/
|
||||
private void response200Ok(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
||||
getServerTransaction(evt).sendResponse(response);
|
||||
}
|
||||
|
||||
private Element getRootElement(RequestEvent evt) throws DocumentException {
|
||||
Request request = evt.getRequest();
|
||||
SAXReader reader = new SAXReader();
|
||||
reader.setEncoding("gbk");
|
||||
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
||||
return xml.getRootElement();
|
||||
}
|
||||
|
||||
public void setCmder(SIPCommander cmder) {
|
||||
this.cmder = cmder;
|
||||
}
|
||||
|
||||
public void setStorager(IVideoManagerStorager storager) {
|
||||
this.storager = storager;
|
||||
}
|
||||
|
||||
public void setPublisher(EventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
public void setRedis(RedisUtil redis) {
|
||||
this.redis = redis;
|
||||
}
|
||||
|
||||
public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {
|
||||
this.deferredResultHolder = deferredResultHolder;
|
||||
}
|
||||
|
||||
public void setOffLineDetector(DeviceOffLineDetector offLineDetector) {
|
||||
this.offLineDetector = offLineDetector;
|
||||
}
|
||||
|
||||
public IRedisCatchStorage getRedisCatchStorage() {
|
||||
return redisCatchStorage;
|
||||
}
|
||||
|
||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
||||
this.redisCatchStorage = redisCatchStorage;
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ public class OtherRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
*/
|
||||
@Override
|
||||
public void process(RequestEvent evt) {
|
||||
System.out.println("no support the method! Method:" + evt.getRequest().getMethod());
|
||||
System.out.println("Unsupported the method: " + evt.getRequest().getMethod());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.genersoft.iot.vmp.gb28181.utils;
|
||||
|
||||
/**
|
||||
* 数值格式判断和处理
|
||||
* @author lawrencehj
|
||||
* @date 2021年1月27日
|
||||
*/
|
||||
public class NumericUtil {
|
||||
|
||||
/**
|
||||
* 判断是否Double格式
|
||||
* @param str
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isDouble(String str) {
|
||||
try {
|
||||
Double num2 = Double.valueOf(str);
|
||||
System.out.println(num2 + " Is an Integer!");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
System.out.println(str + " Is not an Integer!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否Double格式
|
||||
* @param str
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isInteger(String str) {
|
||||
try {
|
||||
int num2 = Integer.valueOf(str);
|
||||
System.out.println(num2 + " Is Number!");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
System.out.println(str + " Is not Number!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import org.dom4j.Attribute;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
@ -20,8 +23,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class XmlUtil
|
||||
{
|
||||
public class XmlUtil {
|
||||
/**
|
||||
* 日志服务
|
||||
*/
|
||||
@ -30,22 +32,18 @@ public class XmlUtil
|
||||
/**
|
||||
* 解析XML为Document对象
|
||||
*
|
||||
* @param xml
|
||||
* 被解析的XMl
|
||||
* @param xml 被解析的XMl
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public static Element parseXml(String xml)
|
||||
{
|
||||
public static Element parseXml(String xml) {
|
||||
Document document = null;
|
||||
//
|
||||
StringReader sr = new StringReader(xml);
|
||||
SAXReader saxReader = new SAXReader();
|
||||
try
|
||||
{
|
||||
try {
|
||||
document = saxReader.read(sr);
|
||||
}
|
||||
catch (DocumentException e)
|
||||
{
|
||||
} catch (DocumentException e) {
|
||||
LOG.error("解析失败", e);
|
||||
}
|
||||
return null == document ? null : document.getRootElement();
|
||||
@ -54,16 +52,12 @@ public class XmlUtil
|
||||
/**
|
||||
* 获取element对象的text的值
|
||||
*
|
||||
* @param em
|
||||
* 节点的对象
|
||||
* @param tag
|
||||
* 节点的tag
|
||||
* @param em 节点的对象
|
||||
* @param tag 节点的tag
|
||||
* @return 节点
|
||||
*/
|
||||
public static String getText(Element em, String tag)
|
||||
{
|
||||
if (null == em)
|
||||
{
|
||||
public static String getText(Element em, String tag) {
|
||||
if (null == em) {
|
||||
return null;
|
||||
}
|
||||
Element e = em.element(tag);
|
||||
@ -74,16 +68,12 @@ public class XmlUtil
|
||||
/**
|
||||
* 递归解析xml节点,适用于 多节点数据
|
||||
*
|
||||
* @param node
|
||||
* node
|
||||
* @param nodeName
|
||||
* nodeName
|
||||
* @param node node
|
||||
* @param nodeName nodeName
|
||||
* @return List<Map<String, Object>>
|
||||
*/
|
||||
public static List<Map<String, Object>> listNodes(Element node, String nodeName)
|
||||
{
|
||||
if (null == node)
|
||||
{
|
||||
public static List<Map<String, Object>> listNodes(Element node, String nodeName) {
|
||||
if (null == node) {
|
||||
return null;
|
||||
}
|
||||
// 初始化返回
|
||||
@ -93,12 +83,9 @@ public class XmlUtil
|
||||
|
||||
Map<String, Object> map = null;
|
||||
// 遍历属性节点
|
||||
for (Attribute attribute : list)
|
||||
{
|
||||
if (nodeName.equals(node.getName()))
|
||||
{
|
||||
if (null == map)
|
||||
{
|
||||
for (Attribute attribute : list) {
|
||||
if (nodeName.equals(node.getName())) {
|
||||
if (null == map) {
|
||||
map = new HashMap<String, Object>();
|
||||
listMap.add(map);
|
||||
}
|
||||
@ -110,12 +97,74 @@ public class XmlUtil
|
||||
// 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称
|
||||
// 使用递归
|
||||
Iterator<Element> iterator = node.elementIterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
while (iterator.hasNext()) {
|
||||
Element e = iterator.next();
|
||||
listMap.addAll(listNodes(e, nodeName));
|
||||
}
|
||||
return listMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* xml转json
|
||||
*
|
||||
* @param element
|
||||
* @param json
|
||||
*/
|
||||
public static void node2Json(Element element, JSONObject json) {
|
||||
// 如果是属性
|
||||
for (Object o : element.attributes()) {
|
||||
Attribute attr = (Attribute) o;
|
||||
if (!isEmpty(attr.getValue())) {
|
||||
json.put("@" + attr.getName(), attr.getValue());
|
||||
}
|
||||
}
|
||||
List<Element> chdEl = element.elements();
|
||||
if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 如果没有子元素,只有一个值
|
||||
json.put(element.getName(), element.getText());
|
||||
}
|
||||
|
||||
for (Element e : chdEl) { // 有子元素
|
||||
if (!e.elements().isEmpty()) { // 子元素也有子元素
|
||||
JSONObject chdjson = new JSONObject();
|
||||
node2Json(e, chdjson);
|
||||
Object o = json.get(e.getName());
|
||||
if (o != null) {
|
||||
JSONArray jsona = null;
|
||||
if (o instanceof JSONObject) { // 如果此元素已存在,则转为jsonArray
|
||||
JSONObject jsono = (JSONObject) o;
|
||||
json.remove(e.getName());
|
||||
jsona = new JSONArray();
|
||||
jsona.add(jsono);
|
||||
jsona.add(chdjson);
|
||||
}
|
||||
if (o instanceof JSONArray) {
|
||||
jsona = (JSONArray) o;
|
||||
jsona.add(chdjson);
|
||||
}
|
||||
json.put(e.getName(), jsona);
|
||||
} else {
|
||||
if (!chdjson.isEmpty()) {
|
||||
json.put(e.getName(), chdjson);
|
||||
}
|
||||
}
|
||||
} else { // 子元素没有子元素
|
||||
for (Object o : element.attributes()) {
|
||||
Attribute attr = (Attribute) o;
|
||||
if (!isEmpty(attr.getValue())) {
|
||||
json.put("@" + attr.getName(), attr.getValue());
|
||||
}
|
||||
}
|
||||
if (!e.getText().isEmpty()) {
|
||||
json.put(e.getName(), e.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String str) {
|
||||
if (str == null || str.trim().isEmpty() || "null".equals(str)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import java.util.List;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
/**
|
||||
@ -151,4 +152,30 @@ public interface IVideoManagerStorager {
|
||||
*/
|
||||
void cleanChannelsForDevice(String deviceId);
|
||||
|
||||
/**
|
||||
* 添加Mobile Position设备移动位置
|
||||
* @param MobilePosition
|
||||
* @return
|
||||
*/
|
||||
public boolean insertMobilePosition(MobilePosition mobilePosition);
|
||||
|
||||
/**
|
||||
* 查询移动位置轨迹
|
||||
* @param deviceId
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
*/
|
||||
public List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime);
|
||||
|
||||
/**
|
||||
* 查询最新移动位置
|
||||
* @param deviceId
|
||||
*/
|
||||
public MobilePosition queryLatestPosition(String deviceId);
|
||||
|
||||
/**
|
||||
* 删除指定设备的所有移动位置
|
||||
* @param deviceId
|
||||
*/
|
||||
public int clearMobilePositionsByDeviceId(String deviceId);
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.genersoft.iot.vmp.storager.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
//import org.springframework.stereotype.Repository;
|
||||
|
||||
@Mapper
|
||||
//@Repository
|
||||
public interface DeviceMobilePositionMapper {
|
||||
|
||||
@Insert("INSERT INTO device_mobile_position (deviceId, deviceName, time, longitude, latitude, altitude, speed, direction, reportSource, geodeticSystem, cnLng, cnLat) " +
|
||||
"VALUES ('${deviceId}', '${deviceName}', '${time}', ${longitude}, ${latitude}, ${altitude}, ${speed}, ${direction}, '${reportSource}', '${geodeticSystem}', '${cnLng}', '${cnLat}')")
|
||||
int insertNewPosition(MobilePosition mobilePosition);
|
||||
|
||||
@Select(value = {" <script>" +
|
||||
"SELECT * FROM device_mobile_position" +
|
||||
" WHERE deviceId = #{deviceId} " +
|
||||
"<if test=\"startTime != null\"> AND time>=#{startTime}</if>" +
|
||||
"<if test=\"endTime != null\"> AND time<=#{endTime}</if>" +
|
||||
" ORDER BY time ASC" +
|
||||
" </script>"})
|
||||
List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String startTime, String endTime);
|
||||
|
||||
@Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" +
|
||||
" ORDER BY time DESC LIMIT 1")
|
||||
MobilePosition queryLatestPositionByDevice(String deviceId);
|
||||
|
||||
@Delete("DELETE FROM device_mobile_position WHERE deviceId = #{deviceId}")
|
||||
int clearMobilePositionsByDeviceId(String deviceId);
|
||||
|
||||
}
|
@ -3,8 +3,10 @@ package com.genersoft.iot.vmp.storager.impl;
|
||||
import java.util.*;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.models.auth.In;
|
||||
@ -27,7 +29,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceChannelMapper deviceChannelMapper;
|
||||
private DeviceChannelMapper deviceChannelMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceMobilePositionMapper deviceMobilePositionMapper;
|
||||
|
||||
|
||||
/**
|
||||
@ -200,11 +205,49 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
||||
return deviceMapper.update(device) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空通道
|
||||
* @param deviceId
|
||||
*/
|
||||
@Override
|
||||
public void cleanChannelsForDevice(String deviceId) {
|
||||
int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Mobile Position设备移动位置
|
||||
* @param MobilePosition
|
||||
*/
|
||||
@Override
|
||||
public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) {
|
||||
return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询移动位置轨迹
|
||||
* @param deviceId
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
*/
|
||||
@Override
|
||||
public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime) {
|
||||
return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最新移动位置
|
||||
* @param deviceId
|
||||
*/
|
||||
@Override
|
||||
public MobilePosition queryLatestPosition(String deviceId) {
|
||||
return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定设备的所有移动位置
|
||||
* @param deviceId
|
||||
*/
|
||||
public int clearMobilePositionsByDeviceId(String deviceId) {
|
||||
return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
|
||||
}
|
||||
}
|
||||
|
68
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java
Normal file
68
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java
Normal file
@ -0,0 +1,68 @@
|
||||
package com.genersoft.iot.vmp.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.Base64;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
|
||||
|
||||
public class GpsUtil {
|
||||
public static BaiduPoint Wgs84ToBd09(String xx, String yy) {
|
||||
try {
|
||||
Socket s = new Socket("api.map.baidu.com", 80);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
|
||||
OutputStream out = s.getOutputStream();
|
||||
StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");
|
||||
sb.append("&x=" + xx + "&y=" + yy);
|
||||
sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
|
||||
sb.append("User-Agent: Java/1.6.0_20\r\n");
|
||||
sb.append("Host: api.map.baidu.com:80\r\n");
|
||||
sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
|
||||
sb.append("Connection: Close\r\n");
|
||||
sb.append("\r\n");
|
||||
out.write(sb.toString().getBytes());
|
||||
String json = "";
|
||||
String tmp = "";
|
||||
while ((tmp = br.readLine()) != null) {
|
||||
// System.out.println(tmp);
|
||||
json += tmp;
|
||||
}
|
||||
|
||||
s.close();
|
||||
int start = json.indexOf("cbk_3976");
|
||||
int end = json.lastIndexOf("}");
|
||||
if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
|
||||
json = json.substring(start, end);
|
||||
String[] point = json.split(",");
|
||||
String x = point[1].split(":")[1].replace("\"", "");
|
||||
String y = point[2].split(":")[1].replace("\"", "");
|
||||
BaiduPoint bdPoint= new BaiduPoint();
|
||||
bdPoint.setBdLng(new String(decode(x)));
|
||||
bdPoint.setBdLat(new String(decode(y)));
|
||||
return bdPoint;
|
||||
//return (new String(decode(x)) + "," + new String(decode(y)));
|
||||
} else {
|
||||
System.out.println("gps坐标无效!!");
|
||||
}
|
||||
out.close();
|
||||
br.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* BASE64解码
|
||||
* @param str
|
||||
* @return string
|
||||
*/
|
||||
public static byte[] decode(String str) {
|
||||
byte[] bt = null;
|
||||
final Base64.Decoder decoder = Base64.getDecoder();
|
||||
bt = decoder.decode(str); // .decodeBuffer(str);
|
||||
return bt;
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package com.genersoft.iot.vmp.vmanager.MobilePosition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
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.storager.IVideoManagerStorager;
|
||||
import com.github.pagehelper.util.StringUtil;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class MobilePositionController {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(MobilePositionController.class);
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
||||
@GetMapping("/positions/{deviceId}/history")
|
||||
public ResponseEntity<List<MobilePosition>> positions(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String start,
|
||||
@RequestParam(required = false) String end) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("查询设备" + deviceId + "的历史轨迹");
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(start)) {
|
||||
start = null;
|
||||
}
|
||||
if (StringUtil.isEmpty(end)) {
|
||||
end = null;
|
||||
}
|
||||
|
||||
List<MobilePosition> result = storager.queryMobilePositions(deviceId, start, end);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/positions/{deviceId}/latest")
|
||||
public ResponseEntity<MobilePosition> latestPosition(@PathVariable String deviceId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("查询设备" + deviceId + "的最新位置");
|
||||
}
|
||||
MobilePosition result = storager.queryLatestPosition(deviceId);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/positions/{deviceId}/realtime")
|
||||
public DeferredResult<ResponseEntity<MobilePosition>> realTimePosition(@PathVariable String deviceId) {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.mobilePostitionQuery(device, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId);
|
||||
msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<MobilePosition>> result = new DeferredResult<ResponseEntity<MobilePosition>>(5*1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取移动位置信息超时"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
|
||||
msg.setData("Timeout");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping("/positions/{deviceId}/subscribe")
|
||||
public ResponseEntity<String> positionSubscribe(@PathVariable String deviceId,
|
||||
@RequestParam String expires,
|
||||
@RequestParam String interval) {
|
||||
String msg = ((expires.equals("0")) ? "取消" : "") + "订阅设备" + deviceId + "的移动位置";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(msg);
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(interval)) {
|
||||
interval = "5";
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
|
||||
String result = msg;
|
||||
if (cmder.mobilePositionSubscribe(device, Integer.parseInt(expires), Integer.parseInt(interval))) {
|
||||
result += ",成功";
|
||||
} else {
|
||||
result += ",失败";
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.SseController;
|
||||
import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
@ -13,6 +14,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
* @data: 2021-01-20
|
||||
*/
|
||||
|
||||
@CrossOrigin
|
||||
@Controller
|
||||
@RequestMapping("/api")
|
||||
public class SseController {
|
||||
|
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 设备设置命令API接口
|
||||
*
|
||||
* @author lawrencehj
|
||||
* @date 2021年2月2日
|
||||
*/
|
||||
|
||||
package com.genersoft.iot.vmp.vmanager.device;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
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.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class DeviceConfig {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
||||
/**
|
||||
* 看守位控制命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param enabled 看守位使能1:开启,0:关闭
|
||||
* @param resetTime 自动归位时间间隔(可选)
|
||||
* @param presetIndex 调用预置位编号(可选)
|
||||
* @param channelId 通道编码(可选)
|
||||
*/
|
||||
@GetMapping("/config/{deviceId}/basicParam")
|
||||
public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String channelId,
|
||||
@RequestParam(required = false) String name,
|
||||
@RequestParam(required = false) String expiration,
|
||||
@RequestParam(required = false) String heartBeatInterval,
|
||||
@RequestParam(required = false) String heartBeatCount) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("报警复位API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData(String.format("设备配置操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("DeviceID", deviceId);
|
||||
json.put("Status", "Timeout");
|
||||
json.put("Description", "设备配置操作超时, 设备未返回应答指令");
|
||||
msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备配置查询请求API接口
|
||||
*
|
||||
* @param deviceId
|
||||
*/
|
||||
@GetMapping("/config/{deviceId}/query/{configType}")
|
||||
public DeferredResult<ResponseEntity<String>> configDownloadApi(@PathVariable String deviceId,
|
||||
@PathVariable String configType,
|
||||
@RequestParam(required = false) String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备状态查询API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.deviceConfigQuery(device, channelId, configType, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData(String.format("获取设备配置失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取设备配置超时"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData("Timeout. Device did not response to this command.");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* 设备控制命令API接口
|
||||
*
|
||||
* @author lawrencehj
|
||||
* @date 2021年2月1日
|
||||
*/
|
||||
|
||||
package com.genersoft.iot.vmp.vmanager.device;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
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.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class DeviceControl {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
||||
/**
|
||||
* 远程启动控制命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/teleboot")
|
||||
@PostMapping("/control/{deviceId}/teleboot")
|
||||
public ResponseEntity<String> teleBootApi(@PathVariable String deviceId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备远程启动API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
boolean sucsess = cmder.teleBootCmd(device);
|
||||
if (sucsess) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("DeviceID", deviceId);
|
||||
json.put("Result", "OK");
|
||||
return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
|
||||
} else {
|
||||
logger.warn("设备远程启动API调用失败!");
|
||||
return new ResponseEntity<String>("设备远程启动API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 录像控制命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param recordCmdStr Record:手动录像,StopRecord:停止手动录像
|
||||
* @param channelId 通道编码(可选)
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/record/{recordCmdStr}")
|
||||
public DeferredResult<ResponseEntity<String>> recordApi(@PathVariable String deviceId,
|
||||
@PathVariable String recordCmdStr, @RequestParam(required = false) String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("开始/停止录像API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.recordCmd(device, channelId, recordCmdStr, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData("Timeout. Device did not response to this command.");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param guardCmdStr SetGuard:布防,ResetGuard:撤防
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/guard/{guardCmdStr}")
|
||||
public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("布防/撤防API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.guardCmd(device, guardCmdStr, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
|
||||
msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
|
||||
msg.setData("Timeout. Device did not response to this command.");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警复位API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param alarmMethod 报警方式(可选)
|
||||
* @param alarmType 报警类型(可选)
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/resetAlarm")
|
||||
public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String alarmMethod,
|
||||
@RequestParam(required = false) String alarmType) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("报警复位API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
|
||||
msg.setData(String.format("报警复位操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
|
||||
msg.setData("Timeout. Device did not response to this command.");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制关键帧API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param channelId
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/iFrame")
|
||||
@PostMapping("/control/{deviceId}/iFrame")
|
||||
public ResponseEntity<String> iFrame(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("强制关键帧API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
boolean sucsess = cmder.iFrameCmd(device, channelId);
|
||||
if (sucsess) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("DeviceID", deviceId);
|
||||
json.put("ChannelID", channelId);
|
||||
json.put("Result", "OK");
|
||||
return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
|
||||
} else {
|
||||
logger.warn("强制关键帧API调用失败!");
|
||||
return new ResponseEntity<String>("强制关键帧API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 看守位控制命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param enabled 看守位使能1:开启,0:关闭
|
||||
* @param resetTime 自动归位时间间隔(可选)
|
||||
* @param presetIndex 调用预置位编号(可选)
|
||||
* @param channelId 通道编码(可选)
|
||||
*/
|
||||
@GetMapping("/control/{deviceId}/homePosition/{enabled}")
|
||||
public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
|
||||
@PathVariable String enabled,
|
||||
@RequestParam(required = false) String resetTime,
|
||||
@RequestParam(required = false) String presetIndex,
|
||||
@RequestParam(required = false) String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("报警复位API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("DeviceID", deviceId);
|
||||
json.put("Status", "Timeout");
|
||||
json.put("Description", "看守位控制操作超时, 设备未返回应答指令");
|
||||
msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
@ -24,9 +25,9 @@ import javax.sip.message.Response;
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class DeviceController {
|
||||
public class DeviceQuery {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceController.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
@ -77,11 +78,9 @@ public class DeviceController {
|
||||
int page, int count,
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Boolean online,
|
||||
@RequestParam(required = false) Boolean channelType
|
||||
){
|
||||
|
||||
@RequestParam(required = false) Boolean channelType) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("查询所有视频设备API调用");
|
||||
logger.debug("查询视频设备通道API调用");
|
||||
}
|
||||
if (StringUtils.isEmpty(query)) {
|
||||
query = null;
|
||||
@ -135,8 +134,8 @@ public class DeviceController {
|
||||
json.put("deviceId", deviceId);
|
||||
return new ResponseEntity<>(json.toString(),HttpStatus.OK);
|
||||
} else {
|
||||
logger.warn("设备预览API调用失败!");
|
||||
return new ResponseEntity<String>("设备预览API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
logger.warn("设备信息删除API调用失败!");
|
||||
return new ResponseEntity<String>("设备信息删除API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +156,7 @@ public class DeviceController {
|
||||
@RequestParam(required = false) Boolean channelType){
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("查询所有视频设备API调用");
|
||||
logger.debug("查询所有视频通道API调用");
|
||||
}
|
||||
DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
|
||||
if (deviceChannel == null) {
|
||||
@ -183,4 +182,74 @@ public class DeviceController {
|
||||
storager.updateDevice(device);
|
||||
return new ResponseEntity<>(null,HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备状态查询请求API接口
|
||||
*
|
||||
* @param deviceId
|
||||
*/
|
||||
@GetMapping("/devices/{deviceId}/status")
|
||||
public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备状态查询API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.deviceStatusQuery(device, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
|
||||
msg.setData(String.format("获取设备状态失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取设备状态超时"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
|
||||
msg.setData("Timeout. Device did not response to this command.");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备报警查询请求API接口
|
||||
*
|
||||
* @param deviceId
|
||||
*/
|
||||
@GetMapping("/alarm/{deviceId}")
|
||||
public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String startPriority,
|
||||
@RequestParam(required = false) String endPriority,
|
||||
@RequestParam(required = false) String alarmMethod,
|
||||
@RequestParam(required = false) String alarmType,
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备报警查询API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
|
||||
msg.setData(String.format("设备报警查询失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("设备报警查询超时"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
|
||||
msg.setData("设备报警查询超时");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -5,14 +5,16 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
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.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
|
||||
@CrossOrigin
|
||||
@ -28,6 +30,9 @@ public class PtzController {
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
||||
/***
|
||||
* 云台控制
|
||||
* @param deviceId 设备id
|
||||
@ -49,16 +54,18 @@ public class PtzController {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||
return new ResponseEntity<String>("success",HttpStatus.OK);
|
||||
}
|
||||
// public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){
|
||||
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed));
|
||||
// }
|
||||
// Device device = storager.queryVideoDevice(deviceId);
|
||||
|
||||
// cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
|
||||
// return new ResponseEntity<String>("success",HttpStatus.OK);
|
||||
// }
|
||||
/**
|
||||
* 通用前端控制命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param channelId
|
||||
* @param cmdCode
|
||||
* @param parameter1
|
||||
* @param parameter2
|
||||
* @param combindCode2
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/frontEndCommand/{deviceId}/{channelId}")
|
||||
public ResponseEntity<String> frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
|
||||
|
||||
@ -70,4 +77,37 @@ public class PtzController {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||
return new ResponseEntity<String>("success",HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预置位查询命令API接口
|
||||
*
|
||||
* @param deviceId
|
||||
* @param channelId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/presetQuery/{deviceId}/{channelId}")
|
||||
public DeferredResult<ResponseEntity<String>> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备预置位查询API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
cmder.presetQuery(device, channelId, event -> {
|
||||
Response response = event.getResponse();
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取设备预置位超时"));
|
||||
// 释放rtpserver
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
|
||||
msg.setData("获取设备预置位超时");
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -35,18 +35,18 @@ server:
|
||||
# 作为28181服务器的配置
|
||||
sip:
|
||||
# [必须修改] 本机的IP, 必须是网卡上的IP
|
||||
ip: 192.168.1.44
|
||||
ip: 192.168.0.100
|
||||
# [可选] 28181服务监听的端口
|
||||
port: 5060
|
||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||
# 后两位为行业编码,定义参照附录D.3
|
||||
# 3701020049标识山东济南历下区 信息行业接入
|
||||
# [可选]
|
||||
domain: 3402000000
|
||||
domain: 4401020049
|
||||
# [可选]
|
||||
id: 34020000002000000001
|
||||
id: 44010200492000000001
|
||||
# [可选] 默认设备认证密码,后续扩展使用设备单独密码
|
||||
password: 12345678
|
||||
password: admin123
|
||||
|
||||
# 登陆的用户名密码
|
||||
auth:
|
||||
@ -58,7 +58,7 @@ auth:
|
||||
#zlm服务器配置
|
||||
media:
|
||||
# [必须修改] zlm服务器的内网IP
|
||||
ip: 192.168.1.44
|
||||
ip: 192.168.0.100
|
||||
# [可选] zlm服务器的公网IP, 内网部署置空即可
|
||||
wanIp:
|
||||
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
|
||||
@ -70,9 +70,9 @@ media:
|
||||
# [可选] zlm服务器的hook.admin_params=secret
|
||||
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||
# [可选] zlm服务器的general.streamNoneReaderDelayMS
|
||||
streamNoneReaderDelayMS: 600000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流
|
||||
streamNoneReaderDelayMS: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流
|
||||
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
||||
autoApplyPlay: true
|
||||
autoApplyPlay: false
|
||||
# [可选] 部分设备需要扩展SDP,需要打开此设置
|
||||
seniorSdp: false
|
||||
# 启用udp多端口模式, 详细解释参考: https://github.com/xia-chu/ZLMediaKit/wiki/GB28181%E6%8E%A8%E6%B5%81 下的高阶使用
|
||||
@ -93,3 +93,7 @@ logging:
|
||||
com:
|
||||
genersoft:
|
||||
iot: debug
|
||||
# [根据业务需求配置]
|
||||
userSettings:
|
||||
# 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
|
||||
savePositionHistory: false
|
Binary file not shown.
@ -7,6 +7,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="./js/EasyWasmPlayer.js"></script>
|
||||
<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=rk73w8dv1rkE4UdZsataG68VarhYQzrx&s=1"></script>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
80
web_src/package-lock.json
generated
80
web_src/package-lock.json
generated
@ -1269,6 +1269,34 @@
|
||||
"integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=",
|
||||
"dev": true
|
||||
},
|
||||
"bmaplib.curveline": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
|
||||
"integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
|
||||
},
|
||||
"bmaplib.heatmap": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
|
||||
"integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
|
||||
},
|
||||
"bmaplib.lushu": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz",
|
||||
"integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w=="
|
||||
},
|
||||
"bmaplib.markerclusterer": {
|
||||
"version": "1.0.13",
|
||||
"resolved": "https://registry.npmjs.org/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
|
||||
"integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
|
||||
"requires": {
|
||||
"bmaplib.texticonoverlay": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"bmaplib.texticonoverlay": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
|
||||
"integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.3.tgz",
|
||||
@ -5266,6 +5294,14 @@
|
||||
"invert-kv": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"linkify-it": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
||||
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
||||
"requires": {
|
||||
"uc.micro": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz",
|
||||
@ -5443,6 +5479,25 @@
|
||||
"object-visit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"markdown-it": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
|
||||
"integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"entities": "~1.1.1",
|
||||
"linkify-it": "^2.0.0",
|
||||
"mdurl": "^1.0.1",
|
||||
"uc.micro": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"math-expression-evaluator": {
|
||||
"version": "1.2.22",
|
||||
"resolved": "https://registry.npm.taobao.org/math-expression-evaluator/download/math-expression-evaluator-1.2.22.tgz",
|
||||
@ -5466,6 +5521,11 @@
|
||||
"integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=",
|
||||
"dev": true
|
||||
},
|
||||
"mdurl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
|
||||
@ -10074,8 +10134,7 @@
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"ssri": {
|
||||
"version": "5.3.0",
|
||||
@ -10489,6 +10548,11 @@
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||
"dev": true
|
||||
},
|
||||
"uc.micro": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.10",
|
||||
"resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1601823880483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz",
|
||||
@ -10841,6 +10905,18 @@
|
||||
"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600441238751&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
|
||||
"integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
|
||||
},
|
||||
"vue-baidu-map": {
|
||||
"version": "0.21.22",
|
||||
"resolved": "https://registry.npmjs.org/vue-baidu-map/-/vue-baidu-map-0.21.22.tgz",
|
||||
"integrity": "sha512-WQMPCih4UTh0AZCKKH/OVOYnyAWjfRNeK6BIeoLmscyY5aF8zzlJhz/NOHLb3mdztIpB0Z6aohn4Jd9mfCSjQw==",
|
||||
"requires": {
|
||||
"bmaplib.curveline": "^1.0.0",
|
||||
"bmaplib.heatmap": "^1.0.4",
|
||||
"bmaplib.lushu": "^1.0.7",
|
||||
"bmaplib.markerclusterer": "^1.0.13",
|
||||
"markdown-it": "^8.4.0"
|
||||
}
|
||||
},
|
||||
"vue-clipboard2": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-clipboard2/download/vue-clipboard2-0.3.1.tgz",
|
||||
|
@ -19,6 +19,7 @@
|
||||
"moment": "^2.29.1",
|
||||
"postcss-pxtorem": "^5.1.1",
|
||||
"vue": "^2.6.11",
|
||||
"vue-baidu-map": "^0.21.22",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-cookies": "^1.7.4",
|
||||
"vue-router": "^3.1.6"
|
||||
|
250
web_src/src/components/GeoConvertTools.js
Normal file
250
web_src/src/components/GeoConvertTools.js
Normal file
@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 经纬度转换
|
||||
*/
|
||||
export default {
|
||||
PI: 3.1415926535897932384626,
|
||||
//PI: 3.14159265358979324,
|
||||
x_pi: (3.1415926535897932384626 * 3000.0) / 180.0,
|
||||
delta: function (lat, lng) {
|
||||
// Krasovsky 1940
|
||||
//
|
||||
// a = 6378245.0, 1/f = 298.3
|
||||
// b = a * (1 - f)
|
||||
// ee = (a^2 - b^2) / a^2;
|
||||
var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
|
||||
var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
|
||||
var dLat = this.transformLat(lng - 105.0, lat - 35.0);
|
||||
var dLng = this.transformLng(lng - 105.0, lat - 35.0);
|
||||
var radLat = (lat / 180.0) * this.PI;
|
||||
var magic = Math.sin(radLat);
|
||||
magic = 1 - ee * magic * magic;
|
||||
var sqrtMagic = Math.sqrt(magic);
|
||||
dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * this.PI);
|
||||
dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * this.PI);
|
||||
return {
|
||||
lat: dLat,
|
||||
lng: dLng
|
||||
};
|
||||
},
|
||||
/**
|
||||
* WGS-84 to GCJ-02 GPS坐标转中国坐标
|
||||
* @param {number} wgsLat GPS纬度
|
||||
* @param {number} wgsLng GPS经度
|
||||
* @return {object} 返回中国坐标经纬度对象
|
||||
*/
|
||||
GPSToChina: function (wgsLat, wgsLng) {
|
||||
if (this.outOfChina(wgsLat, wgsLng)) return {
|
||||
lat: wgsLat,
|
||||
lng: wgsLng
|
||||
};
|
||||
var d = this.delta(wgsLat, wgsLng);
|
||||
return {
|
||||
lat: Number(wgsLat) + Number(d.lat),
|
||||
lng: Number(wgsLng) + Number(d.lng)
|
||||
};
|
||||
},
|
||||
/**
|
||||
* GCJ-02 to WGS-84 中国标准坐标转GPS坐标
|
||||
* @param {number} gcjLat 中国标准坐标纬度
|
||||
* @param {number} gcjLng 中国标准坐标经度
|
||||
* @return {object} 返回GPS经纬度对象
|
||||
*/
|
||||
chinaToGPS: function (gcjLat, gcjLng) {
|
||||
if (this.outOfChina(gcjLat, gcjLng)) return {
|
||||
lat: gcjLat,
|
||||
lng: gcjLng
|
||||
};
|
||||
var d = this.delta(gcjLat, gcjLng);
|
||||
return {
|
||||
lat: Number(gcjLat) - Number(d.lat),
|
||||
lng: Number(gcjLng) - Number(d.lng)
|
||||
};
|
||||
},
|
||||
/**
|
||||
* GCJ-02 to WGS-84 exactly 中国标准坐标转GPS坐标(精确)
|
||||
* @param {number} gcjLat 中国标准坐标纬度
|
||||
* @param {number} gcjLng 中国标准坐标经度
|
||||
* @return {object} 返回GPS经纬度对象(精确)
|
||||
*/
|
||||
chinaToGPSExact: function (gcjLat, gcjLng) {
|
||||
var initDelta = 0.01;
|
||||
var threshold = 0.000000001;
|
||||
var dLat = initDelta,
|
||||
dLng = initDelta;
|
||||
var mLat = gcjLat - dLat,
|
||||
mLng = gcjLng - dLng;
|
||||
var pLat = gcjLat + dLat,
|
||||
pLng = gcjLng + dLng;
|
||||
var wgsLat,
|
||||
wgsLng,
|
||||
i = 0;
|
||||
while (1) {
|
||||
wgsLat = (mLat + pLat) / 2;
|
||||
wgsLng = (mLng + pLng) / 2;
|
||||
var tmp = this.gcj_encrypt(wgsLat, wgsLng);
|
||||
dLat = tmp.lat - gcjLat;
|
||||
dLng = tmp.lng - gcjLng;
|
||||
if (Math.abs(dLat) < threshold && Math.abs(dLng) < threshold) break;
|
||||
|
||||
if (dLat > 0) pLat = wgsLat;
|
||||
else mLat = wgsLat;
|
||||
if (dLng > 0) pLng = wgsLng;
|
||||
else mLng = wgsLng;
|
||||
|
||||
if (++i > 10000) break;
|
||||
}
|
||||
//console.log(i);
|
||||
return {
|
||||
lat: wgsLat,
|
||||
lng: wgsLng
|
||||
};
|
||||
},
|
||||
/**
|
||||
* GCJ-02 to BD-09 中国标准坐标转百度坐标(精确)
|
||||
* @param {number} gcjLat 中国标准坐标纬度
|
||||
* @param {number} gcjLng 中国标准坐标经度
|
||||
* @return {object} 返回百度经纬度对象
|
||||
*/
|
||||
chinaToBaidu: function (gcjLat, gcjLng) {
|
||||
var x = gcjLng,
|
||||
y = gcjLat;
|
||||
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
|
||||
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
|
||||
var bdLng = z * Math.cos(theta) + 0.0065;
|
||||
var bdLat = z * Math.sin(theta) + 0.006;
|
||||
return {
|
||||
lat: bdLat,
|
||||
lng: bdLng
|
||||
};
|
||||
},
|
||||
/**
|
||||
* BD-09 to GCJ-02 百度坐标转中国标准坐标
|
||||
* @param {number} bdLat 百度坐标纬度
|
||||
* @param {number} bdLng 百度坐标经度
|
||||
* @return {object} 返回中国标准经纬度对象
|
||||
*/
|
||||
baiduToChina: function (bdLat, bdLng) {
|
||||
var x = bdLng - 0.0065,
|
||||
y = bdLat - 0.006;
|
||||
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
|
||||
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
|
||||
var gcjLng = z * Math.cos(theta);
|
||||
var gcjLat = z * Math.sin(theta);
|
||||
return {
|
||||
lat: gcjLat,
|
||||
lng: gcjLng
|
||||
};
|
||||
},
|
||||
/**
|
||||
* BD-09 to GCJ-02 百度坐标转gps坐标
|
||||
* @param {number} bdLat 百度坐标纬度
|
||||
* @param {number} bdLng 百度坐标经度
|
||||
* @return {object} 返回gps经纬度对象
|
||||
*/
|
||||
baiduToGPS: function (bdLat, bdLng) {
|
||||
let china = this.baiduToChina(bdLat, bdLng);
|
||||
return this.chinaToGPS(china.lat, china.lng);
|
||||
},
|
||||
/**
|
||||
* WGS-84 to to BD-09 GPS坐标转Baidu坐标
|
||||
* @param {number} gpsLat GPS纬度
|
||||
* @param {number} gpsLng GPS经度
|
||||
* @return {object} 返回百度经纬度对象
|
||||
*/
|
||||
GPSToBaidu: function (gpsLat, gpsLng) {
|
||||
var china = this.GPSToChina(gpsLat, gpsLng);
|
||||
return this.chinaToBaidu(china.lat, china.lng);
|
||||
},
|
||||
/**
|
||||
* WGS-84 to Web mercator GPS坐标转墨卡托坐标
|
||||
* @param {number} wgsLat GPS纬度
|
||||
* @param {number} wgsLng GPS经度
|
||||
* @return {object} 返回墨卡托经纬度对象
|
||||
*/
|
||||
GPSToMercator: function (wgsLat, wgsLng) {
|
||||
var x = (wgsLng * 20037508.34) / 180;
|
||||
var y = Math.log(Math.tan(((90 + wgsLat) * this.PI) / 360)) / (this.PI / 180);
|
||||
y = (y * 20037508.34) / 180;
|
||||
return {
|
||||
lat: y,
|
||||
lng: x
|
||||
};
|
||||
/*
|
||||
if ((Math.abs(wgsLng) > 180 || Math.abs(wgsLat) > 90))
|
||||
return null;
|
||||
var x = 6378137.0 * wgsLng * 0.017453292519943295;
|
||||
var a = wgsLat * 0.017453292519943295;
|
||||
var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
|
||||
return {'lat' : y, 'lng' : x};
|
||||
//*/
|
||||
},
|
||||
/**
|
||||
* Web mercator to WGS-84 墨卡托坐标转GPS坐标
|
||||
* @param {number} mercatorLat 墨卡托纬度
|
||||
* @param {number} mercatorLng 墨卡托经度
|
||||
* @return {object} 返回GPS经纬度对象
|
||||
*/
|
||||
mercatorToGPS: function (mercatorLat, mercatorLng) {
|
||||
var x = (mercatorLng / 20037508.34) * 180;
|
||||
var y = (mercatorLat / 20037508.34) * 180;
|
||||
y = (180 / this.PI) * (2 * Math.atan(Math.exp((y * this.PI) / 180)) - this.PI / 2);
|
||||
return {
|
||||
lat: y,
|
||||
lng: x
|
||||
};
|
||||
/*
|
||||
if (Math.abs(mercatorLng) < 180 && Math.abs(mercatorLat) < 90)
|
||||
return null;
|
||||
if ((Math.abs(mercatorLng) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
|
||||
return null;
|
||||
var a = mercatorLng / 6378137.0 * 57.295779513082323;
|
||||
var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
|
||||
var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
|
||||
return {'lat' : y, 'lng' : x};
|
||||
//*/
|
||||
},
|
||||
/**
|
||||
* 两点之间的距离
|
||||
* @param {number} latA 起点纬度
|
||||
* @param {number} lngA 起点经度
|
||||
* @param {number} latB 终点纬度
|
||||
* @param {number} lngB 终点经度
|
||||
* @return {number} 返回距离(米)
|
||||
*/
|
||||
distance: function (latA, lngA, latB, lngB) {
|
||||
var earthR = 6371000;
|
||||
var x = Math.cos((latA * this.PI) / 180) * Math.cos((latB * this.PI) / 180) * Math.cos(((lngA - lngB) * this.PI) / 180);
|
||||
var y = Math.sin((latA * this.PI) / 180) * Math.sin((latB * this.PI) / 180);
|
||||
var s = x + y;
|
||||
if (s > 1) s = 1;
|
||||
if (s < -1) s = -1;
|
||||
var alpha = Math.acos(s);
|
||||
var distance = alpha * earthR;
|
||||
return distance;
|
||||
},
|
||||
/**
|
||||
* 是否在中国之外
|
||||
* @param {number} lat 纬度
|
||||
* @param {number} lng 经度
|
||||
* @return {boolean]} 返回结果真或假
|
||||
*/
|
||||
outOfChina: function (lat, lng) {
|
||||
if (lat < 72.004 || lat > 137.8347) return true;
|
||||
if (lng < 0.8293 || lng > 55.8271) return true;
|
||||
return false;
|
||||
},
|
||||
transformLat: function (x, y) {
|
||||
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
||||
ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
|
||||
ret += ((20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin((y / 3.0) * this.PI)) * 2.0) / 3.0;
|
||||
ret += ((160.0 * Math.sin((y / 12.0) * this.PI) + 320 * Math.sin((y * this.PI) / 30.0)) * 2.0) / 3.0;
|
||||
return ret;
|
||||
},
|
||||
transformLng: function (x, y) {
|
||||
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
||||
ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
|
||||
ret += ((20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin((x / 3.0) * this.PI)) * 2.0) / 3.0;
|
||||
ret += ((150.0 * Math.sin((x / 12.0) * this.PI) + 300.0 * Math.sin((x / 30.0) * this.PI)) * 2.0) / 3.0;
|
||||
return ret;
|
||||
}
|
||||
};
|
@ -29,14 +29,13 @@ export default {
|
||||
}
|
||||
},
|
||||
created(){
|
||||
var that = this;
|
||||
document.onkeydown = function(e) {
|
||||
var key = window.event.keyCode;
|
||||
if (key == 13) {
|
||||
that.login();
|
||||
var that = this;
|
||||
document.onkeydown = function(e) {
|
||||
var key = window.event.keyCode;
|
||||
if (key == 13) {
|
||||
that.login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
methods:{
|
||||
|
||||
@ -70,6 +69,7 @@ export default {
|
||||
if (res.data == "success") {
|
||||
that.$cookies.set("session", {"username": that.username}) ;
|
||||
//登录成功后
|
||||
that.cancelEnterkeyDefaultAction();
|
||||
that.$router.push('/');
|
||||
}else{
|
||||
that.isLoging = false;
|
||||
@ -84,18 +84,23 @@ export default {
|
||||
that.$message.error(error.response.statusText);
|
||||
that.isLoging = false;
|
||||
});
|
||||
|
||||
|
||||
|
||||
},
|
||||
setCookie: function (cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
||||
var expires = "expires=" + d.toUTCString();
|
||||
console.info(cname + "=" + cvalue + "; " + expires);
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires;
|
||||
console.info(document.cookie);
|
||||
},
|
||||
setCookie: function (cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
||||
var expires = "expires=" + d.toUTCString();
|
||||
console.info(cname + "=" + cvalue + "; " + expires);
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires;
|
||||
console.info(document.cookie);
|
||||
},
|
||||
cancelEnterkeyDefaultAction: function() {
|
||||
document.onkeydown = function(e) {
|
||||
var key = window.event.keyCode;
|
||||
if (key == 13) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -21,7 +21,6 @@ export default {
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
|
||||
loginout(){
|
||||
// 删除cookie,回到登录页面
|
||||
this.$cookies.remove("session");
|
||||
|
388
web_src/src/components/devicePosition.vue
Normal file
388
web_src/src/components/devicePosition.vue
Normal file
@ -0,0 +1,388 @@
|
||||
<template>
|
||||
<div id="devicePosition" style="height: 100%">
|
||||
<el-container style="height: 100%">
|
||||
<el-header>
|
||||
<uiHeader></uiHeader>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
|
||||
<span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>
|
||||
</div>
|
||||
<div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;">
|
||||
<el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button>
|
||||
<!-- <span class="demonstration">从</span> -->
|
||||
<el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
||||
<el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
||||
<el-button-group>
|
||||
<el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button>
|
||||
<el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button>
|
||||
</el-button-group>
|
||||
<el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag>
|
||||
<el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number>
|
||||
<el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag>
|
||||
<el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number>
|
||||
<el-button-group>
|
||||
<el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button>
|
||||
<el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button>
|
||||
</el-button-group>
|
||||
<el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox>
|
||||
</div>
|
||||
<div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);">
|
||||
<div class="baidumap" id="allmap"></div>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uiHeader from "./UiHeader.vue";
|
||||
import moment from "moment";
|
||||
import geoTools from "./GeoConvertTools.js";
|
||||
export default {
|
||||
name: "devicePosition",
|
||||
components: {
|
||||
uiHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickerOptions: {
|
||||
shortcuts: [{
|
||||
text: '今天',
|
||||
onClick(picker) {
|
||||
picker.$emit('pick', new Date());
|
||||
}
|
||||
}, {
|
||||
text: '昨天',
|
||||
onClick(picker) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() - 3600 * 1000 * 24);
|
||||
picker.$emit('pick', date);
|
||||
}
|
||||
}, {
|
||||
text: '一周前',
|
||||
onClick(picker) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
|
||||
picker.$emit('pick', date);
|
||||
}
|
||||
}]
|
||||
},
|
||||
deviceId: this.$route.params.deviceId,
|
||||
showHistoryPosition: false, //显示历史轨迹
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
searchFrom: null,
|
||||
searchTo: null,
|
||||
expired: 600,
|
||||
interval: 5,
|
||||
mobilePositionList: [],
|
||||
mapPointList: [],
|
||||
parentChannelId: this.$route.params.parentChannelId,
|
||||
updateLooper: 0, //数据刷新轮训标志
|
||||
total: 0,
|
||||
beforeUrl: "/videoList",
|
||||
isLoging: false,
|
||||
autoList: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initData();
|
||||
this.initBaiduMap();
|
||||
if (this.autoList) {
|
||||
this.updateLooper = setInterval(this.initData, 5000);
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
// this.$destroy("videojs");
|
||||
clearTimeout(this.updateLooper);
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
// if (this.parentChannelId == "" || this.parentChannelId == 0) {
|
||||
// this.getDeviceChannelList();
|
||||
// } else {
|
||||
// this.showSubchannels();
|
||||
// }
|
||||
},
|
||||
initParam: function () {
|
||||
// this.deviceId = this.$route.params.deviceId;
|
||||
// this.parentChannelId = this.$route.params.parentChannelId;
|
||||
// this.currentPage = parseInt(this.$route.params.page);
|
||||
// this.count = parseInt(this.$route.params.count);
|
||||
// if (this.parentChannelId == "" || this.parentChannelId == 0) {
|
||||
// this.beforeUrl = "/videoList";
|
||||
// }
|
||||
},
|
||||
initBaiduMap() {
|
||||
this.map = new BMap.Map("allmap"); // 创建地图实例
|
||||
let points = [];
|
||||
let point = new BMap.Point(116.231398, 39.567445); // 创建点坐标
|
||||
this.map.centerAndZoom(point, 5); // 初始化地图,设置中心点坐标和地图级别
|
||||
this.map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
|
||||
this.map.addControl(new BMap.NavigationControl());
|
||||
this.map.addControl(new BMap.ScaleControl());
|
||||
this.map.addControl(new BMap.OverviewMapControl());
|
||||
this.map.addControl(new BMap.MapTypeControl());
|
||||
//map.setMapStyle({ style: 'midnight' }) //地图风格
|
||||
},
|
||||
currentChange: function (val) {
|
||||
// var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`;
|
||||
// console.log(url);
|
||||
// this.$router.push(url).then(() => {
|
||||
// this.initParam();
|
||||
// this.initData();
|
||||
// });
|
||||
},
|
||||
handleSizeChange: function (val) {
|
||||
// var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`;
|
||||
// this.$router.push(url).then(() => {
|
||||
// this.initParam();
|
||||
// this.initData();
|
||||
// });
|
||||
},
|
||||
showDevice: function () {
|
||||
this.$router.push(this.beforeUrl).then(() => {
|
||||
this.initParam();
|
||||
this.initData();
|
||||
});
|
||||
},
|
||||
autoListChange: function () {
|
||||
if (this.autoList) {
|
||||
this.updateLooper = setInterval(this.initData, 1500);
|
||||
} else {
|
||||
window.clearInterval(this.updateLooper);
|
||||
}
|
||||
},
|
||||
showHistoryPath: function () {
|
||||
this.map.clearOverlays();
|
||||
this.mapPointList = [];
|
||||
this.mobilePositionList = [];
|
||||
if (!!this.searchFrom) {
|
||||
this.startTime = this.toGBString(this.searchFrom);
|
||||
console.log(this.startTime);
|
||||
} else{
|
||||
this.startTime = null;
|
||||
}
|
||||
if (!!this.searchTo) {
|
||||
this.endTime = this.toGBString(this.searchTo);
|
||||
console.log(this.endTime);
|
||||
} else {
|
||||
this.endTime = null;
|
||||
}
|
||||
let self = this;
|
||||
this.$axios.get(`/api/positions/${this.deviceId}/history`, {
|
||||
params: {
|
||||
start: self.startTime,
|
||||
end: self.endTime,
|
||||
},
|
||||
})
|
||||
.then(function (res) {
|
||||
self.total = res.data.length;
|
||||
self.mobilePositionList = res.data;
|
||||
console.log(self.mobilePositionList);
|
||||
if (self.total == 0) {
|
||||
self.$message({
|
||||
showClose: true,
|
||||
message: '未找到符合条件的移动位置信息',
|
||||
type: 'error'
|
||||
});
|
||||
} else {
|
||||
self.$nextTick(() => {
|
||||
self.showMarkPoints(self);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
showLatestPosition: function() {
|
||||
this.map.clearOverlays();
|
||||
this.mapPointList = [];
|
||||
this.mobilePositionList = [];
|
||||
let self = this;
|
||||
this.$axios.get(`/api/positions/${this.deviceId}/latest`)
|
||||
.then(function (res) {
|
||||
console.log(res.data);
|
||||
self.total = res.data.length;
|
||||
self.mobilePositionList.push(res.data);
|
||||
console.log(self.mobilePositionList);
|
||||
if (self.total == 0) {
|
||||
self.$message({
|
||||
showClose: true,
|
||||
message: '未找到符合条件的移动位置信息',
|
||||
type: 'error'
|
||||
});
|
||||
} else {
|
||||
self.$nextTick(() => {
|
||||
self.showMarkPoints(self);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
subscribeMobilePosition: function() {
|
||||
let self = this;
|
||||
this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, {
|
||||
params: {
|
||||
expires: self.expired,
|
||||
interval: self.interval,
|
||||
},
|
||||
})
|
||||
.then(function (res) {
|
||||
console.log(res.data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
unSubscribeMobilePosition: function() {
|
||||
let self = this;
|
||||
this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, {
|
||||
params: {
|
||||
expires: 0,
|
||||
interval: self.interval,
|
||||
},
|
||||
})
|
||||
.then(function (res) {
|
||||
console.log(res.data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
toGBString: function (dateTime) {
|
||||
return (
|
||||
dateTime.getFullYear() +
|
||||
"-" + this.twoDigits(dateTime.getMonth() + 1) +
|
||||
"-" + this.twoDigits(dateTime.getDate()) +
|
||||
"T" + this.twoDigits(dateTime.getHours()) +
|
||||
":" + this.twoDigits(dateTime.getMinutes()) +
|
||||
":" + this.twoDigits(dateTime.getSeconds())
|
||||
);
|
||||
},
|
||||
twoDigits: function (num) {
|
||||
if (num < 10) {
|
||||
return "0" + num;
|
||||
} else {
|
||||
return "" + num;
|
||||
}
|
||||
},
|
||||
showMarkPoints: function(self) {
|
||||
let that = self;
|
||||
let npointJ = null;
|
||||
let npointW = null;
|
||||
let point = null;
|
||||
for (let i = 0; i < self.mobilePositionList.length; i++) {
|
||||
if (self.mobilePositionList[i].geodeticSystem == "BD-09") {
|
||||
npointJ = self.mobilePositionList[i].cnLng;
|
||||
npointW = self.mobilePositionList[i].cnLat;
|
||||
point = new BMap.Point(npointJ, npointW);
|
||||
} else {
|
||||
npointJ = self.mobilePositionList[i].longitude;
|
||||
npointW = self.mobilePositionList[i].latitude;
|
||||
let bd2 = geoTools.GPSToBaidu(npointJ, npointW);
|
||||
point = new BMap.Point(bd2.lat, bd2.lng);
|
||||
}
|
||||
self.mapPointList.push(point);
|
||||
let marker = new BMap.Marker(point); // 创建标注
|
||||
self.map.addOverlay(marker); // 将标注添加到地图中
|
||||
//提示信息 可以解析 HTML标签以及CSS
|
||||
let infoWindow = new BMap.InfoWindow(`<p style='text-align:left;font-weight:800'>设备: ${self.mobilePositionList[i].deviceId}</p>
|
||||
<p style='text-align:left;font-weight:0'>时间: ${self.mobilePositionList[i].time}</p>`);
|
||||
// 鼠标移上标注点要发生的事
|
||||
marker.addEventListener("mouseover", function () {
|
||||
this.openInfoWindow(infoWindow);
|
||||
});
|
||||
// 鼠标移开标注点要发生的事
|
||||
marker.addEventListener("mouseout", function () {
|
||||
this.closeInfoWindow(infoWindow);
|
||||
});
|
||||
// 鼠标点击标注点要发生的事情
|
||||
marker.addEventListener("click", function () {
|
||||
alert("点击");
|
||||
});
|
||||
}
|
||||
let view = that.map.getViewport(eval(self.mapPointList));
|
||||
that.map.centerAndZoom(view.center, view.zoom);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.videoList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.video-item {
|
||||
position: relative;
|
||||
width: 15rem;
|
||||
height: 10rem;
|
||||
margin-right: 1rem;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.video-item-img:after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background-image: url("../assets/loading.png");
|
||||
background-size: cover;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #000000;
|
||||
background-color: #ffffff;
|
||||
line-height: 1.5rem;
|
||||
padding: 0.3rem;
|
||||
width: 14.4rem;
|
||||
}
|
||||
|
||||
.baidumap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* 去除百度地图版权那行字 和 百度logo */
|
||||
.baidumap > .BMap_cpyCtrl {
|
||||
display: none !important;
|
||||
}
|
||||
.baidumap > .anchorBL {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
@ -11,7 +11,7 @@
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||
<!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
|
||||
<!--设备列表-->
|
||||
<el-table :data="deviceList" border style="width: 100%" :height="winHeight">
|
||||
<el-table-column prop="name" label="名称" width="180" align="center">
|
||||
@ -40,7 +40,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="channelCount" label="通道数" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="180" align="center">
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>
|
||||
@ -49,11 +49,15 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="240" align="center" fixed="right">
|
||||
<el-table-column label="操作" width="360" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
|
||||
<el-button size="mini" icon="el-icon-s-open" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">查看通道</el-button>
|
||||
</template>
|
||||
<el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
|
||||
<el-button-group>
|
||||
<el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
|
||||
<el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
|
||||
<el-button size="mini" icon="el-icon-s-tools" v-bind:disabled="scope.row.online==0" type="primary">控制</el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@ -73,7 +77,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uiHeader from './UiHeader.vue'
|
||||
import uiHeader from './UiHeader.vue'
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
@ -155,7 +159,10 @@
|
||||
console.log(JSON.stringify(row))
|
||||
this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
|
||||
},
|
||||
|
||||
showDevicePosition: function(row) {
|
||||
console.log(JSON.stringify(row))
|
||||
this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
|
||||
},
|
||||
|
||||
//gb28181平台对接
|
||||
//刷新设备信息
|
||||
@ -191,18 +198,18 @@
|
||||
},
|
||||
//通知设备上传媒体流
|
||||
sendDevicePush: function(itemData) {
|
||||
let deviceId = this.currentDevice.deviceId;
|
||||
let channelId = itemData.channelId;
|
||||
console.log("通知设备推流1:" + deviceId + " : " + channelId);
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/api/play/' + deviceId + '/' + channelId
|
||||
}).then(function(res) {
|
||||
let ssrc = res.data.ssrc;
|
||||
that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
|
||||
}).catch(function(e) {
|
||||
});
|
||||
// let deviceId = this.currentDevice.deviceId;
|
||||
// let channelId = itemData.channelId;
|
||||
// console.log("通知设备推流1:" + deviceId + " : " + channelId);
|
||||
// let that = this;
|
||||
// this.$axios({
|
||||
// method: 'get',
|
||||
// url: '/api/play/' + deviceId + '/' + channelId
|
||||
// }).then(function(res) {
|
||||
// let ssrc = res.data.ssrc;
|
||||
// that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
|
||||
// }).catch(function(e) {
|
||||
// });
|
||||
},
|
||||
transportChange: function (row) {
|
||||
console.log(row);
|
||||
|
@ -12,21 +12,21 @@ import VueClipboard from 'vue-clipboard2';
|
||||
import { Notification } from 'element-ui';
|
||||
import Fingerprint2 from 'fingerprintjs2';
|
||||
|
||||
// 生成唯一ID
|
||||
// 生成唯一ID
|
||||
Fingerprint2.get(function(components) {
|
||||
const values = components.map(function(component,index) {
|
||||
if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
|
||||
if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
|
||||
return component.value.replace(/\bNetType\/\w+\b/, '');
|
||||
}
|
||||
return component.value;
|
||||
})
|
||||
//console.log(values) //使用的浏览器信息npm
|
||||
// 生成最终id
|
||||
//console.log(values) //使用的浏览器信息npm
|
||||
// 生成最终id
|
||||
let port = window.location.port;
|
||||
console.log(port);
|
||||
const fingerPrint = Fingerprint2.x64hash128(values.join(port), 31)
|
||||
Vue.prototype.$browserId = fingerPrint;
|
||||
console.log("唯一标识码:" + fingerPrint);
|
||||
console.log("唯一标识码:" + fingerPrint);
|
||||
});
|
||||
|
||||
Vue.use(VueClipboard);
|
||||
|
@ -4,6 +4,7 @@ import VueRouter from 'vue-router'
|
||||
import control from '../components/control.vue'
|
||||
import videoList from '../components/videoList.vue'
|
||||
import channelList from '../components/channelList.vue'
|
||||
import devicePosition from '../components/devicePosition.vue'
|
||||
import login from '../components/Login.vue'
|
||||
|
||||
const originalPush = VueRouter.prototype.push
|
||||
@ -35,5 +36,10 @@ export default new VueRouter({
|
||||
name: 'channelList',
|
||||
component: channelList,
|
||||
},
|
||||
{
|
||||
path: '/devicePosition/:deviceId/:parentChannelId/:count/:page',
|
||||
name: 'devicePosition',
|
||||
component: devicePosition,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user