Compare commits

...

5 Commits

Author SHA1 Message Date
阿斌
c0bf55adfd
Pre Merge pull request !36 from 阿斌/N/A 2026-05-19 15:36:00 +00:00
lin
ce81a0724f 国标录像回放支持切换播放器 2026-05-19 10:59:40 +08:00
lin
459a8cd77a 部标-修复0003注销消息处理 2026-05-18 10:39:41 +08:00
lin
75575f939c 部标-完善位置日志打印 2026-05-18 09:28:55 +08:00
阿斌
da98101aac
update src/main/resources/civilCode.csv.
行政规划错误。江苏南通海门市,修改为海门区,浙江杭州删除下城区、江干区,新增钱塘区,临平区

Signed-off-by: 阿斌 <38912748@qq.com>
2024-12-15 08:58:42 +00:00
10 changed files with 119 additions and 43 deletions

View File

@ -12,17 +12,12 @@ import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author QingtaiJiang
@ -93,6 +88,8 @@ public class Jt808Decoder extends ByteToMessageDecoder {
}
/**
* 转义与验证校验码
*

View File

@ -1,13 +1,13 @@
package com.genersoft.iot.vmp.jt1078.proc.request;
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
import com.genersoft.iot.vmp.jt1078.bean.JTDevice;
import com.genersoft.iot.vmp.jt1078.event.DeviceUpdateEvent;
import com.genersoft.iot.vmp.jt1078.proc.Header;
import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
import com.genersoft.iot.vmp.jt1078.session.Session;
import com.genersoft.iot.vmp.jt1078.session.SessionManager;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
@ -20,27 +20,30 @@ import org.springframework.context.ApplicationEvent;
@MsgId(id = "0003")
public class J0003 extends Re {
int respNo;
String respId;
int result;
private JTDevice deviceForUpdate;
@Override
protected Rs decode0(ByteBuf buf, Header header, Session session) {
respNo = buf.readUnsignedShort();
respId = ByteBufUtil.hexDump(buf.readSlice(2));
result = buf.readUnsignedByte();
log.info("[JT-注销] 设备: {}", header.getPhoneNumber());
return null;
}
@Override
protected Rs handler(Header header, Session session, Ijt1078Service service) {
SessionManager.INSTANCE.response(header.getPhoneNumber(), "0001", (long) respNo, result);
// SessionManager.INSTANCE.response(header.getPhoneNumber(), "0001", (long) respNo, result);
JTDevice device = service.getDevice(header.getPhoneNumber());
if (device != null && device.isStatus()) {
deviceForUpdate = device;
deviceForUpdate.setStatus(false);
service.updateDevice(device);
}
return null;
}
@Override
public ApplicationEvent getEvent() {
return null;
DeviceUpdateEvent registerEvent = new DeviceUpdateEvent(this);
registerEvent.setDevice(deviceForUpdate);
return registerEvent;
}
}

View File

@ -25,7 +25,9 @@ public class J0200 extends Re {
@Override
protected Rs decode0(ByteBuf buf, Header header, Session session) {
positionInfo = JTPositionBaseInfo.decode(buf);
if (log.isDebugEnabled()) {
log.debug("[JT-位置汇报]: phoneNumber={} {}", header.getPhoneNumber(), positionInfo.toSimpleString());
}
// 读取附加信息
// JTPositionAdditionalInfo positionAdditionalInfo = new JTPositionAdditionalInfo();
// Map<Integer, byte[]> additionalMsg = new HashMap<>();

View File

@ -861,7 +861,7 @@
320623,如东县,3206
320681,启东市,3206
320682,如皋市,3206
320684,海门,3206
320684,海门,3206
320685,海安市,3206
3207,连云港市,32
320703,连云区,3207
@ -918,8 +918,6 @@
33,浙江省,
3301,杭州市,33
330102,上城区,3301
330103,下城区,3301
330104,江干区,3301
330105,拱墅区,3301
330106,西湖区,3301
330108,滨江区,3301
@ -927,6 +925,8 @@
330110,余杭区,3301
330111,富阳区,3301
330112,临安区,3301
330113,临平区,3301
330114,钱塘区,3301
330122,桐庐县,3301
330127,淳安县,3301
330182,建德市,3301

1 编号 名称 上级
861 320623 如东县 3206
862 320681 启东市 3206
863 320682 如皋市 3206
864 320684 海门市 海门区 3206
865 320685 海安市 3206
866 3207 连云港市 32
867 320703 连云区 3207
918 33 浙江省
919 3301 杭州市 33
920 330102 上城区 3301
330103 下城区 3301
330104 江干区 3301
921 330105 拱墅区 3301
922 330106 西湖区 3301
923 330108 滨江区 3301
925 330110 余杭区 3301
926 330111 富阳区 3301
927 330112 临安区 3301
928 330113 临平区 3301
929 330114 钱塘区 3301
930 330122 桐庐县 3301
931 330127 淳安县 3301
932 330182 建德市 3301

View File

@ -5,6 +5,10 @@
spring:
spring:
threads:
virtual:
enabled: true
cache:
type: redis
thymeleaf:
@ -181,9 +185,6 @@ media:
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载 0 表示不使用
record-assist-port: 0
# [可选] 日志配置, 如果不需要在jar外修改日志内容那么可以不配置此项
logging:
config: classpath:logback-spring.xml
# [根据业务需求配置]
user-settings:
@ -281,3 +282,12 @@ springdoc:
enabled: false
swagger-ui:
enabled: false
logging:
level:
# 日志级别 debug/info/warn/error
root: info
logback:
rollingpolicy:
# 日志文件最大历史保留天数默认30天
max-history: 30

View File

@ -5,7 +5,7 @@
@dblclick="fullscreenSwich"
>
<div style="width:100%; padding-top: 56.25%; position: relative;" />
<div id="buttonsBox" class="buttons-box" >
<div id="buttonsBox" class="buttons-box" v-if="showButton">
<div class="buttons-box-left">
<i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick" />
<i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause" />

View File

@ -1,6 +1,6 @@
<template>
<div id="rtcPlayer">
<video id="webRtcPlayerBox" controls autoplay style="text-align:left;">
<video id="webRtcPlayerBox" :controls="showControls" autoplay style="text-align:left;">
Your browser is too old which doesn't support HTML5 video.
</video>
</div>
@ -10,7 +10,12 @@
let webrtcPlayer = null
export default {
name: 'RtcPlayer',
props: ['videoUrl', 'error', 'hasaudio'],
props: {
videoUrl: { type: String, default: '' },
error: { type: String, default: '' },
hasaudio: { type: Boolean, default: false },
showControls: { type: Boolean, default: true }
},
data() {
return {
timer: null
@ -97,10 +102,12 @@ export default {
}
#rtcPlayer{
width: 100%;
height: 100%;
}
#webRtcPlayerBox{
width: 100%;
max-height: 56vh;
height: 100%;
max-height: 100%;
background-color: #000;
}
/* 隐藏logo */

View File

@ -49,8 +49,8 @@
</div>
</div>
</div>
<div id="playerBox" style="width: 100%">
<div class="playBox" style="height: calc(100% - 90px); width: 100%; background-color: #000000">
<div id="playerBox" style="width: 100%;">
<div class="playBox" style="height: calc(100vh - 220px); width: 100%; background-color: #000000">
<div
v-if="playLoading"
style="position: relative; left: calc(50% - 32px); top: 43%; z-index: 100;color: #fff;float: left; text-align: center;"
@ -58,10 +58,32 @@
<div class="el-icon-loading" />
<div style="width: 100%; line-height: 2rem">正在加载</div>
</div>
<h265web
<jessibucaPlayer
v-if="activePlayer === 'jessibuca'"
ref="recordVideoPlayer"
:has-audio="true"
:height="'calc(100vh - 90px)'"
:show-button="false"
autoplay
@playStatusChange="playingChange"
@playTimeChange="showPlayTimeChange"
/>
<rtcPlayer
v-if="activePlayer === 'webRTC'"
ref="recordVideoPlayer"
:video-url="videoUrl"
:height="'calc(100vh - 250px)'"
:has-audio="true"
:show-controls="false"
style="height: calc(100vh - 220px)"
autoplay
@playStatusChange="playingChange"
@playTimeChange="showPlayTimeChange"
/>
<h265web
v-if="activePlayer === 'h265web'"
ref="recordVideoPlayer"
:video-url="videoUrl"
:height="'calc(100vh - 220px)'"
:show-button="false"
:has-audio="true"
@playStatusChange="playingChange"
@ -181,6 +203,18 @@
</div>
<div style="text-align: right;">
<div class="record-play-control" style="background-color: transparent; box-shadow: 0 0 10px transparent">
<el-dropdown @command="changePlayer">
<a
target="_blank"
class="record-play-control-item record-play-control-speed"
title="切换播放器"
>{{ playerLabel }}</a>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="jessibuca">Jessibuca</el-dropdown-item>
<el-dropdown-item command="webRTC">WebRTC</el-dropdown-item>
<el-dropdown-item command="h265web">H265Web</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<a
v-if="!isFullScreen"
target="_blank"
@ -208,6 +242,8 @@
<script>
import h265web from '../../common/h265web.vue'
import jessibucaPlayer from '../../common/jessibuca.vue'
import rtcPlayer from '../../common/rtcPlayer.vue'
import VideoTimeline from '../../common/VideoTimeLine/index.vue'
import recordDownload from '../../dialog/recordDownload.vue'
import ChooseTimeRange from '../../dialog/chooseTimeRange.vue'
@ -217,7 +253,7 @@ import screenfull from 'screenfull'
export default {
name: 'DeviceRecord',
components: {
h265web, VideoTimeline, recordDownload, ChooseTimeRange
h265web, jessibucaPlayer, rtcPlayer, VideoTimeline, recordDownload, ChooseTimeRange
},
data() {
return {
@ -251,6 +287,12 @@ export default {
timelineControl: false,
showOtherSpeed: true,
timeSegments: [],
activePlayer: 'jessibuca',
playerUrls: {
jessibuca: ['ws_flv', 'wss_flv'],
webRTC: ['rtc', 'rtcs'],
h265web: ['ws_flv', 'wss_flv']
},
pickerOptions: {
cellClassName: (date) => {
//
@ -266,6 +308,10 @@ export default {
}
},
computed: {
playerLabel() {
const labels = { jessibuca: 'Jessibuca', webRTC: 'WebRTC', h265web: 'H265Web' }
return labels[this.activePlayer] || 'Jessibuca'
},
boxStyle() {
if (this.showSidebar) {
return {
@ -300,6 +346,18 @@ export default {
window.removeEventListener('beforeunload', this.stopPlayRecord)
},
methods: {
changePlayer(player) {
if (this.activePlayer === player) return
this.activePlayer = player
if (this.streamInfo) {
this.videoUrl = this.getUrlByStreamInfo()
this.$nextTick(() => {
if (this.$refs.recordVideoPlayer) {
this.$refs.recordVideoPlayer.play(this.videoUrl)
}
})
}
},
sidebarControl() {
this.showSidebar = !this.showSidebar
},
@ -468,14 +526,20 @@ export default {
this.streamInfo = data
this.videoUrl = this.getUrlByStreamInfo()
this.hasAudio = this.streamInfo.tracks && this.streamInfo.tracks.length > 1
this.$nextTick(() => {
if (this.$refs.recordVideoPlayer) {
this.$refs.recordVideoPlayer.play(this.videoUrl)
}
})
})
}
},
getUrlByStreamInfo() {
const keys = this.playerUrls[this.activePlayer]
if (location.protocol === 'https:') {
this.videoUrl = this.streamInfo['wss_flv']
this.videoUrl = this.streamInfo[keys[1]]
} else {
this.videoUrl = this.streamInfo['ws_flv']
this.videoUrl = this.streamInfo[keys[0]]
}
return this.videoUrl
},

View File

@ -1,4 +1,3 @@
drop table IF EXISTS wvp_jt_terminal;
create table IF NOT EXISTS wvp_jt_terminal (
id serial primary key,
phone_number character varying(50),
@ -23,7 +22,6 @@ create table IF NOT EXISTS wvp_jt_terminal (
constraint uk_jt_device_id_device_id unique (id, phone_number)
);
drop table IF EXISTS wvp_jt_channel;
create table IF NOT EXISTS wvp_jt_channel (
id serial primary key,
terminal_db_id integer,
@ -141,8 +139,6 @@ call wvp_202601025();
DROP PROCEDURE wvp_202601025;
DELIMITER ;
drop table IF EXISTS wvp_alarm;
create table IF NOT EXISTS wvp_alarm (
id serial primary key COMMENT '主键ID',
channel_id integer COMMENT '关联通道的数据库id',

View File

@ -1,4 +1,3 @@
drop table IF EXISTS wvp_jt_terminal;
create table IF NOT EXISTS wvp_jt_terminal (
id serial primary key,
phone_number character varying(50),
@ -22,7 +21,6 @@ create table IF NOT EXISTS wvp_jt_terminal (
sdp_ip character varying(50),
constraint uk_jt_device_id_device_id unique (id, phone_number)
);
drop table IF EXISTS wvp_jt_channel;
create table IF NOT EXISTS wvp_jt_channel (
id serial primary key,
terminal_db_id integer,
@ -48,7 +46,6 @@ drop index uk_media_server_unique_ip_http_port on wvp_media_server;
ALTER table wvp_device DROP COLUMN IF EXISTS register_time;
ALTER table wvp_device DROP COLUMN IF EXISTS keepalive_time;
drop table IF EXISTS wvp_alarm;
create table IF NOT EXISTS wvp_alarm (
id serial primary key,
channel_id integer,