Browse Source

解决串流,解决编辑上级平台却新建了的问题

pull/87/head
panlinlin 4 years ago
parent
commit
937e591430
  1. 4
      src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
  2. 12
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
  3. 2
      src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java
  4. 2
      src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
  5. 22
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  6. 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
  7. 8
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
  8. 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
  9. 4
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  10. 4
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
  11. 28
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
  12. 4
      src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
  13. 15
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
  14. 13
      src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
  15. 2
      src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
  16. 8
      src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
  17. 14
      src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
  18. 8
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
  19. 3
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
  20. 2
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
  21. 6
      src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
  22. BIN
      src/main/resources/wvp.sqlite
  23. 2
      web_src/index.html
  24. 122
      web_src/src/components/Login.vue
  25. 1
      web_src/src/components/dialog/devicePlayer.vue
  26. 41
      web_src/src/components/dialog/platformEdit.vue
  27. 4
      web_src/static/css/font-awesome.min.css
  28. 396
      web_src/static/css/login.css
  29. BIN
      web_src/static/fonts/poppins/Poppins-Bold.ttf
  30. BIN
      web_src/static/fonts/poppins/Poppins-Medium.ttf
  31. BIN
      web_src/static/fonts/poppins/Poppins-Regular.ttf
  32. BIN
      web_src/static/fonts/poppins/Poppins-SemiBold.ttf

4
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java

@ -118,7 +118,7 @@ public class SipLayer implements SipListener {
*/
@Override
public void processRequest(RequestEvent evt) {
logger.debug(evt.getRequest().toString());
// logger.debug(evt.getRequest().toString());
// 由于jainsip是单线程程序,为提高性能并发处理
processThreadPool.execute(() -> {
if (processorFactory != null) {
@ -130,7 +130,7 @@ public class SipLayer implements SipListener {
@Override
public void processResponse(ResponseEvent evt) {
Response response = evt.getResponse();
logger.debug(evt.getResponse().toString());
// logger.debug(evt.getResponse().toString());
int status = response.getStatusCode();
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);

12
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java

@ -2,6 +2,11 @@ package com.genersoft.iot.vmp.gb28181.bean;
public class ParentPlatform {
/**
* id
*/
private Integer id;
/**
* 是否启用
*/
@ -99,6 +104,13 @@ public class ParentPlatform {
*/
private int channelCount;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public boolean isEnable() {
return enable;

2
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java

@ -49,7 +49,7 @@ public class PlatformKeepaliveExpireEventLister implements ApplicationListener<P
if (logger.isDebugEnabled()) {
logger.debug("平台心跳到期事件事件触发,平台国标ID:" + event.getPlatformGbID());
}
ParentPlatform parentPlatform = storager.queryParentPlatById(event.getPlatformGbID());
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID());
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(event.getPlatformGbID());
if (parentPlatformCatch == null) {
return;

2
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java

@ -35,7 +35,7 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
logger.debug("平台未注册事件触发,平台国标ID:" + event.getPlatformGbID());
ParentPlatform parentPlatform = storager.queryParentPlatById(event.getPlatformGbID());
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID());
if (parentPlatform == null) {
logger.debug("平台未注册事件触发,但平台已经删除!!! 平台国标ID:" + event.getPlatformGbID());
return;

22
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@ -365,9 +365,14 @@ public class SIPCommander implements ISIPCommander {
// 添加订阅
JSONObject subscribeKey = new JSONObject();
subscribeKey.put("app", "rtp");
subscribeKey.put("id", streamId);
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, subscribeKey, event);
subscribeKey.put("stream", streamId);
subscribeKey.put("regist", true);
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
if (json.getJSONArray("tracks") == null) return;
event.response(json);
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
});
//
StringBuffer content = new StringBuffer(200);
content.append("v=0\r\n");
@ -465,9 +470,14 @@ public class SIPCommander implements ISIPCommander {
// 添加订阅
JSONObject subscribeKey = new JSONObject();
subscribeKey.put("app", "rtp");
subscribeKey.put("id", streamId);
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, subscribeKey, event);
subscribeKey.put("stream", streamId);
subscribeKey.put("regist", true);
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
if (json.getJSONArray("tracks") == null) return;
event.response(json);
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
});
StringBuffer content = new StringBuffer(200);
content.append("v=0\r\n");

2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java

@ -86,7 +86,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
}
// 查询请求方是否上级平台
ParentPlatform platform = storager.queryParentPlatById(requesterId);
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
if (platform != null) {
// 查询平台下是否有该通道
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);

8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java

@ -238,7 +238,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK
responseAck(evt);
String sn = rootElement.element("SN").getText();
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
}
} else {
@ -303,7 +303,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
if (deviceId.equals(targetGBId)) {
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
logger.info("执行远程启动本平台命令");
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
cmderFroPlatform.unregister(parentPlatform, null, null);
Thread restartThread = new Thread(new Runnable() {
@ -463,7 +463,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// 回复200 OK
responseAck(evt);
String sn = rootElement.element("SN").getText();
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
}
} else {
@ -517,7 +517,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
// if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
// TODO 后续将代码拆分
ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
if (parentPlatform == null) {
response404Ack(evt);
return;

2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java

@ -82,7 +82,7 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor {
redisCatchStorage.delPlatformRegisterInfo(callId);
parentPlatform.setStatus(true);
// 取回Expires设置,避免注销过程中被置为0
ParentPlatform parentPlatformTmp = storager.queryParentPlatById(platformGBId);
ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId);
String expires = parentPlatformTmp.getExpires();
parentPlatform.setExpires(expires);
storager.updateParentPlatform(parentPlatform);

4
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@ -240,6 +240,10 @@ public class ZLMHttpHookListener {
if (logger.isDebugEnabled()) {
logger.debug("ZLM HOOK on_stream_changed API调用,参数:" + json.toString());
}
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
if (subscribe != null) subscribe.response(json);
// 流消失移除redis play
String app = json.getString("app");
String streamId = json.getString("stream");

4
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java

@ -163,6 +163,10 @@ public class ZLMRESTfulUtils {
return sendPost("closeRtpServer",param, null);
}
public JSONObject listRtpServer() {
return sendPost("listRtpServer",null, null);
}
public JSONObject startSendRtp(Map<String, Object> param) {
return sendPost("startSendRtp",param, null);
}

28
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.media.zlm;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.session.SsrcUtil;
@ -27,7 +28,28 @@ public class ZLMRTPServerFactory {
private int currentPort = 0;
private Map<String, Integer> currentStreams = null;
public int createRTPServer(String streamId) {
if (currentStreams == null) {
currentStreams = new HashMap<>();
JSONObject jsonObject = zlmresTfulUtils.listRtpServer();
JSONArray data = jsonObject.getJSONArray("data");
if (data != null) {
for (int i = 0; i < data.size(); i++) {
JSONObject dataItem = data.getJSONObject(i);
currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
}
}
}
// 已经在推流
if (currentStreams.get(streamId) != null) {
Map<String, Object> closeRtpServerParam = new HashMap<>();
closeRtpServerParam.put("stream_id", streamId);
zlmresTfulUtils.closeRtpServer(closeRtpServerParam);
currentStreams.remove(streamId);
}
Map<String, Object> param = new HashMap<>();
int result = -1;
int newPort = getPortFromUdpPortRange();
@ -35,14 +57,16 @@ public class ZLMRTPServerFactory {
param.put("enable_tcp", 1);
param.put("stream_id", streamId);
JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param);
System.out.println(jsonObject);
if (jsonObject != null) {
switch (jsonObject.getInteger("code")){
case 0:
result= newPort;
break;
case -300: // id已经存在
case -300: // id已经存在, 可能已经在其他端口推流
Map<String, Object> closeRtpServerParam = new HashMap<>();
closeRtpServerParam.put("stream_id", streamId);
zlmresTfulUtils.closeRtpServer(closeRtpServerParam);
result = newPort;
break;
case -400: // 端口占用

4
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
/**
@ -21,6 +23,6 @@ public interface IMediaService {
* @param stream
* @return
*/
StreamInfo getStreamInfoByAppAndStream(String app, String stream);
StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks);
}

15
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
@ -25,7 +27,7 @@ public class MediaServiceImpl implements IMediaService {
@Override
public StreamInfo getStreamInfoByAppAndStream(String app, String stream) {
public StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks) {
MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
StreamInfo streamInfoResult = new StreamInfo();
streamInfoResult.setStreamId(stream);
@ -41,7 +43,7 @@ public class MediaServiceImpl implements IMediaService {
streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setRtc(String.format("http://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setTracks(tracks);
return streamInfoResult;
}
@ -50,7 +52,14 @@ public class MediaServiceImpl implements IMediaService {
StreamInfo streamInfo = null;
JSONObject mediaList = zlmresTfulUtils.getMediaList(app, stream);
if (mediaList != null) {
streamInfo = getStreamInfoByAppAndStream(app, stream);
if (mediaList.getInteger("code") == 0) {
JSONArray data = mediaList.getJSONArray("data");
if (data == null) return null;
JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
JSONArray tracks = mediaJSON.getJSONArray("tracks");
streamInfo = getStreamInfoByAppAndStream(app, stream, tracks);
}
}
return streamInfo;
}

13
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -83,6 +84,13 @@ public class PlayServiceImpl implements IPlayService {
});
} else {
String streamId = streamInfo.getStreamId();
if (streamId == null) {
RequestMessage msg = new RequestMessage();
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
msg.setData(String.format("点播失败, redis缓存streamId等于null"));
resultHolder.invokeResult(msg);
return playResult;
}
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
RequestMessage msg = new RequestMessage();
@ -150,8 +158,9 @@ public class PlayServiceImpl implements IPlayService {
}
public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
String streamId = resonse.getString("id");
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId);
String streamId = resonse.getString("stream");
JSONArray tracks = resonse.getJSONArray("tracks");
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId, tracks);
streamInfo.setDeviceID(deviceId);
streamInfo.setChannelId(channelId);
return streamInfo;

2
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java

@ -194,7 +194,7 @@ public interface IVideoManagerStorager {
* @param platformGbId
* @return
*/
ParentPlatform queryParentPlatById(String platformGbId);
ParentPlatform queryParentPlatByServerGBId(String platformGbId);
/**
* 所有平台离线

8
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java

@ -25,6 +25,7 @@ public interface ParentPlatformMapper {
"SET enable=#{enable}, " +
"name=#{name}," +
"deviceGBId=#{deviceGBId}," +
"serverGBId=#{serverGBId}, " +
"serverGBDomain=#{serverGBDomain}, " +
"serverIP=#{serverIP}," +
"serverPort=#{serverPort}, " +
@ -39,7 +40,7 @@ public interface ParentPlatformMapper {
"ptz=#{ptz}, " +
"rtcp=#{rtcp}, " +
"status=#{status} " +
"WHERE serverGBId=#{serverGBId}")
"WHERE id=#{id}")
int updateParentPlatform(ParentPlatform parentPlatform);
@Delete("DELETE FROM parent_platform WHERE serverGBId=#{serverGBId}")
@ -52,7 +53,10 @@ public interface ParentPlatformMapper {
List<ParentPlatform> getEnableParentPlatformList(boolean enable);
@Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}")
ParentPlatform getParentPlatById(String platformGbId);
ParentPlatform getParentPlatByServerGBId(String platformGbId);
@Select("SELECT * FROM parent_platform WHERE id=#{id}")
ParentPlatform getParentPlatById(int id);
@Update("UPDATE parent_platform SET status=false" )
void outlineForAllParentPlatform();

14
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java

@ -271,15 +271,21 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
public boolean updateParentPlatform(ParentPlatform parentPlatform) {
int result = 0;
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId());
if ( platformMapper.getParentPlatById(parentPlatform.getServerGBId()) == null) {
if (parentPlatform.getId() == null ) {
result = platformMapper.addParentPlatform(parentPlatform);
if (parentPlatformCatch == null) {
parentPlatformCatch = new ParentPlatformCatch();
parentPlatformCatch.setParentPlatform(parentPlatform);
parentPlatformCatch.setId(parentPlatform.getServerGBId());
}
}else {
if (parentPlatformCatch == null) { // serverGBId 已变化
ParentPlatform parentPlatById = platformMapper.getParentPlatById(parentPlatform.getId());
// 使用旧的查出缓存ID
parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatById.getServerGBId());
parentPlatformCatch.setId(parentPlatform.getServerGBId());
redisCatchStorage.delPlatformCatchInfo(parentPlatById.getServerGBId());
}
result = platformMapper.updateParentPlatform(parentPlatform);
}
// 更新缓存
@ -305,8 +311,8 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
}
@Override
public ParentPlatform queryParentPlatById(String platformGbId) {
return platformMapper.getParentPlatById(platformGbId);
public ParentPlatform queryParentPlatByServerGBId(String platformGbId) {
return platformMapper.getParentPlatByServerGBId(platformGbId);
}
@Override

8
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java

@ -111,7 +111,7 @@ public class PlatformController {
// TODO 检查是否已经存在,且注册成功, 如果注册成功,需要先注销之前再,修改并注册
// ParentPlatform parentPlatformOld = storager.queryParentPlatById(parentPlatform.getDeviceGBId());
ParentPlatform parentPlatformOld = storager.queryParentPlatById(parentPlatform.getServerGBId());
ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
boolean updateResult = storager.updateParentPlatform(parentPlatform);
@ -123,8 +123,6 @@ public class PlatformController {
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销
commanderForPlatform.unregister(parentPlatform, null, null);
}
return new ResponseEntity<>("success", HttpStatus.OK);
} else {
return new ResponseEntity<>("fail", HttpStatus.OK);
@ -151,7 +149,7 @@ public class PlatformController {
){
return new ResponseEntity<>("missing parameters", HttpStatus.BAD_REQUEST);
}
ParentPlatform parentPlatform = storager.queryParentPlatById(serverGBId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId);
if (parentPlatform == null) return new ResponseEntity<>("fail", HttpStatus.OK);
// 发送离线消息,无论是否成功都删除缓存
commanderForPlatform.unregister(parentPlatform, (event -> {
@ -192,7 +190,7 @@ public class PlatformController {
if (logger.isDebugEnabled()) {
logger.debug("查询上级平台是否存在API调用:" + serverGBId);
}
ParentPlatform parentPlatform = storager.queryParentPlatById(serverGBId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId);
return new ResponseEntity<>(String.valueOf(parentPlatform != null), HttpStatus.OK);
}

3
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java

@ -73,7 +73,6 @@ public class PlayController {
public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId,
@PathVariable String channelId) {
PlayResult playResult = playService.play(deviceId, channelId, null, null);
// 超时处理
@ -181,7 +180,7 @@ public class PlayController {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
result.put("key", data.getString("key"));
StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStream("convert", streamId);
StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId);
result.put("data", streamInfoResult);
}
}else {

2
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java

@ -71,7 +71,7 @@ public class PlaybackController {
logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
}
UUID uuid = UUID.randomUUID();
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
// 超时处理
result.onTimeout(()->{
logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));

6
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java

@ -21,10 +21,10 @@ import javax.security.sasl.AuthenticationException;
public class UserController {
@Autowired
AuthenticationManager authenticationManager;
private AuthenticationManager authenticationManager;
@Autowired
IUserService userService;
private IUserService userService;
@ApiOperation("登录")
@ApiImplicitParams({
@ -33,7 +33,7 @@ public class UserController {
})
@GetMapping("/login")
public String login(String username, String password){
LoginUser user = null;
LoginUser user;
try {
user = SecurityUtils.login(username, password, authenticationManager);
} catch (AuthenticationException e) {

BIN
src/main/resources/wvp.sqlite

Binary file not shown.

2
web_src/index.html

@ -4,6 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>国标28181</title>
<link rel="stylesheet" type="text/css" href="/static/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="/static/css/login.css">
</head>
<body>
<script type="text/javascript" src="./js/EasyWasmPlayer.js"></script>

122
web_src/src/components/Login.vue

@ -1,19 +1,35 @@
<template>
<div class="login" id="login">
<a href="javascript:;" class="log-close"><i class="icons close"></i></a>
<div class="log-bg">
<div class="log-cloud cloud1"></div>
<div class="log-cloud cloud2"></div>
<div class="log-cloud cloud3"></div>
<div class="log-cloud cloud4"></div>
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100">
<span class="login100-form-title p-b-26">WVP视频平台</span>
<span class="login100-form-title p-b-48">
<i class="fa fa-video-camera"></i>
</span>
<div class="log-logo">Welcome!</div>
<div class="log-text"></div>
</div>
<div class="log-email" v-loading="isLoging" >
<input type="text" placeholder="用户名" :class="'log-input' + (username==''?' log-input-empty':'')" v-model="username"><input type="password" placeholder="密码" :class="'log-input' + (password==''?' log-input-empty':'')" v-model="password">
<a href="javascript:;" class="log-btn" @click="login" >登录</a>
<div class="wrap-input100 validate-input" data-validate = "Valid email is: a@b.c">
<input :class="'input100 ' + (username==''?'':'has-val')" type="text" v-model="username" name="username">
<span class="focus-input100" data-placeholder="用户名"></span>
</div>
<div class="wrap-input100 validate-input" data-validate="Enter password">
<span class="btn-show-pass">
<i :class="'fa ' + (!showPassword?'fa-eye':'fa-eye-slash')" @click="showPassword = !showPassword"></i>
</span>
<input :class="'input100 ' + (password==''?'':'has-val')" :type="(!showPassword?'password':'text')" v-model="password" name="password">
<span class="focus-input100" data-placeholder="密码"></span>
</div>
<div class="container-login100-form-btn">
<div class="wrap-login100-form-btn">
<div class="login100-form-bgbtn"></div>
<button class="login100-form-btn" @click="login">登录</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@ -24,6 +40,7 @@ export default {
data(){
return {
isLoging: false,
showPassword: false,
username: '',
password: ''
}
@ -105,84 +122,3 @@ export default {
}
</script>
<style scoped>
.login{position: fixed; overflow: hidden;left: 50%; margin-left: -250px; top:50%; margin-top: -350px; width: 500px; min-height: 555px; z-index: 10; right: 140px; background: #fff;-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px; -webkit-box-shadow: 0px 3px 16px -5px #070707; box-shadow: 0px 3px 16px -5px #070707}
.log-close{display: block; position: absolute; top:12px; right: 12px; opacity: 1;}
.log-close:hover .icons{transform: rotate(180deg);}
.log-close .icons{opacity: 1; transition: all .3s}
.log-cloud{background-image: url(../assets/login-cloud.png); width: 63px ;height: 40px; position: absolute; z-index: 1}
.login .cloud1{top:21px; left: -30px; transform: scale(.6); animation: cloud1 20s linear infinite;}
.login .cloud2{top:87px; right: 20px; animation: cloud2 19s linear infinite;}
.login .cloud3{top:160px; left: 5px;transform: scale(.8);animation: cloud3 21s linear infinite;}
.login .cloud4{top:150px; left: -40px;transform: scale(.4);animation: cloud4 19s linear infinite;}
.log-bg{background: url(../assets/login-bg.jpg); width: 100%; height: 312px; overflow: hidden;}
.log-logo{height: 80px; margin: 120px auto 25px; text-align: center; color: #1fcab3; font-weight: bold; font-size: 40px;}
.log-text{color: #57d4c3; font-size: 13px; text-align: center; margin: 0 auto;}
.log-logo,.log-text{z-index: 2}
.icons{background:url(../assets/icons.png) no-repeat; display: inline-block;}
.close{height:16px;width:16px;background-position:-13px 0;}
.login-email{height:17px;width:29px;background-position:-117px 0;}
.log-btns{padding: 15px 0; margin: 0 auto;}
.log-btn{width:402px; display: block; text-align: left; line-height: 50px;margin:0 auto 15px; height:50px; color:#fff; font-size:13px;-webkit-border-radius: 5px; background-color: #3B5999;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
position: relative;}
.log-btn.tw{background-color: #13B4E9}
.log-btn.email{background-color: #50E3CE}
.log-btn:hover,.log-btn:focus{color: #fff; opacity: .8;}
.log-email{text-align: center; margin-top: 20px;}
.log-email .log-btn{background-color: #50E3CE;text-align: center;}
.log-input-empty{border: 1px solid #f37474 !important;}
.isloading{background: #d6d6d6}
.log-btn .icons{margin-left: 30px; vertical-align: middle;}
.log-btn .text{left: 95px; line-height: 50px; text-align: left; position: absolute;}
.log-input{width: 370px;overflow: hidden; padding: 0 15px;font-size: 13px; border: 1px solid #EBEBEB; margin:0 auto 15px; height: 48px; line-height: 48px; -webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;}
.log-input.warn{border: 1px solid #f88787}
@-webkit-keyframes cloud1 {
0%{left: 200px}
100%{left:-130px;}
}
@keyframes cloud1{
0%{left: 200px}
100%{left:-130px;}
}
@-webkit-keyframes cloud2 {
0%{left:500px;}
100%{left:-90px;}
}
@keyframes cloud2{
0%{left:500px;}
100%{left:-90px;}
}
@-webkit-keyframes cloud3 {
0%{left:620px;}
100%{left:-70px;}
}
@keyframes cloud3{
0%{left:620px;}
100%{left:-70px;}
}@-webkit-keyframes cloud4 {
0%{left:100px;}
100%{left:-70px;}
}
@keyframes cloud4{
0%{left:100px;}
100%{left:-70px;}
}
</style>

1
web_src/src/components/dialog/devicePlayer.vue

@ -138,6 +138,7 @@
<script>
// import player from '../dialog/rtcPlayer.vue'
// import LivePlayer from '@liveqing/liveplayer'
import player from '../dialog/easyPlayer.vue'
export default {
name: 'devicePlayer',

41
web_src/src/components/dialog/platformEdit.vue

@ -122,19 +122,20 @@ export default {
onSubmit_text: "立即创建",
platform: {
id: null,
enable: true,
ptz: true,
rtcp: false,
name: "测试001",
serverGBId: "34020000002000000001",
serverGBDomain: "3402000000",
serverIP: "192.168.1.141",
serverPort: "5060",
deviceGBId: "34020000001320001101",
deviceIp: "192.168.1.20",
devicePort: "5060",
username: "34020000001320001101",
password: "12345678",
name: null,
serverGBId: null,
serverGBDomain: null,
serverIP: null,
serverPort: null,
deviceGBId: null,
deviceIp: null,
devicePort: null,
username: null,
password: null,
expires: 300,
keepTimeout: 60,
transport: "UDP",
@ -163,27 +164,27 @@ export default {
methods: {
openDialog: function (platform, callback) {
var that = this;
this.$axios({
method: 'get',
url:`/api/platform/server_config`
}).then(function (res) {
if (platform == null) {
this.onSubmit_text = "立即创建";
this.$axios({
method: 'get',
url:`/api/platform/server_config`
}).then(function (res) {
console.log(res);
that.platform.deviceGBId = res.data.username;
that.platform.deviceIp = res.data.deviceIp;
that.platform.devicePort = res.data.devicePort;
that.platform.username = res.data.username;
that.platform.password = res.data.password;
}).catch(function (error) {
}).catch(function (error) {
console.log(error);
});
this.showDialog = true;
this.listChangeCallback = callback;
if (platform != null) {
}else {
this.platform = platform;
this.onSubmit_text = "保存";
} else {
this.onSubmit_text = "立即创建";
}
this.showDialog = true;
this.listChangeCallback = callback;
},
onSubmit: function () {
console.log("onSubmit");

4
web_src/static/css/font-awesome.min.css

File diff suppressed because one or more lines are too long

396
web_src/static/css/login.css

@ -0,0 +1,396 @@
/*//////////////////////////////////////////////////////////////////
[ FONT ]*/
@font-face {
font-family: Poppins-Regular;
src: url('../fonts/poppins/Poppins-Regular.ttf');
}
@font-face {
font-family: Poppins-Medium;
src: url('../fonts/poppins/Poppins-Medium.ttf');
}
@font-face {
font-family: Poppins-Bold;
src: url('../fonts/poppins/Poppins-Bold.ttf');
}
@font-face {
font-family: Poppins-SemiBold;
src: url('../fonts/poppins/Poppins-SemiBold.ttf');
}
.limiter {
width: 100%;
margin: 0 auto;
font-family: Poppins-Regular, sans-serif;
}
.container-login100 {
width: 100%;
min-height: 100vh;
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
background: #f2f2f2;
}
.wrap-login100 {
background: #fff;
border-radius: 10px;
overflow: hidden;
padding: 77px 55px 33px 55px;
box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 0.1);
-webkit-box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 0.1);
-o-box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 0.1);
-ms-box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 0.1);
}
/*------------------------------------------------------------------
[ Form ]*/
.login100-form {
width: 100%;
}
.login100-form-title {
display: block;
font-family: Poppins-Bold;
font-size: 30px;
color: #333333;
line-height: 1.2;
text-align: center;
}
.login100-form-title i {
font-size: 60px;
}
/*------------------------------------------------------------------
[ Input ]*/
.wrap-input100 {
width: 100%;
position: relative;
border-bottom: 2px solid #adadad;
margin-bottom: 37px;
}
.input100 {
font-family: Poppins-Regular;
font-size: 15px;
color: #555555;
line-height: 1.2;
display: block;
width: 100%;
height: 45px;
background: transparent;
padding: 0 5px;
outline: none;
border: none;
}
.input100::-webkit-input-placeholder { color: #adadad;}
.input100:-moz-placeholder { color: #adadad;}
.input100::-moz-placeholder { color: #adadad;}
.input100:-ms-input-placeholder { color: #adadad;}
/*---------------------------------------------*/
.focus-input100 {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
color:transparent;
}
.focus-input100::before {
content: "";
display: block;
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
-webkit-transition: all 0.4s;
-o-transition: all 0.4s;
-moz-transition: all 0.4s;
transition: all 0.4s;
background: #6a7dfe;
background: -webkit-linear-gradient(left, #21d4fd, #b721ff);
background: -o-linear-gradient(left, #21d4fd, #b721ff);
background: -moz-linear-gradient(left, #21d4fd, #b721ff);
background: linear-gradient(left, #21d4fd, #b721ff);
}
.focus-input100::after {
font-family: Poppins-Regular;
font-size: 15px;
color: #999999;
line-height: 1.2;
content: attr(data-placeholder);
display: block;
width: 100%;
position: absolute;
top: 16px;
left: 0px;
padding-left: 5px;
-webkit-transition: all 0.4s;
-o-transition: all 0.4s;
-moz-transition: all 0.4s;
transition: all 0.4s;
}
.input100:focus + .focus-input100::after {
top: -15px;
}
.input100:focus + .focus-input100::before {
width: 100%;
}
.has-val.input100 + .focus-input100::after {
top: -15px;
}
.has-val.input100 + .focus-input100::before {
width: 100%;
}
/*---------------------------------------------*/
.btn-show-pass {
font-size: 15px;
color: #999999;
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
align-items: center;
position: absolute;
height: 100%;
top: 0;
right: 0;
padding-right: 5px;
cursor: pointer;
-webkit-transition: all 0.4s;
-o-transition: all 0.4s;
-moz-transition: all 0.4s;
transition: all 0.4s;
}
.btn-show-pass:hover {
color: #6a7dfe;
color: -webkit-linear-gradient(left, #21d4fd, #b721ff);
color: -o-linear-gradient(left, #21d4fd, #b721ff);
color: -moz-linear-gradient(left, #21d4fd, #b721ff);
color: linear-gradient(left, #21d4fd, #b721ff);
}
.btn-show-pass.active {
color: #6a7dfe;
color: -webkit-linear-gradient(left, #21d4fd, #b721ff);
color: -o-linear-gradient(left, #21d4fd, #b721ff);
color: -moz-linear-gradient(left, #21d4fd, #b721ff);
color: linear-gradient(left, #21d4fd, #b721ff);
}
/*------------------------------------------------------------------
[ Button ]*/
.container-login100-form-btn {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
flex-wrap: wrap;
justify-content: center;
padding-top: 13px;
}
.wrap-login100-form-btn {
width: 100%;
display: block;
position: relative;
z-index: 1;
border-radius: 25px;
overflow: hidden;
margin: 0 auto;
}
.login100-form-bgbtn {
position: absolute;
z-index: -1;
width: 300%;
height: 100%;
background: #a64bf4;
background: -webkit-linear-gradient(right, #21d4fd, #b721ff, #21d4fd, #b721ff);
background: -o-linear-gradient(right, #21d4fd, #b721ff, #21d4fd, #b721ff);
background: -moz-linear-gradient(right, #21d4fd, #b721ff, #21d4fd, #b721ff);
background: linear-gradient(right, #21d4fd, #b721ff, #21d4fd, #b721ff);
top: 0;
left: -100%;
-webkit-transition: all 0.4s;
-o-transition: all 0.4s;
-moz-transition: all 0.4s;
transition: all 0.4s;
}
.login100-form-btn {
font-family: Poppins-Medium;
font-size: 15px;
color: #fff;
line-height: 1.2;
text-transform: uppercase;
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
justify-content: center;
align-items: center;
padding: 0 20px;
width: 100%;
height: 50px;
outline: none !important;
border: none;
background: transparent;
}
.login100-form-btn:hover {
cursor: pointer;
}
.wrap-login100-form-btn:hover .login100-form-bgbtn {
left: 0;
}
/*------------------------------------------------------------------
[ Responsive ]*/
@media (max-width: 576px) {
.wrap-login100 {
padding: 77px 15px 33px 15px;
}
}
/*------------------------------------------------------------------
[ Alert validate ]*/
.validate-input {
position: relative;
}
.alert-validate::before {
content: attr(data-validate);
position: absolute;
max-width: 70%;
background-color: #fff;
border: 1px solid #c80000;
border-radius: 2px;
padding: 4px 25px 4px 10px;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
right: 0px;
pointer-events: none;
font-family: Poppins-Regular;
color: #c80000;
font-size: 13px;
line-height: 1.4;
text-align: left;
visibility: hidden;
opacity: 0;
-webkit-transition: opacity 0.4s;
-o-transition: opacity 0.4s;
-moz-transition: opacity 0.4s;
transition: opacity 0.4s;
}
.alert-validate::after {
content: "\f06a";
font-family: FontAwesome;
font-size: 16px;
color: #c80000;
display: block;
position: absolute;
background-color: #fff;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
right: 5px;
}
.alert-validate:hover:before {
visibility: visible;
opacity: 1;
}
@media (max-width: 992px) {
.alert-validate::before {
visibility: visible;
opacity: 1;
}
}
/** util **/
.p-b-26 {padding-bottom: 26px;}
.p-b-48 {padding-bottom: 48px;}
.p-t-115 {padding-top: 115px;}
/**font**/
/* .zmdi {
display: inline-block;
font: normal normal normal 14px/1 'Material-Design-Iconic-Font';
font-size: 14px;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.zmdi-font::before {
content: '\f16a';
}
.login100-form-title i {
font-size: 60px;
} */

BIN
web_src/static/fonts/poppins/Poppins-Bold.ttf

Binary file not shown.

BIN
web_src/static/fonts/poppins/Poppins-Medium.ttf

Binary file not shown.

BIN
web_src/static/fonts/poppins/Poppins-Regular.ttf

Binary file not shown.

BIN
web_src/static/fonts/poppins/Poppins-SemiBold.ttf

Binary file not shown.
Loading…
Cancel
Save