Compare commits

..

4 Commits

Author SHA1 Message Date
阿斌
a8a8e70f7c
Pre Merge pull request !41 from 阿斌/N/A 2026-01-13 09:15:47 +00:00
lin
f396f5f29e 优化设备状态查询 2026-01-13 17:15:29 +08:00
lin
bca77f79cc 优化注销判定,主动注销不再确定状态 2026-01-13 16:25:36 +08:00
lin
8c54895c47 去除过期文件,修复接口文档分组 2026-01-13 13:06:22 +08:00
13 changed files with 38 additions and 159 deletions

View File

@ -1,91 +0,0 @@
#!/bin/bash
######################################################
# Copyright 2019 Pham Ngoc Hoai
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Repo: https://github.com/tyrion9/spring-boot-startup-script
#
######### PARAM ######################################
JAVA_OPT=-Xmx1024m
JARFILE=`ls -1r *.jar 2>/dev/null | head -n 1`
PID_FILE=pid.file
RUNNING=N
PWD=`pwd`
######### DO NOT MODIFY ########
if [ -f $PID_FILE ]; then
PID=`cat $PID_FILE`
if [ ! -z "$PID" ] && kill -0 $PID 2>/dev/null; then
RUNNING=Y
fi
fi
start()
{
if [ $RUNNING == "Y" ]; then
echo "Application already started"
else
if [ -z "$JARFILE" ]
then
echo "ERROR: jar file not found"
else
nohup java $JAVA_OPT -Djava.security.egd=file:/dev/./urandom -jar $PWD/$JARFILE > nohup.out 2>&1 &
echo $! > $PID_FILE
echo "Application $JARFILE starting..."
tail -f nohup.out
fi
fi
}
stop()
{
if [ $RUNNING == "Y" ]; then
kill -9 $PID
rm -f $PID_FILE
echo "Application stopped"
else
echo "Application not running"
fi
}
restart()
{
stop
start
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
restart
;;
*)
echo "Usage: $0 { start | stop | restart }"
exit 1
;;
esac
exit 0

View File

@ -1,20 +0,0 @@
#!/bin/bash
# 获取当前日期并格式化为 YYYY-MM-DD 的形式
current_date=$(date +"%Y-%m-%d")
mkdir -p "$current_date"/数据库
cp -r ./数据库/2.7.3 "$current_date"/数据库
cp src/main/resources/配置详情.yml "$current_date"
cp src/main/resources/application-dev.yml "$current_date"/application.yml
cp ./target/wvp-pro-*.jar "$current_date"
zip -r "$current_date".zip "$current_date"
rm -rf "$current_date"
exit 0

View File

@ -213,17 +213,12 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.6</version>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-security</artifactId>
<version>1.8.0</version>
<version>2.8.5</version>
</dependency>
<dependency>

View File

@ -7,12 +7,12 @@ import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
/**
* @author lin
@ -39,7 +39,7 @@ public class SpringDocConfig {
.info(new Info().title("WVP-PRO 接口文档")
.contact(contact)
.description("开箱即用的28181协议视频平台。 <br/>" +
"1. 打开<a href='/doc.html#/1.%20全部/用户管理/login_1'>登录</a>接口" +
"1. 打开<a href='/doc.html#/1.%20全部/用户管理/login'>登录</a>接口" +
" 登录成功后返回AccessToken。 <br/>" +
"2. 填写到AccessToken到参数值 <a href='/doc.html#/Authorize/1.%20全部'>Token配置</a> <br/>" +
"后续接口就可以直接测试了")

View File

@ -26,7 +26,7 @@ public interface IDeviceService {
* 设备下线
* @param deviceId 设备编号
*/
void offline(String deviceId, String reason);
void offline(String deviceId, String reason, boolean check);
/**
* 添加目录订阅

View File

@ -274,7 +274,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
private void deviceStatusExpire(String deviceId, SipTransactionInfo transactionInfo) {
log.info("[设备状态] 到期, 编号: {}", deviceId);
offline(deviceId, "保活到期");
offline(deviceId, "保活到期", true);
}
@Override
@ -383,7 +383,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
@Override
@Transactional
public void offline(String deviceId, String reason) {
public void offline(String deviceId, String reason, boolean check) {
Device device = getDeviceByDeviceIdFromDb(deviceId);
if (device == null) {
log.warn("[设备不存在] device{}", deviceId);
@ -391,7 +391,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
}
// 主动查询设备状态, 没有HostAddress无法发送请求可能是手动添加的设备
if (device.getHostAddress() != null) {
if (check && device.getHostAddress() != null) {
Boolean deviceStatus = getDeviceStatus(device);
if (deviceStatus != null && deviceStatus) {
log.info("[设备离线] 主动探测发现设备在线,暂不处理 device{}", deviceId);
@ -471,7 +471,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
}
if (!deviceStatusTaskRunner.containsKey(device.getDeviceId())) {
log.debug("[状态丢失] 执行设备离线, 编号: {},", device.getDeviceId());
offline(device.getDeviceId(), "");
offline(device.getDeviceId(), "", true);
}
}
}
@ -1202,7 +1202,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
if ("ONLINE".equalsIgnoreCase(data.trim())) {
online(device, null);
}else {
offline(device.getDeviceId(), "设备状态查询结果:" + data.trim());
offline(device.getDeviceId(), "设备状态查询结果:" + data.trim(), true);
}
if (callback != null) {
callback.run(code, msg, data);

View File

@ -82,7 +82,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag
* @return
*/
void deviceStatusResponse(Platform parentPlatform, String channelId, String sn, String fromTag, boolean status) throws SipException, InvalidArgumentException, ParseException;
void deviceStatusResponse(Platform parentPlatform, String channelId, String sn, String fromTag, Boolean status) throws SipException, InvalidArgumentException, ParseException;
/**
* 向上级回复移动位置订阅消息

View File

@ -329,22 +329,29 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public void deviceStatusResponse(Platform parentPlatform, String channelId, String sn, String fromTag, boolean status) throws SipException, InvalidArgumentException, ParseException {
public void deviceStatusResponse(Platform parentPlatform, String channelId, String sn, String fromTag, Boolean status) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return ;
}
String statusStr = (status)?"ONLINE":"OFFLINE";
String statusStr = null;
if (status != null) {
statusStr = (status)?"ONLINE":"OFFLINE";
}
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Response>\r\n")
.append("<CmdType>DeviceStatus</CmdType>\r\n")
.append("<SN>" +sn + "</SN>\r\n")
.append("<DeviceID>" + channelId + "</DeviceID>\r\n")
.append("<Result>OK</Result>\r\n")
.append("<Online>"+statusStr+"</Online>\r\n")
.append("<Status>OK</Status>\r\n")
.append("</Response>\r\n");
.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
if (statusStr == null) {
deviceStatusXml.append("<Result>ERROR</Result>\r\n");
}else {
deviceStatusXml.append("<Result>OK</Result>\r\n")
.append("<Online>"+statusStr+"</Online>\r\n")
.append("<Status>OK</Status>\r\n");
}
deviceStatusXml.append("</Response>\r\n");
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());

View File

@ -117,7 +117,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
device.setRegisterTime(DateUtil.getNow());
deviceService.online(device, null);
} else {
deviceService.offline(deviceId, "主动注销");
deviceService.offline(deviceId, "主动注销", false);
}
return;
}else {
@ -228,7 +228,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
deviceService.online(device, sipTransactionInfo);
} else {
log.info("[注销成功] deviceId: {}->{}", deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
deviceService.offline(deviceId, "主动注销", false);
}
} catch (SipException | NoSuchAlgorithmException | ParseException e) {
log.error("未处理的异常 ", e);

View File

@ -86,14 +86,14 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} else if (CmdType.CATALOG.equals(cmd)) {
processNotifyCatalogList(request, rootElement);
} else {
log.info("接收到消息:" + cmd);
log.info("接收到消息:{}", cmd);
Response response = getMessageFactory().createResponse(200, request);
if (response != null) {
ExpiresHeader expireHeader = getHeaderFactory().createExpiresHeader(30);
response.setExpires(expireHeader);
}
log.info("response : " + response);
log.info("response : {}", response);
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
}
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
@ -126,9 +126,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
.append("<DeviceID>").append(deviceId).append("</DeviceID>\r\n")
.append("<Result>OK</Result>\r\n")
.append("</Response>\r\n");
try {
int expires = request.getExpires().getExpires();
SIPResponse response = responseXmlAck(request, resultXml.toString(), platform, expires);

View File

@ -73,7 +73,13 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
}
CommonGBChannel channel= channelService.queryOneWithPlatform(platform.getId(), channelId);
if (channel ==null){
log.error("[平台没有该通道的使用权限]:platformId"+platform.getServerGBId()+" deviceID:"+channelId);
log.error("[平台没有该通道的使用权限]:platformId: {} deviceID:{}", platform.getServerGBId(), channelId);
// 上级平台查询本平台状态
try {
cmderFroPlatform.deviceStatusResponse(platform, channelId, sn, fromHeader.getTag(), null);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
}
return;
}
try {

15
zlm.md
View File

@ -1,15 +0,0 @@
1. 增加接口用来返回hook调用耗时。
参数: sn
返回值: hook耗时
功能: zlm收到调用后立即调用心跳hookhook中携带sn信息 zlm收到hook返回后计算此次hook的耗时然后返回耗时
用途: 1. 可以用来检测hook配置是否正常
2. 检测wvp与zlm连接的健康程度
2. 增加接口查询loadMP4File的录像播放位置
参数: app steam
返回: 当前播放的hook位置
功能: zlm收到请求后查询流的seek位置并返回
用途: 1. 获取当前播放位置,可以在页面同步显示时间
2. 用来时快进五秒 快退五秒类似的操作
3. loadMP4File扩展 增加默认seek值和默认倍速开始时直接从这个位置开始并使用指定的倍速
4. 支持下载指定取件的mp4文件这个区间可能包括多个文件和文件的一部分。
5. 希望seek接口和倍速接口可以去除schema的必选作为可选项不传则默认全部