Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

This commit is contained in:
mrjackwang 2022-07-20 13:51:30 +08:00 committed by GitHub
commit 8d87741dea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 2976 additions and 1157 deletions

View File

@ -50,7 +50,7 @@ CREATE TABLE `device` (
`treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -142,7 +142,7 @@ CREATE TABLE `device_channel` (
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,
UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=19324 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=19336 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -179,7 +179,7 @@ CREATE TABLE `device_mobile_position` (
`latitudeWgs84` double DEFAULT NULL,
`createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5649 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=6751 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -208,13 +208,12 @@ CREATE TABLE `gb_stream` (
`latitude` double DEFAULT NULL,
`streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`status` int DEFAULT NULL,
`createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`gbStreamId`) USING BTREE,
UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
UNIQUE KEY `gbId` (`gbId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=301681 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=301740 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -244,7 +243,7 @@ CREATE TABLE `log` (
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=29943 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=37760 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -329,16 +328,16 @@ CREATE TABLE `parent_platform` (
`ptz` int DEFAULT NULL,
`rtcp` int DEFAULT NULL,
`status` bit(1) DEFAULT NULL,
`shareAllLiveStream` int DEFAULT NULL,
`startOfflinePush` int DEFAULT '0',
`administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`catalogGroup` int DEFAULT '1',
`createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,
UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -362,6 +361,8 @@ CREATE TABLE `platform_catalog` (
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`businessGroupId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
@ -388,7 +389,7 @@ CREATE TABLE `platform_gb_channel` (
`catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`deviceChannelId` int NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4889 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=4912 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -414,7 +415,7 @@ CREATE TABLE `platform_gb_stream` (
`id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=302077 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=302134 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -455,7 +456,7 @@ CREATE TABLE `stream_proxy` (
`updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -487,9 +488,10 @@ CREATE TABLE `stream_push` (
`serverId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`pushTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`status` int DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `stream_push_pk` (`app`,`stream`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=305304 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
) ENGINE=InnoDB AUTO_INCREMENT=305390 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -515,6 +517,7 @@ CREATE TABLE `user` (
`roleId` int NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pushKey` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
@ -526,7 +529,7 @@ CREATE TABLE `user` (
LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57','453df297a57a5a7438934sda801fc3');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
@ -566,4 +569,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2022-07-06 9:43:54
-- Dump completed on 2022-07-17 23:15:09

View File

@ -51,10 +51,31 @@ alter table stream_proxy
alter table stream_push
add pushTime varchar(50) default null;
alter table stream_push
add status int DEFAULT NULL;
alter table stream_push
add updateTime varchar(50) default null;
alter table stream_push
add pushIng int DEFAULT NULL;
alter table stream_push
change createStamp createTime varchar(50) default null;
alter table gb_stream
drop column status;
alter table user
add pushKey varchar(50) default null;
update user set pushKey='453df297a57a5a7438934sda801fc3' where id=1;
alter table parent_platform
add treeType varchar(50) not null;
update parent_platform set parent_platform.treeType='BusinessGroup';
alter table parent_platform drop shareAllLiveStream;
alter table platform_catalog
add civilCode varchar(50) default null;
alter table platform_catalog
add businessGroupId varchar(50) default null;

View File

@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import springfox.documentation.oas.annotations.EnableOpenApi;
/**
*
* 启动类
*/
@ServletComponentScan("com.genersoft.iot.vmp.conf")
@SpringBootApplication

View File

@ -9,6 +9,9 @@ public class StreamInfo {
private String deviceID;
private String channelId;
private String flv;
private String ip;
private String https_flv;
private String ws_flv;
private String wss_flv;
@ -292,4 +295,12 @@ public class StreamInfo {
public void setProgress(double progress) {
this.progress = progress;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
}

View File

@ -58,6 +58,8 @@ public class VideoManagerConstants {
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_";
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
@ -71,6 +73,8 @@ public class VideoManagerConstants {
public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
//************************** redis 消息*********************************
// 流变化的通知
@ -79,9 +83,15 @@ public class VideoManagerConstants {
// 接收推流设备的GPS变化通知
public static final String VM_MSG_GPS = "VM_MSG_GPS";
// 接收推流设备的GPS变化通知
public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
// redis 消息通知设备推流到平台
public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
// redis 消息请求所有的在线通道
public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
// 移动位置订阅通知
public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
@ -94,6 +104,10 @@ public class VideoManagerConstants {
// 设备状态订阅的通知
public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
//************************** 第三方 ****************************************
public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";

View File

@ -5,6 +5,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
@ -103,12 +104,9 @@ public class DynamicTask {
public void stop(String key) {
if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
// Runnable runnable = runnableMap.get(key);
// if (runnable instanceof ISubscribeTask) {
// ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
// subscribeTask.stop();
// }
futureMap.get(key).cancel(false);
futureMap.remove(key);
runnableMap.remove(key);
}
}
@ -123,4 +121,19 @@ public class DynamicTask {
public Runnable get(String key) {
return runnableMap.get(key);
}
/**
* 每五分钟检查失效的任务并移除
*/
@Scheduled(cron="0 0/5 * * * ?")
public void execute(){
if (futureMap.size() > 0) {
for (String key : futureMap.keySet()) {
if (futureMap.get(key).isDone()) {
futureMap.remove(key);
runnableMap.remove(key);
}
}
}
}
}

View File

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener;
import com.genersoft.iot.vmp.service.impl.RedisGpsMsgListener;
import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;
import com.genersoft.iot.vmp.service.impl.RedisStreamMsgListener;
import com.genersoft.iot.vmp.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -60,6 +57,9 @@ public class RedisConfig extends CachingConfigurerSupport {
@Autowired
private RedisGbPlayMsgListener redisGbPlayMsgListener;
@Autowired
private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
@Bean
public JedisPool jedisPool() {
if (StringUtils.isBlank(password)) {
@ -108,6 +108,7 @@ public class RedisConfig extends CachingConfigurerSupport {
container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
return container;
}

View File

@ -104,11 +104,6 @@ public class ParentPlatform {
*/
private int channelCount;
/**
* 共享所有的直播流
*/
private boolean shareAllLiveStream;
/**
* 默认目录Id,自动添加的通道多放在这个目录下
*/
@ -154,6 +149,11 @@ public class ParentPlatform {
*/
private String createTime;
/**
* 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup
*/
private String treeType;
public Integer getId() {
return id;
}
@ -314,15 +314,6 @@ public class ParentPlatform {
this.channelCount = channelCount;
}
public boolean isShareAllLiveStream() {
return shareAllLiveStream;
}
public void setShareAllLiveStream(boolean shareAllLiveStream) {
this.shareAllLiveStream = shareAllLiveStream;
}
public String getCatalogId() {
return catalogId;
}
@ -394,4 +385,12 @@ public class ParentPlatform {
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getTreeType() {
return treeType;
}
public void setTreeType(String treeType) {
this.treeType = treeType;
}
}

View File

@ -1,12 +1,28 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 国标级联-目录
* @author lin
*/
public class PlatformCatalog {
private String id;
private String name;
private String platformId;
private String parentId;
private int childrenCount; // 子节点数
private int type; // 0 目录, 1 国标通道, 2 直播流
private String civilCode;
private String businessGroupId;
/**
* 子节点数
*/
private int childrenCount;
/**
* 0 目录, 1 国标通道, 2 直播流
*/
private int type;
public String getId() {
return id;
@ -68,4 +84,19 @@ public class PlatformCatalog {
this.type = 2;
}
public String getCivilCode() {
return civilCode;
}
public void setCivilCode(String civilCode) {
this.civilCode = civilCode;
}
public String getBusinessGroupId() {
return businessGroupId;
}
public void setBusinessGroupId(String businessGroupId) {
this.businessGroupId = businessGroupId;
}
}

View File

@ -1,4 +1,4 @@
package com.genersoft.iot.vmp.domain.req;
package com.genersoft.iot.vmp.gb28181.bean;
/**

View File

@ -0,0 +1,10 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 目录结构类型
* @author lin
*/
public class TreeType {
public static final String BUSINESS_GROUP = "BusinessGroup";
public static final String CIVIL_CODE = "CivilCode";
}

View File

@ -65,7 +65,6 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
}
// 查询是否有推流 如果有则都停止
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID());
logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流size", sendRtpItems.size());
if (sendRtpItems != null && sendRtpItems.size() > 0) {
logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID());
for (SendRtpItem sendRtpItem : sendRtpItems) {

View File

@ -11,13 +11,40 @@ public class CatalogEvent extends ApplicationEvent {
super(source);
}
public static final String ON = "ON"; // 上线
public static final String OFF = "OFF"; // 离线
public static final String VLOST = "VLOST"; // 视频丢失
public static final String DEFECT = "DEFECT"; // 故障
public static final String ADD = "ADD"; // 增加
public static final String DEL = "DEL"; // 删除
public static final String UPDATE = "UPDATE"; // 更新
/**
* 上线
*/
public static final String ON = "ON";
/**
* 离线
*/
public static final String OFF = "OFF";
/**
* 视频丢失
*/
public static final String VLOST = "VLOST";
/**
* 故障
*/
public static final String DEFECT = "DEFECT";
/**
* 增加
*/
public static final String ADD = "ADD";
/**
* 删除
*/
public static final String DEL = "DEL";
/**
* 更新
*/
public static final String UPDATE = "UPDATE";
private List<DeviceChannel> deviceChannels;
private List<GbStream> gbStreams;

View File

@ -58,17 +58,16 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
ParentPlatform parentPlatform = null;
Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
if (event.getPlatformId() != null) {
if (!StringUtils.isEmpty(event.getPlatformId())) {
subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
if (subscribe == null) {
return;
}
parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
if (parentPlatform != null && !parentPlatform.isStatus()) {
return;
}
subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
if (subscribe == null) {
logger.info("发送订阅消息时发现订阅信息已经不存在: {}", event.getPlatformId());
return;
}
}else {
// 获取所用订阅
List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform();
@ -144,11 +143,8 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
}
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
for (GbStream gbStream : event.getGbStreams()) {
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
if (deviceChannelByStream.getParentId().length() <= 10) { // 父节点是行政区划,则设置CivilCode使用此行政区划
deviceChannelByStream.setCivilCode(deviceChannelByStream.getParentId());
}
deviceChannelList.add(deviceChannelByStream);
deviceChannelList.add(
gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform));
}
}
if (deviceChannelList.size() > 0) {

View File

@ -57,23 +57,17 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
if (subscribe != null) {
// if (!parentPlatform.isStatus()) {
// logger.info("发送订阅时发现平台已经离线:{}", platformId);
// return;
// }
// TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
if (gbStreams.size() == 0) {
logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
return;
}
for (GbStream gbStream : gbStreams) {
String gbId = gbStream.getGbId();
for (DeviceChannel deviceChannel : gbStreams) {
String gbId = deviceChannel.getChannelId();
GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
if (gpsMsgInfo != null) { // 无最新位置不发送
if (logger.isDebugEnabled()) {
logger.debug("无最新位置不发送");
}
// 无最新位置不发送
if (gpsMsgInfo != null) {
// 经纬度都为0不发送
if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
continue;

View File

@ -257,37 +257,37 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
if (channels.size() > 0) {
for (DeviceChannel channel : channels) {
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
channel.setParentId(parentPlatform.getDeviceGBId());
}
catalogXml.append("<Item>\r\n");
// 行政区划分组只需要这两项就可以
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParentId() != null) {
// 业务分组加上这一项即可提高兼容性
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}
if (channel.getChannelId().length() == 20) {
if (Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段
catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
}
if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
// 虚拟组织增加BusinessGroupID字段
catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
}
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParental() == 0) {
// 通道项
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下字段
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
catalogXml.append("<Longitude>" + channel.getLongitudeWgs84() + "</Longitude>\r\n");
catalogXml.append("<Latitude>" + channel.getLatitudeWgs84() + "</Latitude>\r\n");
catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
catalogXml.append("<Info>\r\n");
catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
catalogXml.append("</Info>\r\n");
}
}
catalogXml.append("</Item>\r\n");
}
}
@ -592,27 +592,35 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
channel.setParentId(parentPlatform.getDeviceGBId());
}
catalogXml.append("<Item>\r\n");
// 行政区划分组只需要这两项就可以
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParentId() != null) {
// 业务分组加上这一项即可提高兼容性
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段
if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
// 虚拟组织增加BusinessGroupID字段
catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
}
if (channel.getChannelType() == 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner>0</Owner>\r\n");
catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
}
if (!"presence".equals(subscribeInfo.getEventType())) {
catalogXml.append("<Event>" + type + "</Event>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParental() == 0) {
// 通道项
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
}
if (!"presence".equals(subscribeInfo.getEventType())) {
catalogXml.append("<Event>" + type + "</Event>\r\n");
}
}
catalogXml.append("</Item>\r\n");
}

View File

@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -71,6 +72,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
@Autowired
private SIPProcessorObserver sipProcessorObserver;
@Autowired
private IDeviceChannelService deviceChannelService;
private boolean taskQueueHandlerRun = false;
private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
@ -173,28 +177,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
logger.info("[收到 移动位置订阅]{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setReportSource("Mobile Position");
// 默认来源坐标系为WGS-84处理
if ("WGS84".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeGcj02(position[0]);
mobilePosition.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeWgs84(position[0]);
mobilePosition.setLatitudeWgs84(position[1]);
}else {
mobilePosition.setLongitudeGcj02(0.00);
mobilePosition.setLatitudeGcj02(0.00);
mobilePosition.setLongitudeWgs84(0.00);
mobilePosition.setLatitudeWgs84(0.00);
}
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
@ -202,11 +185,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
deviceChannel.setChannelId(channelId);
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
deviceChannel.setGpsTime(mobilePosition.getTime());
deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
@ -281,38 +271,28 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
mobilePosition.setLongitude(deviceAlarm.getLongitude());
mobilePosition.setLatitude(deviceAlarm.getLatitude());
mobilePosition.setReportSource("GPS Alarm");
if ("WGS84".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeGcj02(position[0]);
mobilePosition.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeWgs84(position[0]);
mobilePosition.setLatitudeWgs84(position[1]);
}else {
mobilePosition.setLongitudeGcj02(0.00);
mobilePosition.setLatitudeGcj02(0.00);
mobilePosition.setLongitudeWgs84(0.00);
mobilePosition.setLatitudeWgs84(0.00);
}
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
deviceChannel.setChannelId(channelId);
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
deviceChannel.setGpsTime(mobilePosition.getTime());
deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
}
// TODO: 需要实现存储报警信息报警分类
@ -364,7 +344,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
}else {
event = eventElement.getText().toUpperCase();
}
DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device);
DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
channel.setDeviceId(device.getDeviceId());
logger.info("[收到 目录订阅]{}/{}", device.getDeviceId(), channel.getChannelId());
switch (event) {
@ -389,7 +369,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
case CatalogEvent.ADD:
// 增加
logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId());
storager.updateChannel(deviceId, channel);
deviceChannelService.updateChannel(deviceId, channel);
break;
case CatalogEvent.DEL:
// 删除
@ -399,7 +379,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
case CatalogEvent.UPDATE:
// 更新
logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId());
storager.updateChannel(deviceId, channel);
deviceChannelService.updateChannel(deviceId, channel);
break;
default:
logger.warn("[ NotifyCatalog ] event not found {}", event );

View File

@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -58,6 +59,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
@Autowired
private IDeviceAlarmService deviceAlarmService;
@Autowired
private IDeviceChannelService deviceChannelService;
@Override
public void afterPropertiesSet() throws Exception {
notifyMessageHandler.addHandler(cmdType, this);
@ -119,38 +123,26 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
mobilePosition.setLongitude(deviceAlarm.getLongitude());
mobilePosition.setLatitude(deviceAlarm.getLatitude());
mobilePosition.setReportSource("GPS Alarm");
if ("WGS84".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeGcj02(position[0]);
mobilePosition.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeWgs84(position[0]);
mobilePosition.setLatitudeWgs84(position[1]);
}else {
mobilePosition.setLongitudeGcj02(0.00);
mobilePosition.setLatitudeGcj02(0.00);
mobilePosition.setLongitudeWgs84(0.00);
mobilePosition.setLatitudeWgs84(0.00);
}
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
deviceChannel.setChannelId(channelId);
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
deviceChannel.setGpsTime(mobilePosition.getTime());
deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
}
}

View File

@ -58,85 +58,21 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
// 准备回复通道信息
List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
// 查询关联的直播通道
List<GbStream> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
// 回复目录信息
List<DeviceChannel> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> allChannels = new ArrayList<>();
// 回复目录信息
List<PlatformCatalog> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) {
if (catalog.getParentId().equals(catalog.getPlatformId())) {
catalog.setParentId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(catalog.getId());
deviceChannel.setName(catalog.getName());
deviceChannel.setLongitude(0.0);
deviceChannel.setLatitude(0.0);
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setRegisterWay(1);
if (catalog.getParentId() != null && catalog.getParentId().length() <= 10) {
deviceChannel.setCivilCode(catalog.getParentId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0");
allChannels.add(deviceChannel);
}
allChannels.addAll(catalogs);
}
// 回复级联的通道
if (deviceChannels.size() > 0) {
for (DeviceChannelInPlatform channel : deviceChannels) {
if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {
channel.setCatalogId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
deviceChannel.setParental(0);
deviceChannel.setParentId(channel.getCatalogId());
if (channel.getCatalogId() != null && channel.getCatalogId().length() <= 10) {
channel.setCivilCode(channel.getCatalogId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
allChannels.add(deviceChannel);
}
allChannels.addAll(deviceChannels);
}
// 回复直播的通道
if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
gbStream.setCatalogId(null);
}
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbStream.getGbId());
deviceChannel.setName(gbStream.getName());
deviceChannel.setLongitude(gbStream.getLongitude());
deviceChannel.setLatitude(gbStream.getLatitude());
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
// deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setStatus(1);
deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1);
if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() <= 10) {
deviceChannel.setCivilCode(gbStream.getCatalogId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0);
deviceChannel.setSecrecy("0");
allChannels.add(deviceChannel);
}
allChannels.addAll(gbStreams);
}
if (allChannels.size() > 0) {
cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());

View File

@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.GpsUtil;
@ -42,6 +43,9 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IDeviceChannelService deviceChannelService;
@Override
public void afterPropertiesSet() throws Exception {
notifyMessageHandler.addHandler(cmdType, this);
@ -79,38 +83,26 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
mobilePosition.setAltitude(0.0);
}
mobilePosition.setReportSource("Mobile Position");
if ("WGS84".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeGcj02(position[0]);
mobilePosition.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeWgs84(position[0]);
mobilePosition.setLatitudeWgs84(position[1]);
}else {
mobilePosition.setLongitudeGcj02(0.00);
mobilePosition.setLatitudeGcj02(0.00);
mobilePosition.setLongitudeWgs84(0.00);
mobilePosition.setLatitudeWgs84(0.00);
}
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
deviceChannel.setChannelId(mobilePosition.getChannelId());
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
deviceChannel.setGpsTime(mobilePosition.getTime());
deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
//回复 200 OK
responseAck(evt, Response.OK);

View File

@ -70,86 +70,24 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
Element snElement = rootElement.element("SN");
String sn = snElement.getText();
// 准备回复通道信息
List<DeviceChannelInPlatform> deviceChannelInPlatforms = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> deviceChannelInPlatforms = storager.queryChannelWithCatalog(parentPlatform.getServerGBId());
// 查询关联的直播通道
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
// 回复目录信息
List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
List<DeviceChannel> allChannels = new ArrayList<>();
if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) {
if (catalog.getParentId().equals(catalog.getPlatformId())) {
catalog.setParentId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = new DeviceChannel();
// 通道的类型0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
deviceChannel.setChannelType(2);
deviceChannel.setChannelId(catalog.getId());
deviceChannel.setName(catalog.getName());
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setRegisterWay(1);
if (catalog.getParentId() != null && catalog.getParentId().length() < 10) {
deviceChannel.setCivilCode(catalog.getParentId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
allChannels.add(deviceChannel);
}
allChannels.addAll(catalogs);
}
// 回复级联的通道
if (deviceChannelInPlatforms.size() > 0) {
for (DeviceChannelInPlatform channel : deviceChannelInPlatforms) {
if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {
channel.setCatalogId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
// 通道的类型0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
deviceChannel.setChannelType(0);
deviceChannel.setParental(0);
deviceChannel.setParentId(channel.getCatalogId());
if (channel.getCatalogId() != null && channel.getCatalogId().length() < 10) {
deviceChannel.setCivilCode(channel.getCatalogId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
allChannels.add(deviceChannel);
}
allChannels.addAll(deviceChannelInPlatforms);
}
// 回复直播的通道
if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
gbStream.setCatalogId(null);
}
DeviceChannel deviceChannel = new DeviceChannel();
// 通道的类型0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
deviceChannel.setChannelType(1);
deviceChannel.setChannelId(gbStream.getGbId());
deviceChannel.setName(gbStream.getName());
deviceChannel.setLongitude(gbStream.getLongitude());
deviceChannel.setLatitude(gbStream.getLatitude());
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
// deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setStatus(1);
deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1);
if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() < 10) {
deviceChannel.setCivilCode(gbStream.getCatalogId());
}else {
deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
}
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0);
deviceChannel.setSecrecy("0");
allChannels.add(deviceChannel);
}
allChannels.addAll(gbStreams);
}
if (allChannels.size() > 0) {
cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());

View File

@ -125,11 +125,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
if (channelDeviceElement == null) {
continue;
}
//by brewswang
// if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息就更新一下位置
// processNotifyMobilePosition(evt, itemDevice);
// }
DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device);
DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
deviceChannel.setDeviceId(take.getDevice().getDeviceId());
channelList.add(deviceChannel);

View File

@ -87,7 +87,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
device.setStreamMode("UDP");
}
deviceService.updateDevice(device);
// storager.updateDevice(device);
RequestMessage msg = new RequestMessage();
msg.setKey(key);

View File

@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.GpsUtil;
@ -42,6 +43,9 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IDeviceChannelService deviceChannelService;
@Override
public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this);
@ -79,38 +83,25 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
mobilePosition.setAltitude(0.0);
}
mobilePosition.setReportSource("Mobile Position");
if ("WGS84".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeGcj02(position[0]);
mobilePosition.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
mobilePosition.setLongitudeWgs84(position[0]);
mobilePosition.setLatitudeWgs84(position[1]);
}else {
mobilePosition.setLongitudeGcj02(0.00);
mobilePosition.setLatitudeGcj02(0.00);
mobilePosition.setLongitudeWgs84(0.00);
mobilePosition.setLatitudeWgs84(0.00);
}
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
deviceChannel.setChannelId(mobilePosition.getChannelId());
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
deviceChannel.setGpsTime(mobilePosition.getTime());
deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
//回复 200 OK
responseAck(evt, Response.OK);

View File

@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq;
import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;

View File

@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.dom4j.Attribute;
import org.dom4j.Document;
@ -29,7 +31,7 @@ public class XmlUtil {
/**
* 日志服务
*/
private static Logger LOG = LoggerFactory.getLogger(XmlUtil.class);
private static Logger logger = LoggerFactory.getLogger(XmlUtil.class);
/**
* 解析XML为Document对象
@ -46,7 +48,7 @@ public class XmlUtil {
try {
document = saxReader.read(sr);
} catch (DocumentException e) {
LOG.error("解析失败", e);
logger.error("解析失败", e);
}
return null == document ? null : document.getRootElement();
}
@ -182,47 +184,69 @@ public class XmlUtil {
return xml.getRootElement();
}
public static DeviceChannel channelContentHander(Element itemDevice, Device device){
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";
private enum ChannelType{
CivilCode, BusinessGroup,VirtualOrganization,Other
}
public static DeviceChannel channelContentHander(Element itemDevice, Device device, String event){
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setName(channelName);
deviceChannel.setDeviceId(device.getDeviceId());
Element channdelIdElement = itemDevice.element("DeviceID");
String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : "";
deviceChannel.setChannelId(channelId);
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
deviceChannel.setStatus(1);
if (channdelIdElement == null) {
logger.warn("解析Catalog消息时发现缺少 DeviceID");
return null;
}
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
deviceChannel.setStatus(0);
String channelId = channdelIdElement.getTextTrim();
if (StringUtils.isEmpty(channelId)) {
logger.warn("解析Catalog消息时发现缺少 DeviceID");
return null;
}
deviceChannel.setChannelId(channelId);
if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) {
// 除了ADD和update情况下需要识别全部内容
return deviceChannel;
}
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"));
String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
if (XmlUtil.getText(itemDevice, "Parental") == null
|| XmlUtil.getText(itemDevice, "Parental").equals("")) {
if (deviceChannel.getChannelId().length() <= 10
|| (deviceChannel.getChannelId().length() == 20 && (
Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 215
|| Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216
)
)
) {
deviceChannel.setParental(1);
}else {
deviceChannel.setParental(0);
ChannelType channelType = ChannelType.Other;
if (channelId.length() <= 8) {
channelType = ChannelType.CivilCode;
}else {
if (channelId.length() == 20) {
int code = Integer.parseInt(channelId.substring(10, 13));
switch (code){
case 215:
channelType = ChannelType.BusinessGroup;
break;
case 216:
channelType = ChannelType.VirtualOrganization;
break;
default:
break;
}
}
} else {
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")) == 1?1:0);
}
Element channdelNameElement = itemDevice.element("Name");
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim() : "";
deviceChannel.setName(channelName);
String civilCode = XmlUtil.getText(itemDevice, "CivilCode");
deviceChannel.setCivilCode(civilCode);
if (channelType == ChannelType.CivilCode && civilCode == null) {
deviceChannel.setParental(1);
// 行政区划如果没有传递具体值则推测一个
if (channelId.length() > 2) {
deviceChannel.setCivilCode(channelId.substring(0, channelId.length() - 2));
}
}
if (channelType.equals(ChannelType.CivilCode)) {
// 行政区划其他字段没必要识别了默认在线即可
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setCreateTime(DateUtil.getNow());
deviceChannel.setUpdateTime(DateUtil.getNow());
return deviceChannel;
}
/**
* 行政区划展示设备树与业务分组展示设备树是两种不同的模式
@ -230,7 +254,17 @@ public class XmlUtil {
* 河北省
* --> 石家庄市
* --> 摄像头
* --> 正定县
*String parentId = XmlUtil.getText(itemDevice, "ParentID");
if (parentId != null) {
if (parentId.contains("/")) {
String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
String businessGroup = parentId.substring(0, parentId.indexOf("/"));
deviceChannel.setParentId(lastParentId);
}else {
deviceChannel.setParentId(parentId);
}
}
deviceCh --> 正定县
* --> 摄像头
* --> 摄像头
*
@ -243,59 +277,88 @@ public class XmlUtil {
* --> 摄像头
*/
String parentId = XmlUtil.getText(itemDevice, "ParentID");
String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
if (parentId != null) {
if (parentId.contains("/")) {
String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
if (businessGroupID == null) {
businessGroupID = parentId.substring(0, parentId.indexOf("/"));
}
deviceChannel.setParentId(lastParentId);
}else {
deviceChannel.setParentId(parentId);
}
}
deviceChannel.setBusinessGroupId(businessGroupID);
if (channelType.equals(ChannelType.BusinessGroup) || channelType.equals(ChannelType.VirtualOrganization)) {
// 业务分组和虚拟组织 其他字段没必要识别了默认在线即可
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setCreateTime(DateUtil.getNow());
deviceChannel.setUpdateTime(DateUtil.getNow());
return deviceChannel;
}
// else {
// if (deviceChannel.getChannelId().length() <= 10) { // 此时为行政区划, 上下级行政区划使用DeviceId关联
// deviceChannel.setParentId(deviceChannel.getChannelId().substring(0, deviceChannel.getChannelId().length() - 2));
// }else if (deviceChannel.getChannelId().length() == 20) {
// if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织
// deviceChannel.setBusinessGroupId(businessGroupID);
// }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 如果上级设备编号是NVR则直接将NVR的编号设置给通道的上级编号
// deviceChannel.setParentId(device.getDeviceId());
// }else if (deviceChannel.getCivilCode() != null) {
// // 设备 无parentId的20位是使用CivilCode表示上级的设备
// // 215 业务分组是需要有parentId的
// deviceChannel.setParentId(deviceChannel.getCivilCode());
// }
// }else {
// deviceChannel.setParentId(deviceChannel.getDeviceId());
// }
// }
Element statusElement = itemDevice.element("Status");
if (XmlUtil.getText(itemDevice, "SafetyWay") == null
|| XmlUtil.getText(itemDevice, "SafetyWay") == "") {
if (statusElement != null) {
String status = statusElement.getTextTrim().trim();
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
deviceChannel.setStatus(1);
}
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
deviceChannel.setStatus(0);
}
}else {
deviceChannel.setStatus(1);
}
// 识别自带的目录标识
String parental = XmlUtil.getText(itemDevice, "Parental");
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
if (!StringUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
deviceChannel.setParental(0);
}else {
deviceChannel.setParental(1);
}
deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
if (StringUtils.isEmpty(safetyWay)) {
deviceChannel.setSafetyWay(0);
} else {
deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
}
if (XmlUtil.getText(itemDevice, "RegisterWay") == null
|| XmlUtil.getText(itemDevice, "RegisterWay") == "") {
String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
if (StringUtils.isEmpty(registerWay)) {
deviceChannel.setRegisterWay(1);
} else {
deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
deviceChannel.setRegisterWay(Integer.parseInt(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"));
@ -304,43 +367,23 @@ public class XmlUtil {
} 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")));
String longitude = XmlUtil.getText(itemDevice, "Longitude");
if (NumericUtil.isDouble(longitude)) {
deviceChannel.setLongitude(Double.parseDouble(longitude));
} else {
deviceChannel.setLongitude(0.00);
}
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
String latitude = XmlUtil.getText(itemDevice, "Latitude");
if (NumericUtil.isDouble(latitude)) {
deviceChannel.setLatitude(Double.parseDouble(latitude));
} else {
deviceChannel.setLatitude(0.00);
}
deviceChannel.setGpsTime(DateUtil.getNow());
if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
if ("WGS84".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeGcj02(position[0]);
deviceChannel.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeWgs84(position[0]);
deviceChannel.setLatitudeWgs84(position[1]);
}else {
deviceChannel.setLongitudeGcj02(0.00);
deviceChannel.setLatitudeGcj02(0.00);
deviceChannel.setLongitudeWgs84(0.00);
deviceChannel.setLatitudeWgs84(0.00);
}
}else {
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
}
if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
//兼容INFO中的信息
Element info = itemDevice.element("Info");

View File

@ -136,4 +136,12 @@ public class AssistRESTfulUtils {
return sendGet(mediaServerItem, "api/record/file/duration",param, callback);
}
public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){
Map<String, Object> param = new HashMap<>();
param.put("app",app);
param.put("stream",stream);
param.put("callId",callId);
return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback);
}
}

View File

@ -1,7 +1,8 @@
package com.genersoft.iot.vmp.media.zlm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.common.StreamInfo;
@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@ -79,9 +81,15 @@ public class ZLMHttpHookListener {
@Autowired
private UserSetting userSetting;
@Autowired
private IUserService userService;
@Autowired
private VideoStreamSessionManager sessionManager;
@Autowired
private AssistRESTfulUtils assistRESTfulUtils;
/**
* 服务器定时上报时间上报间隔可配置默认10s上报一次
*
@ -151,12 +159,14 @@ public class ZLMHttpHookListener {
*/
@ResponseBody
@PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> onPlay(@RequestBody JSONObject json){
public ResponseEntity<String> onPlay(@RequestBody OnPlayHookParam param){
JSONObject json = (JSONObject)JSON.toJSON(param);
if (logger.isDebugEnabled()) {
logger.debug("[ ZLM HOOK ]on_play API调用参数" + json.toString());
logger.debug("[ ZLM HOOK ]on_play API调用参数" + JSON.toJSONString(param));
}
String mediaServerId = json.getString("mediaServerId");
String mediaServerId = param.getMediaServerId();
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
if (subscribe != null ) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
@ -165,9 +175,20 @@ public class ZLMHttpHookListener {
}
}
JSONObject ret = new JSONObject();
if (!"rtp".equals(param.getApp())) {
Map<String, String> paramMap = urlParamToMap(param.getParams());
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
if (streamAuthorityInfo == null
|| (streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId")))) {
ret.put("code", 401);
ret.put("msg", "Unauthorized");
return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
}
}
ret.put("code", 0);
ret.put("msg", "success");
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
}
/**
@ -176,23 +197,61 @@ public class ZLMHttpHookListener {
*/
@ResponseBody
@PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> onPublish(@RequestBody JSONObject json) {
public ResponseEntity<String> onPublish(@RequestBody OnPublishHookParam param) {
JSONObject json = (JSONObject) JSON.toJSON(param);
logger.info("[ ZLM HOOK ]on_publish API调用参数" + json.toString());
JSONObject ret = new JSONObject();
String mediaServerId = json.getString("mediaServerId");
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (!"rtp".equals(param.getApp())) {
// 推流鉴权
if (param.getParams() == null) {
logger.info("推流鉴权失败: 缺少不要参数sign=md5(user表的pushKey)");
ret.put("code", 401);
ret.put("msg", "Unauthorized");
return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
}
Map<String, String> paramMap = urlParamToMap(param.getParams());
String sign = paramMap.get("sign");
if (sign == null) {
logger.info("推流鉴权失败: 缺少不要参数sign=md5(user表的pushKey)");
ret.put("code", 401);
ret.put("msg", "Unauthorized");
return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
}
// 推流自定义播放鉴权码
String callId = paramMap.get("callId");
// 鉴权配置
boolean hasAuthority = userService.checkPushAuthority(callId, sign);
if (!hasAuthority) {
logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign);
ret.put("code", 401);
ret.put("msg", "Unauthorized");
return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
}
StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
streamAuthorityInfo.setCallId(callId);
streamAuthorityInfo.setSign(sign);
// 鉴权通过
redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
// 通知assist新的callId
if (mediaInfo != null) {
assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
}
}
ret.put("code", 0);
ret.put("msg", "success");
ret.put("enable_hls", true);
if (json.getInteger("originType") == 1
|| json.getInteger("originType") == 2
|| json.getInteger("originType") == 3) {
if (!"rtp".equals(param.getApp())) {
ret.put("enable_audio", true);
}
String mediaServerId = json.getString("mediaServerId");
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
if (subscribe != null) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo != null) {
subscribe.response(mediaInfo, json);
}else {
@ -200,14 +259,13 @@ public class ZLMHttpHookListener {
ret.put("msg", "zlm not register");
}
}
String app = json.getString("app");
String stream = json.getString("stream");
if ("rtp".equals(app)) {
if ("rtp".equals(param.getApp())) {
ret.put("enable_mp4", userSetting.getRecordSip());
}else {
ret.put("enable_mp4", userSetting.isRecordPushLive());
}
List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, stream);
List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream());
if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) {
String deviceId = ssrcTransactionForAll.get(0).getDeviceId();
String channelId = ssrcTransactionForAll.get(0).getChannelId();
@ -220,14 +278,17 @@ public class ZLMHttpHookListener {
ret.put("mp4_max_second", 10);
ret.put("enable_mp4", true);
ret.put("enable_audio", true);
}
}
}
return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
}
/**
* 录制mp4完成后通知事件此事件对回复不敏感
*
@ -312,9 +373,6 @@ public class ZLMHttpHookListener {
if (logger.isDebugEnabled()) {
logger.debug("[ ZLM HOOK ]on_shell_login API调用参数" + json.toString());
}
// TODO 如果是带有rtpstream则开启按需拉流
// String app = json.getString("app");
// String stream = json.getString("stream");
String mediaServerId = json.getString("mediaServerId");
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
if (subscribe != null ) {
@ -351,12 +409,24 @@ public class ZLMHttpHookListener {
}
// 流消失移除redis play
String app = item.getApp();
String streamId = item.getStream();
String stream = item.getStream();
String schema = item.getSchema();
List<MediaItem.MediaTrack> tracks = item.getTracks();
boolean regist = item.isRegist();
if (regist) {
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
if (streamAuthorityInfo == null) {
streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item);
}else {
streamAuthorityInfo.setOriginType(item.getOriginType());
streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr());
}
redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo);
}else {
redisCatchStorage.removeStreamAuthorityInfo(app, stream);
}
if ("rtmp".equals(schema)){
logger.info("on_stream_changed注册->{}, app->{}, stream->{}", regist, app, streamId);
logger.info("on_stream_changed注册->{}, app->{}, stream->{}", regist, app, stream);
if (regist) {
mediaServerService.addCount(mediaServerId);
}else {
@ -365,15 +435,15 @@ public class ZLMHttpHookListener {
if (item.getOriginType() == OriginType.PULL.ordinal()
|| item.getOriginType() == OriginType.FFMPEG_PULL.ordinal()) {
// 设置拉流代理上线/离线
streamProxyService.updateStatus(regist, app, streamId);
streamProxyService.updateStatus(regist, app, stream);
}
if ("rtp".equals(app) && !regist ) {
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(stream);
if (streamInfo!=null){
redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
}else{
streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null);
if (streamInfo != null) {
redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
streamInfo.getStream(), null);
@ -387,10 +457,12 @@ public class ZLMHttpHookListener {
if (mediaServerItem != null){
if (regist) {
StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
app, stream, tracks, streamAuthorityInfo.getCallId());
item.setStreamInfo(streamInfoByAppAndStream);
redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
item.setSeverId(userSetting.getServerId());
redisCatchStorage.addStream(mediaServerItem, type, app, stream, item);
if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|| item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
@ -413,23 +485,23 @@ public class ZLMHttpHookListener {
}else {
// 兼容流注销时类型从redis记录获取
MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, streamId, mediaServerId);
MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, stream, mediaServerId);
if (mediaItem != null) {
type = OriginType.values()[mediaItem.getOriginType()].getType();
redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId);
redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, stream);
}
GbStream gbStream = storager.getGbStream(app, streamId);
GbStream gbStream = storager.getGbStream(app, stream);
if (gbStream != null) {
// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
}
zlmMediaListManager.removeMedia(app, streamId);
zlmMediaListManager.removeMedia(app, stream);
}
if (type != null) {
// 发送流变化redis消息
JSONObject jsonObject = new JSONObject();
jsonObject.put("serverId", userSetting.getServerId());
jsonObject.put("app", app);
jsonObject.put("stream", streamId);
jsonObject.put("stream", stream);
jsonObject.put("register", regist);
jsonObject.put("mediaServerId", mediaServerId);
redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
@ -565,4 +637,22 @@ public class ZLMHttpHookListener {
ret.put("msg", "success");
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
}
private Map<String, String> urlParamToMap(String params) {
HashMap<String, String> map = new HashMap<>();
if (StringUtils.isEmpty(params)) {
return map;
}
String[] paramsArray = params.split("&");
if (paramsArray.length == 0) {
return map;
}
for (String param : paramsArray) {
String[] paramArray = param.split("=");
if (paramArray.length == 2){
map.put(paramArray[0], paramArray[1]);
}
}
return map;
}
}

View File

@ -115,64 +115,16 @@ public class ZLMMediaListManager {
public StreamPushItem addPush(MediaItem mediaItem) {
// 查找此直播流是否存在redis预设gbId
StreamPushItem transform = streamPushService.transform(mediaItem);
// 从streamId取出查询关键值
Pattern pattern = Pattern.compile(userSetting.getThirdPartyGBIdReg());
Matcher matcher = pattern.matcher(mediaItem.getStream());// 指定要匹配的字符串
String queryKey = null;
if (matcher.find()) { //此处find每次被调用后会偏移到下一个匹配
queryKey = matcher.group();
StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
transform.setPushIng(true);
transform.setUpdateTime(DateUtil.getNow());
transform.setPushTime(DateUtil.getNow());
if (pushInDb == null) {
transform.setCreateTime(DateUtil.getNow());
streamPushMapper.add(transform);
}else {
streamPushMapper.update(transform);
}
if (queryKey != null) {
ThirdPartyGB thirdPartyGB = redisCatchStorage.queryMemberNoGBId(queryKey);
if (thirdPartyGB != null && !StringUtils.isEmpty(thirdPartyGB.getNationalStandardNo())) {
transform.setGbId(thirdPartyGB.getNationalStandardNo());
transform.setName(thirdPartyGB.getName());
}
}
if (!StringUtils.isEmpty(transform.getGbId())) {
// 如果这个国标ID已经给了其他推流且流已离线则移除其他推流
List<GbStream> gbStreams = gbStreamMapper.selectByGBId(transform.getGbId());
if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
// 出现使用相同国标Id的视频流时使用新流替换旧流
if (queryKey != null && gbStream.getApp().equals(mediaItem.getApp())) {
Matcher matcherForStream = pattern.matcher(gbStream.getStream());
String queryKeyForStream = null;
if (matcherForStream.find()) { //此处find每次被调用后会偏移到下一个匹配
queryKeyForStream = matcherForStream.group();
}
if (queryKeyForStream == null || !queryKeyForStream.equals(queryKey)) {
// 此时不是同一个流
gbStreamMapper.del(gbStream.getApp(), gbStream.getStream());
if (!gbStream.isStatus()) {
streamPushMapper.del(gbStream.getApp(), gbStream.getStream());
}
}
}
}
}
List<GbStream> gbStreamList = gbStreamMapper.selectByGBId(transform.getGbId());
if (gbStreamList != null && gbStreamList.size() == 1) {
transform.setGbStreamId(gbStreamList.get(0).getGbStreamId());
transform.setPlatformId(gbStreamList.get(0).getPlatformId());
transform.setCatalogId(gbStreamList.get(0).getCatalogId());
transform.setGbId(gbStreamList.get(0).getGbId());
gbStreamMapper.update(transform);
streamPushMapper.del(gbStreamList.get(0).getApp(), gbStreamList.get(0).getStream());
}else {
transform.setCreateTime(DateUtil.getNow());
transform.setUpdateTime(DateUtil.getNow());
gbStreamMapper.add(transform);
}
if (transform != null) {
if (channelOnlineEvents.get(transform.getGbId()) != null) {
channelOnlineEvents.get(transform.getGbId()).run(transform.getApp(), transform.getStream(), transform.getServerId());
channelOnlineEvents.remove(transform.getGbId());
}
}
}
storager.updateMedia(transform);
return transform;
}
@ -206,13 +158,13 @@ public class ZLMMediaListManager {
public int removeMedia(String app, String streamId) {
// 查找是否关联了国标 关联了不删除 置为离线
StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(app, streamId);
int result = 0;
if (streamProxyItem == null) {
GbStream gbStream = gbStreamMapper.selectOne(app, streamId);
int result;
if (gbStream == null) {
result = storager.removeMedia(app, streamId);
}else {
// TODO 暂不设置为离线
result =storager.mediaOutline(app, streamId);
result =storager.mediaOffline(app, streamId);
}
return result;
}

View File

@ -66,7 +66,7 @@ public class ZLMRTPServerFactory {
String stream = UUID.randomUUID().toString();
param.put("enable_tcp", 1);
param.put("stream_id", stream);
param.put("port", 0);
// param.put("port", 0);
JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
if (openRtpServerResultJson != null) {
@ -101,9 +101,10 @@ public class ZLMRTPServerFactory {
}
Map<String, Object> param = new HashMap<>();
// 推流端口设置0则使用随机端口
param.put("enable_tcp", 1);
param.put("stream_id", streamId);
// 推流端口设置0则使用随机端口
param.put("port", 0);
param.put("ssrc", ssrc);
JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
@ -291,7 +292,7 @@ public class ZLMRTPServerFactory {
logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg"));
return -1;
}
if ( code == 0 && ! mediaInfo.getBoolean("online")) {
if ( code == 0 && mediaInfo.getBoolean("online") != null && !mediaInfo.getBoolean("online")) {
logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg"));
return -1;
}

View File

@ -0,0 +1,17 @@
package com.genersoft.iot.vmp.media.zlm.dto;
/**
* zlm hook事件的参数
* @author lin
*/
public class HookParam {
private String mediaServerId;
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
}

View File

@ -4,6 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
import java.util.List;
/**
* @author lin
*/
public class MediaItem {
/**
@ -21,6 +24,11 @@ public class MediaItem {
*/
private String stream;
/**
* 推流鉴权Id
*/
private String callId;
/**
* 观看总人数包括hls/rtsp/rtmp/http-flv/ws-flv
*/
@ -427,4 +435,12 @@ public class MediaItem {
public void setSeverId(String severId) {
this.severId = severId;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
}

View File

@ -0,0 +1,82 @@
package com.genersoft.iot.vmp.media.zlm.dto;
/**
* zlm hook事件中的on_play事件的参数
* @author lin
*/
public class OnPlayHookParam extends HookParam{
private String id;
private String app;
private String stream;
private String ip;
private String params;
private int port;
private String schema;
private String vhost;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getVhost() {
return vhost;
}
public void setVhost(String vhost) {
this.vhost = vhost;
}
}

View File

@ -0,0 +1,82 @@
package com.genersoft.iot.vmp.media.zlm.dto;
/**
* zlm hook事件中的on_publish事件的参数
* @author lin
*/
public class OnPublishHookParam extends HookParam{
private String id;
private String app;
private String stream;
private String ip;
private String params;
private int port;
private String schema;
private String vhost;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getVhost() {
return vhost;
}
public void setVhost(String vhost) {
this.vhost = vhost;
}
}

View File

@ -0,0 +1,114 @@
package com.genersoft.iot.vmp.media.zlm.dto;
/**
* 流的鉴权信息
* @author lin
*/
public class StreamAuthorityInfo {
private String id;
private String app;
private String stream;
/**
* 产生源类型
* unknown = 0,
* rtmp_push=1,
* rtsp_push=2,
* rtp_push=3,
* pull=4,
* ffmpeg_pull=5,
* mp4_vod=6,
* device_chn=7
*/
private int originType;
/**
* 产生源类型的字符串描述
*/
private String originTypeStr;
/**
* 推流时自定义的播放鉴权ID
*/
private String callId;
/**
* 推流的鉴权签名
*/
private String sign;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public int getOriginType() {
return originType;
}
public void setOriginType(int originType) {
this.originType = originType;
}
public String getOriginTypeStr() {
return originTypeStr;
}
public void setOriginTypeStr(String originTypeStr) {
this.originTypeStr = originTypeStr;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public static StreamAuthorityInfo getInstanceByHook(OnPublishHookParam hookParam) {
StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo();
streamAuthorityInfo.setApp(hookParam.getApp());
streamAuthorityInfo.setStream(hookParam.getStream());
streamAuthorityInfo.setId(hookParam.getId());
return streamAuthorityInfo;
}
public static StreamAuthorityInfo getInstanceByHook(MediaItem mediaItem) {
StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo();
streamAuthorityInfo.setApp(mediaItem.getApp());
streamAuthorityInfo.setStream(mediaItem.getStream());
streamAuthorityInfo.setId(mediaItem.getMediaServerId());
streamAuthorityInfo.setOriginType(mediaItem.getOriginType());
streamAuthorityInfo.setOriginTypeStr(mediaItem.getOriginTypeStr());
return streamAuthorityInfo;
}
}

View File

@ -103,6 +103,11 @@ public class StreamPushItem extends GbStream implements Comparable<StreamPushIte
*/
private String createTime;
/**
* 是否正在推流
*/
private boolean pushIng;
public String getVhost() {
return vhost;
}
@ -277,5 +282,13 @@ public class StreamPushItem extends GbStream implements Comparable<StreamPushIte
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public boolean isPushIng() {
return pushIng;
}
public void setPushIng(boolean pushIng) {
this.pushIng = pushIng;
}
}

View File

@ -0,0 +1,35 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import java.util.List;
/**
* 国标通道业务类
* @author lin
*/
public interface IDeviceChannelService {
/**
* 更新gps信息
*/
DeviceChannel updateGps(DeviceChannel deviceChannel, Device device);
/**
* 添加设备通道
*
* @param deviceId 设备id
* @param channel 通道
*/
void updateChannel(String deviceId, DeviceChannel channel);
/**
* 批量添加设备通道
*
* @param deviceId 设备id
* @param channels 多个通道
*/
int updateChannels(String deviceId, List<DeviceChannel> channels);
}

View File

@ -18,7 +18,7 @@ public interface IGbStreamService {
* @param count
* @return
*/
PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,Boolean pushing,String mediaServerId);
PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,String mediaServerId);
/**

View File

@ -15,7 +15,7 @@ public interface IMediaService {
* @param stream
* @return
*/
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr);
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr, boolean authority);
/**
@ -24,7 +24,7 @@ public interface IMediaService {
* @param stream
* @return
*/
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId);
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority);
/**
* 根据应用名和流ID获取播放地址, 只是地址拼接
@ -32,7 +32,7 @@ public interface IMediaService {
* @param stream
* @return
*/
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks);
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks, String callId);
/**
* 根据应用名和流ID获取播放地址, 只是地址拼接返回的ip使用远程访问ip适用与zlm与wvp在一台主机的情况
@ -40,5 +40,5 @@ public interface IMediaService {
* @param stream
* @return
*/
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr);
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId);
}

View File

@ -0,0 +1,22 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import java.util.List;
/**
* 平台关联通道管理
* @author lin
*/
public interface IPlatformChannelService {
/**
* 更新目录下的通道
* @param platformId 平台编号
* @param channelReduces 通道信息
* @param catalogId 目录编号
* @return
*/
int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
}

View File

@ -101,4 +101,9 @@ public interface IStreamProxyService {
void zlmServerOffline(String mediaServerId);
void clean();
/**
* 更新代理流
*/
boolean updateStreamProxy(StreamProxyItem streamProxyItem);
}

View File

@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
import com.github.pagehelper.PageInfo;
@ -44,31 +45,55 @@ public interface IStreamPushService {
* 停止一路推流
* @param app 应用名
* @param streamId 流ID
* @return
*/
boolean stop(String app, String streamId);
/**
* 新的节点加入
* @param mediaServerId
* @return
*/
void zlmServerOnline(String mediaServerId);
/**
* 节点离线
* @param mediaServerId
* @return
*/
void zlmServerOffline(String mediaServerId);
/**
* 清空
*/
void clean();
boolean saveToRandomGB();
/**
* 批量添加
*/
void batchAdd(List<StreamPushItem> streamPushExcelDtoList);
/**
* 中止多个推流
*/
boolean batchStop(List<GbStream> streamPushItems);
/**
* 导入时批量增加
*/
void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll);
/**
* 全部离线
*/
void allStreamOffline();
/**
* 推流离线
*/
void offline(List<StreamPushItemFromRedis> offlineStreams);
/**
* 推流上线
*/
void online(List<StreamPushItemFromRedis> onlineStreams);
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.storager.dao.dto.User;
import com.github.pagehelper.PageInfo;
import java.util.List;
@ -19,4 +20,10 @@ public interface IUserService {
List<User> getAllUsers();
int updateUsers(User user);
boolean checkPushAuthority(String callId, String sign);
PageInfo<User> getUsers(int page, int count);
int changePushKey(int id, String pushKey);
}

View File

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.service.bean;
import java.util.List;
/**
* 收到redis通知修改推流通道状态
* @author lin
*/
public class PushStreamStatusChangeFromRedisDto {
private boolean setAllOffline;
private List<StreamPushItemFromRedis> onlineStreams;
private List<StreamPushItemFromRedis> offlineStreams;
public boolean isSetAllOffline() {
return setAllOffline;
}
public void setSetAllOffline(boolean setAllOffline) {
this.setAllOffline = setAllOffline;
}
public List<StreamPushItemFromRedis> getOnlineStreams() {
return onlineStreams;
}
public void setOnlineStreams(List<StreamPushItemFromRedis> onlineStreams) {
this.onlineStreams = onlineStreams;
}
public List<StreamPushItemFromRedis> getOfflineStreams() {
return offlineStreams;
}
public void setOfflineStreams(List<StreamPushItemFromRedis> offlineStreams) {
this.offlineStreams = offlineStreams;
}
}

View File

@ -0,0 +1,34 @@
package com.genersoft.iot.vmp.service.bean;
public class StreamPushItemFromRedis {
private String app;
private String stream;
private long timeStamp;
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public long getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
}

View File

@ -17,7 +17,6 @@ public class DeviceAlarmServiceImpl implements IDeviceAlarmService {
@Autowired
private DeviceAlarmMapper deviceAlarmMapper;
@Override
public PageInfo<DeviceAlarm> getAllAlarm(int page, int count, String deviceId, String alarmPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
PageHelper.startPage(page, count);

View File

@ -0,0 +1,165 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author lin
*/
@Service
public class DeviceChannelServiceImpl implements IDeviceChannelService {
private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class);
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private DeviceChannelMapper channelMapper;
@Autowired
private DeviceMapper deviceMapper;
@Override
public DeviceChannel updateGps(DeviceChannel deviceChannel, Device device) {
if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
if (device == null) {
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
}
if ("WGS84".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeGcj02(position[0]);
deviceChannel.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeWgs84(position[0]);
deviceChannel.setLatitudeWgs84(position[1]);
}else {
deviceChannel.setLongitudeGcj02(0.00);
deviceChannel.setLatitudeGcj02(0.00);
deviceChannel.setLongitudeWgs84(0.00);
deviceChannel.setLatitudeWgs84(0.00);
}
}else {
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
}
return deviceChannel;
}
@Override
public void updateChannel(String deviceId, DeviceChannel channel) {
String channelId = channel.getChannelId();
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
DeviceChannel deviceChannel = channelMapper.queryChannel(deviceId, channelId);
channel = updateGps(channel, null);
if (deviceChannel == null) {
channel.setCreateTime(now);
channelMapper.add(channel);
}else {
channelMapper.update(channel);
}
channelMapper.updateChannelSubCount(deviceId,channel.getParentId());
}
@Override
public int updateChannels(String deviceId, List<DeviceChannel> channels) {
List<DeviceChannel> addChannels = new ArrayList<>();
List<DeviceChannel> updateChannels = new ArrayList<>();
HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (channels != null && channels.size() > 0) {
List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null);
if (channelList.size() == 0) {
for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
channel.setCreateTime(now);
channel = updateGps(channel, device);
addChannels.add(channel);
}
}else {
for (DeviceChannel deviceChannel : channelList) {
channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
}
for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
channel = updateGps(channel, device);
if (channelsInStore.get(channel.getChannelId()) != null) {
updateChannels.add(channel);
}else {
addChannels.add(channel);
channel.setCreateTime(now);
}
}
}
int limitCount = 300;
if (addChannels.size() > 0) {
if (addChannels.size() > limitCount) {
for (int i = 0; i < addChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > addChannels.size()) {
toIndex = addChannels.size();
}
channelMapper.batchAdd(addChannels.subList(i, toIndex));
}
}else {
channelMapper.batchAdd(addChannels);
}
}
if (updateChannels.size() > 0) {
if (updateChannels.size() > limitCount) {
for (int i = 0; i < updateChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > updateChannels.size()) {
toIndex = updateChannels.size();
}
channelMapper.batchUpdate(updateChannels.subList(i, toIndex));
}
}else {
channelMapper.batchUpdate(updateChannels);
}
}
}
return addChannels.size() + updateChannels.size();
}
}

View File

@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
@ -55,6 +56,9 @@ public class DeviceServiceImpl implements IDeviceService {
@Autowired
private DeviceMapper deviceMapper;
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private DeviceChannelMapper deviceChannelMapper;
@ -324,23 +328,12 @@ public class DeviceServiceImpl implements IDeviceService {
private void updateDeviceChannelGeoCoordSys(Device device) {
List<DeviceChannel> deviceChannels = deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId());
if (deviceChannels.size() > 0) {
List<DeviceChannel> deviceChannelsForStore = new ArrayList<>();
for (DeviceChannel deviceChannel : deviceChannels) {
if ("WGS84".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeGcj02(position[0]);
deviceChannel.setLatitudeGcj02(position[1]);
}else if ("GCJ02".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
deviceChannel.setLongitudeWgs84(position[0]);
deviceChannel.setLatitudeWgs84(position[1]);
}
deviceChannelsForStore.add(deviceChannelService.updateGps(deviceChannel, device));
}
deviceChannelService.updateChannels(device.getDeviceId(), deviceChannelsForStore);
}
storage.updateChannels(device.getDeviceId(), deviceChannels);
}
@ -352,11 +345,11 @@ public class DeviceServiceImpl implements IDeviceService {
}
if (parentId == null || parentId.equals(deviceId)) {
// 字根节点开始查询
List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), true, !onlyCatalog);
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
return transportChannelsToTree(rootNodes, "");
}
if ("CivilCode".equals(device.getTreeType())) {
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
if (parentId.length()%2 != 0) {
return null;
}
@ -386,7 +379,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
// 使用业务分组展示树
if ("BusinessGroup".equals(device.getTreeType())) {
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
if (parentId.length() < 14 ) {
return null;
}
@ -406,11 +399,11 @@ public class DeviceServiceImpl implements IDeviceService {
}
if (parentId == null || parentId.equals(deviceId)) {
// 字根节点开始查询
List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), false, true);
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
return rootNodes;
}
if ("CivilCode".equals(device.getTreeType())) {
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
if (parentId.length()%2 != 0) {
return null;
}
@ -431,7 +424,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
// 使用业务分组展示树
if ("BusinessGroup".equals(device.getTreeType())) {
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
if (parentId.length() < 14 ) {
return null;
}

View File

@ -1,14 +1,13 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
import com.genersoft.iot.vmp.service.IGbStreamService;
import com.github.pagehelper.PageHelper;
@ -46,15 +45,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
private ParentPlatformMapper platformMapper;
@Autowired
private SipConfig sipConfig;
private PlatformCatalogMapper catalogMapper;
@Autowired
private EventPublisher eventPublisher;
@Override
public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, Boolean pushing, String mediaServerId) {
public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, String mediaServerId) {
PageHelper.startPage(page, count);
List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, pushing, mediaServerId);
List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, mediaServerId);
return new PageInfo<>(all);
}
@ -102,16 +101,25 @@ public class GbStreamServiceImpl implements IGbStreamService {
deviceChannel.setLatitude(gbStream.getLatitude());
deviceChannel.setDeviceId(platform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
// deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setStatus(1);
deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setRegisterWay(1);
if (catalogId.length() > 0 && catalogId.length() <= 10) {
// 父节点是行政区划,则设置CivilCode使用此行政区划
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
deviceChannel.setCivilCode(catalogId);
}else {
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
PlatformCatalog catalog = catalogMapper.select(catalogId);
if (catalog == null) {
deviceChannel.setParentId(platform.getDeviceGBId());
deviceChannel.setBusinessGroupId(null);
}else {
deviceChannel.setParentId(catalog.getId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}
}
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0);
@ -149,9 +157,9 @@ public class GbStreamServiceImpl implements IGbStreamService {
if (gbStream.getGbId() != null) {
gbStreams.add(gbStream);
}else {
StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(gbStream.getApp(), gbStream.getStream());
if (streamProxyItem != null && streamProxyItem.getGbId() != null){
gbStreams.add(streamProxyItem);
GbStream gbStreamIndb = gbStreamMapper.selectOne(gbStream.getApp(), gbStream.getStream());
if (gbStreamIndb != null && gbStreamIndb.getGbId() != null){
gbStreams.add(gbStreamIndb);
}
}
sendCatalogMsgs(gbStreams, type);

View File

@ -7,12 +7,15 @@ import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.service.IMediaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class MediaServiceImpl implements IMediaService {
@ -36,20 +39,24 @@ public class MediaServiceImpl implements IMediaService {
@Override
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks) {
return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String callId) {
return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId);
}
@Override
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr, boolean authority) {
StreamInfo streamInfo = null;
if (mediaServerId == null) {
mediaServerId = mediaConfig.getId();
}
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);;
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo == null) {
return null;
}
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
if (streamAuthorityInfo == null) {
return null;
}
JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
if (mediaList != null) {
if (mediaList.getInteger("code") == 0) {
@ -59,7 +66,12 @@ public class MediaServiceImpl implements IMediaService {
}
JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
JSONArray tracks = mediaJSON.getJSONArray("tracks");
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks);
if (authority) {
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, streamAuthorityInfo.getCallId());
}else {
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
}
}
}
return streamInfo;
@ -68,46 +80,48 @@ public class MediaServiceImpl implements IMediaService {
@Override
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId) {
return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null);
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority) {
return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null, authority);
}
@Override
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) {
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId) {
StreamInfo streamInfoResult = new StreamInfo();
streamInfoResult.setStream(stream);
streamInfoResult.setApp(app);
if (addr == null) {
addr = mediaInfo.getStreamIp();
}
streamInfoResult.setIp(addr);
streamInfoResult.setMediaServerId(mediaInfo.getId());
streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", addr, mediaInfo.getRtmpPort(), app, stream));
String callIdParam = StringUtils.isEmpty(callId)?"":"?callId=" + callId;
streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpPort(), app, stream, callIdParam));
if (mediaInfo.getRtmpSSlPort() != 0) {
streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s", addr, mediaInfo.getRtmpSSlPort(), app, stream));
streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpSSlPort(), app, stream, callIdParam));
}
streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", addr, mediaInfo.getRtspPort(), app, stream));
streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s%s", addr, mediaInfo.getRtspPort(), app, stream, callIdParam));
if (mediaInfo.getRtspSSLPort() != 0) {
streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s", addr, mediaInfo.getRtspSSLPort(), app, stream));
streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s%s", addr, mediaInfo.getRtspSSLPort(), app, stream, callIdParam));
}
streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpPort(), app, stream));
streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
if (mediaInfo.getHttpSSlPort() != 0) {
streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setHttps_hls(String.format("https://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setWss_hls(String.format("wss://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setHttps_fmp4(String.format("https://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setWss_fmp4(String.format("wss://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app, stream));
streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setHttps_hls(String.format("https://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_hls(String.format("wss://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setHttps_fmp4(String.format("https://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_fmp4(String.format("wss://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app, stream, StringUtils.isEmpty(callId)?"":"&callId=" + callId));
}
streamInfoResult.setTracks(tracks);

View File

@ -0,0 +1,106 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.service.IPlatformChannelService;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author lin
*/
@Service
public class PlatformChannelServiceImpl implements IPlatformChannelService {
private final static Logger logger = LoggerFactory.getLogger(PlatformChannelServiceImpl.class);
@Autowired
private PlatformChannelMapper platformChannelMapper;
@Autowired
private DeviceChannelMapper deviceChannelMapper;
@Autowired
private PlatformCatalogMapper catalogManager;
@Autowired
private ParentPlatformMapper platformMapper;
@Autowired
EventPublisher eventPublisher;
@Override
public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
if (platform == null) {
logger.warn("更新级联通道信息时未找到平台{}的信息", platformId);
return 0;
}
Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
for (ChannelReduce channelReduce : channelReduces) {
channelReduce.setCatalogId(catalogId);
deviceAndChannels.put(channelReduce.getId(), channelReduce);
}
List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
// 查询当前已经存在的
List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
if (deviceAndChannelList != null) {
deviceAndChannelList.removeAll(channelIds);
}
for (Integer channelId : channelIds) {
deviceAndChannels.remove(channelId);
}
List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
// 对剩下的数据进行存储
int result = 0;
if (channelReducesToAdd.size() > 0) {
result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
// TODO 后续给平台增加控制开关以控制是否响应目录订阅
List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
}
return result;
}
private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) {
List<DeviceChannel> deviceChannelList = new ArrayList<>();
if (channelReduces.size() > 0){
PlatformCatalog catalog = catalogManager.select(catalogId);
if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
logger.warn("未查询到目录{}的信息", catalogId);
return null;
}
for (ChannelReduce channelReduce : channelReduces) {
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
deviceChannel.setParental(0);
deviceChannelList.add(deviceChannel);
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
deviceChannel.setCivilCode(catalogId);
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
deviceChannel.setParentId(catalogId);
if (catalog != null) {
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}
}
}
}
return deviceChannelList;
}
}

View File

@ -620,7 +620,7 @@ public class PlayServiceImpl implements IPlayService {
public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) {
String streamId = resonse.getString("stream");
JSONArray tracks = resonse.getJSONArray("tracks");
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks, null);
streamInfo.setDeviceID(deviceId);
streamInfo.setChannelId(channelId);
return streamInfo;

View File

@ -25,9 +25,7 @@ public class RedisGpsMsgListener implements MessageListener {
@Override
public void onMessage(@NotNull Message message, byte[] bytes) {
if (logger.isDebugEnabled()) {
logger.debug("收到来自REDIS的GPS通知 {}", new String(message.getBody()));
}
// TODO 加消息队列
GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
}

View File

@ -0,0 +1,92 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 接收redis发送的推流设备上线下线通知
* @author lin
*/
@Component
public class RedisPushStreamStatusMsgListener implements MessageListener, ApplicationRunner {
private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusMsgListener.class);
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IStreamPushService streamPushService;
@Autowired
private EventPublisher eventPublisher;
@Autowired
private UserSetting userSetting;
@Autowired
private DynamicTask dynamicTask;
@Override
public void onMessage(Message message, byte[] bytes) {
PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(message.getBody(), PushStreamStatusChangeFromRedisDto.class);
if (statusChangeFromPushStream == null) {
logger.warn("[REDIS 消息]推流设备状态变化消息解析失败");
return;
}
if (statusChangeFromPushStream.isSetAllOffline()) {
// 所有设备离线
streamPushService.allStreamOffline();
}
if (statusChangeFromPushStream.getOfflineStreams() != null
&& statusChangeFromPushStream.getOfflineStreams().size() > 0) {
// 更新部分设备离线
streamPushService.offline(statusChangeFromPushStream.getOfflineStreams());
}
if (statusChangeFromPushStream.getOnlineStreams() != null &&
statusChangeFromPushStream.getOnlineStreams().size() > 0) {
// 更新部分设备上线
streamPushService.online(statusChangeFromPushStream.getOnlineStreams());
}
}
@Override
public void run(ApplicationArguments args) throws Exception {
// 启动时设置所有推流通道离线发起查询请求
redisCatchStorage.sendStreamPushRequestedMsgForStatus();
dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
logger.info("[REDIS 消息]未收到redis回复推流设备状态执行推流设备离线");
// 五秒收不到请求就设置通道离线然后通知上级离线
streamPushService.allStreamOffline();
}, 5000);
}
}

View File

@ -3,16 +3,12 @@ package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -22,6 +18,7 @@ import org.springframework.stereotype.Component;
/**
* 接收其他wvp发送流变化通知
* @author lin
*/
@Component

View File

@ -3,10 +3,10 @@ package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@ -23,14 +23,19 @@ import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.StringUtils;
import java.net.InetAddress;
import java.util.*;
/**
@ -48,7 +53,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
private IMediaService mediaService;
@Autowired
private ZLMRESTfulUtils zlmresTfulUtils;;
private ZLMRESTfulUtils zlmresTfulUtils;
@Autowired
private StreamProxyMapper streamProxyMapper;
@ -62,9 +67,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
@Autowired
private UserSetting userSetting;
@Autowired
private SipConfig sipConfig;
@Autowired
private GbStreamMapper gbStreamMapper;
@ -83,6 +85,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
@Autowired
private IMediaServerService mediaServerService;
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;
@Override
public WVPResult<StreamInfo> save(StreamProxyItem param) {
@ -99,6 +107,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
wvpResult.setMsg("保存失败");
return wvpResult;
}
String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
param.getStream() );
param.setDst_url(dstUrl);
@ -108,9 +117,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
boolean saveResult;
// 更新
if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
saveResult = videoManagerStorager.updateStreamProxy(param);
saveResult = updateStreamProxy(param);
}else { // 新增
saveResult = videoManagerStorager.addStreamProxy(param);
saveResult = addStreamProxy(param);
}
if (saveResult) {
result.append("保存成功");
@ -124,7 +133,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if (param.isEnable_remove_none_reader()) {
del(param.getApp(), param.getStream());
}else {
videoManagerStorager.updateStreamProxy(param);
updateStreamProxy(param);
}
}else {
@ -147,27 +156,81 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败");
}
}
if (!StringUtils.isEmpty(param.getGbId())) {
// 查找开启了全部直播流共享的上级平台
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) {
param.setPlatformId(parentPlatform.getServerGBId());
param.setCatalogId(parentPlatform.getCatalogId());
String stream = param.getStream();
StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId());
if (streamProxyItems == null) {
platformGbStreamMapper.add(param);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), param, CatalogEvent.ADD);
}
}
}
}
wvpResult.setMsg(result.toString());
return wvpResult;
}
/**
* 新增代理流
* @param streamProxyItem
* @return
*/
private boolean addStreamProxy(StreamProxyItem streamProxyItem) {
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
boolean result = false;
streamProxyItem.setStreamType("proxy");
streamProxyItem.setStatus(true);
String now = DateUtil.getNow();
streamProxyItem.setCreateTime(now);
try {
if (streamProxyMapper.add(streamProxyItem) > 0) {
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
if (gbStreamMapper.add(streamProxyItem) < 0) {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
}
}else {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
result = true;
dataSourceTransactionManager.commit(transactionStatus); //手动提交
}catch (Exception e) {
logger.error("向数据库添加流代理失败:", e);
dataSourceTransactionManager.rollback(transactionStatus);
}
return result;
}
/**
* 更新代理流
* @param streamProxyItem
* @return
*/
@Override
public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
boolean result = false;
streamProxyItem.setStreamType("proxy");
try {
if (streamProxyMapper.update(streamProxyItem) > 0) {
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
}
} else {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
dataSourceTransactionManager.commit(transactionStatus); //手动提交
result = true;
}catch (Exception e) {
e.printStackTrace();
dataSourceTransactionManager.rollback(transactionStatus);
}
return result;
}
@Override
public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
JSONObject result = null;
@ -239,7 +302,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if (jsonObject.getInteger("code") == 0) {
result = true;
streamProxy.setEnable(true);
videoManagerStorager.updateStreamProxy(streamProxy);
updateStreamProxy(streamProxy);
}
}
return result;
@ -253,7 +316,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
streamProxyDto.setEnable(false);
result = videoManagerStorager.updateStreamProxy(streamProxyDto);
result = updateStreamProxy(streamProxyDto);
}
}
return result;
@ -319,7 +382,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
}
streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId);
// 其他的流设置离线
streamProxyMapper.updateStatusByMediaServerId(false, mediaServerId);
streamProxyMapper.updateStatusByMediaServerId(mediaServerId, false);
String type = "PULL";
// 发送redis消息
@ -346,7 +409,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
@Override
public int updateStatus(boolean status, String app, String stream) {
return streamProxyMapper.updateStatus(status, app, stream);
return streamProxyMapper.updateStatus(app, stream, status);
}
private void syncPullStream(String mediaServerId){

View File

@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.service.IGbStreamService;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.*;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -38,6 +39,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
@Autowired
private StreamPushMapper streamPushMapper;
@Autowired
private StreamProxyMapper streamProxyMapper;
@Autowired
private ParentPlatformMapper parentPlatformMapper;
@ -130,29 +134,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
stream.setStatus(true);
stream.setCreateTime(DateUtil.getNow());
int add = gbStreamMapper.add(stream);
// 查找开启了全部直播流共享的上级平台
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) {
stream.setCatalogId(parentPlatform.getCatalogId());
stream.setPlatformId(parentPlatform.getServerGBId());
String streamId = stream.getStream();
StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
if (streamProxyItem == null) {
platformGbStreamMapper.add(stream);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
}else {
if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
// 此流使用另一个国标Id已经与该平台关联移除此记录
platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
platformGbStreamMapper.add(stream);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
}
}
}
}
return add > 0;
}
@ -178,7 +159,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
@Override
public StreamPushItem getPush(String app, String streamId) {
return streamPushMapper.selectOne(app, streamId);
}
@ -285,7 +265,8 @@ public class StreamPushServiceImpl implements IStreamPushService {
streamPushMapper.deleteWithoutGBId(mediaServerId);
gbStreamMapper.deleteWithoutGBId("push", mediaServerId);
// 其他的流设置未启用
gbStreamMapper.updateStatusByMediaServerId(mediaServerId, false);
streamPushMapper.updateStatusByMediaServerId(mediaServerId, false);
streamProxyMapper.updateStatusByMediaServerId(mediaServerId, false);
// 发送流停止消息
String type = "PUSH";
// 发送redis消息
@ -341,31 +322,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
public void batchAdd(List<StreamPushItem> streamPushItems) {
streamPushMapper.addAll(streamPushItems);
gbStreamMapper.batchAdd(streamPushItems);
// 查找开启了全部直播流共享的上级平台
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) {
for (StreamPushItem stream : streamPushItems) {
for (ParentPlatform parentPlatform : parentPlatforms) {
stream.setCatalogId(parentPlatform.getCatalogId());
stream.setPlatformId(parentPlatform.getServerGBId());
String streamId = stream.getStream();
StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
if (streamProxyItem == null) {
platformGbStreamMapper.add(stream);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
}else {
if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
// 此流使用另一个国标Id已经与该平台关联移除此记录
platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
platformGbStreamMapper.add(stream);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
stream.setGbId(streamProxyItem.getGbId());
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.DEL);
}
}
}
}
}
}
@Override
@ -477,4 +433,34 @@ public class StreamPushServiceImpl implements IStreamPushService {
}
return true;
}
@Override
public void allStreamOffline() {
List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGb();
if (onlinePushers.size() == 0) {
return;
}
streamPushMapper.setAllStreamOffline();
// 发送通知
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
}
@Override
public void offline(List<StreamPushItemFromRedis> offlineStreams) {
// 更新部分设备离线
List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGbInList(offlineStreams);
streamPushMapper.offline(offlineStreams);
// 发送通知
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
}
@Override
public void online(List<StreamPushItemFromRedis> onlineStreams) {
// 更新部分设备上线streamPushService
List<GbStream> onlinePushers = streamPushMapper.getOfflinePusherForGbInList(onlineStreams);
streamPushMapper.online(onlineStreams);
// 发送通知
eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.ON);
}
}

View File

@ -14,38 +14,60 @@ import java.util.*;
public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> {
// 错误数据的回调用于将错误数据发送给页面
/**
* 错误数据的回调用于将错误数据发送给页面
*/
private ErrorDataHandler errorDataHandler;
// 推流的业务类用于存储数据
/**
* 推流的业务类用于存储数据
*/
private IStreamPushService pushService;
// 默认流媒体节点ID
/**
* 默认流媒体节点ID
*/
private String defaultMediaServerId;
// 用于存储不加过滤的所有数据
/**
* 用于存储不加过滤的所有数据
*/
private List<StreamPushItem> streamPushItems = new ArrayList<>();
// 用于存储更具APP+Stream过滤后的数据可以直接存入stream_push表与gb_stream表
/**
* 用于存储更具APP+Stream过滤后的数据可以直接存入stream_push表与gb_stream表
*/
private Map<String,StreamPushItem> streamPushItemForSave = new HashMap<>();
// 用于存储按照APP+Stream为KEY 平台ID+目录Id 为value的数据用于存储到gb_stream表后获取app+Stream对应的平台与目录信息然后存入关联表
/**
* 用于存储按照APP+Stream为KEY 平台ID+目录Id 为value的数据用于存储到gb_stream表后获取app+Stream对应的平台与目录信息然后存入关联表
*/
private Map<String, List<String[]>> streamPushItemsForPlatform = new HashMap<>();
// 用于判断文件是否存在重复的app+Stream+平台ID
/**
* 用于判断文件是否存在重复的app+Stream+平台ID
*/
private Set<String> streamPushStreamSet = new HashSet<>();
// 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应全局判断APP+Stream->国标ID是否存在不对应
/**
* 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应全局判断APP+Stream->国标ID是否存在不对应
*/
private BiMap<String,String> gBMap = HashBiMap.create();
// 记录错误的APP+Stream
/**
* 记录错误的APP+Stream
*/
private List<String> errorStreamList = new ArrayList<>();
// 记录错误的国标ID
/**
* 记录错误的国标ID
*/
private List<String> errorGBList = new ArrayList<>();
// 读取数量计数器
/**
* 读取数量计数器
*/
private int loadedSize = 0;
public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) {

View File

@ -3,14 +3,17 @@ package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.service.IUserService;
import com.genersoft.iot.vmp.storager.dao.UserMapper;
import com.genersoft.iot.vmp.storager.dao.dto.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
@ -55,4 +58,24 @@ public class UserServiceImpl implements IUserService {
}
@Override
public boolean checkPushAuthority(String callId, String sign) {
if (StringUtils.isEmpty(callId)) {
return userMapper.checkPushAuthorityByCallId(sign).size() > 0;
}else {
return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0;
}
}
@Override
public PageInfo<User> getUsers(int page, int count) {
PageHelper.startPage(page, count);
List<User> users = userMapper.getUsers();
return new PageInfo<>(users);
}
@Override
public int changePushKey(int id, String pushKey) {
return userMapper.changePushKey(id,pushKey);
}
}

View File

@ -3,9 +3,7 @@ package com.genersoft.iot.vmp.storager;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@ -213,4 +211,31 @@ public interface IRedisCatchStorage {
*/
public boolean deviceIsOnline(String deviceId);
/**
* 存储推流的鉴权信息
* @param app 应用名
* @param stream
* @param streamAuthorityInfo 鉴权信息
*/
void updateStreamAuthorityInfo(String app, String stream, StreamAuthorityInfo streamAuthorityInfo);
/**
* 移除推流的鉴权信息
* @param app 应用名
* @param streamId
*/
void removeStreamAuthorityInfo(String app, String streamId);
/**
* 获取推流的鉴权信息
* @param app 应用名
* @param stream
* @return
*/
StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream);
/**
* 发送redis消息 查询所有推流设备的状态
*/
void sendStreamPushRequestedMsgForStatus();
}

View File

@ -26,22 +26,6 @@ public interface IVideoManagerStorage {
*/
public boolean exists(String deviceId);
/**
* 添加设备通道
*
* @param deviceId 设备id
* @param channel 通道
*/
public void updateChannel(String deviceId, DeviceChannel channel);
/**
* 批量添加设备通道
*
* @param deviceId 设备id
* @param channels 多个通道
*/
public int updateChannels(String deviceId, List<DeviceChannel> channels);
/**
* 开始播放
* @param deviceId 设备id
@ -224,13 +208,6 @@ public interface IVideoManagerStorage {
List<DeviceChannelInPlatform> queryChannelListInParentPlatform(String platformId);
/**
* 更新上级平台的通道信息
* @param platformId
* @param channelReduces
* @return
*/
int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
/**
* 移除上级平台的通道信息
@ -276,20 +253,6 @@ public interface IVideoManagerStorage {
*/
public int clearMobilePositionsByDeviceId(String deviceId);
/**
* 新增代理流
* @param streamProxyDto
* @return
*/
public boolean addStreamProxy(StreamProxyItem streamProxyDto);
/**
* 更新代理流
* @param streamProxyDto
* @return
*/
public boolean updateStreamProxy(StreamProxyItem streamProxyDto);
/**
* 移除代理流
* @param app
@ -334,7 +297,7 @@ public interface IVideoManagerStorage {
* @param platformId
* @return
*/
List<GbStream> queryGbStreamListInPlatform(String platformId);
List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
/**
* 批量更新推流列表
@ -372,14 +335,16 @@ public interface IVideoManagerStorage {
/**
* 设置流离线
* @param app
* @param streamId
*/
int mediaOutline(String app, String streamId);
int mediaOffline(String app, String streamId);
/**
* 设置流上线
*/
int mediaOnline(String app, String streamId);
/**
* 设置平台在线/离线
* @param online
*/
void updateParentPlatformStatus(String platformGbID, boolean online);
@ -443,7 +408,7 @@ public interface IVideoManagerStorage {
int setDefaultCatalog(String platformId, String catalogId);
List<PlatformCatalog> queryCatalogInPlatform(String serverGBId);
List<DeviceChannel> queryCatalogInPlatform(String serverGBId);
int delRelation(PlatformCatalog platformCatalog);
@ -464,4 +429,8 @@ public interface IVideoManagerStorage {
List<ChannelSourceInfo> getChannelSource(String platformId, String gbId);
void updateChannelPosition(DeviceChannel deviceChannel);
void cleanContentForPlatform(String serverGBId);
List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
}

View File

@ -329,5 +329,13 @@ public interface DeviceChannelMapper {
@Select("select * from device_channel where deviceId=#{deviceId} and SUBSTRING(channelId, 11, 3)=#{typeCode}")
List<DeviceChannel> getBusinessGroups(String deviceId, String typeCode);
@Select("select dc.id, dc.channelId, dc.deviceId, dc.name, dc.manufacture,dc.model,dc.owner, pc.civilCode,dc.block, " +
" dc.address, '0' as parental,'0' as channelType, pc.id as parentId, dc.safetyWay, dc.registerWay,dc.certNum, dc.certifiable, " +
" dc.errCode,dc.endTime, dc.secrecy, dc.ipAddress, dc.port, dc.PTZType, dc.password, dc.status, " +
" dc.longitudeWgs84 as longitude, dc.latitudeWgs84 as latitude, pc.businessGroupId " +
" from device_channel dc" +
" left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId" +
" left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" +
" where pgc.platformId=#{serverGBId}")
List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
@ -15,10 +16,10 @@ import java.util.List;
public interface GbStreamMapper {
@Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " +
"longitude, latitude, streamType, mediaServerId, status, createTime) VALUES" +
"longitude, latitude, streamType, mediaServerId, createTime) VALUES" +
"('${app}', '${stream}', '${gbId}', '${name}', " +
"'${longitude}', '${latitude}', '${streamType}', " +
"'${mediaServerId}', ${status}, '${createTime}')")
"'${mediaServerId}', '${createTime}')")
@Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
int add(GbStream gbStream);
@ -30,8 +31,7 @@ public interface GbStreamMapper {
"streamType=#{streamType}," +
"longitude=#{longitude}, " +
"latitude=#{latitude}," +
"mediaServerId=#{mediaServerId}," +
"status=${status} " +
"mediaServerId=#{mediaServerId}" +
"WHERE app=#{app} AND stream=#{stream}")
int updateByAppAndStream(GbStream gbStream);
@ -43,8 +43,7 @@ public interface GbStreamMapper {
"streamType=#{streamType}," +
"longitude=#{longitude}, " +
"latitude=#{latitude}," +
"mediaServerId=#{mediaServerId}," +
"status=${status} " +
"mediaServerId=#{mediaServerId}" +
"WHERE gbStreamId=#{gbStreamId}")
int update(GbStream gbStream);
@ -60,15 +59,13 @@ public interface GbStreamMapper {
" <if test='catalogId == null'> AND gs.gbStreamId not in" +
"(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " +
" <if test='query != null'> AND (gs.app LIKE '%${query}%' OR gs.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
" <if test='pushing == true' > AND gs.status=1</if>" +
" <if test='pushing == false' > AND gs.status=0</if>" +
" <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" +
" order by gs.gbStreamId asc " +
"</script>")
List<GbStream> selectAll(String platformId, String catalogId, String query, Boolean pushing, String mediaServerId);
List<GbStream> selectAll(String platformId, String catalogId, String query, String mediaServerId);
@Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
StreamProxyItem selectOne(String app, String stream);
GbStream selectOne(String app, String stream);
@Select("SELECT * FROM gb_stream WHERE gbId=#{gbId}")
List<GbStream> selectByGBId(String gbId);
@ -78,26 +75,24 @@ public interface GbStreamMapper {
"WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
GbStream queryStreamInPlatform(String platformId, String gbId);
@Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +
"LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " +
"WHERE pgs.platformId = #{platformId}")
List<GbStream> queryGbStreamListInPlatform(String platformId);
@Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," +
" '1' as registerWay, pc.civilCode, 'live' as model, 'wvp-pro' as owner, '0' as parental,'0' as secrecy" +
" from gb_stream gt " +
" left join (" +
" select sp.status, sp.app, sp.stream from stream_push sp" +
" union all" +
" select spxy.status, spxy.app, spxy.stream from stream_proxy spxy" +
" ) st on st.app = gt.app and st.stream = gt.stream" +
" left join platform_gb_stream pgs on gt.gbStreamId = pgs.gbStreamId" +
" left join platform_catalog pc on pgs.catalogId = pc.id and pgs.platformId = pc.platformId" +
" where pgs.platformId=#{platformId}")
List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
@Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " +
"ON gs.gbStreamId = pgs.gbStreamId WHERE pgs.gbStreamId is NULL")
List<GbStream> queryStreamNotInPlatform();
@Update("UPDATE gb_stream " +
"SET status=${status} " +
"WHERE app=#{app} AND stream=#{stream}")
int setStatus(String app, String stream, boolean status);
@Update("UPDATE gb_stream " +
"SET status=${status} " +
"WHERE mediaServerId=#{mediaServerId} ")
void updateStatusByMediaServerId(String mediaServerId, boolean status);
@Delete("DELETE FROM gb_stream WHERE streamType=#{type} AND gbId=NULL AND mediaServerId=#{mediaServerId}")
void deleteWithoutGBId(String type, String mediaServerId);
@ -120,12 +115,12 @@ public interface GbStreamMapper {
@Insert("<script> " +
"INSERT IGNORE into gb_stream " +
"(app, stream, gbId, name, " +
"longitude, latitude, streamType, mediaServerId, status, createTime)" +
"longitude, latitude, streamType, mediaServerId, createTime)" +
"values " +
"<foreach collection='subList' index='index' item='item' separator=','> " +
"('${item.app}', '${item.stream}', '${item.gbId}', '${item.name}', " +
"'${item.longitude}', '${item.latitude}', '${item.streamType}', " +
"'${item.mediaServerId}', ${item.status}, '${item.createTime}') "+
"'${item.mediaServerId}', '${item.createTime}') "+
"</foreach> " +
"</script>")
@Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")

View File

@ -16,10 +16,10 @@ public interface ParentPlatformMapper {
@Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
" devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
" status, shareAllLiveStream, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime) " +
" status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
" VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
" '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " +
" ${status}, ${shareAllLiveStream}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})")
" ${status}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
int addParentPlatform(ParentPlatform parentPlatform);
@Update("UPDATE parent_platform " +
@ -41,12 +41,12 @@ public interface ParentPlatformMapper {
"ptz=#{ptz}, " +
"rtcp=#{rtcp}, " +
"status=#{status}, " +
"shareAllLiveStream=#{shareAllLiveStream}, " +
"startOfflinePush=${startOfflinePush}, " +
"catalogGroup=#{catalogGroup}, " +
"administrativeDivision=#{administrativeDivision}, " +
"createTime=#{createTime}, " +
"updateTime=#{updateTime}, " +
"treeType=#{treeType}, " +
"catalogId=#{catalogId} " +
"WHERE id=#{id}")
int updateParentPlatform(ParentPlatform parentPlatform);
@ -83,9 +83,6 @@ public interface ParentPlatformMapper {
@Update("UPDATE parent_platform SET status=#{online} WHERE serverGBId=#{platformGbID}" )
int updateParentPlatformStatus(String platformGbID, boolean online);
@Select("SELECT * FROM parent_platform WHERE shareAllLiveStream=true")
List<ParentPlatform> selectAllAhareAllLiveStream();
@Update(value = {" <script>" +
"UPDATE parent_platform " +
"SET catalogId=#{catalogId}, updateTime=#{updateTime}" +

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
@ -14,8 +15,8 @@ import java.util.List;
@Repository
public interface PlatformCatalogMapper {
@Insert("INSERT INTO platform_catalog (id, name, platformId, parentId) VALUES" +
"(#{id}, #{name}, #{platformId}, #{parentId})")
@Insert("INSERT INTO platform_catalog (id, name, platformId, parentId, civilCode, businessGroupId) VALUES" +
"(#{id}, #{name}, #{platformId}, #{parentId}, #{civilCode}, #{businessGroupId})")
int add(PlatformCatalog platformCatalog);
@Delete("DELETE FROM platform_catalog WHERE id=#{id}")
@ -44,4 +45,12 @@ public interface PlatformCatalogMapper {
@Select("SELECT pc.* FROM platform_catalog pc WHERE pc.id = (SELECT pp.catalogId from parent_platform pp WHERE pp.serverGBId=#{platformId})")
PlatformCatalog selectDefaultByPlatFormId(String platformId);
@Select("SELECT pc.* FROM platform_catalog pc WHERE pc.id = #{id}")
PlatformCatalog selectParentCatalog(String id);
@Select("SELECT pc.id as channelId, pc.name, pc.civilCode, pc.businessGroupId,'0' as parental, pc.parentId " +
" FROM platform_catalog pc WHERE pc.platformId=#{platformId}")
List<DeviceChannel> queryCatalogInPlatform(String platformId);
}

View File

@ -62,12 +62,12 @@ public interface StreamProxyMapper {
@Update("UPDATE stream_proxy " +
"SET status=#{status} " +
"WHERE mediaServerId=#{mediaServerId}")
void updateStatusByMediaServerId(boolean status, String mediaServerId);
void updateStatusByMediaServerId(String mediaServerId, boolean status);
@Update("UPDATE stream_proxy " +
"SET status=${status} " +
"WHERE app=#{app} AND stream=#{stream}")
int updateStatus(boolean status, String app, String stream);
int updateStatus(String app, String stream, boolean status);
@Delete("DELETE FROM stream_proxy WHERE enable_remove_none_reader=true AND mediaServerId=#{mediaServerId}")
void deleteAutoRemoveItemByMediaServerId(String mediaServerId);

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import org.apache.ibatis.annotations.*;
// import org.omg.PortableInterceptor.INACTIVE;
import org.springframework.stereotype.Repository;
@ -14,21 +15,24 @@ import java.util.List;
public interface StreamPushMapper {
@Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
"createStamp, aliveSecond, mediaServerId, serverId) VALUES" +
"pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng) VALUES" +
"('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " +
"'${createStamp}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' )")
"'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', ${pushIng} )")
int add(StreamPushItem streamPushItem);
@Update("UPDATE stream_push " +
"SET app=#{app}," +
"stream=#{stream}," +
"mediaServerId=#{mediaServerId}," +
"totalReaderCount=#{totalReaderCount}, " +
"originType=#{originType}," +
"originTypeStr=#{originTypeStr}, " +
"createStamp=#{createStamp}, " +
"aliveSecond=#{aliveSecond} " +
"WHERE app=#{app} AND stream=#{stream}")
@Update(value = {" <script>" +
"UPDATE stream_push " +
"SET updateTime='${updateTime}'" +
"<if test=\"mediaServerId != null\">, mediaServerId='${mediaServerId}'</if>" +
"<if test=\"totalReaderCount != null\">, totalReaderCount='${totalReaderCount}'</if>" +
"<if test=\"originType != null\">, originType=${originType}</if>" +
"<if test=\"originTypeStr != null\">, originTypeStr='${originTypeStr}'</if>" +
"<if test=\"pushTime != null\">, pushTime='${pushTime}'</if>" +
"<if test=\"aliveSecond != null\">, aliveSecond='${aliveSecond}'</if>" +
"<if test=\"pushIng != null\">, pushIng=${pushIng}</if>" +
"WHERE app=#{app} AND stream=#{stream}"+
" </script>"})
int update(StreamPushItem streamPushItem);
@Delete("DELETE FROM stream_push WHERE app=#{app} AND stream=#{stream}")
@ -62,7 +66,7 @@ public interface StreamPushMapper {
@Select(value = {" <script>" +
"SELECT " +
"st.*, " +
"gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude, gs.gbStreamId " +
"gs.gbId, gs.name, gs.longitude, gs.latitude, gs.gbStreamId " +
"from " +
"stream_push st " +
"LEFT JOIN gb_stream gs " +
@ -70,25 +74,26 @@ public interface StreamPushMapper {
"WHERE " +
"1=1 " +
" <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
" <if test='pushing == true' > AND (gs.gbId is null OR gs.status=1)</if>" +
" <if test='pushing == false' > AND gs.status=0</if>" +
" <if test='pushing == true' > AND (gs.gbId is null OR st.status=1)</if>" +
" <if test='pushing == false' > AND st.status=0</if>" +
" <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
"order by st.createStamp desc" +
"order by st.createTime desc" +
" </script>"})
List<StreamPushItem> selectAllForList(String query, Boolean pushing, String mediaServerId);
@Select("SELECT st.*, gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream order by st.createStamp desc")
@Select("SELECT st.*, gs.gbId, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream order by st.createTime desc")
List<StreamPushItem> selectAll();
@Select("SELECT st.*, gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream WHERE st.app=#{app} AND st.stream=#{stream}")
@Select("SELECT st.*, gs.gbId, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream WHERE st.app=#{app} AND st.stream=#{stream}")
StreamPushItem selectOne(String app, String stream);
@Insert("<script>" +
"Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
"createStamp, aliveSecond, mediaServerId) " +
"createTime, aliveSecond, mediaServerId, status, pushIng) " +
"VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
"( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " +
"'${item.originTypeStr}',#{item.createStamp}, #{item.aliveSecond}, '${item.mediaServerId}' )" +
"'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}', ${item.status} ," +
" ${item.pushIng} )" +
" </foreach>" +
"</script>")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@ -106,4 +111,59 @@ public interface StreamPushMapper {
@Select("SELECT sp.* FROM stream_push sp left join gb_stream gs on gs.app = sp.app and gs.stream= sp.stream WHERE sp.mediaServerId=#{mediaServerId} and gs.gbId is null")
List<StreamPushItem> selectAllByMediaServerIdWithOutGbID(String mediaServerId);
@Update("UPDATE stream_push " +
"SET status=${status} " +
"WHERE app=#{app} AND stream=#{stream}")
int updateStatus(String app, String stream, boolean status);
@Update("UPDATE stream_push " +
"SET pushIng=${pushIng} " +
"WHERE app=#{app} AND stream=#{stream}")
int updatePushStatus(String app, String stream, boolean status);
@Update("UPDATE stream_push " +
"SET status=#{status} " +
"WHERE mediaServerId=#{mediaServerId}")
void updateStatusByMediaServerId(String mediaServerId, boolean status);
@Select("<script> "+
"SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
"where sp.status = 1 and (gs.app, gs.stream) in (" +
"<foreach collection='offlineStreams' item='item' separator=','>" +
"(#{item.app}, #{item.stream}) " +
"</foreach>" +
")</script>")
List<GbStream> getOnlinePusherForGbInList(List<StreamPushItemFromRedis> offlineStreams);
@Update("<script> "+
"UPDATE stream_push SET status=0 where (app, stream) in (" +
"<foreach collection='offlineStreams' item='item' separator=','>" +
"(#{item.app}, #{item.stream}) " +
"</foreach>" +
")</script>")
void offline(List<StreamPushItemFromRedis> offlineStreams);
@Select("<script> "+
"SELECT * FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
"where sp.status = 0 and (gs.app, gs.stream) in (" +
"<foreach collection='onlineStreams' item='item' separator=','>" +
"(#{item.app}, #{item.stream}) " +
"</foreach>" +
") </script>")
List<GbStream> getOfflinePusherForGbInList(List<StreamPushItemFromRedis> onlineStreams);
@Update("<script> "+
"UPDATE stream_push SET status=1 where (app, stream) in (" +
"<foreach collection='onlineStreams' item='item' separator=','>" +
"(#{item.app}, #{item.stream}) " +
"</foreach>" +
")</script>")
void online(List<StreamPushItemFromRedis> onlineStreams);
@Select("SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream where sp.status = 1")
List<GbStream> getOnlinePusherForGb();
@Update("UPDATE stream_push SET status=0")
void setAllStreamOffline();
}

View File

@ -10,13 +10,14 @@ import java.util.List;
@Repository
public interface UserMapper {
@Insert("INSERT INTO user (username, password, roleId, createTime, updateTime) VALUES" +
"('${username}', '${password}', '${role.id}', '${createTime}', '${updateTime}')")
@Insert("INSERT INTO user (username, password, roleId, pushKey, createTime, updateTime) VALUES" +
"('${username}', '${password}', '${role.id}', '${pushKey}', '${createTime}', '${updateTime}')")
int add(User user);
@Update(value = {" <script>" +
"UPDATE user " +
"SET updateTime='${updateTime}' " +
"<if test=\"pushKey != null\">, pushKey='${pushKey}'</if>" +
"<if test=\"role != null\">, roleId='${role.id}'</if>" +
"<if test=\"password != null\">, password='${password}'</if>" +
"<if test=\"username != null\">, username='${username}'</if>" +
@ -48,4 +49,17 @@ public interface UserMapper {
@Select("select u.*, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u, user_role r WHERE u.roleId=r.id")
@ResultMap(value="roleMap")
List<User> selectAll();
@Select("select * from (select user.*, concat('${callId}_', pushKey) as str1 from user) as u where md5(u.str1) = '${sign}'")
List<User> checkPushAuthorityByCallIdAndSign(String callId, String sign);
@Select("select * from user where md5(pushKey) = '${sign}'")
List<User> checkPushAuthorityByCallId(String sign);
@Select("select u.id, u.username,u.pushKey,u.roleId, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u join user_role r on u.roleId=r.id")
@ResultMap(value="roleMap")
List<User> getUsers();
@Update("update user set pushKey=#{pushKey} where id=#{id}")
int changePushKey(int id, String pushKey);
}

View File

@ -7,6 +7,7 @@ public class User {
private String password;
private String createTime;
private String updateTime;
private String pushKey;
private Role role;
public int getId() {
@ -56,4 +57,12 @@ public class User {
public void setRole(Role role) {
this.role = role;
}
public String getPushKey() {
return pushKey;
}
public void setPushKey(String pushKey) {
this.pushKey = pushKey;
}
}

View File

@ -9,6 +9,8 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
@ -20,6 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.*;
@ -482,7 +485,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
// 查找是否使用了callID
StreamAuthorityInfo streamAuthorityInfo = getStreamAuthorityInfo(app, streamId);
String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
if (streamAuthorityInfo != null) {
mediaItem.setCallId(streamAuthorityInfo.getCallId());
}
redis.set(key, mediaItem);
}
@ -598,6 +606,26 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
return result;
}
@Override
public void updateStreamAuthorityInfo(String app, String stream, StreamAuthorityInfo streamAuthorityInfo) {
String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream;
redis.set(key, streamAuthorityInfo);
}
@Override
public void removeStreamAuthorityInfo(String app, String stream) {
String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
redis.del(key);
}
@Override
public StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream) {
String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
return (StreamAuthorityInfo) redis.get(key);
}
@Override
public MediaItem getStreamInfo(String app, String streamId, String mediaServerId) {
String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_*_" + app + "_" + streamId + "_" + mediaServerId;
@ -682,4 +710,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
public boolean deviceIsOnline(String deviceId) {
return getDevice(deviceId).getOnline() == 1;
}
@Override
public void sendStreamPushRequestedMsgForStatus() {
String key = VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED;
logger.info("[redis 通知]获取所有推流设备的状态");
JSONObject jsonObject = new JSONObject();
jsonObject.put(key, key);
redis.convertAndSend(key, jsonObject);
}
}

View File

@ -48,12 +48,13 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
@Autowired
SipConfig sipConfig;
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private DeviceMapper deviceMapper;
@ -104,96 +105,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
return deviceMapper.getDeviceByDeviceId(deviceId) != null;
}
@Override
public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
String channelId = channel.getChannelId();
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
if (deviceChannel == null) {
channel.setCreateTime(now);
deviceChannelMapper.add(channel);
}else {
deviceChannelMapper.update(channel);
}
deviceChannelMapper.updateChannelSubCount(deviceId,channel.getParentId());
}
@Override
public int updateChannels(String deviceId, List<DeviceChannel> channels) {
List<DeviceChannel> addChannels = new ArrayList<>();
List<DeviceChannel> updateChannels = new ArrayList<>();
HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
if (channels != null && channels.size() > 0) {
List<DeviceChannel> channelList = deviceChannelMapper.queryChannels(deviceId, null, null, null, null);
if (channelList.size() == 0) {
for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
channel.setCreateTime(now);
addChannels.add(channel);
}
}else {
for (DeviceChannel deviceChannel : channelList) {
channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
}
for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId);
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
if (streamInfo != null) {
channel.setStreamId(streamInfo.getStream());
}
String now = DateUtil.getNow();
channel.setUpdateTime(now);
if (channelsInStore.get(channel.getChannelId()) != null) {
updateChannels.add(channel);
}else {
addChannels.add(channel);
channel.setCreateTime(now);
}
}
}
int limitCount = 300;
if (addChannels.size() > 0) {
if (addChannels.size() > limitCount) {
for (int i = 0; i < addChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > addChannels.size()) {
toIndex = addChannels.size();
}
deviceChannelMapper.batchAdd(addChannels.subList(i, toIndex));
}
}else {
deviceChannelMapper.batchAdd(addChannels);
}
}
if (updateChannels.size() > 0) {
if (updateChannels.size() > limitCount) {
for (int i = 0; i < updateChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > updateChannels.size()) {
toIndex = updateChannels.size();
}
deviceChannelMapper.batchUpdate(updateChannels.subList(i, toIndex));
}
}else {
deviceChannelMapper.batchUpdate(updateChannels);
}
}
}
return addChannels.size() + updateChannels.size();
}
@Override
public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
if (CollectionUtils.isEmpty(deviceChannelList)) {
@ -532,20 +443,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
// 更新缓存
parentPlatformCatch.setParentPlatform(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
if (parentPlatform.isEnable()) {
// 共享所有视频流需要将现有视频流添加到此平台
List<GbStream> gbStreams = gbStreamMapper.queryStreamNotInPlatform();
if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
gbStream.setCatalogId(parentPlatform.getCatalogId());
}
if (parentPlatform.isShareAllLiveStream()) {
gbStreamService.addPlatformInfo(gbStreams, parentPlatform.getServerGBId(), parentPlatform.getCatalogId());
}else {
gbStreamService.delPlatformInfo(parentPlatform.getServerGBId(), gbStreams);
}
}
}
return result > 0;
}
@ -596,36 +493,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
return deviceChannelMapper.queryChannelByPlatformId(platformId);
}
@Override
public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
for (ChannelReduce channelReduce : channelReduces) {
channelReduce.setCatalogId(catalogId);
deviceAndChannels.put(channelReduce.getId(), channelReduce);
}
List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
// 查询当前已经存在的
List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
if (deviceAndChannelList != null) {
deviceAndChannelList.removeAll(channelIds);
}
for (Integer channelId : channelIds) {
deviceAndChannels.remove(channelId);
}
List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
// 对剩下的数据进行存储
int result = 0;
if (channelReducesToAdd.size() > 0) {
result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
// TODO 后续给平台增加控制开关以控制是否响应目录订阅
List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId);
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
}
return result;
}
@Override
public int delChannelForGB(String platformId, List<ChannelReduce> channelReduces) {
@ -701,77 +568,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
}
/**
* 新增代理流
* @param streamProxyItem
* @return
*/
@Override
public boolean addStreamProxy(StreamProxyItem streamProxyItem) {
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
boolean result = false;
streamProxyItem.setStreamType("proxy");
streamProxyItem.setStatus(true);
String now = DateUtil.getNow();
streamProxyItem.setCreateTime(now);
try {
if (streamProxyMapper.add(streamProxyItem) > 0) {
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
if (gbStreamMapper.add(streamProxyItem) < 0) {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
}
}else {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
result = true;
dataSourceTransactionManager.commit(transactionStatus); //手动提交
}catch (Exception e) {
logger.error("向数据库添加流代理失败:", e);
dataSourceTransactionManager.rollback(transactionStatus);
}
return result;
}
/**
* 更新代理流
* @param streamProxyItem
* @return
*/
@Override
public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
boolean result = false;
streamProxyItem.setStreamType("proxy");
try {
if (streamProxyMapper.update(streamProxyItem) > 0) {
if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
}
} else {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
dataSourceTransactionManager.commit(transactionStatus); //手动提交
result = true;
}catch (Exception e) {
e.printStackTrace();
dataSourceTransactionManager.rollback(transactionStatus);
}
return result;
}
/**
* 移除代理流
@ -824,7 +620,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
* @return
*/
@Override
public List<GbStream> queryGbStreamListInPlatform(String platformId) {
public List<DeviceChannel> queryGbStreamListInPlatform(String platformId) {
return gbStreamMapper.queryGbStreamListInPlatform(platformId);
}
@ -848,7 +644,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
streamPushMapper.addAll(streamPushItems);
// TODO 待优化
for (int i = 0; i < streamPushItems.size(); i++) {
int onlineResult = gbStreamMapper.setStatus(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream(), true);
int onlineResult = mediaOnline(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream());
if (onlineResult > 0) {
// 发送上线通知
eventPublisher.catalogEventPublishForStream(null, streamPushItems.get(i), CatalogEvent.ON);
@ -856,29 +652,13 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
}
@Override
public void updateMedia(StreamPushItem streamPushItem) {
streamPushMapper.del(streamPushItem.getApp(), streamPushItem.getStream());
streamPushMapper.add(streamPushItem);
gbStreamMapper.setStatus(streamPushItem.getApp(), streamPushItem.getStream(), true);
if(!StringUtils.isEmpty(streamPushItem.getGbId() )){
// 查找开启了全部直播流共享的上级平台
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) {
StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(streamPushItem.getApp(), streamPushItem.getStream(),
parentPlatform.getServerGBId());
if (streamProxyItem == null) {
streamPushItem.setCatalogId(parentPlatform.getCatalogId());
streamPushItem.setPlatformId(parentPlatform.getServerGBId());
platformGbStreamMapper.add(streamPushItem);
eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), streamPushItem, CatalogEvent.ADD);
}
}
}
}
mediaOffline(streamPushItem.getApp(), streamPushItem.getStream());
}
@Override
@ -897,8 +677,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
@Override
public int mediaOutline(String app, String streamId) {
return gbStreamMapper.setStatus(app, streamId, false);
public int mediaOffline(String app, String stream) {
GbStream gbStream = gbStreamMapper.selectOne(app, stream);
int result;
if ("proxy".equals(gbStream.getStreamType())) {
result = streamProxyMapper.updateStatus(app, stream, false);
}else {
result = streamPushMapper.updateStatus(app, stream, false);
}
return result;
}
@Override
public int mediaOnline(String app, String stream) {
GbStream gbStream = gbStreamMapper.selectOne(app, stream);
int result;
if ("proxy".equals(gbStream.getStreamType())) {
result = streamProxyMapper.updateStatus(app, stream, true);
}else {
result = streamPushMapper.updateStatus(app, stream, true);
}
return result;
}
@Override
@ -934,6 +733,24 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
@Override
public int addCatalog(PlatformCatalog platformCatalog) {
ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformCatalog.getPlatformId());
if (platform == null) {
return 0;
}
if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
// 第一层节点
platformCatalog.setBusinessGroupId(platformCatalog.getId());
}else {
// 获取顶层的
PlatformCatalog topCatalog = getTopCatalog(platformCatalog.getParentId(), platformCatalog.getPlatformId());
platformCatalog.setBusinessGroupId(topCatalog.getId());
}
}
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)) {
platformCatalog.setCivilCode(platformCatalog.getId());
}
int result = catalogMapper.add(platformCatalog);
if (result > 0) {
DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog);
@ -942,6 +759,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
return result;
}
private PlatformCatalog getTopCatalog(String id, String platformId) {
PlatformCatalog catalog = catalogMapper.selectParentCatalog(id);
if (catalog.getParentId().equals(platformId)) {
return catalog;
}else {
return getTopCatalog(catalog.getParentId(), platformId);
}
}
@Override
public PlatformCatalog getCatalog(String id) {
return catalogMapper.select(id);
@ -1012,8 +838,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
@Override
public List<PlatformCatalog> queryCatalogInPlatform(String platformId) {
return catalogMapper.selectByPlatForm(platformId);
public List<DeviceChannel> queryCatalogInPlatform(String platformId) {
return catalogMapper.queryCatalogInPlatform(platformId);
}
@Override
@ -1056,20 +882,24 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) {
ParentPlatform parentPlatByServerGBId = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
ParentPlatform platform = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(catalog.getId());
deviceChannel.setName(catalog.getName());
deviceChannel.setLongitude(0.0);
deviceChannel.setLatitude(0.0);
deviceChannel.setDeviceId(parentPlatByServerGBId.getDeviceGBId());
deviceChannel.setDeviceId(platform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setRegisterWay(1);
// 行政区划应该是Domain的前八位
deviceChannel.setCivilCode(parentPlatByServerGBId.getAdministrativeDivision());
if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0");
@ -1131,4 +961,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
deviceChannelMapper.updatePosition(deviceChannel);
}
@Override
public void cleanContentForPlatform(String serverGBId) {
// List<PlatformCatalog> catalogList = catalogMapper.selectByPlatForm(serverGBId);
// if (catalogList.size() > 0) {
// int result = catalogMapper.delByPlatformId(serverGBId);
// if (result > 0) {
// List<DeviceChannel> deviceChannels = new ArrayList<>();
// for (PlatformCatalog catalog : catalogList) {
// deviceChannels.add(getDeviceChannelByCatalog(catalog));
// }
// eventPublisher.catalogEventPublish(serverGBId, deviceChannels, CatalogEvent.DEL);
// }
// }
catalogMapper.delByPlatformId(serverGBId);
platformChannelMapper.delByPlatformId(serverGBId);
platformGbStreamMapper.delByPlatformId(serverGBId);
}
@Override
public List<DeviceChannel> queryChannelWithCatalog(String serverGBId) {
return deviceChannelMapper.queryChannelWithCatalog(serverGBId);
}
}

View File

@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
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.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@ -52,6 +53,9 @@ public class DeviceQuery {
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@ -280,7 +284,7 @@ public class DeviceQuery {
})
@PostMapping("/channel/update/{deviceId}")
public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
storager.updateChannel(deviceId, channel);
deviceChannelService.updateChannel(deviceId, channel);
return new ResponseEntity<>(null,HttpStatus.OK);
}

View File

@ -44,7 +44,6 @@ public class GbStreamController {
@ApiImplicitParam(name = "platformId", value = "平台ID", required = true , dataTypeClass = String.class),
@ApiImplicitParam(name = "catalogId", value = "目录ID", required = false , dataTypeClass = String.class),
@ApiImplicitParam(name="query", value = "查询内容", required = false , dataTypeClass = String.class),
@ApiImplicitParam(name="pushing", value = "是否正在推流", required = false , dataTypeClass = Boolean.class),
@ApiImplicitParam(name="mediaServerId", value = "流媒体ID", required = false , dataTypeClass = String.class),
})
@ -55,7 +54,6 @@ public class GbStreamController {
@RequestParam(required = true)String platformId,
@RequestParam(required = false)String catalogId,
@RequestParam(required = false)String query,
@RequestParam(required = false)Boolean pushing,
@RequestParam(required = false)String mediaServerId){
if (StringUtils.isEmpty(catalogId)) {
catalogId = null;
@ -69,7 +67,7 @@ public class GbStreamController {
// catalogId 为null 查询未在平台下分配的数据
// catalogId 不为null 查询平台下这个目录下的通道
return gbStreamService.getAll(page, count, platformId, catalogId, query, pushing, mediaServerId);
return gbStreamService.getAll(page, count, platformId, catalogId, query, mediaServerId);
}

View File

@ -1,9 +1,14 @@
package com.genersoft.iot.vmp.vmanager.gb28181.media;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.security.SecurityUtils;
import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.annotations.Api;
@ -16,6 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@Api(tags = "媒体流相关")
@Controller
@ -26,17 +33,11 @@ public class MediaController {
private final static Logger logger = LoggerFactory.getLogger(MediaController.class);
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IStreamPushService streamPushService;
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IMediaService mediaService;
@Autowired
private IMediaServerService mediaServerService;
/**
* 根据应用名和流id获取播放地址
@ -52,13 +53,47 @@ public class MediaController {
})
@GetMapping(value = "/stream_info_by_app_and_stream")
@ResponseBody
public WVPResult<StreamInfo> getStreamInfoByAppAndStream(@RequestParam String app, @RequestParam String stream, @RequestParam(required = false) String mediaServerId){
StreamInfo streamInfoByAppAndStreamWithCheck = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId);
public WVPResult<StreamInfo> getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
@RequestParam String stream,
@RequestParam(required = false) String mediaServerId,
@RequestParam(required = false) String callId,
@RequestParam(required = false) Boolean useSourceIpAsStreamIp){
boolean authority = false;
if (callId != null) {
// 权限校验
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
if (streamAuthorityInfo.getCallId().equals(callId)) {
authority = true;
}else {
WVPResult<StreamInfo> result = new WVPResult<>();
result.setCode(401);
result.setMsg("fail");
return result;
}
}else {
// 是否登陆用户, 登陆用户返回完整信息
LoginUser userInfo = SecurityUtils.getUserInfo();
if (userInfo!= null) {
authority = true;
}
}
StreamInfo streamInfo;
if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
String host = request.getHeader("Host");
String localAddr = host.split(":")[0];
logger.info("使用{}作为返回流的ip", localAddr);
streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority);
}else {
streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
}
WVPResult<StreamInfo> result = new WVPResult<>();
if (streamInfoByAppAndStreamWithCheck != null){
if (streamInfo != null){
result.setCode(0);
result.setMsg("scccess");
result.setData(streamInfoByAppAndStreamWithCheck);
result.setData(streamInfo);
}else {
result.setCode(-1);
result.setMsg("fail");

View File

@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -48,6 +49,9 @@ public class PlatformController {
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IPlatformChannelService platformChannelService;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@ -236,6 +240,12 @@ public class PlatformController {
parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());
ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
parentPlatform.setUpdateTime(DateUtil.getNow());
if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {
// 目录结构发生变化清空之前的关联关系
logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId());
storager.cleanContentForPlatform(parentPlatform.getServerGBId());
}
boolean updateResult = storager.updateParentPlatform(parentPlatform);
if (updateResult) {
@ -256,6 +266,8 @@ public class PlatformController {
}
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
commanderForPlatform.unregister(parentPlatformOld, null, null);
// 停止订阅相关的定时任务
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
}
wvpResult.setCode(0);
wvpResult.setMsg("success");
@ -405,7 +417,7 @@ public class PlatformController {
if (logger.isDebugEnabled()) {
logger.debug("给上级平台添加国标通道API调用");
}
int result = storager.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
}
@ -485,7 +497,6 @@ public class PlatformController {
PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
if (platformCatalogInStore != null) {
result.setCode(-1);
result.setMsg(platformCatalog.getId() + " already exists");

View File

@ -193,7 +193,7 @@ public class PlayController {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
result.put("key", data.getString("key"));
StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId());
StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId(), false);
result.put("data", streamInfoResult);
}
}else {

View File

@ -3,11 +3,16 @@ package com.genersoft.iot.vmp.vmanager.streamPush;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.security.SecurityUtils;
import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler;
import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam;
@ -30,6 +35,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@ -54,6 +60,9 @@ public class StreamPushController {
@Autowired
private DeferredResultHolder resultHolder;
@Autowired
private IMediaService mediaService;
@ApiOperation("推流列表查询")
@ApiImplicitParams({
@ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
@ -237,5 +246,43 @@ public class StreamPushController {
return result;
}
/**
* 获取推流播放地址
* @param app 应用名
* @param stream 流id
* @return
*/
@ApiOperation("获取推流播放地址")
@ApiImplicitParams({
@ApiImplicitParam(name = "app", value = "应用名", dataTypeClass = String.class),
@ApiImplicitParam(name = "stream", value = "流id", dataTypeClass = String.class),
@ApiImplicitParam(name = "mediaServerId", value = "媒体服务器id", dataTypeClass = String.class, required = false),
})
@GetMapping(value = "/getPlayUrl")
@ResponseBody
public WVPResult<StreamInfo> getPlayUrl(HttpServletRequest request, @RequestParam String app,
@RequestParam String stream,
@RequestParam(required = false) String mediaServerId){
boolean authority = false;
// 是否登陆用户, 登陆用户返回完整信息
LoginUser userInfo = SecurityUtils.getUserInfo();
if (userInfo!= null) {
authority = true;
}
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
WVPResult<StreamInfo> result = new WVPResult<>();
if (streamInfo != null){
result.setCode(0);
result.setMsg("scccess");
result.setData(streamInfo);
}else {
result.setCode(-1);
result.setMsg("fail");
}
return result;
}
}

View File

@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.storager.dao.dto.Role;
import com.genersoft.iot.vmp.storager.dao.dto.User;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -123,7 +124,8 @@ public class UserController {
User user = new User();
user.setUsername(username);
user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
//新增用户的pushKey的生成规则为md5(时间戳+用户名)
user.setPushKey(DigestUtils.md5DigestAsHex((System.currentTimeMillis()+password).getBytes()));
Role role = roleService.getRoleById(roleId);
if (role == null) {
@ -137,6 +139,7 @@ public class UserController {
user.setUpdateTime(DateUtil.getNow());
int addResult = userService.addUser(user);
result.setCode(addResult > 0 ? 0 : -1);
result.setMsg(addResult > 0 ? "success" : "fail");
result.setData(addResult);
@ -177,4 +180,68 @@ public class UserController {
result.setData(allUsers);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* 分页查询用户
*
* @param page 当前页
* @param count 每页查询数量
* @return 分页用户列表
*/
@ApiOperation("分页查询用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "当前页", required = true, dataTypeClass = Integer.class),
@ApiImplicitParam(name = "count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
})
@GetMapping("/users")
public PageInfo<User> users(int page, int count) {
return userService.getUsers(page, count);
}
@ApiOperation("修改pushkey")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", required = true, value = "用户Id", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "pushKey", required = true, value = "新的pushKey", dataTypeClass = String.class),
})
@RequestMapping("/changePushKey")
public ResponseEntity<WVPResult<String>> changePushKey(@RequestParam Integer userId,@RequestParam String pushKey) {
// 获取当前登录用户id
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
WVPResult<String> result = new WVPResult<>();
if (currenRoleId != 1) {
// 只用角色id为0才可以删除和添加用户
result.setCode(-1);
result.setMsg("用户无权限");
return new ResponseEntity<>(result, HttpStatus.FORBIDDEN);
}
int resetPushKeyResult = userService.changePushKey(userId,pushKey);
result.setCode(resetPushKeyResult > 0 ? 0 : -1);
result.setMsg(resetPushKeyResult > 0 ? "success" : "fail");
return new ResponseEntity<>(result, HttpStatus.OK);
}
@ApiOperation("管理员修改普通用户密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "adminId", required = true, value = "管理员id", dataTypeClass = String.class),
@ApiImplicitParam(name = "userId", required = true, value = "用户id", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", required = true, value = "新密码未md5加密的密码", dataTypeClass = String.class),
})
@PostMapping("/changePasswordForAdmin")
public String changePasswordForAdmin(@RequestParam int userId, @RequestParam String password) {
// 获取当前登录用户id
LoginUser userInfo = SecurityUtils.getUserInfo();
if (userInfo == null) {
return "fail";
}
Role role = userInfo.getRole();
if (role != null && role.getId() == 1) {
boolean result = userService.changePassword(userId, DigestUtils.md5DigestAsHex(password.getBytes()));
if (result) {
return "success";
}
}
return "fail";
}
}

Binary file not shown.

View File

@ -185,8 +185,6 @@ user-settings:
record-sip: true
# 是否将日志存储进数据库
logInDatebase: true
# 第三方匹配用于从stream钟获取有效信息
thirdPartyGBIdReg: "[\\s\\S]*"
# 在线文档: swagger-ui生产环境建议关闭
swagger-ui:

View File

@ -86,7 +86,7 @@ export default {
}).then(function (res) {
console.log(JSON.stringify(res));
if (res.data.code == 0 && res.data.msg == "success") {
that.$cookies.set("session", {"username": that.username}) ;
that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ;
//
that.cancelEnterkeyDefaultAction();
that.$router.push('/');

View File

@ -143,7 +143,7 @@ export default {
});
},
chooseChannel: function(platform) {
this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, this.initData)
this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, platform.treeType, this.initData)
},
initData: function() {
this.getPlatformList();

View File

@ -56,13 +56,18 @@
<el-table-column label="开始时间" min-width="200">
<template slot-scope="scope">
<el-button-group>
{{ dateFormat(parseInt(scope.row.createStamp)) }}
{{ scope.row.pushTime == null? "-":scope.row.pushTime }}
</el-button-group>
</template>
</el-table-column>
<el-table-column label="正在推流" min-width="100">
<template slot-scope="scope">
{{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '是' : '否' }}
{{scope.row.pushIng ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="本平台推流" min-width="100">
<template slot-scope="scope">
{{scope.row.pushIng && !!!scope.row.serverId ? '是' : '否' }}
</template>
</el-table-column>
@ -187,7 +192,7 @@ export default {
this.getListLoading = true;
this.$axios({
method: 'get',
url: '/api/media/stream_info_by_app_and_stream',
url: '/api/push/getPlayUrl',
params: {
app: row.app,
stream: row.stream,
@ -242,19 +247,6 @@ export default {
console.error(error);
});
},
dateFormat: function (/** timestamp=0 **/) {
let ts = arguments[0] || 0;
let t, y, m, d, h, i, s;
t = ts ? new Date(ts) : new Date();
y = t.getFullYear();
m = t.getMonth() + 1;
d = t.getDate();
h = t.getHours();
i = t.getMinutes();
s = t.getSeconds();
//
return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' + (h < 10 ? '0' + h : h) + ':' + (i < 10 ? '0' + i : i) + ':' + (s < 10 ? '0' + s : s);
},
importChannel: function () {
this.$refs.importChannel.openDialog(() => {

View File

@ -0,0 +1,236 @@
<template>
<div id="app" style="width: 100%">
<div class="page-header">
<div class="page-title">用户列表</div>
<div class="page-header-btn">
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUser">
添加用户
</el-button>
</div>
</div>
<!--用户列表-->
<el-table :data="userList" style="width: 100%;font-size: 12px;" :height="winHeight"
header-row-class-name="table-header">
<el-table-column prop="username" label="用户名" min-width="160"/>
<el-table-column prop="pushKey" label="pushkey" min-width="160"/>
<el-table-column prop="role.name" label="类型" min-width="160"/>
<el-table-column label="操作" min-width="450" fixed="right">
<template slot-scope="scope">
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">修改密码</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUser(scope.row)"
style="color: #f56c6c">删除
</el-button>
</template>
</el-table-column>
</el-table>
<changePasswordForAdmin ref="changePasswordForAdmin"></changePasswordForAdmin>
<changePushKey ref="changePushKey"></changePushKey>
<addUser ref="addUser"></addUser>
<el-pagination
style="float: right"
@size-change="handleSizeChange"
@current-change="currentChange"
:current-page="currentPage"
:page-size="count"
:page-sizes="[15, 25, 35, 50]"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
</div>
</template>
<script>
import uiHeader from '../layout/UiHeader.vue'
import changePasswordForAdmin from './dialog/changePasswordForAdmin.vue'
import changePushKey from './dialog/changePushKey.vue'
import addUser from '../components/dialog/addUser.vue'
export default {
name: 'userManager',
components: {
uiHeader,
changePasswordForAdmin,
changePushKey,
addUser
},
data() {
return {
userList: [], //
currentUser: {}, //
videoComponentList: [],
updateLooper: 0, //
currentUserLenth: 0,
winHeight: window.innerHeight - 200,
currentPage: 1,
count: 15,
total: 0,
getUserListLoading: false
};
},
mounted() {
this.initData();
this.updateLooper = setInterval(this.initData, 10000);
},
destroyed() {
this.$destroy('videojs');
clearTimeout(this.updateLooper);
},
methods: {
initData: function () {
this.getUserList();
},
currentChange: function (val) {
this.currentPage = val;
this.getUserList();
},
handleSizeChange: function (val) {
this.count = val;
this.getUserList();
},
getUserList: function () {
let that = this;
this.getUserListLoading = true;
this.$axios({
method: 'get',
url: `/api/user/users`,
params: {
page: that.currentPage,
count: that.count
}
}).then(function (res) {
that.total = res.data.total;
that.userList = res.data.list;
that.getUserListLoading = false;
}).catch(function (error) {
that.getUserListLoading = false;
});
},
edit: function (row) {
this.$refs.changePasswordForAdmin.openDialog(row, () => {
this.$refs.changePasswordForAdmin.close();
this.$message({
showClose: true,
message: "密码修改成功",
type: "success",
});
setTimeout(this.getUserList, 200)
})
},
deleteUser: function (row) {
let msg = "确定删除此用户?"
if (row.online !== 0) {
msg = "<strong>确定删除此用户?</strong>"
}
this.$confirm(msg, '提示', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
center: true,
type: 'warning'
}).then(() => {
this.$axios({
method: 'delete',
url: `/api/user/delete?id=${row.id}`
}).then((res) => {
this.getUserList();
}).catch((error) => {
console.error(error);
});
}).catch(() => {
});
},
changePushKey: function (row) {
this.$refs.changePushKey.openDialog(row, () => {
this.$refs.changePushKey.close();
this.$message({
showClose: true,
message: "pushKey修改成功",
type: "success",
});
setTimeout(this.getUserList, 200)
})
},
addUser: function () {
// this.$refs.addUser.openDialog()
this.$refs.addUser.openDialog( () => {
this.$refs.addUser.close();
this.$message({
showClose: true,
message: "用户添加成功",
type: "success",
});
setTimeout(this.getUserList, 200)
})
}
}
}
</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;
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<div id="addUser" v-loading="isLoging">
<el-dialog
title="添加用户"
width="40%"
top="2rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<div id="shared" style="margin-right: 20px;">
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input v-model="username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="用户类型" prop="roleId">
<el-select v-model="roleId" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="confirmPassword" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "addUser",
props: {},
computed: {},
created() {
this.getAllRole();
},
data() {
let validatePass1 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入新密码'));
} else {
if (this.confirmPassword !== '') {
this.$refs.passwordForm.validateField('confirmPassword');
}
callback();
}
};
let validatePass2 = (rule, value, callback) => {
if (this.confirmPassword === '') {
callback(new Error('请再次输入密码'));
} else if (this.confirmPassword !== this.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
value:"",
options: [],
loading: false,
username: null,
password: null,
roleId: null,
confirmPassword: null,
listChangeCallback: null,
showDialog: false,
isLoging: false,
rules: {
newPassword: [{required: true, validator: validatePass1, trigger: "blur"}, {
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
},],
confirmPassword: [{required: true, validator: validatePass2, trigger: "blur"}],
},
};
},
methods: {
openDialog: function (callback) {
this.listChangeCallback = callback;
this.showDialog = true;
},
onSubmit: function () {
this.$axios({
method: 'post',
url: "/api/user/add",
params: {
username: this.username,
password: this.password,
roleId: this.roleId
}
}).then((res) => {
if (res.data.code === 0) {
this.$message({
showClose: true,
message: '添加成功',
type: 'success',
});
this.showDialog = false;
this.listChangeCallback()
} else {
this.$message({
showClose: true,
message: res.data.msg,
type: 'error'
});
}
}).catch((error) => {
console.error(error)
});
},
close: function () {
this.showDialog = false;
this.password = null;
this.confirmPassword = null;
this.username = null;
this.roleId = null;
},
getAllRole:function () {
this.$axios({
method: 'get',
url: "/api/role/all"
}).then((res) => {
this.loading = true;
console.info(res)
res.data
console.info(res.data.code)
if (res.data.code === 0) {
console.info(res.data.data)
this.options=res.data.data
}
}).catch((error) => {
console.error(error)
});
}
},
};
</script>

View File

@ -49,11 +49,43 @@ export default {
props: ['platformId'],
created() {},
data() {
let checkId = (rule, value, callback) => {
console.log("checkId")
console.log(this.treeType)
console.log(rule)
console.log(value)
console.log(value.length)
console.log(this.level)
if (!value) {
return callback(new Error('编号不能为空'));
}
if (this.treeType === "BusinessGroup" && value.length !== 20) {
return callback(new Error('编号必须由20位数字组成'));
}
if (this.treeType === "CivilCode" && value.length <= 8 && value.length%2 !== 0) {
return callback(new Error('行政区划必须是八位以下的偶数个数字组成'));
}
if (this.treeType === "BusinessGroup") {
let catalogType = value.substring(10, 13);
console.log(catalogType)
// 216 215
if (this.level === 1 && catalogType !== "215") {
return callback(new Error('业务分组模式下第一层目录的编号10到13位必须为215'));
}
if (this.level > 1 && catalogType !== "216") {
return callback(new Error('业务分组模式下第一层以下目录的编号10到13位必须为216'));
}
}
callback();
}
return {
submitCallback: null,
showDialog: false,
isLoging: false,
isEdit: false,
treeType: null,
level: 0,
form: {
id: null,
name: null,
@ -62,12 +94,12 @@ export default {
},
rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
id: [{ required: true, message: "请输入ID", trigger: "blur" }]
id: [{ trigger: "blur",validator: checkId }]
},
};
},
methods: {
openDialog: function (isEdit, id, name, parentId, callback) {
openDialog: function (isEdit, id, name, parentId, treeType, level, callback) {
console.log("parentId: " + parentId)
console.log(this.form)
this.isEdit = isEdit;
@ -77,6 +109,8 @@ export default {
this.form.parentId = parentId;
this.showDialog = true;
this.submitCallback = callback;
this.treeType = treeType;
this.level = level;
},
onSubmit: function () {
console.log("onSubmit");

View File

@ -0,0 +1,121 @@
<template>
<div id="changePassword" v-loading="isLoging">
<el-dialog
title="修改密码"
width="40%"
top="2rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<div id="shared" style="margin-right: 20px;">
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
<el-form-item label="新密码" prop="newPassword" >
<el-input v-model="newPassword" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="confirmPassword" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "changePasswordForAdmin",
props: {},
computed: {},
created() {},
data() {
let validatePass1 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入新密码'));
} else {
if (this.confirmPassword !== '') {
this.$refs.passwordForm.validateField('confirmPassword');
}
callback();
}
};
let validatePass2 = (rule, value, callback) => {
if (this.confirmPassword === '') {
callback(new Error('请再次输入密码'));
} else if (this.confirmPassword !== this.newPassword) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
newPassword: null,
confirmPassword: null,
userId: null,
showDialog: false,
isLoging: false,
listChangeCallback: null,
form: {},
rules: {
newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
},],
confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
},
};
},
methods: {
openDialog: function (row, callback) {
console.log(row)
this.showDialog = true;
this.listChangeCallback = callback;
if (row != null) {
this.form = row;
}
},
onSubmit: function () {
this.$axios({
method: 'post',
url:"/api/user/changePasswordForAdmin",
params: {
password: this.newPassword,
userId: this.form.id,
}
}).then((res)=> {
if (res.data === "success"){
this.$message({
showClose: true,
message: '修改成功',
type: 'success'
});
this.showDialog = false;
}else {
this.$message({
showClose: true,
message: '修改密码失败,是否已登录(接口鉴权关闭无法修改密码)',
type: 'error'
});
}
}).catch((error)=> {
console.error(error)
});
},
close: function () {
this.showDialog = false;
this.newPassword = null;
this.confirmPassword = null;
this.userId=null;
this.adminId=null;
},
},
};
</script>

View File

@ -0,0 +1,102 @@
<template>
<div id="changepushKey" v-loading="isLoging">
<el-dialog
title="修改密码"
width="42%"
top="2rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<div id="shared" style="margin-right: 18px;">
<el-form ref="pushKeyForm" :rules="rules" status-icon label-width="86px">
<el-form-item label="新pushKey" prop="newPushKey" >
<el-input v-model="newPushKey" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "changePushKey",
props: {},
computed: {},
created() {},
data() {
let validatePass1 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入新pushKey'));
} else {
callback();
}
};
return {
newPushKey: null,
confirmpushKey: null,
userId: null,
showDialog: false,
isLoging: false,
listChangeCallback: null,
form: {},
rules: {
newpushKey: [{ required: true, validator: validatePass1, trigger: "blur" }],
},
};
},
methods: {
openDialog: function (row, callback) {
console.log(row)
this.showDialog = true;
this.listChangeCallback = callback;
if (row != null) {
this.form = row;
}
},
onSubmit: function () {
this.$axios({
method: 'post',
url:"/api/user/changePushKey",
params: {
pushKey: this.newPushKey,
userId: this.form.id,
}
}).then((res)=> {
console.log(res.data)
if (res.data.msg === "success"){
this.$message({
showClose: true,
message: '修改成功',
type: 'success'
});
this.showDialog = false;
this.listChangeCallback();
}else {
this.$message({
showClose: true,
message: '修改密码失败,是否已登录(接口鉴权关闭无法修改密码)',
type: 'error'
});
}
}).catch((error)=> {
console.error(error)
});
},
close: function () {
this.showDialog = false;
this.newpushKey = null;
this.userId=null;
this.adminId=null;
},
},
};
</script>

View File

@ -8,7 +8,7 @@
<el-tab-pane label="目录结构" name="catalog">
<el-container>
<el-main v-bind:style="{backgroundColor: '#FFF', maxHeight: winHeight + 'px'}">
<chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" ></chooseChannelForCatalog>
<chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" :treeType=treeType ></chooseChannelForCatalog>
</el-main>
</el-container>
</el-tab-pane>
@ -66,18 +66,20 @@ export default {
platformName: "",
defaultCatalogId: "",
showDialog: false,
treeType: null,
chooseData: {},
winHeight: window.innerHeight - 250,
};
},
methods: {
openDialog(platformId, platformName, defaultCatalogId, closeCallback) {
openDialog(platformId, platformName, defaultCatalogId, treeType, closeCallback) {
this.platformId = platformId
this.platformName = platformName
this.defaultCatalogId = defaultCatalogId
this.showDialog = true
this.closeCallback = closeCallback
this.treeType = treeType
},
tabClick (tab, event){

View File

@ -38,7 +38,7 @@
import catalogEdit from './catalogEdit.vue'
export default {
name: 'chooseChannelForCatalog',
props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange'],
props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
created() {
this.chooseId = this.defaultCatalogId;
this.defaultCatalogIdSign = this.defaultCatalogId;
@ -102,8 +102,9 @@ export default {
},
addCatalog: function (parentId, node){
let that = this;
console.log(this.treeType)
//
that.$refs.catalogEdit.openDialog(false, null, null, parentId, ()=>{
that.$refs.catalogEdit.openDialog(false, null, null, parentId, this.treeType, node.level, ()=>{
node.loaded = false
node.expand();
});

View File

@ -174,7 +174,6 @@ export default {
page: that.currentPage,
count: that.count,
query: that.searchSrt,
pushing: that.pushing,
platformId: that.platformId,
catalogId: that.catalogId,
mediaServerId: that.mediaServerId

View File

@ -78,6 +78,12 @@
<el-option label="8" value="8"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目录结构" prop="treeType" >
<el-select v-model="platform.treeType" style="width: 100%" >
<el-option key="WGS84" label="行政区划" value="CivilCode"></el-option>
<el-option key="GCJ02" label="业务分组" value="BusinessGroup"></el-option>
</el-select>
</el-form-item>
<el-form-item label="字符集" prop="characterSet">
<el-select
v-model="platform.characterSet"
@ -91,7 +97,6 @@
<el-form-item label="其他选项">
<el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
<el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
<el-checkbox label="共享所有直播流" v-model="platform.shareAllLiveStream"></el-checkbox>
<el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
</el-form-item>
<el-form-item>
@ -153,10 +158,10 @@ export default {
keepTimeout: 60,
transport: "UDP",
characterSet: "GB2312",
shareAllLiveStream: false,
startOfflinePush: false,
catalogGroup: 1,
administrativeDivision: null,
treeType: "BusinessGroup",
},
rules: {
name: [{ required: true, message: "请输入平台名称", trigger: "blur" }],
@ -194,6 +199,7 @@ export default {
that.platform.devicePort = res.data.devicePort;
that.platform.username = res.data.username;
that.platform.password = res.data.password;
that.platform.treeType = "BusinessGroup";
that.platform.administrativeDivision = res.data.username.substr(0, 6);
}).catch(function (error) {
console.log(error);
@ -217,11 +223,11 @@ export default {
this.platform.keepTimeout = platform.keepTimeout;
this.platform.transport = platform.transport;
this.platform.characterSet = platform.characterSet;
this.platform.shareAllLiveStream = platform.shareAllLiveStream;
this.platform.catalogId = platform.catalogId;
this.platform.startOfflinePush = platform.startOfflinePush;
this.platform.catalogGroup = platform.catalogGroup;
this.platform.administrativeDivision = platform.administrativeDivision;
this.platform.treeType = platform.treeType;
this.onSubmit_text = "保存";
this.saveUrl = "/api/platform/save";
}
@ -242,32 +248,49 @@ export default {
},
onSubmit: function () {
if (this.onSubmit_text === "保存") {
this.$confirm("修改目录结构会导致关联目录与通道数据被清空", '提示', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
center: true,
type: 'warning'
}).then(() => {
this.saveForm()
}).catch(() => {
});
}else {
this.saveForm()
}
},
saveForm: function (){
var that = this;
that.$axios({
method: 'post',
url: this.saveUrl,
data: that.platform
}).then(function (res) {
if (res.data.code === 0) {
that.$message({
showClose: true,
message: "保存成功",
type: "success",
});
that.showDialog = false;
if (that.listChangeCallback != null) {
that.listChangeCallback();
}
}else {
that.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
if (res.data.code === 0) {
that.$message({
showClose: true,
message: "保存成功",
type: "success",
});
that.showDialog = false;
if (that.listChangeCallback != null) {
that.listChangeCallback();
}
}).catch(function (error) {
console.log(error);
});
}else {
that.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
}).catch(function (error) {
console.log(error);
});
},
close: function () {
this.showDialog = false;
@ -293,7 +316,7 @@ export default {
keepTimeout: 60,
transport: "UDP",
characterSet: "GB2312",
shareAllLiveStream: false,
treeType: "BusinessGroup",
startOfflinePush: false,
catalogGroup: 1,
}

View File

@ -13,6 +13,7 @@
<el-menu-item index="/cloudRecord">云端录像</el-menu-item>
<el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
<el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
<el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item>
<!-- <el-submenu index="/setting">-->
<!-- <template slot="title">系统设置</template>-->
@ -23,12 +24,12 @@
<!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
<el-submenu index="" style="float: right;">
<template slot="title">欢迎{{ this.$cookies.get("session").username }}</template>
<el-menu-item @click="changePassword">修改密码</el-menu-item>
<el-menu-item @click="loginout">注销</el-menu-item>
<el-menu-item @click="openDoc">在线文档</el-menu-item>
<el-menu-item >
<el-switch v-model="alarmNotify" inactive-text="报警信息推送" @change="alarmNotifyChannge"></el-switch>
</el-menu-item>
<el-menu-item @click="changePassword">修改密码</el-menu-item>
<el-menu-item @click="loginout">注销</el-menu-item>
</el-submenu>
</el-menu>
<changePasswordDialog ref="changePasswordDialog"></changePasswordDialog>
@ -47,9 +48,11 @@ export default {
alarmNotify: false,
sseSource: null,
activeIndex: this.$route.path,
editUser: this.$cookies.get("session").roleId==1
};
},
created() {
console.log(this.$cookies.get("session"))
if (this.$route.path.startsWith("/channelList")) {
this.activeIndex = "/deviceList"
}

View File

@ -17,6 +17,7 @@ import sip from '../components/setting/Sip.vue'
import media from '../components/setting/Media.vue'
import live from '../components/live.vue'
import deviceTree from '../components/common/DeviceTree.vue'
import userManager from '../components/UserManager.vue'
import wasmPlayer from '../components/common/jessibuca.vue'
import rtcPlayer from '../components/dialog/rtcPlayer.vue'
@ -103,6 +104,11 @@ export default new VueRouter({
name: 'map',
component: map,
},
{
path: '/userManager',
name: 'userManager',
component: userManager,
}
]
},
{