Compare commits

...

307 Commits

Author SHA1 Message Date
lin
5c25385d29 更新README 2025-08-07 16:35:09 +08:00
lin
1da487f02a [1078] 优化鉴权码位置,支持1078国标级联 2025-08-06 15:17:44 +08:00
lin
e555df52d3 [1078] 通用通道支持位置更新 2025-08-06 06:38:37 +08:00
lin
c90836261a [1078] 增加状态变化通知和位置事件 2025-08-05 18:05:18 +08:00
lin
d7f5e7d771 [1078] 通用通道录像回放支持 2025-08-03 17:20:24 +08:00
lin
0a19ce4f34 [1078] 临时提交 2025-08-01 19:45:40 +08:00
lin
efbd302260 Merge branch 'master' into 重构/1078 2025-08-01 19:00:13 +08:00
lin
e272d25939 [1078] 适配新结构接入通用通道支持云台控制 2025-08-01 14:39:33 +08:00
lin
2ee9a3fa71 [1078] 适配新结构接入通用通道 2025-07-31 21:21:31 +08:00
lin
333965255f Merge branch 'master' into 重构/1078
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/common/enums/ChannelDataType.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/service/IGbChannelPlayService.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/GbChannelPlayServiceImpl.java
2025-07-31 21:14:23 +08:00
lin
61a761e288 [1078] 修改颜色 2025-07-30 18:02:29 +08:00
lin
f3bd58acfe [1078] FTP使用随机用户和密码 2025-07-29 19:34:33 +08:00
lin
9e880786b3 [1078] 去除ftp配置中的ip配置 从连接中获取 2025-07-29 18:40:03 +08:00
lin
0ed395ff2e [1078] 支持通用通道的点播 2025-07-29 14:46:16 +08:00
lin
4c97022c78 [1078] 支持语音对讲 中心广播模式 2025-07-28 17:50:03 +08:00
lin
4fb04776f2 [1078] 代码整理 2025-07-28 14:32:38 +08:00
lin
e9eeeeefd7 Merge branch 'master' into 重构/1078 2025-07-28 08:47:30 +08:00
lin
a79429115f [1078] 增加功能入口 2025-07-25 18:05:22 +08:00
lin
34fb79093e [1078] 完善立即拍摄的结果查询和下载 2025-07-25 17:49:22 +08:00
lin
43ef080f55 [1078] 增加立即拍摄 2025-07-25 15:37:03 +08:00
lin
ee52b43c99 [1078] 增加多媒体文件检索 2025-07-23 23:30:48 +08:00
lin
4cc399ce39 [1078] 增加设置电话本 2025-07-23 20:58:23 +08:00
lin
a69e3d5dde [1078] 增加音视频属性查询 2025-07-22 20:56:32 +08:00
lin
c0ab010475 [1078] 增加音视频属性查询 2025-07-22 20:51:03 +08:00
lin
79ee116174 [1078] 优化netty bytebuf释放 2025-07-22 10:02:32 +08:00
lin
045c14da0d [1078] 完善终端参数 2025-07-22 06:50:55 +08:00
lin
0c78a9460b [1078] 完善终端参数 2025-07-22 06:47:28 +08:00
lin
6e5cadd32b [1078] 去除多余选项 2025-07-22 06:14:30 +08:00
lin
fb150da97a [1078] 完善终端参数 2025-07-22 06:05:20 +08:00
lin
a4e20f0f50 [1078] 优化终端参数查询和设置 2025-07-21 18:01:44 +08:00
lin
9388c279e7 [1078] 补充终端参数 2025-07-21 17:48:02 +08:00
lin
03b5c0241f [1078] 优化终端参数查询和设置 2025-07-21 10:35:30 +08:00
lin
a60eb082fe [1078] 临时提交 2025-07-20 23:05:49 +08:00
lin
9d0678f765 [1078] 修复终端参数保存 2025-07-20 22:56:33 +08:00
lin
9b0d091e4e [1078] 优化终端参数查询和设置 2025-07-18 17:34:01 +08:00
lin
ebd95250c0 [1078] 增加车辆控制 2025-07-17 15:53:35 +08:00
lin
47e4f2343b [1078] 增加连接到指定服务器 2025-07-17 15:12:23 +08:00
lin
f7b35e8e14 [1078] 增加恢复出厂和终端复位 2025-07-17 13:03:23 +08:00
lin
8b17e97682 [1078] 增加驾驶员信息 2025-07-17 12:56:07 +08:00
lin
e730bf2d15 [1078] 修复mediaServer入库错误 2025-07-17 07:03:11 +08:00
lin
ca07935232 [1078] 增加电话回拨 2025-07-16 21:57:26 +08:00
lin
56b70d335a [1078] 增加文本下发 2025-07-16 18:23:34 +08:00
lin
29802ccded [1078] 增加文本下发 2025-07-16 18:22:33 +08:00
lin
3f2089f584 [1078] 增加位置信息展示 2025-07-16 16:02:07 +08:00
lin
45af124eb0 [1078] 支持终端属性和链路检测的UI 2025-07-16 11:00:43 +08:00
lin
5874d4d1fa [1078] 修复webrtc地址 2025-07-15 18:37:53 +08:00
lin
d40bc5a034 [1078] 设备列表增加搜索和状态筛选 2025-07-15 18:21:11 +08:00
lin
44ed06bcbe [1078] 支持无人观看自动停流 2025-07-15 18:11:23 +08:00
lin
be04660de8 [1078] 修复分包合并,优化设备列表排序,优化设备上线逻辑 2025-07-15 16:30:34 +08:00
lin
e28141da6e [1078] 临时提交 2025-07-14 18:06:18 +08:00
lin
04bcb6dcb8 [1078] 优化多媒体数据上传处理 2025-07-14 11:03:45 +08:00
lin
9d47fe30f5 [1078] 增加单条存储多媒体数据上传 2025-07-11 22:07:32 +08:00
lin
cefc87ad47 [1078] 完善抓图 2025-07-11 21:41:50 +08:00
lin
8c3e9320fa [1078] 增加抓图 2025-07-11 20:15:45 +08:00
lin
b7a2b6816b [1078] 完善录像下载 2025-07-10 18:48:25 +08:00
lin
1655e5903b [1078] 完善录像回放 2025-07-09 16:44:54 +08:00
lin
055bbc2dca [1078] 修复回放结束发送失败 2025-07-09 16:37:33 +08:00
lin
3c6b715ce1 [1078] 临时提交 2025-07-09 16:16:04 +08:00
lin
48eff320fd [1078] 适配abl的播放1078 2025-07-09 12:32:31 +08:00
lin
17c967ed4e [1078] 修复标签显示错误 2025-07-07 17:42:08 +08:00
lin
fae839af05 [1078] 兼容2013版本的设备属性查询和注册鉴权 2025-07-07 17:23:12 +08:00
lin
93c24a74e6 Merge branch 'master' into 重构/1078 2025-07-07 11:46:13 +08:00
lin
a424f270e8 [1078] 兼容abl流媒体 2025-07-03 17:30:59 +08:00
lin
1bfb51c90e Merge branch 'dev/abl支持' into 重构/1078
# Conflicts:
#	src/main/resources/application.yml
2025-07-03 15:29:13 +08:00
lin
5bcdf5dfb6 [abl] 合并主线 2025-07-03 15:28:47 +08:00
lin
bab5534134 Merge branch 'master' into dev/abl支持
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
#	src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java
#	src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java
#	src/main/java/com/genersoft/iot/vmp/media/bean/RecordInfo.java
#	src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java
#	src/main/resources/application.yml
2025-07-03 14:58:24 +08:00
lin
537d86ca89 [1078] 合并主线 2025-07-03 14:54:29 +08:00
lin
465e03d15d Merge branch 'master' into 重构/1078
# Conflicts:
#	web/src/router/index.js
#	web/src/views/common/channelPlayer/chooseChannelForJt.vue
#	web/src/views/common/channelPlayer/jtDeviceEdit.vue
#	web/src/views/common/channelPlayer/jtDevicePlayer.vue
#	web_src/src/layout/UiHeader.vue
#	web_src/src/main.js
#	web_src/src/router/index.js
2025-07-03 09:41:55 +08:00
lin
d15307533a Merge branch 'master' into 重构/1078
# Conflicts:
#	src/main/resources/application.yml
2025-06-03 17:21:21 +08:00
lin
1420fcfcd0 Merge branch 'master' into 重构/1078
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCode.java
#	src/main/resources/application.yml
2025-05-29 17:10:32 +08:00
lin
0c29c90d3b Merge branch 'master' into 重构/1078 2025-05-26 15:07:58 +08:00
lin
420b3889c5 [1078] 合并新UI 2025-05-16 15:17:35 +08:00
lin
7c5cee5d87 Merge branch 'refs/heads/master' into dev/1078-newUI 2025-05-16 11:03:40 +08:00
lin
27d7f3cc6e Merge branch 'master' into dev/1078-newUI 2025-05-16 08:50:26 +08:00
lin
592c1c2b71 [1078] 合并新UI 2025-05-15 18:32:03 +08:00
lin
5b89145337 增加接入信息展示 2025-05-15 10:28:02 +08:00
lin
6a2ecd937d Merge branch 'refs/heads/master' into dev/1078-newUI 2025-05-15 10:25:07 +08:00
lin
98e6cfcc4c Merge branch 'master' into dev/1078-newUI 2025-05-15 10:00:40 +08:00
lin
081a146f2a [1078] 合并新UI 2025-05-14 18:01:12 +08:00
648540858
68f7d3ef74 [1078] 适配新UI 2025-05-14 15:48:35 +08:00
648540858
1a7f517c5a Merge branch 'refs/heads/master' into dev/1078-newUI 2025-05-13 21:22:01 +08:00
lin
e4a0a37f0b [1078] 合并新UI 2025-05-12 18:01:10 +08:00
648540858
c4ab55a456 [部标1078] 适配新UI 2025-05-11 08:01:45 +08:00
648540858
10c75036f5 Merge branch 'master' into dev/1078-newUI 2025-05-11 07:00:10 +08:00
648540858
3b7ba3eb46 Merge branch 'master' into dev/1078-newUI
# Conflicts:
#	src/main/resources/application.yml
2025-05-10 08:59:45 +08:00
648540858
e754d0d804 [1078] 去除测试程序中的调用错误 2025-04-24 22:39:15 +08:00
lin
e284c3857c Merge branch 'master' into 重构/1078 2025-04-09 12:17:22 +08:00
lin
f0eb101130 [1078] 适配新的数据库结构 2025-03-24 17:53:43 +08:00
lin
fd5079a652 Merge branch 'refs/heads/master' into 重构/1078 2025-03-24 17:28:43 +08:00
lin
20135726eb Merge branch 'master' into 重构/1078 2025-03-24 15:19:07 +08:00
lin
242062bda3 [1078] 合并主线 2025-03-18 16:35:40 +08:00
lin
0329c8f5d1 Merge remote-tracking branch 'origin/master' into 重构/1078
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/dao/CommonGBChannelMapper.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/dao/PlatformChannelMapper.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/dao/provider/ChannelProvider.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java
#	数据库/2.7.3/初始化-mysql-2.7.3.sql
#	数据库/2.7.3/初始化-postgresql-kingbase-2.7.3.sql
2025-03-18 15:30:35 +08:00
648540858
51f126e571 Merge branch 'master' into 重构/1078
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
#	数据库/2.7.3/初始化-mysql-2.7.3.sql
#	数据库/2.7.3/初始化-postgresql-kingbase-2.7.3.sql
2024-12-19 23:19:09 +08:00
648540858
4e48eb6cab 修复添加通道时未设置设备ID 2024-12-09 14:41:14 +08:00
648540858
1323d081e8 Merge remote-tracking branch 'origin/重构/1078' into 重构/1078 2024-12-05 11:06:06 +08:00
648540858
f528735119 Merge branch 'master' into 重构/1078 2024-12-05 11:05:44 +08:00
648540858
d3d7ea8fbb 合并主线通道编辑样式 2024-11-15 23:14:37 +08:00
648540858
991dd0ea41 合并主线云台控制页面样式 2024-11-15 22:31:06 +08:00
648540858
1dfbb875b2 Merge branch 'master' into 重构/1078 2024-11-15 21:45:40 +08:00
648540858
a4ca333abb 合并主线 2024-11-10 22:09:13 +08:00
648540858
e5fd66ef96 Merge branch 'master' into 重构/1078
# Conflicts:
#	pom.xml
#	src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
2024-11-10 15:29:53 +08:00
648540858
556f0ebf2f 临时提交 2024-10-29 22:11:46 +08:00
648540858
13b896ce23 修复启动异常 2024-10-21 06:57:53 +08:00
648540858
f62b655602 合并主线 2024-10-19 19:59:14 +08:00
648540858
46fa390387 临时提交 2024-10-19 00:04:32 +08:00
648540858
277f2db137 Merge branch 'master' into 重构/1078
# Conflicts:
#	pom.xml
#	src/main/java/com/genersoft/iot/vmp/gb28181/bean/CommonGBChannel.java
#	src/main/java/com/genersoft/iot/vmp/jt1078/codec/decode/Jt808Decoder.java
#	src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/Jt808Handler.java
#	src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/TcpServer.java
#	src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/Re.java
#	src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java
#	src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java
#	src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/utils/CivilCodeUtil.java
#	src/main/resources/application.yml
#	web_src/src/layout/UiHeader.vue
#	web_src/src/router/index.js
2024-10-18 13:55:23 +08:00
panlinlin
601daa1092 1078-移除暂未实现的按钮 2024-06-27 22:05:31 +08:00
panlinlin
03497c55f0 Merge branch 'refs/heads/master' into 1078
# Conflicts:
#	src/main/resources/application.yml
2024-06-27 21:52:59 +08:00
panlinlin
a5b48e5b19 1078-添加国标级联中管理部标通道 2024-06-23 08:21:24 +08:00
panlinlin
b22e894e94 1078-通道信息增加数据库ID 2024-06-21 21:46:55 +08:00
panlinlin
282e0db96e 1078-调整通道信息 2024-06-21 21:30:15 +08:00
panlinlin
5db39a2265 1078-完善接入国标通道页面以及属性 2024-06-20 06:21:20 +08:00
panlinlin
edeea61318 1078-完善接入国标通道页面以及属性 2024-06-19 00:02:08 +08:00
panlinlin
a94b18bde9 1078-添加接入国标通道页面以及属性 2024-06-18 20:42:09 +08:00
648540858
5846a4ed5b 丰富表单内容 2024-06-18 12:50:54 +08:00
panlinlin
358799a391 1078-添加接入国标通道页面以及属性 2024-06-18 05:55:42 +08:00
panlinlin
4ba04661ab 1078-添加接入国标通道表 2024-06-16 09:14:35 +08:00
panlinlin
36e15c80b0 1078-增加位置信息并发处理能力 2024-06-16 06:41:57 +08:00
648540858
449b215367 Merge branch 'refs/heads/master' into dev/abl支持 2024-06-14 09:47:27 +08:00
panlinlin
b034faad62 Merge branch 'refs/heads/master' into dev/abl支持 2024-06-14 00:04:04 +08:00
panlinlin
261945ca62 Merge branch 'refs/heads/master' into dev/abl支持
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
2024-06-13 23:41:29 +08:00
648540858
ff975b47ba Merge branch 'refs/heads/master' into dev/abl支持 2024-06-13 18:13:54 +08:00
648540858
93532a6b3b Merge remote-tracking branch 'origin/1078' into 1078 2024-06-12 12:49:58 +08:00
648540858
e0adc7306b Merge branch 'refs/heads/master' into 1078 2024-06-12 12:49:47 +08:00
panlinlin
291a87e1f7 1078-支持自动点播 2024-06-12 00:22:16 +08:00
panlinlin
46bf5b7a39 1078-支持无人观看自动停流 2024-06-11 23:49:55 +08:00
panlinlin
824690a37f 1078-终端参数回显 2024-06-10 15:20:48 +08:00
panlinlin
3410fae879 1078-添加终端参数的前端UI 2024-06-10 08:30:22 +08:00
panlinlin
c0dea69839 1078-添加接口的前端UI 2024-06-10 00:48:18 +08:00
panlinlin
f564ff0aba 1078-支持设备录像FTP方式下载 2024-06-10 00:33:55 +08:00
panlinlin
a030c15c8f 1078-支持设备录像播放以及播放控制 2024-06-09 22:09:04 +08:00
panlinlin
4b90298c99 1078-支持设备录像检索播放 2024-06-09 20:50:59 +08:00
panlinlin
b4dddb0b08 1078-支持云台控制 2024-06-08 23:55:06 +08:00
panlinlin
9c2c4a92b1 1078-支持编辑通道 2024-06-08 23:11:56 +08:00
panlinlin
18cfba612b 1078-支持快照的展示 2024-06-08 22:58:23 +08:00
panlinlin
6074638f5b 1078-支持控制是否要音频 2024-06-08 22:47:25 +08:00
panlinlin
dbb2492640 1078-修复断开连接时设备未下线的BUG 2024-06-08 21:54:58 +08:00
panlinlin
7ffe773175 1078-调整数据库建表语句 2024-06-08 21:17:37 +08:00
648540858
942a41c630 1078-增加流地址标识 2024-06-08 00:56:05 +08:00
648540858
595d9be283 1078-优化点播以及通道表结构 2024-06-08 00:46:08 +08:00
648540858
6ae623d639 1078-临时提交 2024-06-07 14:35:07 +08:00
648540858
0103d5819b 1078-调整页面 2024-06-07 14:03:41 +08:00
648540858
972ef30f8d 1078-部标通道添加音频控制 2024-06-07 07:21:40 +08:00
648540858
913d358a11 1078-部标通道添加音频控制 2024-06-07 00:20:52 +08:00
648540858
5d5d654410 1078-添加部标通道页面 2024-06-07 00:10:36 +08:00
648540858
f7d811a299 1078-调整业务信息 2024-06-06 07:26:20 +08:00
648540858
5c826ef449 1078-添加通道信息 2024-06-06 00:23:16 +08:00
648540858
0de2bb54cd 1078-完成录像文件下载 2024-06-04 23:59:08 +08:00
648540858
83875a5905 1078-修复ftp-server对文件上传的通知 2024-06-04 07:15:05 +08:00
648540858
3728219177 1078-添加录像上传 2024-06-02 00:50:45 +08:00
648540858
62ae1ee978 调整录像下载 2024-05-31 22:54:08 +08:00
648540858
e8d832d0a5 1078-添加ftpserver 2024-05-30 23:41:22 +08:00
648540858
89101b2731 1078-增加ftp-server 2024-05-30 18:36:24 +08:00
648540858
56fdbd34f4 1078-优化回放流地址格式 2024-05-30 11:34:18 +08:00
648540858
6efff9daf9 1078-优化回放 2024-05-30 10:29:14 +08:00
648540858
74c98c8636 1078-录像回放控制 2024-05-29 23:53:20 +08:00
648540858
15a551d983 1078-标记待实现 9105 2024-05-29 18:40:31 +08:00
648540858
2b1645729b 1078-切换码流类型 2024-05-29 18:36:19 +08:00
648540858
84ef932964 1078-修复双向对讲 2024-05-29 18:27:10 +08:00
648540858
2aef6ab6f1 1078-支持语音广播 2024-05-29 17:34:38 +08:00
648540858
de6a3ceb76 1078-双向对讲完成 2024-05-29 17:26:28 +08:00
648540858
87ecf68332 1078-双向对讲 2024-05-29 16:55:07 +08:00
648540858
01fbf102c2 Merge branch 'refs/heads/master' into 1078 2024-05-29 15:03:20 +08:00
648540858
3e9def7aac 支持abl录像下载 2024-05-29 10:52:28 +08:00
648540858
a945078788 1078-语音对讲 2024-05-29 00:02:31 +08:00
648540858
9ece77d54a 1078-点播添加类型 2024-05-28 18:58:16 +08:00
648540858
37b79633f0 Merge branch 'refs/heads/master' into 1078 2024-05-28 18:40:44 +08:00
648540858
98c62b93f7 支持abl录像下载中 2024-05-28 17:39:14 +08:00
648540858
bae9b2571a Merge branch 'refs/heads/master' into dev/abl支持
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
2024-05-28 16:07:41 +08:00
648540858
2c0c576d93 临时提交 2024-05-28 15:55:26 +08:00
648540858
5011a6b74a 去除多余依赖 2024-05-28 11:03:15 +08:00
648540858
271bb19c99 Merge branch 'refs/heads/master' into dev/abl支持 2024-05-28 11:02:05 +08:00
648540858
adfce4464d 1078-终端上传乘客流量 2024-05-27 23:55:44 +08:00
648540858
c8ddee905f 1078-补充终端音视频参数设置 + 查询终端音视频属性 2024-05-27 23:29:59 +08:00
648540858
8be6979911 1078-图像分析报警参数设置 2024-05-24 00:15:52 +08:00
648540858
1e9cdfe87f 1078-单独视频通道参数设置+特殊报警录像参数设置+视频相关报警屏蔽字 2024-05-22 21:24:47 +08:00
648540858
9817bf3fb7 1078-音视频参数设置+音视频通道列表设置 2024-05-21 23:58:23 +08:00
648540858
82ab524fc4 1078-音视频参数设置+音视频通道列表设置 2024-05-21 23:56:51 +08:00
648540858
e085258d74 1078-数据下行透传+数据上行透传 + 数据压缩上报 + 平台 RSA公钥 + 终端 RSA公钥 2024-05-20 00:04:04 +08:00
648540858
2f1ebca335 1078-单条存储多媒体数据检索上传命令 2024-05-19 23:50:37 +08:00
648540858
b626a583f4 1078-录音 2024-05-19 17:50:40 +08:00
648540858
dcc20d0d15 1078-存储多媒体数据上传接口优化 2024-05-19 17:08:31 +08:00
648540858
6af9b8da1f 1078-存储多媒体数据上传 2024-05-18 16:52:02 +08:00
648540858
e9562d7d31 1078-存储多媒体数据上传命令 2024-05-18 07:29:15 +08:00
648540858
b0e25ef784 1078-修复分包消息处理 2024-05-18 05:59:23 +08:00
648540858
7ddf066878 1078-修复存储多媒体数据检索 2024-05-17 07:43:28 +08:00
648540858
9161a090f6 1078-存储多媒体数据检索接口 2024-05-15 13:15:14 +08:00
648540858
7bf548492a 1078-修复摄像头立即拍摄命令应答 2024-05-14 23:21:57 +08:00
648540858
e02a047eb2 1078-存储多媒体数据检索 + 存储多媒体数据检索应答 2024-05-14 13:13:58 +08:00
648540858
aaa1d3a46f 1078-摄像头立即拍摄命令 2024-05-12 07:36:29 +08:00
648540858
db4ba4035f Merge branch 'refs/heads/master' into 1078 2024-05-12 06:53:53 +08:00
648540858
cc71b7d9ca 1078-定位数据批量上传+多媒体事件信息上传+多媒体数据上传 2024-05-09 00:03:54 +08:00
648540858
c6e3df685a 1078-上报驾驶员身份信息请求+驾驶员身份信息采集上报 2024-05-08 22:51:29 +08:00
648540858
ad67155d73 1078-查询区域或线路数据 2024-05-06 23:58:17 +08:00
648540858
2112fffc26 1078-查询区域或线路数据应答... 2024-05-06 18:00:26 +08:00
648540858
364d613ccb 1078-修复删除路线 2024-05-06 16:05:16 +08:00
648540858
c53e4f6fbc 1078-设置路线 2024-05-06 15:55:14 +08:00
648540858
cc91db30c5 1078-查询区域或线路数据 2024-05-05 23:02:49 +08:00
648540858
00749619da 1078-设置路线... 2024-05-05 21:54:56 +08:00
648540858
9280b57974 1078-设置路线... 2024-05-04 23:19:27 +08:00
648540858
a3149139e2 1078-设置多边形区域+删除多边形区域 2024-05-04 21:56:47 +08:00
648540858
58401b1444 1078-设置多边形区域... 2024-05-04 14:57:48 +08:00
648540858
4a5de5a2db 1078-设置矩形区域+删除矩形区域 2024-05-04 14:35:45 +08:00
648540858
faa0a01b9f 1078-设置圆形区域 2024-05-04 00:09:12 +08:00
648540858
5dd49b3d44 1078-设置圆形区域... 2024-05-03 18:58:49 +08:00
648540858
4011e54dd8 1078-设置圆形区域... 2024-05-03 01:02:00 +08:00
648540858
738b3b6a8e 1078-车辆控制应答 2024-05-02 07:35:44 +08:00
648540858
a5bfe5049d 1078-车辆控制 2024-05-02 07:29:00 +08:00
648540858
c946b97514 1078-优化消息汇报消息体的解析 2024-05-02 06:43:59 +08:00
648540858
0fc0cd6e41 1078-优化编码 2024-05-02 06:25:09 +08:00
648540858
734f0c7e04 1078-设置电话本+电话回拨 2024-05-02 05:21:50 +08:00
648540858
16bc3dabd6 1078-修改文本信息下发标记类型注释 2024-05-02 04:46:34 +08:00
648540858
7c833f3d12 1078-文本信息下发 2024-05-01 15:07:38 +08:00
648540858
e5acf7f1e4 1078-人工确认报警消息+链路检测 2024-05-01 10:05:33 +08:00
648540858
eb43ffd98f 1078-临时提交 2024-05-01 00:01:55 +08:00
648540858
e45b2479d3 1078-临时位置跟踪控制+位置信息查询 2024-04-30 23:37:44 +08:00
648540858
7bdde6907a 1078-添加设备属性查询接口 2024-04-30 12:13:49 +08:00
648540858
5be7c7636e 1078-查询终端属性完成 2024-04-30 00:42:22 +08:00
648540858
76580d8fdc 1078-查询终端属性... 2024-04-30 00:28:40 +08:00
648540858
5b489d7c26 1078-设置终端参数-添加接口 2024-04-29 23:06:15 +08:00
648540858
5a392372cb 1078-添加设备控制 2024-04-29 22:15:21 +08:00
648540858
8aa97ba695 1078-添加设备控制 2024-04-29 22:12:27 +08:00
648540858
516c5ce3d1 1078-添加设备控制 2024-04-29 22:01:26 +08:00
648540858
9facff13b1 1078-添加发送分包支持 2024-04-29 21:24:08 +08:00
648540858
91b81ceb7a 1078-添加发送分包支持 2024-04-29 16:27:01 +08:00
648540858
06b27beedc 1078-设置终端参数... 2024-04-29 07:00:00 +08:00
648540858
bc356849c7 1078-设置终端参数... 2024-04-29 00:05:04 +08:00
648540858
225940825b 1078-设置终端参数... 2024-04-24 23:34:21 +08:00
648540858
62122f95f0 1078-完善查询终端参数接口 2024-04-24 23:15:07 +08:00
648540858
67b846fe2f 1078-支持8103 修改注释错误 2024-04-24 22:21:47 +08:00
648540858
714e1ff62c 1078-支持8103 设置终端参数 2024-04-21 23:54:06 +08:00
648540858
0058f1b0a9 1078-解析104... 2024-04-21 00:24:24 +08:00
648540858
34b6b516ab 1078-解析104... 2024-04-21 00:16:07 +08:00
648540858
f9c22fcb3d 1078-解析104中... 2024-04-20 18:59:23 +08:00
648540858
c5ac7e218a 1078-解析104中... 2024-04-20 14:23:05 +08:00
648540858
975e94eee1 1078-支持分包消息 2024-04-20 13:03:39 +08:00
648540858
50e2565643 1078-处理分包发送 2024-04-20 00:07:37 +08:00
648540858
dd5ab573f2 1078-解析104... 2024-04-19 07:19:40 +08:00
648540858
a6236a2c13 1078-解析104... 2024-04-19 00:01:20 +08:00
648540858
16143a3fff 1078-解析104中 2024-04-18 20:11:13 +08:00
648540858
fce96def9f 1078-添加查询终端参数 2024-04-15 00:40:36 +08:00
648540858
570307669e 1078-添加查询指定终端参数 2024-04-15 00:31:11 +08:00
648540858
205e529660 1078-补充终端设置参数 2024-04-14 23:03:43 +08:00
648540858
21e7ca0e46 1078-临时提交 2024-04-12 23:36:02 +08:00
648540858
6729df4992 合并主线 2024-04-12 22:15:26 +08:00
648540858
c6bd4ac352 添加导包 2024-04-12 11:23:57 +08:00
648540858
9f3cab6486 Merge branch 'master' into 1078 2024-04-12 10:38:45 +08:00
648540858
be787d1a14 添加日志 2024-04-12 09:55:42 +08:00
648540858
8716160d96 支持推流鉴权 2024-04-11 23:36:06 +08:00
648540858
9800fd6e7b Merge branch 'refs/heads/master' into dev/abl支持
# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
2024-04-11 22:47:03 +08:00
648540858
4005a12403 Merge remote-tracking branch 'origin/1078' into 1078 2024-04-11 22:46:03 +08:00
648540858
59c91bdaf8 1078-暂时注释位置附加信息读取 2024-04-11 22:45:50 +08:00
648540858
7d08b56267 Merge branch 'master' into 1078 2024-04-11 09:39:12 +08:00
648540858
05c83cf6ef Merge branch 'master' into 1078 2024-04-11 09:39:04 +08:00
648540858
1d36382986 修改抓拍存储 2024-04-10 16:52:39 +08:00
648540858
bb350e847d 修复抓拍存储 2024-04-10 16:35:47 +08:00
648540858
d410a3ca18 添加抓拍支持 2024-04-10 16:26:46 +08:00
648540858
b08f00104e abl添加getMediaInfo接口实现 2024-04-10 00:03:45 +08:00
648540858
2dc7eecb47 abl添加checkMediaServer实现 2024-04-09 23:41:48 +08:00
648540858
48a0e88b95 Merge branch 'refs/heads/master' into dev/abl支持 2024-04-09 22:52:33 +08:00
648540858
0077df29d4 临时提交 2024-04-09 21:42:08 +08:00
648540858
5457407601 恢复abl实现 2024-04-09 20:56:41 +08:00
648540858
ae239c8848 Merge branch 'master' into 1078 2024-04-08 18:15:06 +08:00
648540858
9badf1c7fe 1078-添加位置附加信息定义 2024-04-08 18:15:02 +08:00
648540858
d54787f323 1078-添加读取位置信息汇报附加信息读取 2024-04-07 23:50:58 +08:00
648540858
8a2dc6031e 1078-实现云台控制接口 2024-04-07 22:06:41 +08:00
648540858
9255ea802f 1078-添加云台控制接口 2024-04-07 20:59:21 +08:00
648540858
349b0442d6 Merge remote-tracking branch 'origin/1078' into 1078 2024-04-07 20:42:32 +08:00
648540858
403eb4499d Merge branch 'master' into 1078 2024-04-07 20:42:10 +08:00
648540858
6757f4b719 1078-云台变倍控制 2024-04-07 07:21:21 +08:00
648540858
8ba30e83ef 1078-修复错别字 2024-04-07 07:19:02 +08:00
648540858
98d9eb5314 1078-添加云台红外补光控制 2024-04-07 07:17:35 +08:00
648540858
a8a4aecc15 1078-添加云台雨刷控制 2024-04-07 07:15:43 +08:00
648540858
b649464753 1078-添加云台光圈控制 2024-04-07 07:12:51 +08:00
648540858
ebdd9ab534 1078-添加云台焦距控制 2024-04-07 07:09:49 +08:00
648540858
a1ab834875 1078-添加云台旋转 2024-04-07 07:07:27 +08:00
648540858
4ec4d618d6 1078-添加文件上传控制 2024-04-07 07:02:06 +08:00
648540858
5fc1000fcc 1078-添加文件上传完成通知 2024-04-07 06:56:39 +08:00
648540858
302eb98d51 1078-添加文件上传指令 2024-04-07 06:44:52 +08:00
648540858
984d8743be 1078-优化录像回放开始和停止 2024-04-06 00:42:54 +08:00
648540858
26bbeac6c7 1078-添加录像回放开始和停止 2024-04-06 00:06:40 +08:00
648540858
81c2b5715c 1078-添加录像回放列表查询 2024-04-04 16:54:08 +08:00
648540858
3e5da98539 1078-支持点播暂停/继续 2024-04-04 07:19:46 +08:00
648540858
a7b7371e74 1078-增加结束点播 2024-04-03 18:00:48 +08:00
648540858
0f420c43ac 1078-优化点播 2024-04-03 16:59:33 +08:00
648540858
abc3766556 1078-优化点播 2024-04-03 16:33:49 +08:00
648540858
603ce18573 1078-添加点播支持 2024-04-02 23:26:40 +08:00
648540858
6acc395ad2 Merge branch 'master' into 1078 2024-04-02 18:33:53 +08:00
648540858
da33471dfd 1078-修改9101编码为GBK 2024-03-17 23:45:08 +08:00
648540858
98199ec657 1078-优化BCD码解析 2024-03-16 23:41:29 +08:00
648540858
3e672ca38c 1078-支持位置汇报 2024-03-16 23:22:07 +08:00
648540858
9bc9dbe43b 1078-解析位置汇报 2024-03-16 00:29:30 +08:00
648540858
60d51cf23a 1078-支持展示车牌颜色 2024-03-15 22:51:49 +08:00
648540858
93946407e8 1078-简化设备注册取值写法 2024-03-15 17:50:03 +08:00
648540858
23a72e94e6 1078-优化列表展示效果 2024-03-14 18:04:28 +08:00
648540858
d4c531dc12 Merge branch 'master' into 1078 2024-03-14 14:55:03 +08:00
648540858
dff7b8e31f 添加设备新增页面 2024-03-13 23:33:03 +08:00
648540858
e400c92f53 添加设备新增接口 2024-03-13 23:21:49 +08:00
648540858
4eb0163e43 添加设备查询和设备更新接口 2024-03-13 23:16:01 +08:00
648540858
d78f76e58b 1078-设备注册支持从数据库校验是否合法 2024-03-13 18:18:23 +08:00
648540858
44f17c723b Merge remote-tracking branch 'origin/1078' into 1078 2024-03-13 16:46:31 +08:00
648540858
18bd959541 Merge branch 'master' into 1078 2024-03-13 16:46:21 +08:00
648540858
dc38df6288 支持从数据库查询注册的设备是否合法 2024-03-13 00:04:52 +08:00
648540858
613452b3fc 1078-设备注册兼容1078-2013 2024-03-12 18:21:10 +08:00
648540858
9494b6dc85 优化架构,获取设备注册时的设备相关信息 2024-03-12 17:32:10 +08:00
648540858
79dc7e79d2 Merge branch 'master' into 1078 2024-03-08 16:22:13 +08:00
648540858
6275372455 添加service 2023-07-31 17:34:44 +08:00
297 changed files with 25571 additions and 827 deletions

View File

@ -1,5 +1,5 @@
![logo](doc/_media/logo.png)
# 开箱即用的28181协议视频平台
# 开箱即用的国标28181和部标808+1078协议视频平台
[![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
[![license](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/xia-chu/ZLMediaKit/blob/master/LICENSE)
@ -8,7 +8,7 @@
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-yellow.svg)](https://github.com/xia-chu/ZLMediaKit/pulls)
WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网络视频平台负责实现核心信令与设备管理后台部分支持NAT穿透支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
WEB VIDEO PLATFORM是一个基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台负责实现核心信令与设备管理后台部分支持NAT穿透支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
流媒体服务基于@夏楚 ZLMediaKit [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
播放器使用@dexter jessibuca [https://github.com/langhuihui/jessibuca/tree/v3](https://github.com/langhuihui/jessibuca/tree/v3)
@ -120,20 +120,22 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 支持MysqlPostgresql金仓等数据库
- [X] 支持录制计划, 根据设定的时间对通道进行录制. 暂不支持将录制的内容转发到国标上级
- [X] 支持国标信令集群
- [X] 新增支持部标808和部标1078大量新特性不一一列表了。支持作为网关被国标上级调用部标设备
# 闭源内容
- [X] 支持ONVIF协议设备检索支持点播云台控制国标级联点播自动点播等。
- [X] 支持部标1078+808协议支持点播云台控制录像回放位置上报自动点播等。
- [X] 支持国标28181-2022协议支持巡航轨迹查询PTZ精准控制存储卡格式化设备软件升级OSD配置h265+aac支持辅码流录像倒放等。
- [X] 支持国网B接口协议。支持注册获取资源预览, 云台控制,预置位控制等,可免费定制支持语音对讲、录像回放和抓拍图像
- [X] 功能加强版本
- [X] 国标增强版: 支持国标28181-2022协议支持巡航轨迹查询PTZ精准控制存储卡格式化设备软件升级OSD配置h265+aac支持辅码流录像倒放等。
- [X] 全功能版:
- [X] 支持开源所有功能
- [X] 支持ONVIF协议设备检索支持点播云台控制国标级联点播自动点播等
- [X] 支持国网B接口协议。支持注册获取资源预览, 云台控制,预置位控制等,可免费定制支持语音对讲、录像回放和抓拍图像。
- [X] 支持按权限分配可以使用的通道
- [X] 支持电子地图。支持展示通道位置支持在地图上修改通道位置。可扩展接入高德地图API支持搜索位置附近设备。
- [X] 支持表格导出
- [X] 拉流代理支持按照品牌拼接url。
- [X] 播放鉴权,更加安全。
- [X] 功能持续扩展,可根据用户需要增加支持。
- [X] 此版本后续开发功能支持直接更新提供,无需二次付费。
- [X] 提供源码不限制部署次数和支持路数。
# 授权协议

22
pom.xml
View File

@ -342,6 +342,27 @@
<version>32.1.3-jre</version>
</dependency>
<!--ftp server-->
<dependency>
<groupId>org.apache.ftpserver</groupId>
<artifactId>ftpserver-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.ftpserver</groupId>
<artifactId>ftplet-api</artifactId>
<version>1.2.0</version>
</dependency>
<!-- 自动化生成代码工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- 自动化生成代码工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
@ -361,6 +382,7 @@
<artifactId>log-viewer-spring-boot</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@ -182,6 +182,7 @@ public class StreamInfo implements Serializable, Cloneable{
if (callIdParam != null) {
callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
}
// String file = String.format("%s/%s?type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
if (port > 0) {
this.rtc = new StreamURL("http", host, port, file);

View File

@ -153,4 +153,15 @@ public class VideoManagerConstants {
*/
public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:";
//************************** 1078 ****************************************
public static final String INVITE_INFO_1078_POSITION = "INVITE_INFO_1078_POSITION:";
public static final String INVITE_INFO_1078_PLAY = "INVITE_INFO_1078_PLAY:";
public static final String INVITE_INFO_1078_PLAYBACK = "INVITE_INFO_1078_PLAYBACK:";
public static final String INVITE_INFO_1078_TALK = "INVITE_INFO_1078_TALK:";
public static final String RECORD_LIST_1078 = "RECORD_LIST_1078:";
}

View File

@ -9,6 +9,7 @@ public class ChannelDataType {
public final static int GB28181 = 1;
public final static int STREAM_PUSH = 2;
public final static int STREAM_PROXY = 3;
public final static int JT_1078 = 200;
public final static String PLAY_SERVICE = "sourceChannelPlayService";
public final static String PLAYBACK_SERVICE = "sourceChannelPlaybackService";

View File

@ -66,6 +66,9 @@ public class MediaConfig{
@Value("${media.rtp-proxy-port:0}")
private Integer rtpProxyPort = 0;
@Value("${media.jtt-proxy-port:0}")
private Integer jttProxyPort = 0;
@Value("${media.rtsp-port:0}")
private Integer rtspPort = 0;
@ -122,7 +125,7 @@ public class MediaConfig{
public int getRtmpPort() {
return rtmpPort;
}
public int getRtmpSSlPort() {
return rtmpSSlPort;
}
@ -136,6 +139,14 @@ public class MediaConfig{
}
public Integer getJttProxyPort() {
if (jttProxyPort == null) {
return 0;
}else {
return jttProxyPort;
}
}
public int getRtspPort() {
return rtspPort;
}
@ -159,7 +170,7 @@ public class MediaConfig{
public String getRtpPortRange() {
return rtpPortRange;
}
public int getRecordAssistPort() {
return recordAssistPort;
}
@ -229,6 +240,7 @@ public class MediaConfig{
mediaServer.setRtmpPort(rtmpPort);
mediaServer.setRtmpSSlPort(rtmpSSlPort);
mediaServer.setRtpProxyPort(getRtpProxyPort());
mediaServer.setJttProxyPort(getJttProxyPort());
mediaServer.setRtspPort(rtspPort);
mediaServer.setRtspSSLPort(rtspSSLPort);
mediaServer.setAutoConfig(autoConfig);

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.conf;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
@ -9,17 +10,14 @@ import org.springframework.stereotype.Component;
@Component
public class ServiceInfo implements ApplicationListener<WebServerInitializedEvent> {
@Getter
private static int serverPort;
public static int getServerPort() {
return serverPort;
}
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
// 项目启动获取启动的端口号
ServiceInfo.serverPort = event.getWebServer().getPort();
log.info("项目启动获取启动的端口号: " + ServiceInfo.serverPort);
log.info("项目启动获取启动的端口号: {}", ServiceInfo.serverPort);
}
public void setServerPort(int serverPort) {

View File

@ -98,4 +98,12 @@ public class SpringDocConfig {
.packagesToScan("com.genersoft.iot.vmp.user")
.build();
}
@Bean
public GroupedOpenApi publicApi7() {
return GroupedOpenApi.builder()
.group("6. 部标设备")
.packagesToScan("com.genersoft.iot.vmp.jt1078.controller")
.build();
}
}

View File

@ -0,0 +1,8 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import java.io.OutputStream;
public interface FileCallback {
OutputStream run(String path);
}

View File

@ -0,0 +1,17 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.AuthorizationRequest;
public class FtpAuthority implements Authority {
@Override
public boolean canAuthorize(AuthorizationRequest authorizationRequest) {
return true;
}
@Override
public AuthorizationRequest authorize(AuthorizationRequest authorizationRequest) {
return authorizationRequest;
}
}

View File

@ -0,0 +1,33 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import org.apache.ftpserver.ftplet.FileSystemFactory;
import org.apache.ftpserver.ftplet.FileSystemView;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class FtpFileSystemFactory implements FileSystemFactory {
private final Map<String, OutputStream> outputStreamMap = new ConcurrentHashMap<>();
@Override
public FileSystemView createFileSystemView(User user) throws FtpException {
return new FtpFileSystemView(user, path -> {
return outputStreamMap.get(path);
});
}
public void addOutputStream(String filePath, OutputStream outputStream) {
outputStreamMap.put(filePath, outputStream);
}
public void removeOutputStream(String filePath) {
outputStreamMap.remove(filePath);
}
}

View File

@ -0,0 +1,63 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import org.apache.ftpserver.ftplet.FileSystemView;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpFile;
import org.apache.ftpserver.ftplet.User;
import java.io.OutputStream;
public class FtpFileSystemView implements FileSystemView {
private User user;
private FileCallback fileCallback;
public FtpFileSystemView(User user, FileCallback fileCallback) {
this.user = user;
this.fileCallback = fileCallback;
}
public static String HOME_PATH = "root";
public FtpFile workDir = VirtualFtpFile.getDir(HOME_PATH);
@Override
public FtpFile getHomeDirectory() throws FtpException {
return VirtualFtpFile.getDir(HOME_PATH);
}
@Override
public FtpFile getWorkingDirectory() throws FtpException {
return workDir;
}
@Override
public boolean changeWorkingDirectory(String dir) throws FtpException {
workDir = VirtualFtpFile.getDir(dir);
return true;
}
@Override
public FtpFile getFile(String file) throws FtpException {
VirtualFtpFile ftpFile = VirtualFtpFile.getFile(file);
if (fileCallback != null) {
OutputStream outputStream = fileCallback.run(workDir.getName());
if (outputStream != null) {
ftpFile.setOutputStream(outputStream);
}
}
return ftpFile;
}
@Override
public boolean isRandomAccessible() throws FtpException {
return true;
}
@Override
public void dispose() {
}
}

View File

@ -0,0 +1,69 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.ftpserver.*;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.listener.Listener;
import org.apache.ftpserver.listener.ListenerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@ConditionalOnProperty(value = "ftp.enable", havingValue = "true")
@Slf4j
public class FtpServerConfig {
@Autowired
private UserManager userManager;
@Autowired
private FtpFileSystemFactory fileSystemFactory;
@Autowired
private Ftplet ftplet;
@Autowired
private FtpSetting ftpSetting;
/**
* ftp server init
*/
@Bean
public FtpServer ftpServer() {
FtpServerFactory serverFactory = new FtpServerFactory();
ListenerFactory listenerFactory = new ListenerFactory();
// 1设置服务端口
listenerFactory.setPort(ftpSetting.getPort());
// 2设置被动模式数据上传的接口范围,云服务器需要开放对应区间的端口给客户端
DataConnectionConfigurationFactory dataConnectionConfFactory = new DataConnectionConfigurationFactory();
dataConnectionConfFactory.setPassivePorts(ftpSetting.getPassivePorts());
listenerFactory.setDataConnectionConfiguration(dataConnectionConfFactory.createDataConnectionConfiguration());
// 4替换默认的监听器
Listener listener = listenerFactory.createListener();
serverFactory.addListener("default", listener);
// 5配置自定义用户事件
Map<String, org.apache.ftpserver.ftplet.Ftplet> ftpLets = new HashMap<>();
ftpLets.put("ftpService", ftplet);
serverFactory.setFtplets(ftpLets);
// 6读取用户的配置信息
// 6.2设置用信息
serverFactory.setUserManager(userManager);
serverFactory.setFileSystem(fileSystemFactory);
// 7实例化FTP Server
FtpServer server = serverFactory.createServer();
try {
server.start();
if (!server.isStopped()) {
log.info("[FTP服务] 已启动, 端口: {}", ftpSetting.getPort());
}
} catch (FtpException e) {
log.info("[FTP服务] 启动失败 ", e);
}
return server;
}
}

View File

@ -0,0 +1,21 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 配置文件 user-settings 映射的配置信息
*/
@Component
@ConfigurationProperties(prefix = "ftp", ignoreInvalidFields = true)
@Order(0)
@Data
public class FtpSetting {
private Boolean enable = Boolean.FALSE;
private int port = 21;
private String passivePorts = "10000-10500";
}

View File

@ -0,0 +1,59 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import com.genersoft.iot.vmp.jt1078.event.FtpUploadEvent;
import org.apache.ftpserver.ftplet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class Ftplet extends DefaultFtplet {
private final Logger logger = LoggerFactory.getLogger(Ftplet.class);
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
if (file == null) {
return super.onUploadEnd(session, request);
}
sendEvent(file.getAbsolutePath());
return super.onUploadUniqueEnd(session, request);
}
@Override
public FtpletResult onAppendEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
if (file == null) {
return super.onUploadEnd(session, request);
}
sendEvent(file.getAbsolutePath());
return super.onUploadUniqueEnd(session, request);
}
@Override
public FtpletResult onUploadUniqueEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
if (file == null) {
return super.onUploadEnd(session, request);
}
sendEvent(file.getAbsolutePath());
return super.onUploadUniqueEnd(session, request);
}
private void sendEvent(String filePath){
FtpUploadEvent event = new FtpUploadEvent(this);
logger.info("[文件已上传]: {}", filePath);
event.setFileName(filePath);
applicationEventPublisher.publishEvent(event);
}
}

View File

@ -0,0 +1,86 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.ftpserver.ftplet.*;
import org.apache.ftpserver.usermanager.UsernamePasswordAuthentication;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.io.File;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@Component
public class UserManager implements org.apache.ftpserver.ftplet.UserManager {
private static final String PREFIX = "VMP_FTP_USER_";
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Override
public User getUserByName(String username) throws FtpException {
return (BaseUser)redisTemplate.opsForValue().get(PREFIX + username);
}
@Override
public String[] getAllUserNames() throws FtpException {
return new String[0];
}
@Override
public void delete(String username) throws FtpException {
}
@Override
public void save(User user) throws FtpException {}
@Override
public boolean doesExist(String username) throws FtpException {
return redisTemplate.opsForValue().get(PREFIX + username) != null;
}
@Override
public User authenticate(Authentication authentication) throws AuthenticationFailedException {
UsernamePasswordAuthentication usernamePasswordAuthentication = (UsernamePasswordAuthentication) authentication;
BaseUser user = (BaseUser)redisTemplate.opsForValue().get(PREFIX + usernamePasswordAuthentication.getUsername());
if (user != null && usernamePasswordAuthentication.getPassword().equals(user.getPassword())) {
return user;
}
return null;
}
@Override
public String getAdminName() throws FtpException {
return null;
}
@Override
public boolean isAdmin(String username) throws FtpException {
return false;
}
public BaseUser getRandomUser(){
BaseUser use = new BaseUser();
use.setName(RandomStringUtils.randomAlphabetic(6).toLowerCase());
use.setPassword(RandomStringUtils.randomAlphabetic(6).toLowerCase());
use.setEnabled(true);
use.setHomeDirectory("/");
List<Authority> authorities = new ArrayList<>();
authorities.add(new FtpAuthority());
use.setAuthorities(authorities);
String key = PREFIX + use.getName();
// 随机用户信息十分钟自动失效
Duration duration = Duration.ofMinutes(10);
redisTemplate.opsForValue().set(key, use, duration);
return use;
}
}

View File

@ -0,0 +1,166 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import lombok.Setter;
import org.apache.ftpserver.ftplet.FtpFile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
public class VirtualFtpFile implements FtpFile {
@Setter
private String name;
@Setter
private boolean hidden = false;
@Setter
private boolean directory = false;
@Setter
private String ownerName;
private Long lastModified = null;
@Setter
private long size = 0;
@Setter
private OutputStream outputStream;
public static VirtualFtpFile getFile(String name) {
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
virtualFtpFile.setName(name);
return virtualFtpFile;
}
public static VirtualFtpFile getDir(String name) {
if (name.endsWith("/")) {
name = name.replaceAll("/", "");
}
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
virtualFtpFile.setName(name);
virtualFtpFile.setDirectory(true);
return virtualFtpFile;
}
@Override
public String getAbsolutePath() {
return FtpFileSystemView.HOME_PATH + "/" + name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean isHidden() {
return hidden;
}
@Override
public boolean isDirectory() {
return directory;
}
@Override
public boolean isFile() {
return !directory;
}
@Override
public boolean doesExist() {
return false;
}
@Override
public boolean isReadable() {
return true;
}
@Override
public boolean isWritable() {
return true;
}
@Override
public boolean isRemovable() {
return true;
}
@Override
public String getOwnerName() {
return ownerName;
}
@Override
public String getGroupName() {
return "root";
}
@Override
public int getLinkCount() {
return 0;
}
@Override
public long getLastModified() {
if (lastModified == null) {
lastModified = System.currentTimeMillis();
}
return lastModified;
}
@Override
public boolean setLastModified(long time) {
lastModified = time;
return true;
}
@Override
public long getSize() {
return size;
}
@Override
public Object getPhysicalFile() {
System.err.println("getPhysicalFile");
return null;
}
@Override
public boolean mkdir() {
return true;
}
@Override
public boolean delete() {
return true;
}
@Override
public boolean move(FtpFile destination) {
this.name = destination.getName();
return true;
}
@Override
public List<? extends FtpFile> listFiles() {
return Collections.emptyList();
}
@Override
public OutputStream createOutputStream(long offset) throws IOException {
return outputStream;
}
@Override
public InputStream createInputStream(long offset) throws IOException {
System.out.println("createInputStream----");
return null;
}
}

View File

@ -58,7 +58,7 @@ public class JwtUtils implements InitializingBean {
private static IUserService userService;
private static IUserApiKeyService userApiKeyService;
private static UserSetting userSetting;
public static String getApiKeyHeader() {
@ -236,7 +236,7 @@ public class JwtUtils implements InitializingBean {
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
} else {
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
}
}
} else {
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
}

View File

@ -100,6 +100,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
defaultExcludes.add("/index/hook/**");
defaultExcludes.add("/api/device/query/snap/**");
defaultExcludes.add("/index/hook/abl/**");
defaultExcludes.add("/api/jt1078/playback/download");
defaultExcludes.add("/api/jt1078/snap");

View File

@ -11,4 +11,7 @@ public class CommonRecordInfo {
// 结束时间
private String endTime;
// 文件大小 单位byte
private String fileSize;
}

View File

@ -2,15 +2,19 @@ package com.genersoft.iot.vmp.gb28181.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.Instant;
import java.util.List;
/**
* @description:设备录像信息bean
/**
* @description:设备录像信息bean
* @author: swwheihei
* @date: 2020年5月8日 下午2:05:56
* @date: 2020年5月8日 下午2:05:56
*/
@Setter
@Getter
@Schema(description = "设备录像查询结果信息")
public class RecordInfo {
@ -36,67 +40,4 @@ public class RecordInfo {
@Schema(description = "")
private List<RecordItem> recordList;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSumNum() {
return sumNum;
}
public void setSumNum(int sumNum) {
this.sumNum = sumNum;
}
public List<RecordItem> getRecordList() {
return recordList;
}
public void setRecordList(List<RecordItem> recordList) {
this.recordList = recordList;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public Instant getLastTime() {
return lastTime;
}
public void setLastTime(Instant lastTime) {
this.lastTime = lastTime;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

View File

@ -44,7 +44,7 @@ public class RecordItem implements Comparable<RecordItem>{
@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
private int secrecy;
@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
@Schema(description = "录像产生类型(可选)time或alarm 或 manual")
private String type;
@Schema(description = "录像触发者ID(可选)")

View File

@ -0,0 +1,19 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import lombok.Data;
@Data
public class SipSendFailEvent extends SipSubscribe.EventResult<String> {
private String callId;
private String msg;
public static SipSendFailEvent getInstance(String callId, String msg){
SipSendFailEvent sipSendFailEvent = new SipSendFailEvent();
sipSendFailEvent.setMsg(msg);
sipSendFailEvent.setCallId(callId);
return sipSendFailEvent;
}
}

View File

@ -308,7 +308,6 @@ public class ChannelController {
wvpResult.setCode(code);
wvpResult.setMsg(msg);
}
result.setResult(wvpResult);
}else {
result.setResult(WVPResult.fail(code, msg));

View File

@ -583,4 +583,18 @@ public interface CommonGBChannelMapper {
@Update("UPDATE wvp_device_channel SET stream_id = #{stream} where id = #{gbId}")
void updateStream(int gbId, String stream);
@Update("<script> " +
"<foreach collection='commonGBChannels' index='index' item='item' separator=';'> " +
"UPDATE wvp_device_channel " +
" SET gb_longitude=#{item.gbLongitude}" +
", gb_latitude=#{item.gbLatitude} " +
", gps_speed=#{item.gpsSpeed} " +
", gps_altitude=#{item.gpsAltitude} " +
", gps_direction=#{item.gpsDirection} " +
", gps_time=#{item.gpsTime} " +
"WHERE id = #{item.gbId}" +
"</foreach> " +
"</script>")
void updateGps(List<CommonGBChannel> commonGBChannels);
}

View File

@ -96,4 +96,5 @@ public interface IGbChannelService {
void updateGPSFromGPSMsgInfo(List<GPSMsgInfo> gpsMsgInfoList);
void updateGPS(List<CommonGBChannel> channelList);
}

View File

@ -7,6 +7,9 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
import com.genersoft.iot.vmp.gb28181.service.*;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078PlayService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import lombok.extern.slf4j.Slf4j;
@ -30,6 +33,9 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
@Autowired
private Map<String, ISourcePlayService> sourcePlayServiceMap;
@Autowired
private Ijt1078PlayService jt1078PlayService;
@Autowired
private Map<String, ISourcePlaybackService> sourcePlaybackServiceMap;
@ -79,6 +85,8 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
}
}
@Override
public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback) {
log.info("[通用通道] 播放, 类型: {} 编号:{}", channel.getDataType(), channel.getGbDeviceId());

View File

@ -771,4 +771,21 @@ public class GbChannelServiceImpl implements IGbChannelService {
}
commonGBChannelMapper.updateGpsByDeviceId(gpsMsgInfoList);
}
@Transactional
@Override
public void updateGPS(List<CommonGBChannel> commonGBChannels) {
int limitCount = 1000;
if (commonGBChannels.size() > limitCount) {
for (int i = 0; i < commonGBChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > commonGBChannels.size()) {
toIndex = commonGBChannels.size();
}
commonGBChannelMapper.updateGps(commonGBChannels.subList(i, toIndex));
}
} else {
commonGBChannelMapper.updateGps(commonGBChannels);
}
}
}

View File

@ -684,17 +684,11 @@ public class PlayServiceImpl implements IPlayService {
* @param stream ssrc
*/
private void snapOnPlay(MediaServer mediaServerItemInuse, String deviceId, String channelId, String stream) {
String streamUrl;
if (mediaServerItemInuse.getRtspPort() != 0) {
streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", stream);
} else {
streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", stream);
}
String path = "snap";
String fileName = deviceId + "_" + channelId + ".jpg";
// 请求截图
log.info("[请求截图]: " + fileName);
mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
mediaServerService.getSnap(mediaServerItemInuse, "rtp", stream, 15, 1, path, fileName);
}
public StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, Device device, DeviceChannel channel) {
@ -1643,17 +1637,11 @@ public class PlayServiceImpl implements IPlayService {
if (inviteInfo != null) {
if (inviteInfo.getStreamInfo() != null) {
// 已存在线直接截图
MediaServer mediaServerItemInuse = inviteInfo.getStreamInfo().getMediaServer();
String streamUrl;
if (mediaServerItemInuse.getRtspPort() != 0) {
streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", inviteInfo.getStreamInfo().getStream());
}else {
streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", inviteInfo.getStreamInfo().getStream());
}
MediaServer mediaServer = inviteInfo.getStreamInfo().getMediaServer();
String path = "snap";
// 请求截图
log.info("[请求截图]: " + fileName);
mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
mediaServerService.getSnap(mediaServer, "rtp", inviteInfo.getStreamInfo().getStream(), 15, 1, path, fileName);
File snapFile = new File(path + File.separator + fileName);
if (snapFile.exists()) {
errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile());

View File

@ -101,6 +101,7 @@ public class SourcePlaybackServiceForGbImpl implements ISourcePlaybackService {
CommonRecordInfo recordInfo = new CommonRecordInfo();
recordInfo.setStartTime(recordItem.getStartTime());
recordInfo.setEndTime(recordItem.getEndTime());
recordInfo.setFileSize(recordItem.getFileSize());
recordInfoList.add(recordInfo);
}
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), recordInfoList);

View File

@ -1,13 +1,11 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.record.RecordInfoEventListener;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderForPlatform;
@ -27,6 +25,8 @@ import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
@ -40,6 +40,9 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
@Autowired
private IGbChannelService channelService;
@Autowired
private IGbChannelPlayService playService;
@Autowired
private IDeviceService deviceService;
@ -105,55 +108,105 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
}
return;
}
if (channel.getDataType() != ChannelDataType.GB28181) {
log.info("[平台查询录像记录] 只支持查询国标28181的录像数据 {}/{}", platform.getName(), channelId );
try {
responseAck(request, Response.NOT_IMPLEMENTED); // 回复未实现
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 平台查询录像记录: {}", e.getMessage());
if (channel.getDataType() == ChannelDataType.GB28181) {
Device device = deviceService.getDevice(channel.getDataDeviceId());
if (device == null) {
log.warn("[平台查询录像记录] 未找到通道对应的设备 {}/{}", platform.getName(), channelId );
try {
responseAck(request, Response.BAD_REQUEST);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] [平台查询录像记录] 未找到通道对应的设备: {}", e.getMessage());
}
return;
}
return;
}
Device device = deviceService.getDevice(channel.getDataDeviceId());
if (device == null) {
log.warn("[平台查询录像记录] 未找到通道对应的设备 {}/{}", platform.getName(), channelId );
// 获取通道的原始信息
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
// 接收录像数据
recordInfoEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{
try {
log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId);
cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
}
});
try {
responseAck(request, Response.BAD_REQUEST);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] [平台查询录像记录] 未找到通道对应的设备: {}", e.getMessage());
commander.recordInfoQuery(device, deviceChannel.getDeviceId(), DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
// 回复200 OK
try {
responseAck(request, Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
}
}),(eventResult -> {
// 查询失败
try {
responseAck(request, eventResult.statusCode, eventResult.msg);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
}
}));
} catch (InvalidArgumentException | ParseException | SipException e) {
log.error("[命令发送失败] 录像查询: {}", e.getMessage());
}
return;
}
// 获取通道的原始信息
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
// 接收录像数据
recordInfoEventListener.addEndEventHandler(device.getDeviceId(), deviceChannel.getDeviceId(), (recordInfo)->{
}else {
// 回复200 OK
try {
log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId);
cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo);
responseAck(request, Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
log.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
}
});
try {
commander.recordInfoQuery(device, deviceChannel.getDeviceId(), DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
// 回复200 OK
try {
responseAck(request, Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
}
}),(eventResult -> {
// 查询失败
try {
responseAck(request, eventResult.statusCode, eventResult.msg);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
}
}));
} catch (InvalidArgumentException | ParseException | SipException e) {
log.error("[命令发送失败] 录像查询: {}", e.getMessage());
playService.queryRecord(channel, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime),
(code, msg, commonRecordInfoList) -> {
RecordInfo recordInfo = new RecordInfo();
recordInfo.setSumNum(commonRecordInfoList.size());
recordInfo.setChannelId(channelId);
recordInfo.setSn(sn + "");
List<RecordItem> recordList = new ArrayList<>(commonRecordInfoList.size());
for (int i = 0; i < commonRecordInfoList.size(); i++) {
CommonRecordInfo commonRecordInfo = commonRecordInfoList.get(i);
RecordItem recordItem = new RecordItem();
recordItem.setDeviceId(channelId);
recordItem.setName(commonRecordInfo.getStartTime());
recordItem.setFilePath("/" + commonRecordInfo.getStartTime());
recordItem.setAddress("/" + commonRecordInfo.getStartTime());
recordItem.setStartTime(commonRecordInfo.getStartTime());
recordItem.setEndTime(commonRecordInfo.getEndTime());
recordItem.setSecrecy(0);
recordItem.setRecorderId("");
recordItem.setType("");
recordItem.setFileSize(commonRecordInfo.getFileSize());
recordList.add(recordItem);
}
recordInfo.setRecordList(recordList);
try {
log.info("[国标级联] 录像查询收到数据, 通道: {},准备转发===", channelId);
cmderFroPlatform.recordInfo(channel, platform, request.getFromTag(), recordInfo);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
}
});
}
//
//
//
//
//
//
//
// if (channel.getDataType() != ChannelDataType.GB28181) {
// log.info("[平台查询录像记录] 只支持查询国标28181的录像数据 {}/{}", platform.getName(), channelId );
// try {
// responseAck(request, Response.NOT_IMPLEMENTED); // 回复未实现
// } catch (SipException | InvalidArgumentException | ParseException e) {
// log.error("[命令发送失败] 平台查询录像记录: {}", e.getMessage());
// }
// return;
// }
}
}

View File

@ -0,0 +1,264 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.bean.config.JTDeviceSubConfig;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 报警标志
*/
@Data
@Schema(description = "报警标志")
public class JTAlarmSign implements JTDeviceSubConfig {
@Schema(description = "紧急报警,触动报警开关后触发")
private boolean urgent;
@Schema(description = "超速报警")
private boolean alarmSpeeding;
@Schema(description = "疲劳驾驶报警")
private boolean alarmTired;
@Schema(description = "危险驾驶行为报警")
private boolean alarmDangerous;
@Schema(description = "GNSS 模块发生故障报警")
private boolean alarmGnssFault;
@Schema(description = "GNSS 天线未接或被剪断报警")
private boolean alarmGnssBreak;
@Schema(description = "GNSS 天线短路报警")
private boolean alarmGnssShortCircuited;
@Schema(description = "终端主电源欠压报警")
private boolean alarmUnderVoltage;
@Schema(description = "终端主电源掉电报警")
private boolean alarmPowerOff;
@Schema(description = "终端 LCD或显示器故障报警")
private boolean alarmLCD;
@Schema(description = "TTS 模块故障报警")
private boolean alarmTtsFault;
@Schema(description = "摄像头故障报警")
private boolean alarmCameraFault;
@Schema(description = "道路运输证 IC卡模块故障报警")
private boolean alarmIcFault;
@Schema(description = "超速预警")
private boolean warningSpeeding;
@Schema(description = "疲劳驾驶预警")
private boolean warningTired;
@Schema(description = "违规行驶报警")
private boolean alarmWrong;
@Schema(description = "胎压预警")
private boolean warningTirePressure;
@Schema(description = "右转盲区异常报警")
private boolean alarmBlindZone;
@Schema(description = "当天累计驾驶超时报警")
private boolean alarmDrivingTimeout;
@Schema(description = "超时停车报警")
private boolean alarmParkingTimeout;
@Schema(description = "进出区域报警")
private boolean alarmRegion;
@Schema(description = "进出路线报警")
private boolean alarmRoute;
@Schema(description = "路段行驶时间不足/过长报警")
private boolean alarmTravelTime;
@Schema(description = "路线偏离报警")
private boolean alarmRouteDeviation;
@Schema(description = "车辆 VSS 故障")
private boolean alarmVSS;
@Schema(description = "车辆油量异常报警")
private boolean alarmOil;
@Schema(description = "车辆被盗报警(通过车辆防盗器)")
private boolean alarmStolen;
@Schema(description = "车辆非法点火报警")
private boolean alarmIllegalIgnition;
@Schema(description = "车辆非法位移报警")
private boolean alarmIllegalDisplacement;
@Schema(description = "碰撞侧翻报警")
private boolean alarmRollover;
@Schema(description = "侧翻预警")
private boolean warningRollover;
public JTAlarmSign() {
}
public JTAlarmSign(long alarmSignInt) {
if (alarmSignInt == 0) {
return;
}
// 解析alarm参数
this.urgent = (alarmSignInt & 1) == 1;
this.alarmSpeeding = (alarmSignInt >>> 1 & 1) == 1;
this.alarmTired = (alarmSignInt >>> 2 & 1) == 1;
this.alarmDangerous = (alarmSignInt >>> 3 & 1) == 1;
this.alarmGnssFault = (alarmSignInt >>> 4 & 1) == 1;
this.alarmGnssBreak = (alarmSignInt >>> 5 & 1) == 1;
this.alarmGnssShortCircuited = (alarmSignInt >>> 6 & 1) == 1;
this.alarmUnderVoltage = (alarmSignInt >>> 7 & 1) == 1;
this.alarmPowerOff = (alarmSignInt >>> 8 & 1) == 1;
this.alarmLCD = (alarmSignInt >>> 9 & 1) == 1;
this.alarmTtsFault = (alarmSignInt >>> 10 & 1) == 1;
this.alarmCameraFault = (alarmSignInt >>> 11 & 1) == 1;
this.alarmIcFault = (alarmSignInt >>> 12 & 1) == 1;
this.warningSpeeding = (alarmSignInt >>> 13 & 1) == 1;
this.warningTired = (alarmSignInt >>> 14 & 1) == 1;
this.alarmWrong = (alarmSignInt >>> 15 & 1) == 1;
this.warningTirePressure = (alarmSignInt >>> 16 & 1) == 1;
this.alarmBlindZone = (alarmSignInt >>> 17 & 1) == 1;
this.alarmDrivingTimeout = (alarmSignInt >>> 18 & 1) == 1;
this.alarmParkingTimeout = (alarmSignInt >>> 19 & 1) == 1;
this.alarmRegion = (alarmSignInt >>> 20 & 1) == 1;
this.alarmRoute = (alarmSignInt >>> 21 & 1) == 1;
this.alarmTravelTime = (alarmSignInt >>> 22 & 1) == 1;
this.alarmRouteDeviation = (alarmSignInt >>> 23 & 1) == 1;
this.alarmVSS = (alarmSignInt >>> 24 & 1) == 1;
this.alarmOil = (alarmSignInt >>> 25 & 1) == 1;
this.alarmStolen = (alarmSignInt >>> 26 & 1) == 1;
this.alarmIllegalIgnition = (alarmSignInt >>> 27 & 1) == 1;
this.alarmIllegalDisplacement = (alarmSignInt >>> 28 & 1) == 1;
this.alarmRollover = (alarmSignInt >>> 29 & 1) == 1;
this.warningRollover = (alarmSignInt >>> 30 & 1) == 1;
}
public static JTAlarmSign decode(ByteBuf byteBuf) {
long alarmSignByte = byteBuf.readUnsignedInt();
return new JTAlarmSign(alarmSignByte);
}
@Override
public ByteBuf encode() {
// 限定容量 避免影响后续占位
ByteBuf byteBuf = Unpooled.buffer();
int alarmSignValue = 0;
if (urgent) {
alarmSignValue = alarmSignValue | 1;
}
if (alarmSpeeding) {
alarmSignValue = alarmSignValue | 1 << 1;
}
if (alarmTired) {
alarmSignValue = alarmSignValue | 1 << 2;
}
if (alarmDangerous) {
alarmSignValue = alarmSignValue | 1 << 3;
}
if (alarmGnssFault) {
alarmSignValue = alarmSignValue | 1 << 4;
}
if (alarmGnssBreak) {
alarmSignValue = alarmSignValue | 1 << 5;
}
if (alarmGnssShortCircuited) {
alarmSignValue = alarmSignValue | 1 << 6;
}
if (alarmUnderVoltage) {
alarmSignValue = alarmSignValue | 1 << 7;
}
if (alarmPowerOff) {
alarmSignValue = alarmSignValue | 1 << 8;
}
if (alarmLCD) {
alarmSignValue = alarmSignValue | 1 << 9;
}
if (alarmTtsFault) {
alarmSignValue = alarmSignValue | 1 << 10;
}
if (alarmCameraFault) {
alarmSignValue = alarmSignValue | 1 << 11;
}
if (alarmIcFault) {
alarmSignValue = alarmSignValue | 1 << 12;
}
if (warningSpeeding) {
alarmSignValue = alarmSignValue | 1 << 13;
}
if (warningTired) {
alarmSignValue = alarmSignValue | 1 << 14;
}
if (alarmWrong) {
alarmSignValue = alarmSignValue | 1 << 15;
}
if (warningTirePressure) {
alarmSignValue = alarmSignValue | 1 << 16;
}
if (alarmBlindZone) {
alarmSignValue = alarmSignValue | 1 << 17;
}
if (alarmDrivingTimeout) {
alarmSignValue = alarmSignValue | 1 << 18;
}
if (alarmParkingTimeout) {
alarmSignValue = alarmSignValue | 1 << 19;
}
if (alarmRegion) {
alarmSignValue = alarmSignValue | 1 << 20;
}
if (alarmRoute) {
alarmSignValue = alarmSignValue | 1 << 21;
}
if (alarmTravelTime) {
alarmSignValue = alarmSignValue | 1 << 22;
}
if (alarmRouteDeviation) {
alarmSignValue = alarmSignValue | 1 << 23;
}
if (alarmVSS) {
alarmSignValue = alarmSignValue | 1 << 24;
}
if (alarmOil) {
alarmSignValue = alarmSignValue | 1 << 25;
}
if (alarmStolen) {
alarmSignValue = alarmSignValue | 1 << 26;
}
if (alarmIllegalIgnition) {
alarmSignValue = alarmSignValue | 1 << 27;
}
if (alarmIllegalDisplacement) {
alarmSignValue = alarmSignValue | 1 << 28;
}
if (alarmRollover) {
alarmSignValue = alarmSignValue | 1 << 29;
}
if (warningRollover) {
alarmSignValue = alarmSignValue | 1 << 30;
}
byteBuf.writeInt(alarmSignValue);
return byteBuf;
}
@Override
public String toString() {
return "状态报警标志位:" +
"\n 紧急报警:" + (urgent?"":"") +
"\n 超速报警:" + (alarmSpeeding?"":"") +
"\n 疲劳驾驶报警:" + (alarmTired?"":"") +
"\n 危险驾驶行为报警:" + (alarmDangerous?"":"") +
"\n GNSS 模块发生故障报警:" + (alarmGnssFault?"":"") +
"\n GNSS 天线未接或被剪断报警:" + (alarmGnssBreak?"":"") +
"\n GNSS 天线短路报警:" + (alarmGnssShortCircuited?"":"") +
"\n 终端主电源欠压报警:" + (alarmUnderVoltage?"":"") +
"\n 终端主电源掉电报警:" + (alarmPowerOff?"":"") +
"\n 终端LCD或显示器故障报警" + (alarmLCD?"":"") +
"\n TTS 模块故障报警:" + (alarmTtsFault?"":"") +
"\n 摄像头故障报警:" + (alarmCameraFault?"":"") +
"\n 道路运输证IC卡模块故障报警" + (alarmIcFault?"":"") +
"\n 超速预警:" + (warningSpeeding?"":"") +
"\n 疲劳驾驶预警:" + (warningTired?"":"") +
"\n 违规行驶报警:" + (alarmWrong ?"":"") +
"\n 胎压预警:" + (warningTirePressure?"":"") +
"\n 右转盲区异常报警:" + (alarmBlindZone?"":"") +
"\n 当天累计驾驶超时报警:" + (alarmDrivingTimeout?"":"") +
"\n 超时停车报警:" + (alarmParkingTimeout?"":"") +
"\n 进出区域报警:" + (alarmRegion?"":"") +
"\n 进出路线报警:" + (alarmRoute?"":"") +
"\n 路段行驶时间不足/过长报警:" + (alarmTravelTime?"":"") +
"\n 路线偏离报警:" + (alarmRouteDeviation?"":"") +
"\n 车辆 VSS 故障:" + (alarmVSS?"":"") +
"\n 车辆油量异常报警:" + (alarmOil?"":"") +
"\n 车辆被盗报警(通过车辆防盗器)" + (alarmStolen?"":"") +
"\n 车辆非法点火报警:" + (alarmIllegalIgnition?"":"") +
"\n 车辆非法位移报警:" + (alarmIllegalDisplacement?"":"") +
"\n 碰撞侧翻报警:" + (alarmRollover?"":"") +
"\n 侧翻预警:" + (warningRollover?"":"") +
"\n ";
}
}

View File

@ -0,0 +1,103 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "区域属性")
public class JTAreaAttribute {
@Schema(description = "是否启用起始时间与结束时间的判断规则 ,falsetrue")
private boolean ruleForTimeLimit;
@Schema(description = "是否启用最高速度、超速持续时间和夜间最高速度的判断规则 ,falsetrue")
private boolean ruleForSpeedLimit;
@Schema(description = "进区域是否报警给驾驶员,falsetrue")
private boolean ruleForAlarmToDriverWhenEnter;
@Schema(description = "进区域是否报警给平台 ,falsetrue")
private boolean ruleForAlarmToPlatformWhenEnter;
@Schema(description = "出区域是否报警给驾驶员,falsetrue")
private boolean ruleForAlarmToDriverWhenExit;
@Schema(description = "出区域是否报警给平台 ,falsetrue")
private boolean ruleForAlarmToPlatformWhenExit;
@Schema(description = "false北纬true南纬")
private boolean southLatitude;
@Schema(description = "false东经true西经")
private boolean westLongitude;
@Schema(description = "false允许开门true禁止开门")
private boolean prohibitOpeningDoors;
@Schema(description = "false进区域开启通信模块true进区域关闭通信模块")
private boolean ruleForTurnOffCommunicationWhenEnter;
@Schema(description = "false进区域不采集 GNSS 详细定位数据true进区域采集 GNSS 详细定位数据")
private boolean ruleForGnssWhenEnter;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
short content = 0 ;
if (ruleForTimeLimit) {
content |= 1;
}
if (ruleForSpeedLimit) {
content |= (1 << 1);
}
if (ruleForAlarmToDriverWhenEnter) {
content |= (1 << 2);
}
if (ruleForAlarmToPlatformWhenEnter) {
content |= (1 << 3);
}
if (ruleForAlarmToDriverWhenExit) {
content |= (1 << 4);
}
if (ruleForAlarmToPlatformWhenExit) {
content |= (1 << 5);
}
if (southLatitude) {
content |= (1 << 6);
}
if (westLongitude) {
content |= (byte) (1 << 7);
}
if (prohibitOpeningDoors) {
content |= (1 << (0 + 8));
}
if (ruleForTurnOffCommunicationWhenEnter) {
content |= (1 << (1 + 8));
}
if (ruleForGnssWhenEnter) {
content |= (1 << (2 + 8));
}
byteBuf.writeShort((short)(content & 0xffff));
return byteBuf;
}
public static JTAreaAttribute decode(int attributeInt) {
JTAreaAttribute attribute = new JTAreaAttribute();
attribute.setRuleForTimeLimit((attributeInt & 1) == 1);
attribute.setRuleForSpeedLimit((attributeInt >> 1 & 1) == 1);
attribute.setRuleForAlarmToDriverWhenEnter((attributeInt >> 2 & 1) == 1);
attribute.setRuleForAlarmToPlatformWhenEnter((attributeInt >> 3 & 1) == 1);
attribute.setRuleForAlarmToDriverWhenExit((attributeInt >> 4 & 1) == 1);
attribute.setRuleForAlarmToPlatformWhenExit((attributeInt >> 5 & 1) == 1);
attribute.setSouthLatitude((attributeInt >> 6 & 1) == 1);
attribute.setWestLongitude((attributeInt >> 7 & 1) == 1);
attribute.setProhibitOpeningDoors((attributeInt >> 8 & 1) == 1);
attribute.setRuleForTurnOffCommunicationWhenEnter((attributeInt >> 9 & 1) == 1);
attribute.setRuleForGnssWhenEnter((attributeInt >> 10 & 1) == 1);
return attribute;
}
}

View File

@ -0,0 +1,4 @@
package com.genersoft.iot.vmp.jt1078.bean;
public interface JTAreaOrRoute {
}

View File

@ -0,0 +1,67 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.util.ObjectUtils;
/**
* JT 通道
*/
@Data
@Schema(description = "jt808通道")
@EqualsAndHashCode(callSuper = true)
public class JTChannel extends CommonGBChannel {
@Schema(description = "数据库自增ID")
private int id;
@Schema(description = "名称")
private String name;
@Schema(description = "设备的数据库ID")
private int terminalDbId;
@Schema(description = "通道ID")
private Integer channelId;
@Schema(description = "是否含有音频")
private boolean hasAudio;
@Schema(description = "创建时间")
private String createTime;
@Schema(description = "更新时间")
private String updateTime;
@Schema(description = "流信息")
private String stream;
private Integer dataType = ChannelDataType.JT_1078;
@Override
public String toString() {
return "JTChannel{" +
"id=" + id +
", name='" + name + '\'' +
", terminalDbId=" + terminalDbId +
", channelId=" + channelId +
", createTime='" + createTime + '\'' +
", updateTime='" + updateTime + '\'' +
", hasAudio='" + hasAudio + '\'' +
'}';
}
public CommonGBChannel buildCommonGBChannel() {
if (ObjectUtils.isEmpty(this.getGbDeviceId())) {
return null;
}
if (ObjectUtils.isEmpty(this.getGbName())) {
this.setGbName(this.getName());
}
return this;
}
}

View File

@ -0,0 +1,94 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.nio.charset.Charset;
import java.util.Date;
@Setter
@Getter
@Schema(description = "圆形区域")
public class JTCircleArea implements JTAreaOrRoute{
@Schema(description = "区域 ID")
private long id;
@Schema(description = "")
private JTAreaAttribute attribute;
@Schema(description = "中心点纬度")
private Double latitude;
@Schema(description = "中心点经度")
private Double longitude;
@Schema(description = "半径,单位为米(m)")
private long radius;
@Schema(description = "起始时间, yyyy-MM-dd HH:mm:ss")
private String startTime;
@Schema(description = "结束时间, yyyy-MM-dd HH:mm:ss")
private String endTime;
@Schema(description = "最高速度, 单位为千米每小时(km/h)")
private int maxSpeed;
@Schema(description = "超速持续时间, 单位为秒(s)")
private int overSpeedDuration;
@Schema(description = "夜间最高速度, 单位为千米每小时(km/h)")
private int nighttimeMaxSpeed;
@Schema(description = "区域的名称")
private String name;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (id & 0xffffffffL));
byteBuf.writeBytes(attribute.encode());
byteBuf.writeInt((int) (Math.round((latitude * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((longitude * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (radius & 0xffffffffL));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime)));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime)));
byteBuf.writeShort((short)(maxSpeed & 0xffff));
byteBuf.writeByte(overSpeedDuration);
byteBuf.writeShort((short)(nighttimeMaxSpeed & 0xffff));
byteBuf.writeShort((short)(name.getBytes(Charset.forName("GBK")).length & 0xffff));
byteBuf.writeCharSequence(name, Charset.forName("GBK"));
return byteBuf;
}
public static JTCircleArea decode(ByteBuf buf) {
JTCircleArea area = new JTCircleArea();
area.setId(buf.readUnsignedInt());
int attributeInt = buf.readUnsignedShort();
JTAreaAttribute areaAttribute = JTAreaAttribute.decode(attributeInt);
area.setAttribute(areaAttribute);
area.setLatitude(buf.readUnsignedInt()/1000000D);
area.setLongitude(buf.readUnsignedInt()/1000000D);
area.setRadius(buf.readUnsignedInt());
byte[] startTimeBytes = new byte[6];
buf.readBytes(startTimeBytes);
area.setStartTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(startTimeBytes)));
byte[] endTimeBytes = new byte[6];
buf.readBytes(endTimeBytes);
area.setEndTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(endTimeBytes)));
area.setMaxSpeed(buf.readUnsignedShort());
area.setOverSpeedDuration(buf.readUnsignedByte());
area.setNighttimeMaxSpeed(buf.readUnsignedShort());
int nameLength = buf.readUnsignedShort();
area.setName(buf.readCharSequence(nameLength, Charset.forName("GBK")).toString().trim());
return area;
}
}

View File

@ -0,0 +1,57 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* JT 通信模块属性
*/
@Setter
@Getter
@Schema(description = "JT通信模块属性")
public class JTCommunicationModuleAttribute {
private boolean gprs ;
private boolean cdma ;
private boolean tdScdma ;
private boolean wcdma ;
private boolean cdma2000 ;
private boolean tdLte ;
private boolean other ;
public static JTCommunicationModuleAttribute getInstance(short content) {
boolean gprs = (content & 1) == 1;
boolean cdma = (content >>> 1 & 1) == 1;
boolean tdScdma = (content >>> 2 & 1) == 1;
boolean wcdma = (content >>> 3 & 1) == 1;
boolean cdma2000 = (content >>> 4 & 1) == 1;
boolean tdLte = (content >>> 5 & 1) == 1;
boolean other = (content >>> 7 & 1) == 1;
return new JTCommunicationModuleAttribute(gprs, cdma, tdScdma, wcdma, cdma2000, tdLte, other);
}
public JTCommunicationModuleAttribute(boolean gprs, boolean cdma, boolean tdScdma, boolean wcdma, boolean cdma2000, boolean tdLte, boolean other) {
this.gprs = gprs;
this.cdma = cdma;
this.tdScdma = tdScdma;
this.wcdma = wcdma;
this.cdma2000 = cdma2000;
this.tdLte = tdLte;
this.other = other;
}
@Override
public String toString() {
return "JCommunicationModuleAttribute{" +
"gprs=" + gprs +
", cdma=" + cdma +
", tdScdma=" + tdScdma +
", wcdma=" + wcdma +
", cdma2000=" + cdma2000 +
", tdLte=" + tdLte +
", other=" + other +
'}';
}
}

View File

@ -0,0 +1,65 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "人工确认报警类型")
public class JTConfirmationAlarmMessageType {
@Schema(description = "确认紧急报警")
private boolean urgent;
@Schema(description = "确认危险预警")
private boolean alarmDangerous;
@Schema(description = "确认进出区域报警")
private boolean alarmRegion;
@Schema(description = "确认进出路线报警")
private boolean alarmRoute;
@Schema(description = "确认路段行驶时间不足/过长报警")
private boolean alarmTravelTime;
@Schema(description = "确认车辆非法点火报警")
private boolean alarmIllegalIgnition;
@Schema(description = "确认车辆非法位移报警")
private boolean alarmIllegalDisplacement;
public long encode(){
long result = 0L;
if (urgent) {
result |= 0x01;
}
if (alarmDangerous) {
result |= (0x01 << 3);
}
if (alarmRegion) {
result |= (0x01 << 20);
}
if (alarmRoute) {
result |= (0x01 << 21);
}
if (alarmTravelTime) {
result |= (0x01 << 22);
}
if (alarmIllegalIgnition) {
result |= (0x01 << 27);
}
if (alarmIllegalDisplacement) {
result |= (0x01 << 28);
}
return result;
}
@Override
public String toString() {
return "JConfirmationAlarmMessageType{" +
"urgent=" + urgent +
", alarmDangerous=" + alarmDangerous +
", alarmRegion=" + alarmRegion +
", alarmRoute=" + alarmRoute +
", alarmTravelTime=" + alarmTravelTime +
", alarmIllegalIgnition=" + alarmIllegalIgnition +
", alarmIllegalDisplacement=" + alarmIllegalDisplacement +
'}';
}
}

View File

@ -0,0 +1,92 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* JT 设备
*/
@Data
@Schema(description = "jt808设备")
public class JTDevice {
private int id;
@Schema(description = "省域ID")
private String provinceId;
@Schema(description = "省域文字描述")
private String provinceText;
@Schema(description = "市县域ID")
private String cityId;
@Schema(description = "市县域文字描述")
private String cityText;
@Schema(description = "制造商ID")
private String makerId;
@Schema(description = "终端型号")
private String model;
@Schema(description = "终端手机号")
private String phoneNumber;
@Schema(description = "终端ID")
private String terminalId;
@Schema(description = "车牌颜色")
private int plateColor;
@Schema(description = "车牌")
private String plateNo;
@Schema(description = "鉴权码")
private String authenticationCode;
@Schema(description = "经度")
private Double longitude;
@Schema(description = "纬度")
private Double latitude;
@Schema(description = "注册时间")
private String registerTime;
@Schema(description = "创建时间")
private String createTime;
@Schema(description = "更新时间")
private String updateTime;
@Schema(description = "状态")
private boolean status;
@Schema(description = "设备使用的媒体id, 默认为null")
private String mediaServerId;
@Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
private String geoCoordSys;
@Schema(description = "收流IP")
private String sdpIp;
@Override
public String toString() {
return "JTDevice{" +
" 终端手机号='" + phoneNumber + '\'' +
", 省域ID='" + provinceId + '\'' +
", 省域文字描述='" + provinceText + '\'' +
", 市县域ID='" + cityId + '\'' +
", 市县域文字描述='" + cityText + '\'' +
", 制造商ID='" + makerId + '\'' +
", 终端型号='" + model + '\'' +
", 设备ID='" + terminalId + '\'' +
", 车牌颜色=" + plateColor +
", 车牌='" + plateNo + '\'' +
", 注册时间='" + registerTime + '\'' +
", status=" + status +
'}';
}
}

View File

@ -0,0 +1,56 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* JT 终端属性
*/
@Setter
@Getter
@Schema(description = "JT终端属性")
public class JTDeviceAttribute {
@Schema(description = "终端类型")
private JTDeviceType type;
@Schema(description = "制造商 ID")
private String makerId;
@Schema(description = "终端型号")
private String deviceModel;
@Schema(description = "终端 ID")
private String terminalId;
@Schema(description = "终端 SIM卡 ICCID")
private String iccId;
@Schema(description = "终端硬件版本号")
private String hardwareVersion;
@Schema(description = "固件版本号")
private String firmwareVersion ;
@Schema(description = "GNSS 模块属性")
private JTGnssAttribute gnssAttribute ;
@Schema(description = "通信模块属性")
private JTCommunicationModuleAttribute communicationModuleAttribute ;
@Override
public String toString() {
return "JTDeviceAttribute{" +
"type=" + type +
", makerId='" + makerId + '\'' +
", deviceModel='" + deviceModel + '\'' +
", terminalId='" + terminalId + '\'' +
", iccId='" + iccId + '\'' +
", hardwareVersion='" + hardwareVersion + '\'' +
", firmwareVersion='" + firmwareVersion + '\'' +
", gnssAttribute=" + gnssAttribute +
", communicationModuleAttribute=" + communicationModuleAttribute +
'}';
}
}

View File

@ -0,0 +1,380 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.bean.common.ConfigAttribute;
import com.genersoft.iot.vmp.jt1078.bean.config.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* JT 终端参数设置
*/
@Schema(description = "JT终端参数设置")
@Data
public class JTDeviceConfig {
@ConfigAttribute(id = 0x1, type="Long", description = "终端心跳发送间隔,单位为秒(s)")
private Long keepaliveInterval;
@ConfigAttribute(id = 0x2, type="Long", description = "TCP消息应答超时时间,单位为秒(s)")
private Long tcpResponseTimeout;
@ConfigAttribute(id = 0x3, type="Long", description = "TCP消息重传次数")
private Long tcpRetransmissionCount;
@ConfigAttribute(id = 0x4, type="Long", description = "UDP消息应答超时时间,单位为秒(s)")
private Long udpResponseTimeout;
@ConfigAttribute(id = 0x5, type="Long", description = "UDP消息重传次数")
private Long udpRetransmissionCount;
@ConfigAttribute(id = 0x6, type="Long", description = "SMS 消息应答超时时间,单位为秒(s)")
private Long smsResponseTimeout;
@ConfigAttribute(id = 0x7, type="Long", description = "SMS 消息重传次数")
private Long smsRetransmissionCount;
@ConfigAttribute(id = 0x10, type="String", description = "主服务器APN无线通信拨号访问点,若网络制式为 CDMA,则该处 为 PPP拨号号码")
private String apnMaster;
@ConfigAttribute(id = 0x11, type="String", description = "主服务器无线通信拨号用户名")
private String dialingUsernameMaster;
@ConfigAttribute(id = 0x12, type="String", description = "主服务器无线通信拨号密码")
private String dialingPasswordMaster;
@ConfigAttribute(id = 0x13, type="String", description = "主服务器地址IP或域名,以冒号分割主机和端口 多个服务器使用分号分割")
private String addressMaster;
@ConfigAttribute(id = 0x14, type="String", description = "备份服务器APN")
private String apnBackup;
@ConfigAttribute(id = 0x15, type="String", description = "备份服务器无线通信拨号用户名")
private String dialingUsernameBackup;
@ConfigAttribute(id = 0x16, type="String", description = "备份服务器无线通信拨号密码")
private String dialingPasswordBackup;
@ConfigAttribute(id = 0x17, type="String", description = "备用服务器备份地址IP或域名,以冒号分割主机和端口 多个服务器使用分号分割")
private String addressBackup;
@ConfigAttribute(id = 0x1a, type="String", description = "道路运输证IC卡认证主服务器IP地址或域名")
private String addressIcMaster;
@ConfigAttribute(id = 0x1b, type="Long", description = "道路运输证IC卡认证主服务器TCP端口")
private Long tcpPortIcMaster;
@ConfigAttribute(id = 0x1c, type="Long", description = "道路运输证IC卡认证主服务器UDP端口")
private Long udpPortIcMaster;
@ConfigAttribute(id = 0x1d, type="String", description = "道路运输证IC卡认证备份服务器IP地址或域名,端口同主服务器")
private String addressIcBackup;
@ConfigAttribute(id = 0x20, type="Long", description = "位置汇报策略, 0定时汇报 1定距汇报 2定时和定距汇报")
private Long locationReportingStrategy;
@ConfigAttribute(id = 0x21, type="Long", description = "位置汇报方案,0根据ACC状态 1根据登录状态和ACC状态,先判断登录状态,若登录再根据ACC状态")
private Long locationReportingPlan;
@ConfigAttribute(id = 0x22, type="Long", description = "驾驶员未登录汇报时间间隔,单位为秒,值大于零")
private Long reportingIntervalOffline;
@ConfigAttribute(id = 0x23, type="String", description = "从服务器 APN# 该值为空时 !终端应使用主服务器相同配置")
private String apnSlave;
@ConfigAttribute(id = 0x24, type="String", description = "从服务器无线通信拨号用户名 # 该值为空时 !终端应使用主服务器 相同配置")
private String dialingUsernameSlave;
@ConfigAttribute(id = 0x25, type="String", description = "从服务器无线通信拨号密码 # 该值为空时 !终端应使用主服务器相 同配置")
private String dialingPasswordSlave;
@ConfigAttribute(id = 0x26, type="String", description = "从服务器备份地址 IP或域名 !主机和端口用冒号分割 !多个服务器 使用分号分割")
private String addressSlave;
@ConfigAttribute(id = 0x27, type="Long", description = "休眠时汇报时间间隔 单位为秒 值大于0")
private Long reportingIntervalDormancy;
@ConfigAttribute(id = 0x28, type="Long", description = "紧急报警时汇报时间间隔 单位为秒 值大于0")
private Long reportingIntervalEmergencyAlarm;
@ConfigAttribute(id = 0x29, type="Long", description = "缺省时间汇报间隔 单位为秒 值大于0")
private Long reportingIntervalDefault;
@ConfigAttribute(id = 0x2c, type="Long", description = "缺省距离汇报间隔 单位为米 值大于0")
private Long reportingDistanceDefault;
@ConfigAttribute(id = 0x2d, type="Long", description = "驾驶员未登录汇报距离间隔 单位为米 值大于0")
private Long reportingDistanceOffline;
@ConfigAttribute(id = 0x2e, type="Long", description = "休眠时汇报距离间隔 单位为米 值大于0")
private Long reportingDistanceDormancy;
@ConfigAttribute(id = 0x2f, type="Long", description = "紧急报警时汇报距离间隔 单位为米 值大于0")
private Long reportingDistanceEmergencyAlarm;
@ConfigAttribute(id = 0x30, type="Long", description = "拐点补传角度 ,值小于180")
private Long inflectionPointAngle;
@ConfigAttribute(id = 0x31, type="Integer", description = "电子围栏半径(非法位移國值) ,单位为米(m)")
private Integer fenceRadius;
@ConfigAttribute(id = 0x32, type="IllegalDrivingPeriods", description = "违规行驶时段范围 ,精确到分")
private JTIllegalDrivingPeriods illegalDrivingPeriods;
@ConfigAttribute(id = 0x40, type="String", description = "监控平台电话号码")
private String platformPhoneNumber;
@ConfigAttribute(id = 0x41, type="String", description = "复位电话号码 ,可采用此电话号码拨打终端电话让终端复位")
private String phoneNumberForReset;
@ConfigAttribute(id = 0x42, type="String", description = "恢复出厂设置电话号码 ,可采用此电话号码拨打终端电话让终端恢 复出厂设置")
private String phoneNumberForFactoryReset;
@ConfigAttribute(id = 0x42, type="String", description = "监控平台 SMS 电话号码")
private String phoneNumberForSms;
@ConfigAttribute(id = 0x44, type="String", description = "接收终端 SMS 文本报警号码")
private String phoneNumberForReceiveTextAlarm;
@ConfigAttribute(id = 0x45, type="Long", description = "终端电话接听策略 。0:自动接听1:ACC ON时自动接听 ,OFF时手动接听")
private Long phoneAnsweringPolicy;
@ConfigAttribute(id = 0x46, type="Long", description = "每次最长通话时间 ,单位为秒(s) ,0 为不允许通话 ,0xFFFFFFFF为不限制")
private Long longestCallTimeForPerSession;
@ConfigAttribute(id = 0x47, type="Long", description = "当月最长通话时间 ,单位为秒(s) ,0 为不允许通话 ,0xFFFFFFFF为 不限制")
private Long longestCallTimeInMonth;
@ConfigAttribute(id = 0x48, type="String", description = "监听电话号码")
private String phoneNumbersForListen;
@ConfigAttribute(id = 0x49, type="String", description = "监管平台特权短信号码")
private String privilegedSMSNumber;
@ConfigAttribute(id = 0x50, type="AlarmSign", description = "报警屏蔽字 ,与位置信息汇报消息中的报警标志相对应 ,相应位为 1 则相应报警被屏蔽")
private JTAlarmSign alarmMaskingWord;
@ConfigAttribute(id = 0x51, type="AlarmSign", description = "报警发送文本 SMS 开关 , 与位置信息汇报消息中的报警标志相对 应 ,相应位为1 则相应报警时发送文本 SMS")
private JTAlarmSign alarmSendsTextSmsSwitch;
@ConfigAttribute(id = 0x52, type="AlarmSign", description = "报警拍摄开关 ,与位置信息汇报消息中的报警标志相对应 ,相应位为 1 则相应报警时摄像头拍摄")
private JTAlarmSign alarmShootingSwitch;
@ConfigAttribute(id = 0x53, type="AlarmSign", description = "报警拍摄存储标志 ,与位置信息汇报消息中的报警标志相对应 ,相应 位为1 则对相应报警时拍的照片进行存储 ,否则实时上传")
private JTAlarmSign alarmShootingStorageFlags;
@ConfigAttribute(id = 0x54, type="AlarmSign", description = "关键标志 ,与位置信息汇报消息中的报警标志相对应 ,相应位为 1 则 对相应报警为关键报警")
private JTAlarmSign KeySign;
@ConfigAttribute(id = 0x55, type="Long", description = "最高速度 ,单位为千米每小时(km/h)")
private Long maxSpeed;
@ConfigAttribute(id = 0x56, type="Long", description = "超速持续时间 ,单位为秒(s)")
private Long overSpeedDuration;
@ConfigAttribute(id = 0x57, type="Long", description = "连续驾驶时间门限 单位为秒(s)")
private Long continuousDrivingTimeThreshold;
@ConfigAttribute(id = 0x58, type="Long", description = "当天累计驾驶时间门限 单位为秒(s)")
private Long cumulativeDrivingTimeThresholdForTheDay;
@ConfigAttribute(id = 0x59, type="Long", description = "最小休息时间 单位为秒(s)")
private Long minimumBreakTime;
@ConfigAttribute(id = 0x5a, type="Long", description = "最长停车时间 单位为秒(s)")
private Long maximumParkingTime;
@ConfigAttribute(id = 0x5b, type="Integer", description = "超速预警差值 单位为1/10 千米每小时(1/10km/h)")
private Integer overSpeedWarningDifference;
@ConfigAttribute(id = 0x5c, type="Integer", description = "疲劳驾驶预警差值 单位为秒 值大于零")
private Integer drowsyDrivingWarningDifference;
@ConfigAttribute(id = 0x5d, type="CollisionAlarmParams", description = "碰撞报警参数设置")
private JTCollisionAlarmParams collisionAlarmParams;
@ConfigAttribute(id = 0x5e, type="Integer", description = "侧翻报警参数设置:侧翻角度,单位为度,默认为30")
private Integer rolloverAlarm;
@ConfigAttribute(id = 0x64, type="CameraTimer", description = "定时拍照控制")
private JTCameraTimer cameraTimer;
@ConfigAttribute(id = 0x70, type="Long", description = "图像/视频质量 设置范围为1~10 1表示最优质量")
private Long qualityForVideo;
@ConfigAttribute(id = 0x71, type="Long", description = "亮度设置范围为0 ~ 255")
private Long brightness;
@ConfigAttribute(id = 0x72, type="Long", description = "对比度设置范围为0 ~ 127")
private Long contrastRatio;
@ConfigAttribute(id = 0x73, type="Long", description = "饱和度设置范围为0 ~ 127")
private Long saturation;
@ConfigAttribute(id = 0x74, type="Long", description = "色度设置范围为0 ~ 255")
private Long chroma;
@ConfigAttribute(id = 0x75, type="VideoParam", description = "音视频参数设置")
private JTVideoParam videoParam;
@ConfigAttribute(id = 0x76, type="ChannelListParam", description = "音视频通道列表设置")
private JTChannelListParam channelListParam;
@ConfigAttribute(id = 0x77, type="ChannelParam", description = "单独视频通道参数设置")
private JTChannelParam channelParam;
@ConfigAttribute(id = 0x79, type="AlarmRecordingParam", description = "特殊报警录像参数设置")
private JTAlarmRecordingParam alarmRecordingParam;
@ConfigAttribute(id = 0x7a, type="VideoAlarmBit", description = "视频相关报警屏蔽字")
private JTVideoAlarmBit videoAlarmBit;
@ConfigAttribute(id = 0x7b, type="AnalyzeAlarmParam", description = "图像分析报警参数设置")
private JTAnalyzeAlarmParam analyzeAlarmParam;
@ConfigAttribute(id = 0x7c, type="AwakenParam", description = "终端休眠唤醒模式设置")
private JTAwakenParam awakenParam;
@ConfigAttribute(id = 0x80, type="Long", description = "车辆里程表读数,单位'1/10km")
private Long mileage;
@ConfigAttribute(id = 0x81, type="Integer", description = "车辆所在的省域ID")
private Integer provincialId;
@ConfigAttribute(id = 0x82, type="Integer", description = "车辆所在的市域ID")
private Integer cityId;
@ConfigAttribute(id = 0x83, type="String", description = "公安交通管理部门颁发的机动车号牌")
private String licensePlate;
@ConfigAttribute(id = 0x84, type="Short", description = "车牌颜色,值按照JT/T697-7.2014中的规定,未上牌车辆填0")
private Short licensePlateColor;
@ConfigAttribute(id = 0x90, type="GnssPositioningMode", description = "GNSS定位模式")
private JTGnssPositioningMode gnssPositioningMode;
@ConfigAttribute(id = 0x91, type="Short", description = "GNSS 波特率,定义如下: 0: 4800, 1:9600, 219200, 3:38400, 4:57600, 5:115200")
private Short gnssBaudRate;
@ConfigAttribute(id = 0x92, type="Short", description = "GNSS 模块详细定位数据输出频率,定义如下: 0: 500ms, 1:1000ms(默认值), 22000ms, 3:3000ms, 4:4000ms")
private Short gnssOutputFrequency;
@ConfigAttribute(id = 0x93, type="Long", description = "GNSS 模块详细定位数据采集频率 ,单位为秒(s) ,默认为1")
private Long gnssCollectionFrequency;
@ConfigAttribute(id = 0x94, type="Short", description = "GNSS 模块详细定位数据上传方式:,定义如下: " +
"0: 本地存储 ,不上传(默认值) , " +
"1:按时间间隔上传, " +
"2按距离间隔上传, " +
"11:按累计时间上传 ,达到传输时间后自动停止上传, " +
"12:按累计距离上传 ,达到距离后自动停止上传, " +
"13:按累计条数上传 ,达到上传条数后自动停止上传")
private Short gnssDataUploadMethod;
@ConfigAttribute(id = 0x95, type="Long", description = "GNSS 模块详细定位数据上传设置:,定义如下: " +
"1:单位为秒(s), " +
"2单位为米(m) , " +
"11:单位为 秒(s), " +
"12:单位为米(m), " +
"13:单位 为条")
private Long gnssDataUploadMethodUnit;
@ConfigAttribute(id = 0x100, type="Long", description = "CAN总线通道1 采集时间间隔 ,单位为毫秒(ms) ,0 表示不采集")
private Long canCollectionTimeForChannel1;
@ConfigAttribute(id = 0x101, type="Integer", description = "CAN总线通道1 上传时间间隔 ,单位为秒(s) ,0 表示不上传")
private Integer canUploadIntervalForChannel1;
@ConfigAttribute(id = 0x102, type="Long", description = "CAN总线通道2 采集时间间隔 ,单位为毫秒(ms) ,0 表示不采集")
private Long canCollectionTimeForChannel2;
@ConfigAttribute(id = 0x103, type="Integer", description = "CAN总线通道2 上传时间间隔 ,单位为秒(s) ,0 表示不上传")
private Integer canUploadIntervalForChannel2;
@Override
public String toString() {
return "JTDeviceConfig{" +
"终端心跳发送间隔: " + keepaliveInterval + "" +
", TCP消息应答超时时间" + tcpResponseTimeout + "" +
", TCP消息重传次数 " + tcpRetransmissionCount + "" +
", UDP消息应答超时时间 " + udpResponseTimeout +
", UDP消息重传次数 " + udpRetransmissionCount +
", SMS 消息应答超时时间: " + smsResponseTimeout + "" +
", SMS 消息重传次数: " + smsRetransmissionCount +
", 主服务器APN无线通信拨号访问点 " + apnMaster + '\'' +
", 主服务器无线通信拨号用户名: " + dialingUsernameMaster +
", 主服务器无线通信拨号密码: " + dialingPasswordMaster +
", 主服务器地址IP或域名 " + addressMaster +
", 备份服务器APN " + apnBackup +
", 备份服务器无线通信拨号用户名: " + dialingUsernameBackup +
", 备份服务器无线通信拨号密码: " + dialingPasswordBackup +
", 备用服务器备份地址IP或域名 " + addressBackup +
", 道路运输证IC卡认证主服务器IP地址或域名 " + addressIcMaster +
", 道路运输证IC卡认证主服务器TCP端口 " + tcpPortIcMaster +
", 道路运输证IC卡认证主服务器UDP端口 " + udpPortIcMaster +
", 道路运输证IC卡认证备份服务器IP地址或域名 " + addressIcBackup +
", 位置汇报策略: " + locationReportingStrategy +
", 位置汇报方案: " + locationReportingPlan +
", 驾驶员未登录汇报时间间隔: " + reportingIntervalOffline + "" +
", 从服务器 APN " + apnSlave +
", 从服务器无线通信拨号密码: " + dialingUsernameSlave +
", 从服务器备份地址 IP或域名 " + dialingPasswordSlave +
", 从服务器备份地址 IP或域名 " + addressSlave +
", reportingIntervalDormancy " + reportingIntervalDormancy +
", reportingIntervalEmergencyAlarm " + reportingIntervalEmergencyAlarm +
", reportingIntervalDefault " + reportingIntervalDefault +
", reportingDistanceDefault " + reportingDistanceDefault +
", reportingDistanceOffline " + reportingDistanceOffline +
", reportingDistanceDormancy " + reportingDistanceDormancy +
", reportingDistanceEmergencyAlarm " + reportingDistanceEmergencyAlarm +
", inflectionPointAngle " + inflectionPointAngle +
", fenceRadius " + fenceRadius +
", illegalDrivingPeriods " + illegalDrivingPeriods +
", platformPhoneNumber " + platformPhoneNumber +
", phoneNumberForReset " + phoneNumberForReset +
", phoneNumberForFactoryReset " + phoneNumberForFactoryReset +
", phoneNumberForSms " + phoneNumberForSms +
", phoneNumberForReceiveTextAlarm " + phoneNumberForReceiveTextAlarm +
", phoneAnsweringPolicy " + phoneAnsweringPolicy +
", longestCallTimeForPerSession " + longestCallTimeForPerSession +
", longestCallTimeInMonth " + longestCallTimeInMonth +
", phoneNumbersForListen " + phoneNumbersForListen +
", privilegedSMSNumber " + privilegedSMSNumber +
", alarmMaskingWord " + alarmMaskingWord +
", alarmSendsTextSmsSwitch " + alarmSendsTextSmsSwitch +
", alarmShootingSwitch " + alarmShootingSwitch +
", alarmShootingStorageFlags " + alarmShootingStorageFlags +
", KeySign " + KeySign +
", topSpeed " + maxSpeed +
", overSpeedDuration " + overSpeedDuration +
", continuousDrivingTimeThreshold " + continuousDrivingTimeThreshold +
", cumulativeDrivingTimeThresholdForTheDay " + cumulativeDrivingTimeThresholdForTheDay +
", minimumBreakTime " + minimumBreakTime +
", maximumParkingTime " + maximumParkingTime +
", overSpeedWarningDifference " + overSpeedWarningDifference +
", drowsyDrivingWarningDifference " + drowsyDrivingWarningDifference +
", collisionAlarmParams " + collisionAlarmParams +
", rolloverAlarm " + rolloverAlarm +
", cameraTimer " + cameraTimer +
", qualityForVideo " + qualityForVideo +
", brightness " + brightness +
", contrastRatio " + contrastRatio +
", saturation " + saturation +
", chroma " + chroma +
", mileage " + mileage +
", provincialId " + provincialId +
", cityId " + cityId +
", licensePlate " + licensePlate +
", licensePlateColor " + licensePlateColor +
", gnssPositioningMode " + gnssPositioningMode +
", gnssBaudRate " + gnssBaudRate +
", gnssOutputFrequency " + gnssOutputFrequency +
", gnssCollectionFrequency " + gnssCollectionFrequency +
", gnssDataUploadMethod " + gnssDataUploadMethod +
", gnssDataUploadMethodUnit " + gnssDataUploadMethodUnit +
", canCollectionTimeForChannel1 " + canCollectionTimeForChannel1 +
", canUploadIntervalForChannel1 " + canUploadIntervalForChannel1 +
", canCollectionTimeForChannel2 " + canCollectionTimeForChannel2 +
", canUploadIntervalForChannel2 " + canUploadIntervalForChannel2 +
'}';
}
}

View File

@ -0,0 +1,71 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* JT 终端控制
*/
@Data
@Schema(description = "终端控制")
public class JTDeviceConnectionControl {
/**
* false 表示切换到指定监管平台服务器 ,true 表示切换回原 缺省监控平台服务器
*/
private Boolean switchOn;
/**
* 监管平台鉴权码
*/
private String authentication;
/**
* 拨号点名称
*/
private String name;
/**
* 拨号用户名
*/
private String username;
/**
* 拨号密码
*/
private String password;
/**
* 地址
*/
private String address;
/**
* TCP端口
*/
private Integer tcpPort;
/**
* UDP端口
*/
private Integer udpPort;
/**
* 连接到指定服务器时限
*/
private Long timeLimit;
@Override
public String toString() {
return "JTDeviceConnectionControl{" +
"switchOn=" + switchOn +
", authentication='" + authentication + '\'' +
", name='" + name + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", address='" + address + '\'' +
", tcpPort=" + tcpPort +
", udpPort=" + udpPort +
", timeLimit=" + timeLimit +
'}';
}
}

View File

@ -0,0 +1,83 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* JT 终端类型
*/
@Setter
@Getter
@Schema(description = "JT终端参数设置")
public class JTDeviceType {
/**
* 适用客运车辆
*/
private boolean passengerVehicles;
/**
* 适用危险品车辆
*/
private boolean dangerousGoodsVehicles;
/**
* 普通货运车辆
*/
private boolean freightVehicles;
/**
* 出租车辆
*/
private boolean rentalVehicles;
/**
* 支持硬盘录像
*/
private boolean hardDiskRecording;
/**
* false一体机 ,true分体机
*/
private boolean splittingMachine;
/**
* 适用挂车
*/
private boolean trailer;
public static JTDeviceType getInstance(int content) {
boolean passengerVehicles = (content & 1) == 1;
boolean dangerousGoodsVehicles = (content >>> 1 & 1) == 1;
boolean freightVehicles = (content >>> 2 & 1) == 1;
boolean rentalVehicles = (content >>> 3 & 1) == 1;
boolean hardDiskRecording = (content >>> 6 & 1) == 1;
boolean splittingMachine = (content >>> 7 & 1) == 1;
boolean trailer = (content >>> 8 & 1) == 1;
return new JTDeviceType(passengerVehicles, dangerousGoodsVehicles, freightVehicles, rentalVehicles, hardDiskRecording, splittingMachine, trailer);
}
public JTDeviceType(boolean passengerVehicles, boolean dangerousGoodsVehicles, boolean freightVehicles, boolean rentalVehicles, boolean hardDiskRecording, boolean splittingMachine, boolean trailer) {
this.passengerVehicles = passengerVehicles;
this.dangerousGoodsVehicles = dangerousGoodsVehicles;
this.freightVehicles = freightVehicles;
this.rentalVehicles = rentalVehicles;
this.hardDiskRecording = hardDiskRecording;
this.splittingMachine = splittingMachine;
this.trailer = trailer;
}
@Override
public String toString() {
return "JTDeviceType{" +
"passengerVehicles=" + passengerVehicles +
", dangerousGoodsVehicles=" + dangerousGoodsVehicles +
", freightVehicles=" + freightVehicles +
", rentalVehicles=" + rentalVehicles +
", hardDiskRecording=" + hardDiskRecording +
", splittingMachine=" + splittingMachine +
", trailer=" + trailer +
'}';
}
}

View File

@ -0,0 +1,99 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.Charset;
@Data
@Slf4j
@Schema(description = "驾驶员身份信息")
public class JTDriverInformation {
@Schema(description = "0x01:从业资格证 IC卡插入( 驾驶员上班)0x02:从 业资格证 IC卡拔出(驾驶员下班)")
private int status;
@Schema(description = "插卡/拔卡时间 ,以下字段在状 态为0x01 时才有效并做填充")
private String time;
@Schema(description = "IC卡读取结果:" +
"0x00:IC卡读卡成功" +
"0x01:读卡失败 ,原因为卡片密钥认证未通过;" +
"0x02:读卡失败 ,原因为卡片已被锁定;" +
"0x03:读卡失败 ,原因为卡片被拔出;" +
"0x04:读卡失败 ,原因为数据校验错误。" +
"以下字段在 IC卡读取结果等于0x00 时才有效")
private Integer result;
@Schema(description = "驾驶员姓名")
private String name;
@Schema(description = "从业资格证编码")
private String certificateCode;
@Schema(description = "发证机构名称")
private String certificateIssuanceMechanismName;
@Schema(description = "证件有效期")
private String expire;
@Schema(description = "驾驶员身份证号")
private String driverIdNumber;
public static JTDriverInformation decode(ByteBuf buf, boolean is2019) {
JTDriverInformation jtDriverInformation = new JTDriverInformation();
jtDriverInformation.setStatus(buf.readUnsignedByte());
byte[] bytes = new byte[6];
buf.readBytes(bytes);
String timeStr = BCDUtil.transform(bytes);
try {
jtDriverInformation.setTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(timeStr));
}catch (Exception e) {
log.error("[JT-驾驶员身份信息] 解码时无法格式化时间: {}", timeStr);
}
if (jtDriverInformation.getStatus() == 1) {
int result = (int)buf.readUnsignedByte();
jtDriverInformation.setResult(result);
if (result == 0) {
// IC卡读卡成功
int nameLength = buf.readUnsignedByte();
jtDriverInformation.setName(buf.readCharSequence(nameLength, Charset.forName("GBK")).toString().trim());
jtDriverInformation.setCertificateCode(buf.readCharSequence(20, Charset.forName("GBK")).toString().trim());
int certificateIssuanceMechanismNameLength = buf.readUnsignedByte();
jtDriverInformation.setCertificateIssuanceMechanismName(buf.readCharSequence(
certificateIssuanceMechanismNameLength, Charset.forName("GBK")).toString().trim());
byte[] bytesForExpire = new byte[4];
buf.readBytes(bytesForExpire);
String bytesForExpireStr = BCDUtil.transform(bytesForExpire);
try {
jtDriverInformation.setExpire(DateUtil.jt1078dateToyyyy_MM_dd(bytesForExpireStr));
}catch (Exception e) {
log.error("[JT-驾驶员身份信息] 解码时无法格式化时间: {}", bytesForExpireStr);
}
if (is2019) {
jtDriverInformation.setDriverIdNumber(buf.readCharSequence(20, Charset.forName("GBK")).toString().trim());
}
}
}
return jtDriverInformation;
}
@Override
public String toString() {
return "JTDriverInformation{" +
"status=" + status +
", time='" + time + '\'' +
", result=" + result +
", name='" + name + '\'' +
", certificateCode='" + certificateCode + '\'' +
", certificateIssuanceMechanismName='" + certificateIssuanceMechanismName + '\'' +
", expire='" + expire + '\'' +
", driverIdNumber='" + driverIdNumber + '\'' +
'}';
}
}

View File

@ -0,0 +1,47 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* JT GNSS 模块属性
*/
@Setter
@Getter
@Schema(description = "JTGNSS 模块属性")
public class JTGnssAttribute {
private boolean gps;
private boolean beidou;
private boolean glonass ;
private boolean gaLiLeo;
public static JTGnssAttribute getInstance(short content) {
boolean gps = (content & 1) == 1;
boolean beidou = (content >>> 1 & 1) == 1;
boolean glonass = (content >>> 2 & 1) == 1;
boolean gaLiLeo = (content >>> 3 & 1) == 1;
return new JTGnssAttribute(gps, beidou, glonass, gaLiLeo);
}
public JTGnssAttribute(boolean gps, boolean beidou, boolean glonass, boolean gaLiLeo) {
this.gps = gps;
this.beidou = beidou;
this.glonass = glonass;
this.gaLiLeo = gaLiLeo;
}
@Override
public String toString() {
return "JGnssAttribute{" +
"gps=" + gps +
", beidou=" + beidou +
", glonass=" + glonass +
", gaLiLeo=" + gaLiLeo +
'}';
}
}

View File

@ -0,0 +1,129 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.bean.config.JTDeviceSubConfig;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 终端上传音视频属性
*/
@Setter
@Getter
public class JTMediaAttribute implements JTDeviceSubConfig {
/**
* 输入音频编码方式:
* 1 G. 721
* 2 G. 722
* 3 G. 723
* 4 G. 728
* 5 G. 729
* 6 G. 711A
* 7 G. 711U
* 8 G. 726
* 9 G. 729A
* 10 DVI4_3
* 11 DVI4_4
* 12 DVI4_8K
* 13 DVI4_16K
* 14 LPC
* 15 S16BE_STEREO
* 16 S16BE_MONO
* 17 MPEGAUDIO
* 18 LPCM
* 19 AAC
* 20 WMA9STD
* 21 HEAAC
* 22 PCM_VOICE
* 23 PCM_AUDIO
* 24 AACLC
* 25 MP3
* 26 ADPCMA
* 27 MP4AUDIO
* 28 AMR
*/
private int audioEncoder;
/**
* 输入音频声道数
*/
private int audioChannels;
/**
* 输入音频采样率:
* 0:8 kHz;
* 1:22. 05 kHz;
* 2:44. 1 kHz;
* 3:48 kHz
*/
private int audioSamplingRate;
/**
* 输入音频采样位数:
* 0:8 ;
* 1:16 ;
* 2:32
*/
private int audioSamplingBits;
/**
* 音频帧长度: 范围 1 ~ 4 294 967 295
*/
private int audioFrameLength;
/**
* 是否支持音频输出:
* 0:不支持;1:支持
*/
private int audioOutputEnable;
/**
* 视频编码方式:
* 98 H. 264
* 99 H. 265
* 100 AVS
* 101 SVAC
*/
private int videoEncoder;
/**
* 终端支持的最大音频物理通道数量:
*/
private int audioChannelMax;
/**
* 终端支持的最大视频物理通道数量:
*/
private int videoChannelMax;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(audioEncoder);
byteBuf.writeByte(audioChannels);
byteBuf.writeByte(audioSamplingRate);
byteBuf.writeByte(audioSamplingBits);
byteBuf.writeShort(audioFrameLength);
byteBuf.writeByte(audioOutputEnable);
byteBuf.writeByte(videoEncoder);
byteBuf.writeByte(audioChannelMax);
byteBuf.writeByte(videoChannelMax);
return byteBuf;
}
public static JTMediaAttribute decode(ByteBuf byteBuf) {
JTMediaAttribute jtMediaAttribute = new JTMediaAttribute();
jtMediaAttribute.setAudioEncoder(byteBuf.readUnsignedByte());
jtMediaAttribute.setAudioChannels(byteBuf.readUnsignedByte());
jtMediaAttribute.setAudioSamplingRate(byteBuf.readUnsignedByte());
jtMediaAttribute.setAudioSamplingBits(byteBuf.readUnsignedByte());
jtMediaAttribute.setAudioFrameLength(byteBuf.readUnsignedShort());
jtMediaAttribute.setAudioOutputEnable(byteBuf.readUnsignedByte());
jtMediaAttribute.setVideoEncoder(byteBuf.readUnsignedByte());
jtMediaAttribute.setAudioChannelMax(byteBuf.readUnsignedByte());
jtMediaAttribute.setVideoChannelMax(byteBuf.readUnsignedByte());
return jtMediaAttribute;
}
}

View File

@ -0,0 +1,48 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "多媒体检索项数据")
public class JTMediaDataInfo {
@Schema(description = "多媒体数据 ID")
private long id;
@Schema(description = "多媒体类型, 0图像1音频2视频")
private int type;
@Schema(description = "事件项编码: 0平台下发指令1定时动作2抢劫报警触发3碰 撞侧翻报警触发4门开拍照5门关拍照6车门由开 变关 ,车速从小于20km到超过20km7定距拍照")
private int eventCode;
@Schema(description = "通道 ID")
private int channelId;
@Schema(description = "表示拍摄或录制的起始时刻的汇报消息")
private JTPositionBaseInfo positionBaseInfo;
public static JTMediaDataInfo decode(ByteBuf buf) {
JTMediaDataInfo jtMediaEventInfo = new JTMediaDataInfo();
jtMediaEventInfo.setId(buf.readUnsignedInt());
jtMediaEventInfo.setType(buf.readUnsignedByte());
jtMediaEventInfo.setChannelId(buf.readUnsignedByte());
jtMediaEventInfo.setEventCode(buf.readUnsignedByte());
jtMediaEventInfo.setPositionBaseInfo(JTPositionBaseInfo.decode(buf));
return jtMediaEventInfo;
}
@Override
public String toString() {
return "JTMediaDataInfo{" +
"id=" + id +
", type=" + type +
", eventCode=" + eventCode +
", channelId=" + channelId +
", positionBaseInfo=" + positionBaseInfo +
'}';
}
}

View File

@ -0,0 +1,62 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "多媒体事件信息")
public class JTMediaEventInfo {
@Schema(description = "多媒体数据 ID")
private long id;
@Schema(description = "多媒体类型, 0图像1音频2视频")
private int type;
@Schema(description = "多媒体格式编码, 0JPEG1TIF2MP33WAV4WMV其他保留")
private int code;
@Schema(description = "事件项编码: 0平台下发指令1定时动作2抢劫报警触发3碰 撞侧翻报警触发4门开拍照5门关拍照6车门由开 变关 ,车速从小于20km到超过20km7定距拍照")
private int eventCode;
@Schema(description = "通道 ID")
private int channelId;
@Schema(description = "媒体数据")
private byte[] mediaData;
@Schema(description = "位置信息汇报")
private JTPositionBaseInfo positionBaseInfo;
public static JTMediaEventInfo decode(ByteBuf buf) {
JTMediaEventInfo jtMediaEventInfo = new JTMediaEventInfo();
jtMediaEventInfo.setId(buf.readUnsignedInt());
jtMediaEventInfo.setType(buf.readUnsignedByte());
jtMediaEventInfo.setCode(buf.readUnsignedByte());
jtMediaEventInfo.setEventCode(buf.readUnsignedByte());
jtMediaEventInfo.setChannelId(buf.readUnsignedByte());
if (buf.readableBytes() > 28) {
ByteBuf byteBuf = buf.readSlice(28);
jtMediaEventInfo.setPositionBaseInfo(JTPositionBaseInfo.decode(byteBuf));
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
jtMediaEventInfo.setMediaData(bytes);
}
return jtMediaEventInfo;
}
@Override
public String toString() {
return "JTMediaEventInfo{" +
"id=" + id +
", type=" + type +
", code=" + code +
", eventCode=" + eventCode +
", channelId=" + channelId +
", fileSize=" + (mediaData == null ? 0 : mediaData.length) +
'}';
}
}

View File

@ -0,0 +1,5 @@
package com.genersoft.iot.vmp.jt1078.bean;
public enum JTMediaStreamType {
PLAY,PLAYBACK,TALK
}

View File

@ -0,0 +1,63 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.bean.config.JTDeviceSubConfig;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 终端上传乘客流量
*/
@Setter
@Getter
public class JTPassengerNum implements JTDeviceSubConfig {
/**
* 起始时间, YY-MM-DD-HH-MM-SS( GMT + 8 时间,本标准中之后涉及的时间均采用此时区)
*/
private String startTime;
/**
* 结束时间, YY-MM-DD-HH-MM-SS( GMT + 8 时间,本标准中之后涉及的时间均采用此时区)
*/
private String endTime;
/**
* 上车人数
*/
private int getIn;
/**
* 下车人数
*/
private int getOut;
@Override
public ByteBuf encode() {
return null;
}
public static JTPassengerNum decode(ByteBuf buf) {
JTPassengerNum jtPassengerNum = new JTPassengerNum();
byte[] bytes = new byte[6];
buf.readBytes(bytes);
jtPassengerNum.setStartTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(bytes)));
buf.readBytes(bytes);
jtPassengerNum.setEndTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(bytes)));
jtPassengerNum.setGetIn(buf.readUnsignedShort());
jtPassengerNum.setGetOut(buf.readUnsignedShort());
return jtPassengerNum;
}
@Override
public String toString() {
return "终端上传乘客流量:" +
" 时间: " + startTime + "" + endTime +
", 上车:" + getIn +
", 下车:" + getOut
;
}
}

View File

@ -0,0 +1,43 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.nio.charset.Charset;
@Setter
@Getter
@Schema(description = "电话本联系人")
public class JTPhoneBookContact {
@Schema(description = "1:呼入,2:呼出,3:呼入/呼出")
private int sign;
@Schema(description = "电话号码")
private String phoneNumber;
@Schema(description = "联系人")
private String contactName;
public ByteBuf encode(){
ByteBuf buffer = Unpooled.buffer();
buffer.writeByte(sign);
buffer.writeByte(phoneNumber.getBytes(Charset.forName("GBK")).length);
buffer.writeCharSequence(phoneNumber, Charset.forName("GBK"));
buffer.writeByte(contactName.getBytes(Charset.forName("GBK")).length);
buffer.writeCharSequence(contactName, Charset.forName("GBK"));
return buffer;
}
@Override
public String toString() {
return "JTPhoneBookContact{" +
"sign=" + sign +
", phoneNumber='" + phoneNumber + '\'' +
", contactName='" + contactName + '\'' +
'}';
}
}

View File

@ -0,0 +1,97 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
@Schema(description = "多边形区域")
public class JTPolygonArea implements JTAreaOrRoute{
@Schema(description = "区域 ID")
private long id;
@Schema(description = "")
private JTAreaAttribute attribute;
@Schema(description = "起始时间, yyyy-MM-dd HH:mm:ss")
private String startTime;
@Schema(description = "结束时间, yyyy-MM-dd HH:mm:ss")
private String endTime;
@Schema(description = "最高速度, 单位为千米每小时(km/h)")
private int maxSpeed;
@Schema(description = "超速持续时间, 单位为秒(s)")
private int overSpeedDuration;
@Schema(description = "区域顶点")
private List<JTPolygonPoint> polygonPoints;
@Schema(description = "夜间最高速度, 单位为千米每小时(km/h)")
private int nighttimeMaxSpeed;
@Schema(description = "区域的名称")
private String name;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (id & 0xffffffffL));
byteBuf.writeBytes(attribute.encode());
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime)));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime)));
byteBuf.writeShort((short)(maxSpeed & 0xffff));
byteBuf.writeByte(overSpeedDuration);
byteBuf.writeShort((short)(polygonPoints.size() & 0xffff));
if (!polygonPoints.isEmpty()) {
for (JTPolygonPoint polygonPoint : polygonPoints) {
byteBuf.writeBytes(polygonPoint.encode());
}
}
byteBuf.writeShort((short)(nighttimeMaxSpeed & 0xffff));
byteBuf.writeShort((short)(name.getBytes(Charset.forName("GBK")).length & 0xffff));
byteBuf.writeCharSequence(name, Charset.forName("GBK"));
return byteBuf;
}
public static JTPolygonArea decode(ByteBuf buf) {
JTPolygonArea area = new JTPolygonArea();
area.setId(buf.readUnsignedInt());
int attributeInt = buf.readUnsignedShort();
JTAreaAttribute areaAttribute = JTAreaAttribute.decode(attributeInt);
area.setAttribute(areaAttribute);
byte[] startTimeBytes = new byte[6];
buf.readBytes(startTimeBytes);
area.setStartTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(startTimeBytes)));
byte[] endTimeBytes = new byte[6];
buf.readBytes(endTimeBytes);
area.setEndTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(endTimeBytes)));
area.setMaxSpeed(buf.readUnsignedShort());
area.setOverSpeedDuration(buf.readUnsignedByte());
int polygonPointsSize = buf.readUnsignedShort();
List<JTPolygonPoint> polygonPointList = new ArrayList<>(polygonPointsSize);
for (int i = 0; i < polygonPointsSize; i++) {
JTPolygonPoint polygonPoint = new JTPolygonPoint();
polygonPoint.setLatitude(buf.readUnsignedInt()/1000000D);
polygonPoint.setLongitude(buf.readUnsignedInt()/1000000D);
polygonPointList.add(polygonPoint);
}
area.setPolygonPoints(polygonPointList);
area.setNighttimeMaxSpeed(buf.readUnsignedShort());
int nameLength = buf.readUnsignedShort();
area.setName(buf.readCharSequence(nameLength, Charset.forName("GBK")).toString().trim());
return area;
}
}

View File

@ -0,0 +1,27 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "多边形区域的顶点")
public class JTPolygonPoint {
@Schema(description = "顶点纬度")
private Double latitude;
@Schema(description = "顶点经度")
private Double longitude;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (Math.round((latitude * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((longitude * 1000000)) & 0xffffffffL));
return byteBuf;
}
}

View File

@ -0,0 +1,29 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Schema(description = "位置附加信息")
public class JTPositionAdditionalInfo {
@Schema(description = "里程, 单位为1/10km, 对应车上里程表读数")
private int mileage;
@Schema(description = "油量, 单位为1/10L, 对应车上油量表读数")
private int oil;
@Schema(description = "行驶记录功能获取的速度,单位为1/10km/h")
private int speed;
@Schema(description = "报警事件的 ID")
private int alarmId;
// TODO 暂不支持胎压
@Schema(description = "车厢温度 ,单位为摄氏度")
private int carriageTemperature;
// TODO 暂不支持胎压
}

View File

@ -0,0 +1,118 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import io.netty.buffer.ByteBuf;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.nio.ByteBuffer;
@Setter
@Getter
@Slf4j
@Schema(description = "位置基本信息")
public class JTPositionBaseInfo {
/**
* 报警标志
*/
@Schema(description = "报警标志")
private JTAlarmSign alarmSign;
/**
* 状态
*/
@Schema(description = "状态")
private JTStatus status;
/**
* 经度
*/
@Schema(description = "经度")
private Double longitude;
/**
* 纬度
*/
@Schema(description = "纬度")
private Double latitude;
/**
* 高程
*/
@Schema(description = "高程")
private Integer altitude;
/**
* 速度
*/
@Schema(description = "速度")
private Integer speed;
/**
* 方向
*/
@Schema(description = "方向")
private Integer direction;
/**
* 时间
*/
@Schema(description = "时间")
private String time;
/**
* 视频报警
*/
@Schema(description = "视频报警")
private JTVideoAlarm videoAlarm;
public static JTPositionBaseInfo decode(ByteBuf buf) {
JTPositionBaseInfo positionInfo = new JTPositionBaseInfo();
if (buf.readableBytes() < 17) {
log.error("[位置基本信息] 解码失败,长度不足: {}", buf.readableBytes());
return positionInfo;
}
positionInfo.setAlarmSign(new JTAlarmSign(buf.readUnsignedInt()));
positionInfo.setStatus(new JTStatus(buf.readUnsignedInt()));
positionInfo.setLatitude(buf.readInt() * 0.000001D);
positionInfo.setLongitude(buf.readInt() * 0.000001D);
positionInfo.setAltitude(buf.readUnsignedShort());
positionInfo.setSpeed(buf.readUnsignedShort());
positionInfo.setDirection(buf.readUnsignedShort());
byte[] timeBytes = new byte[6];
buf.readBytes(timeBytes);
positionInfo.setTime(BCDUtil.transform(timeBytes));
return positionInfo;
}
public String toSimpleString() {
return "简略位置汇报信息: " +
" \n 经度:" + longitude +
" \n 纬度:" + latitude +
" \n 高程: " + altitude +
" \n 速度: " + speed +
" \n 方向: " + direction +
" \n 时间: " + time +
" \n";
}
@Override
public String toString() {
return "位置汇报信息: " +
" \n 报警标志:" + alarmSign.toString() +
" \n 状态:" + status.toString() +
" \n 经度:" + longitude +
" \n 纬度:" + latitude +
" \n 高程: " + altitude +
" \n 速度: " + speed +
" \n 方向: " + direction +
" \n 时间: " + time +
" \n";
}
}

View File

@ -0,0 +1,29 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
@Getter
@Schema(description = "位置信息")
public class JTPositionInfo {
/**
* 位置基本信息
*/
@Schema(description = "位置基本信息")
private JTPositionBaseInfo base;
/**
* 位置基本信息
*/
@Schema(description = "位置附加信息")
private JTPositionAdditionalInfo additional;
public void setBase(JTPositionBaseInfo base) {
this.base = base;
}
public void setAdditional(JTPositionAdditionalInfo additional) {
this.additional = additional;
}
}

View File

@ -0,0 +1,67 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "存储多媒体数据")
public class JTQueryMediaDataCommand {
@Schema(description = "多媒体类型: 0图像1音频2视频")
private int type;
@Schema(description = "通道 ID, 0 表示检索该媒体类型的所有通道")
private int chanelId;
@Schema(description = "事件项编码: 0平台下发指令1定时动作2抢劫报警触发3碰 撞侧翻报警触发;其他保留")
private int event;
@Schema(description = "开始时间")
private String startTime;
@Schema(description = "结束时间")
private String endTime;
@Schema(description = "删除标志, 0:保留1:删除, 存储多媒体数据上传命令中使用")
private Integer delete;
public ByteBuf decode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(type);
byteBuf.writeByte(chanelId);
byteBuf.writeByte(event);
if (startTime == null) {
byteBuf.writeBytes(BCDUtil.strToBcd("000000000000"));
}else {
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime)));
}
if (endTime == null) {
byteBuf.writeBytes(BCDUtil.strToBcd("000000000000"));
}else {
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime)));
}
if (delete != null) {
byteBuf.writeByte(delete);
}
return byteBuf;
}
@Override
public String toString() {
return "JTQueryMediaDataCommand{" +
"type=" + type +
", chanelId=" + chanelId +
", event=" + event +
", startTime='" + startTime + '\'' +
", endTime='" + endTime + '\'' +
", delete='" + delete + '\'' +
'}';
}
}

View File

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.proc.response.J9206;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class JTRecordDownloadCatch implements Delayed {
@Getter
@Setter
private String phoneNumber;
@Getter
@Setter
private String path;
@Getter
@Setter
private J9206 j9206;
/**
* 超时时间(单位 毫秒)
*/
@Getter
@Setter
private long delayTime;
@Override
public long getDelay(@NotNull TimeUnit unit) {
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(@NotNull Delayed o) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
}
}

View File

@ -0,0 +1,97 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.nio.charset.Charset;
@Setter
@Getter
@Schema(description = "矩形区域")
public class JTRectangleArea implements JTAreaOrRoute{
@Schema(description = "区域 ID")
private long id;
@Schema(description = "")
private JTAreaAttribute attribute;
@Schema(description = "左上点纬度")
private Double latitudeForUpperLeft;
@Schema(description = "左上点经度")
private Double longitudeForUpperLeft;
@Schema(description = "右下点纬度")
private Double latitudeForLowerRight;
@Schema(description = "右下点经度")
private Double longitudeForLowerRight;
@Schema(description = "起始时间, yyyy-MM-dd HH:mm:ss")
private String startTime;
@Schema(description = "结束时间, yyyy-MM-dd HH:mm:ss")
private String endTime;
@Schema(description = "最高速度, 单位为千米每小时(km/h)")
private int maxSpeed;
@Schema(description = "超速持续时间, 单位为秒(s)")
private int overSpeedDuration;
@Schema(description = "夜间最高速度, 单位为千米每小时(km/h)")
private int nighttimeMaxSpeed;
@Schema(description = "区域的名称")
private String name;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (id & 0xffffffffL));
byteBuf.writeBytes(attribute.encode());
byteBuf.writeInt((int) (Math.round((latitudeForUpperLeft * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((longitudeForUpperLeft * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((latitudeForLowerRight * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((longitudeForLowerRight * 1000000)) & 0xffffffffL));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime)));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime)));
byteBuf.writeShort((short)(maxSpeed & 0xffff));
byteBuf.writeByte(overSpeedDuration);
byteBuf.writeShort((short)(nighttimeMaxSpeed & 0xffff));
byteBuf.writeShort((short)(name.getBytes(Charset.forName("GBK")).length & 0xffff));
byteBuf.writeCharSequence(name, Charset.forName("GBK"));
return byteBuf;
}
public static JTRectangleArea decode(ByteBuf buf) {
JTRectangleArea area = new JTRectangleArea();
area.setId(buf.readUnsignedInt());
int attributeInt = buf.readUnsignedShort();
JTAreaAttribute areaAttribute = JTAreaAttribute.decode(attributeInt);
area.setAttribute(areaAttribute);
area.setLatitudeForUpperLeft(buf.readUnsignedInt()/1000000D);
area.setLongitudeForUpperLeft(buf.readUnsignedInt()/1000000D);
area.setLatitudeForLowerRight(buf.readUnsignedInt()/1000000D);
area.setLongitudeForLowerRight(buf.readUnsignedInt()/1000000D);
byte[] startTimeBytes = new byte[6];
buf.readBytes(startTimeBytes);
area.setStartTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(startTimeBytes)));
byte[] endTimeBytes = new byte[6];
buf.readBytes(endTimeBytes);
area.setEndTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(endTimeBytes)));
area.setMaxSpeed(buf.readUnsignedShort());
area.setOverSpeedDuration(buf.readUnsignedByte());
area.setNighttimeMaxSpeed(buf.readUnsignedShort());
int nameLength = buf.readUnsignedShort();
area.setName(buf.readCharSequence(nameLength, Charset.forName("GBK")).toString().trim());
return area;
}
}

View File

@ -0,0 +1,90 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
@Schema(description = "路线")
public class JTRoute implements JTAreaOrRoute{
@Schema(description = "路线 ID")
private long id;
@Schema(description = "路线属性")
private JTRouteAttribute attribute;
@Schema(description = "起始时间, yyyy-MM-dd HH:mm:ss")
private String startTime;
@Schema(description = "结束时间, yyyy-MM-dd HH:mm:ss")
private String endTime;
@Schema(description = "路线拐点")
private List<JTRoutePoint> routePointList;
@Schema(description = "区域的名称")
private String name;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (id & 0xffffffffL));
byteBuf.writeBytes(attribute.encode());
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime)));
byteBuf.writeBytes(BCDUtil.strToBcd(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime)));
byteBuf.writeShort((short)(routePointList.size() & 0xffff));
if (!routePointList.isEmpty()){
for (JTRoutePoint jtRoutePoint : routePointList) {
byteBuf.writeBytes(jtRoutePoint.encode());
}
}
byteBuf.writeShort((short)(name.getBytes(Charset.forName("GBK")).length & 0xffff));
byteBuf.writeCharSequence(name, Charset.forName("GBK"));
return byteBuf;
}
public static JTRoute decode(ByteBuf buf) {
JTRoute route = new JTRoute();
route.setId(buf.readUnsignedInt());
int attributeInt = buf.readUnsignedShort();
JTRouteAttribute routeAttribute = JTRouteAttribute.decode(attributeInt);
route.setAttribute(routeAttribute);
byte[] startTimeBytes = new byte[6];
buf.readBytes(startTimeBytes);
route.setStartTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(startTimeBytes)));
byte[] endTimeBytes = new byte[6];
buf.readBytes(endTimeBytes);
route.setEndTime(DateUtil.jt1078Toyyyy_MM_dd_HH_mm_ss(BCDUtil.transform(endTimeBytes)));
int routePointsSize = buf.readUnsignedShort();
List<JTRoutePoint> jtRoutePoints = new ArrayList<>(routePointsSize);
for (int i = 0; i < routePointsSize; i++) {
jtRoutePoints.add(JTRoutePoint.decode(buf));
}
route.setRoutePointList(jtRoutePoints);
int nameLength = buf.readUnsignedShort();
route.setName(buf.readCharSequence(nameLength, Charset.forName("GBK")).toString().trim());
return route;
}
@Override
public String toString() {
return "JTRoute{" +
"id=" + id +
", attribute=" + attribute +
", startTime='" + startTime + '\'' +
", endTime='" + endTime + '\'' +
", routePointList=" + routePointList +
", name='" + name + '\'' +
'}';
}
}

View File

@ -0,0 +1,71 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "路线属性")
public class JTRouteAttribute {
@Schema(description = "是否启用起始时间与结束时间的判断规则 ,falsetrue")
private boolean ruleForTimeLimit;
@Schema(description = "进区域是否报警给驾驶员,falsetrue")
private boolean ruleForAlarmToDriverWhenEnter;
@Schema(description = "进区域是否报警给平台 ,falsetrue")
private boolean ruleForAlarmToPlatformWhenEnter;
@Schema(description = "出区域是否报警给驾驶员,falsetrue")
private boolean ruleForAlarmToDriverWhenExit;
@Schema(description = "出区域是否报警给平台 ,falsetrue")
private boolean ruleForAlarmToPlatformWhenExit;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
short content = 0;
if (ruleForTimeLimit) {
content |= 1;
}
if (ruleForAlarmToDriverWhenEnter) {
content |= (1 << 2);
}
if (ruleForAlarmToPlatformWhenEnter) {
content |= (1 << 3);
}
if (ruleForAlarmToDriverWhenExit) {
content |= (1 << 4);
}
if (ruleForAlarmToPlatformWhenExit) {
content |= (1 << 5);
}
byteBuf.writeShort((short)(content & 0xffff));
return byteBuf;
}
public static JTRouteAttribute decode(int attributeInt) {
JTRouteAttribute attribute = new JTRouteAttribute();
attribute.setRuleForTimeLimit((attributeInt & 1) == 1);
attribute.setRuleForAlarmToDriverWhenEnter((attributeInt >> 2 & 1) == 1);
attribute.setRuleForAlarmToPlatformWhenEnter((attributeInt >> 3 & 1) == 1);
attribute.setRuleForAlarmToDriverWhenExit((attributeInt >> 4 & 1) == 1);
attribute.setRuleForAlarmToPlatformWhenExit((attributeInt >> 5 & 1) == 1);
return attribute;
}
@Override
public String toString() {
return "JTRouteAttribute{" +
"ruleForTimeLimit=" + ruleForTimeLimit +
", ruleForAlarmToDriverWhenEnter=" + ruleForAlarmToDriverWhenEnter +
", ruleForAlarmToPlatformWhenEnter=" + ruleForAlarmToPlatformWhenEnter +
", ruleForAlarmToDriverWhenExit=" + ruleForAlarmToDriverWhenExit +
", ruleForAlarmToPlatformWhenExit=" + ruleForAlarmToPlatformWhenExit +
'}';
}
}

View File

@ -0,0 +1,98 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "路线拐点")
public class JTRoutePoint {
@Schema(description = "拐点 ID")
private long id;
@Schema(description = "路段 ID")
private long routeSectionId;
@Schema(description = "拐点纬度")
private Double latitude;
@Schema(description = "拐点经度")
private Double longitude;
@Schema(description = "路段宽度")
private int routeSectionAttributeWidth;
@Schema(description = "路段属性")
private JTRouteSectionAttribute routeSectionAttribute;
@Schema(description = "路段行驶过长國值")
private int routeSectionMaxLength;
@Schema(description = "路段行驶不足國值")
private int routeSectionMinLength;
@Schema(description = "路段最高速度")
private int routeSectionMaxSpeed;
@Schema(description = "路段超速持续时间")
private int routeSectionOverSpeedDuration;
@Schema(description = "路段夜间最高速度")
private int routeSectionNighttimeMaxSpeed;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt((int) (id & 0xffffffffL));
byteBuf.writeInt((int) (routeSectionId & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((latitude * 1000000)) & 0xffffffffL));
byteBuf.writeInt((int) (Math.round((longitude * 1000000)) & 0xffffffffL));
byteBuf.writeByte(routeSectionAttributeWidth);
byteBuf.writeByte(routeSectionAttribute.encode());
byteBuf.writeShort((short)(routeSectionMaxLength & 0xffff));
byteBuf.writeShort((short)(routeSectionMinLength & 0xffff));
byteBuf.writeShort((short)(routeSectionMaxSpeed & 0xffff));
byteBuf.writeByte(routeSectionOverSpeedDuration);
byteBuf.writeShort((short)(routeSectionNighttimeMaxSpeed & 0xffff));
return byteBuf;
}
public static JTRoutePoint decode(ByteBuf buf) {
JTRoutePoint point = new JTRoutePoint();
point.setId(buf.readUnsignedInt());
point.setRouteSectionId(buf.readUnsignedInt());
point.setLatitude(buf.readUnsignedInt()/1000000D);
point.setLongitude(buf.readUnsignedInt()/1000000D);
point.setRouteSectionAttributeWidth(buf.readUnsignedByte());
JTRouteSectionAttribute areaAttribute = JTRouteSectionAttribute.decode(buf.readUnsignedByte());
point.setRouteSectionAttribute(areaAttribute);
point.setRouteSectionMaxLength(buf.readUnsignedShort());
point.setRouteSectionMinLength(buf.readUnsignedShort());
point.setRouteSectionMaxSpeed(buf.readUnsignedShort());
point.setRouteSectionOverSpeedDuration(buf.readUnsignedByte());
point.setRouteSectionNighttimeMaxSpeed(buf.readUnsignedShort());
return point;
}
@Override
public String toString() {
return "JTRoutePoint{" +
"id=" + id +
", routeSectionId=" + routeSectionId +
", latitude=" + latitude +
", longitude=" + longitude +
", routeSectionAttributeWidth=" + routeSectionAttributeWidth +
", routeSectionAttribute=" + routeSectionAttribute +
", routeSectionMaxLength=" + routeSectionMaxLength +
", routeSectionMinLength=" + routeSectionMinLength +
", routeSectionMaxSpeed=" + routeSectionMaxSpeed +
", routeSectionOverSpeedDuration=" + routeSectionOverSpeedDuration +
", routeSectionNighttimeMaxSpeed=" + routeSectionNighttimeMaxSpeed +
'}';
}
}

View File

@ -0,0 +1,52 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "路段属性")
public class JTRouteSectionAttribute {
@Schema(description = "行驶时间 ,falsetrue")
private boolean ruleForTimeLimit;
@Schema(description = "限速 ,falsetrue")
private boolean ruleForSpeedLimit;
@Schema(description = "false北纬true南纬")
private boolean southLatitude;
@Schema(description = "false东经true西经")
private boolean westLongitude;
public byte encode(){
byte attributeByte = 0;
if (ruleForTimeLimit) {
attributeByte |= 1;
}
if (ruleForSpeedLimit) {
attributeByte |= (1 << 1);
}
if (southLatitude) {
attributeByte |= (1 << 2);
}
if (westLongitude) {
attributeByte |= (1 << 3);
}
return attributeByte;
}
public static JTRouteSectionAttribute decode(short attributeShort) {
JTRouteSectionAttribute attribute = new JTRouteSectionAttribute();
attribute.setRuleForTimeLimit((attributeShort & 1) == 1);
attribute.setRuleForSpeedLimit((attributeShort >> 1 & 1) == 1);
attribute.setSouthLatitude((attributeShort >> 2 & 1) == 1);
attribute.setWestLongitude((attributeShort >> 3 & 1) == 1);
return attribute;
}
}

View File

@ -0,0 +1,85 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Schema(description = "拍摄命令参数")
public class JTShootingCommand {
@Schema(description = "通道 ID")
private int chanelId;
@Schema(description = "0:停止拍摄0xFFFF:录像;其他:拍照张数")
private int command;
@Schema(description = "拍照间隔/录像时间, 单位为秒(s) ,0 表示按最小间隔拍照或一直录像")
private int time;
@Schema(description = "1:保存; 0:实时上传")
private int save;
@Schema(description = "分辨率: " +
"0x00:最低分辨率" +
"0x01:320 x240" +
"0x02:640 x480" +
"0x03:800 x600" +
"0x04:1024 x768" +
"0x05:176 x144" +
"0x06:352 x288" +
"0x07:704 x288" +
"0x08:704 x576" +
"0xff:最高分辨率")
private int resolvingPower;
@Schema(description = "图像/视频质量: 取值范围为 1 ~ 10 ,1 代表质量损失最小 ,10 表示压缩 比最大")
private int quality;
@Schema(description = "亮度, 0 ~ 255")
private int brightness;
@Schema(description = "对比度,0 ~ 127")
private int contrastRatio;
@Schema(description = "饱和度,0 ~ 127")
private int saturation;
@Schema(description = "色度,0 ~ 255")
private int chroma;
public ByteBuf decode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(chanelId);
byteBuf.writeShort((short)(command & 0xffff));
byteBuf.writeShort((short)(time & 0xffff));
byteBuf.writeByte(save);
byteBuf.writeByte(resolvingPower);
byteBuf.writeByte(quality);
byteBuf.writeByte(brightness);
byteBuf.writeByte(contrastRatio);
byteBuf.writeByte(saturation);
byteBuf.writeByte(chroma);
return byteBuf;
}
@Override
public String toString() {
return "JTShootingCommand{" +
"chanelId=" + chanelId +
", command=" + command +
", time=" + time +
", save=" + save +
", resolvingPower=" + resolvingPower +
", quality=" + quality +
", brightness=" + brightness +
", contrastRatio=" + contrastRatio +
", saturation=" + saturation +
", chroma=" + chroma +
'}';
}
}

View File

@ -0,0 +1,136 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "状态信息")
public class JTStatus {
@Schema(description = "false:ACC关true: ACC开")
private boolean acc;
@Schema(description = "false:未定位true: 定位")
private boolean positioning;
@Schema(description = "false:北纬true: 南纬")
private boolean southLatitude;
@Schema(description = "false:东经true: 西经")
private boolean wesLongitude;
@Schema(description = "false:运营状态true: 停运状态")
private boolean outage;
@Schema(description = "false:经纬度未经保密插件加密true: 经纬度已经保密插件加密")
private boolean positionEncryption;
@Schema(description = "true: 紧急刹车系统采集的前撞预警")
private boolean warningFrontCrash;
@Schema(description = "true: 车道偏移预警")
private boolean warningShifting;
@Schema(description = "00:空车01:半载10:保留11:满载。可表示客车的空载状态 ,重车及货车的空载、满载状态 ,该状态可由人工输入或传感器获取")
private int load;
@Schema(description = "false:车辆油路正常true: 车辆油路断开")
private boolean oilWayBreak;
@Schema(description = "false:车辆电路正常true: 车辆电路断开")
private boolean circuitBreak;
@Schema(description = "false:车门解锁true: 车门加锁")
private boolean doorLocking;
@Schema(description = "false:门1 关true: 门1 开(前门)")
private boolean door1Open;
@Schema(description = "false:门2 关true: 门2 开(中门)")
private boolean door2Open;
@Schema(description = "false:门3 关true: 门3 开(后门)")
private boolean door3Open;
@Schema(description = "false:门4 关true: 门4 开(驾驶席门)")
private boolean door4Open;
@Schema(description = "false:门5 关true: 门5 开(自定义)")
private boolean door5Open;
@Schema(description = "false:未使用 GPS 卫星进行定位true:使用 GPS 卫星进行定位")
private boolean gps;
@Schema(description = "false:未使用北斗卫星进行定位true:使用北斗卫星进行定位")
private boolean beidou;
@Schema(description = "false:未使用GLONASS 卫星进行定位true:使用GLONASS 卫星进行定位")
private boolean glonass;
@Schema(description = "false:未使用GaLiLeo 卫星进行定位true:使用GaLiLeo 卫星进行定位")
private boolean gaLiLeo;
@Schema(description = "false:车辆处于停止状态true:车辆处于行驶状态")
private boolean driving;
public JTStatus() {
}
public JTStatus(long statusInt) {
if (statusInt == 0) {
return;
}
this.acc = (statusInt & 1) == 1;
this.positioning = (statusInt >>> 1 & 1) == 1;
this.southLatitude = (statusInt >>> 2 & 1) == 1;
this.wesLongitude = (statusInt >>> 3 & 1) == 1;
this.outage = (statusInt >>> 4 & 1) == 1;
this.positionEncryption = (statusInt >>> 5 & 1) == 1;
this.warningFrontCrash = (statusInt >>> 6 & 1) == 1;
this.warningShifting = (statusInt >>> 7 & 1) == 1;
this.load = (int)(statusInt >>> 8 & 3);
this.oilWayBreak = (statusInt >>> 10 & 1) == 1;
this.circuitBreak = (statusInt >>> 11 & 1) == 1;
this.doorLocking = (statusInt >>> 12 & 1) == 1;
this.door1Open = (statusInt >>> 13 & 1) == 1;
this.door2Open = (statusInt >>> 14 & 1) == 1;
this.door3Open = (statusInt >>> 15 & 1) == 1;
this.door4Open = (statusInt >>> 16 & 1) == 1;
this.door5Open = (statusInt >>> 17 & 1) == 1;
this.gps = (statusInt >>> 18 & 1) == 1;
this.beidou = (statusInt >>> 19 & 1) == 1;
this.glonass = (statusInt >>> 20 & 1) == 1;
this.gaLiLeo = (statusInt >>> 21 & 1) == 1;
this.driving = (statusInt >>> 22 & 1) == 1;
}
@Override
public String toString() {
return "状态位:" +
"\n acc状态" + (acc?"":"") +
"\n 定位状态:" + (positioning?"定位":"未定位") +
"\n 南北纬:" + (southLatitude?"南纬":"北纬") +
"\n 东西经:" + (wesLongitude?"西经":"东经") +
"\n 运营状态:" + (outage?"停运":"运营") +
"\n 经纬度保密:" + (positionEncryption?"加密":"未加密") +
"\n 前撞预警:" + (warningFrontCrash?"紧急刹车系统采集的前撞预警":"") +
"\n 车道偏移预警:" + (warningShifting?"车道偏移预警":"") +
"\n 空/半/满载状态:" + (load == 0?"空车":(load == 1?"半载":(load == 3?"满载":"未定义状态"))) +
"\n 车辆油路状态:" + (oilWayBreak?"车辆油路断开":"车辆油路正常") +
"\n 车辆电路状态:" + (circuitBreak?"车辆电路断开":"车辆电路正常") +
"\n 门锁状态:" + (doorLocking?"车门加锁":"车门解锁") +
"\n 门1(前门)状态:" + (door1Open?"":"") +
"\n 门2(中门)状态:" + (door2Open?"":"") +
"\n 门3(后门)状态:" + (door3Open?"":"") +
"\n 门4(驾驶席门)状态:" + (door4Open?"":"") +
"\n 门5(自定义)状态:" + (door5Open?"":"") +
"\n GPS卫星定位状态 " + (gps?"使用":"未使用") +
"\n 北斗卫星定位状态: " + (beidou?"使用":"未使用") +
"\n GLONASS卫星定位状态 " + (glonass?"使用":"未使用") +
"\n GaLiLeo卫星定位状态 " + (gaLiLeo?"使用":"未使用") +
"\n GaLiLeo卫星定位状态 " + (gaLiLeo?"使用":"未使用") +
"\n 车辆行驶状态: " + (driving?"车辆行驶":"车辆停止") +
"\n ";
}
}

View File

@ -0,0 +1,45 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 文本信息标志
*/
@Data
@Schema(description = "文本信息标志")
public class JTTextSign {
@Schema(description = "1紧急,2服务,3通知")
private int type;
@Schema(description = "1终端显示器显示")
private boolean terminalDisplay;
@Schema(description = "1广告屏显示")
private boolean adScreen;
@Schema(description = "1终端 TTS 播读")
private boolean tts;
@Schema(description = "false: 中心导航信息 true CAN故障码信息")
private boolean source;
public byte encode(){
byte byteSign = 0;
byteSign |= (byte) type;
if (terminalDisplay) {
byteSign |= (0x1 << 2);
}
if (tts) {
byteSign |= (0x1 << 3);
}
if (adScreen) {
byteSign |= (0x1 << 4);
}
if (source) {
byteSign |= (0x1 << 5);
}
return byteSign;
}
}

View File

@ -0,0 +1,33 @@
package com.genersoft.iot.vmp.jt1078.bean;
import com.genersoft.iot.vmp.jt1078.bean.common.ConfigAttribute;
import lombok.Getter;
import lombok.Setter;
import java.util.Objects;
/**
* 车辆控制类型
*/
@Setter
@Getter
public class JTVehicleControl {
private int length;
private void setLength(Object value) {
if (Objects.isNull(value)) {
length--;
}else {
length ++;
}
}
@ConfigAttribute(id = 0X0001, type="Byte", description = "车门, 0车门锁闭 1车门开启")
private Integer controlCarDoor;
public void setControlCarDoor(Integer controlCarDoor) {
this.controlCarDoor = controlCarDoor;
setLength(controlCarDoor);
}
}

View File

@ -0,0 +1,92 @@
package com.genersoft.iot.vmp.jt1078.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
@Schema(description = "视频报警上报")
public class JTVideoAlarm {
@Schema(description = "视频信号丢失报警的通道")
private List<Integer> videoLossChannels;
@Schema(description = "视频信号遮挡报警的通道")
private List<Integer> videoOcclusionChannels;
@Schema(description = "存储器故障报警状态,第 1-12 个主存储器12-15 分别表示第 1-4 个灾备存储装置")
private List<Integer> storageFaultAlarm;
@Schema(description = "异常驾驶行为-疲劳")
private boolean drivingForFatigue;
@Schema(description = "异常驾驶行为-打电话")
private boolean drivingForCall;
@Schema(description = "异常驾驶行为-抽烟")
private boolean drivingSmoking;
@Schema(description = "其他视频设备故障")
private boolean otherDeviceFailure;
@Schema(description = "客车超员报警")
private boolean overcrowding;
@Schema(description = "特殊报警录像达到存储阈值报警")
private boolean specialRecordFull;
public JTVideoAlarm() {
}
public static JTVideoAlarm getInstance(int alarm, int loss, int occlusion, short storageFault, short driving) {
JTVideoAlarm jtVideoAlarm = new JTVideoAlarm();
if (alarm == 0) {
return jtVideoAlarm;
}
boolean lossAlarm = (alarm & 1) == 1;
boolean occlusionAlarm = (alarm >>> 1 & 1) == 1;
boolean storageFaultAlarm = (alarm >>> 2 & 1) == 1;
jtVideoAlarm.setOtherDeviceFailure((alarm >>> 3 & 1) == 1);
jtVideoAlarm.setOvercrowding((alarm >>> 4 & 1) == 1);
boolean drivingAlarm = (alarm >>> 5 & 1) == 1;
jtVideoAlarm.setSpecialRecordFull((alarm >>> 6 & 1) == 1);
if (lossAlarm && loss > 0) {
List<Integer> videoLossChannels = new ArrayList<>();
for (int i = 0; i < 32; i++) {
if ((loss >>> i & 1) == 1 ) {
videoLossChannels.add(i);
}
}
jtVideoAlarm.setVideoLossChannels(videoLossChannels);
}
if (occlusionAlarm && occlusion > 0) {
List<Integer> videoOcclusionChannels = new ArrayList<>();
for (int i = 0; i < 32; i++) {
if ((occlusion >>> i & 1) == 1) {
videoOcclusionChannels.add(i);
}
}
jtVideoAlarm.setVideoOcclusionChannels(videoOcclusionChannels);
}
if (storageFaultAlarm && storageFault > 0) {
List<Integer> storageFaultAlarmContent = new ArrayList<>();
for (int i = 0; i < 16; i++) {
if ((storageFault >>> i & 1) == 1) {
storageFaultAlarmContent.add(i);
}
}
jtVideoAlarm.setStorageFaultAlarm(storageFaultAlarmContent);
}
if (drivingAlarm && driving > 0) {
jtVideoAlarm.setDrivingForFatigue((driving & 1) == 1 );
jtVideoAlarm.setDrivingForCall((driving >>> 1 & 1) == 1 );
jtVideoAlarm.setDrivingSmoking((driving >>> 2 & 1) == 1 );
}
return jtVideoAlarm;
}
}

View File

@ -0,0 +1,14 @@
package com.genersoft.iot.vmp.jt1078.bean.common;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigAttribute {
long id();
String type();
String description();
}

View File

@ -0,0 +1,46 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 特殊报警录像参数
*/
@Setter
@Getter
public class JTAlarmRecordingParam implements JTDeviceSubConfig{
/**
* 特殊报警录像存储阈值, 百分比,取值 特殊报警录像占用主存储器存储阈值百 1 ~ 99,默认值为 20
*/
private int storageLimit;
/**
* 特殊报警录像持续时间,特殊报警录像的最长持续时间,单位为分钟(min) ,默认值为 5
*/
private int duration;
/**
* 特殊报警标识起始时间, 特殊报警发生前进行标记的录像时间, 单位为分钟( min) ,默认值为 1
*/
private int startTime;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(storageLimit);
byteBuf.writeByte(duration);
byteBuf.writeByte(startTime);
return byteBuf;
}
public static JTAlarmRecordingParam decode(ByteBuf byteBuf) {
JTAlarmRecordingParam alarmRecordingParam = new JTAlarmRecordingParam();
alarmRecordingParam.setStorageLimit(byteBuf.readUnsignedByte());
alarmRecordingParam.setDuration(byteBuf.readUnsignedByte());
alarmRecordingParam.setStartTime(byteBuf.readUnsignedByte());
return alarmRecordingParam;
}
}

View File

@ -0,0 +1,136 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 单独通道视频
*/
@Setter
@Getter
public class JTAloneChanel implements JTDeviceSubConfig{
/**
* 逻辑通道号
*/
private int logicChannelId;
/**
* 实时流编码模式
* 0:CBR( 固定码率) ;
* 1:VBR( 可变码率) ;
* 2:ABR( 平均码率) ;
* 100 ~ 127:自定义
*/
private int liveStreamCodeRateType;
/**
* 实时流分辨率
* 0:QCIF;
* 1:CIF;
* 2:WCIF;
* 3:D1;
* 4:WD1;
* 5:720P;
* 6:1 080P;
* 100 ~ 127:自定义
*/
private int liveStreamResolving;
/**
* 实时流关键帧间隔, 范围(1 ~ 1 000)
*/
private int liveStreamIInterval;
/**
* 实时流目标帧率,范围(1 ~ 120) / s
*/
private int liveStreamFrameRate;
/**
* 实时流目标码率,单位为千位每秒( kbps)
*/
private long liveStreamCodeRate;
/**
* 存储流编码模式
* 0:CBR( 固定码率) ;
* 1:VBR( 可变码率) ;
* 2:ABR( 平均码率) ;
* 100 ~ 127:自定义
*/
private int storageStreamCodeRateType;
/**
* 存储流分辨率
* 0:QCIF;
* 1:CIF;
* 2:WCIF;
* 3:D1;
* 4:WD1;
* 5:720P;
* 6:1 080P;
* 100 ~ 127:自定义
*/
private int storageStreamResolving;
/**
* 存储流关键帧间隔, 范围(1 ~ 1 000)
*/
private int storageStreamIInterval;
/**
* 存储流目标帧率,范围(1 ~ 120) / s
*/
private int storageStreamFrameRate;
/**
* 存储流目标码率,单位为千位每秒( kbps)
*/
private long storageStreamCodeRate;
/**
* 字幕叠加设置
*/
private JTOSDConfig osd;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(logicChannelId);
byteBuf.writeByte(liveStreamCodeRateType);
byteBuf.writeByte(liveStreamResolving);
byteBuf.writeShort((short)(liveStreamIInterval & 0xffff));
byteBuf.writeByte(liveStreamFrameRate);
byteBuf.writeInt((int) (liveStreamCodeRate & 0xffffffffL));
byteBuf.writeByte(storageStreamCodeRateType);
byteBuf.writeByte(storageStreamResolving);
byteBuf.writeShort((short)(storageStreamIInterval & 0xffff));
byteBuf.writeByte(storageStreamFrameRate);
byteBuf.writeInt((int) (storageStreamCodeRate & 0xffffffffL));
byteBuf.writeBytes(osd.encode());
return byteBuf;
}
public static JTAloneChanel decode(ByteBuf buf) {
JTAloneChanel jtAloneChanel = new JTAloneChanel();
jtAloneChanel.setLogicChannelId(buf.readByte());
jtAloneChanel.setLiveStreamCodeRateType(buf.readByte());
jtAloneChanel.setLiveStreamResolving(buf.readByte());
jtAloneChanel.setLiveStreamIInterval(buf.readUnsignedShort());
jtAloneChanel.setLiveStreamFrameRate(buf.readByte());
jtAloneChanel.setLiveStreamCodeRate(buf.readUnsignedInt());
jtAloneChanel.setStorageStreamCodeRateType(buf.readByte());
jtAloneChanel.setStorageStreamResolving(buf.readByte());
jtAloneChanel.setStorageStreamIInterval(buf.readUnsignedShort());
jtAloneChanel.setStorageStreamFrameRate(buf.readByte());
jtAloneChanel.setStorageStreamCodeRate(buf.readUnsignedInt());
jtAloneChanel.setOsd(JTOSDConfig.decode(buf));
return null;
}
}

View File

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 视频分析报警参数
*/
@Setter
@Getter
public class JTAnalyzeAlarmParam implements JTDeviceSubConfig{
/**
* 车辆核载人数
*/
private int numberForPeople;
/**
* 疲劳程度阈值
*/
private int fatigueThreshold;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(numberForPeople);
byteBuf.writeByte(fatigueThreshold);
return byteBuf;
}
public static JTAnalyzeAlarmParam decode(ByteBuf byteBuf) {
JTAnalyzeAlarmParam analyzeAlarmParam = new JTAnalyzeAlarmParam();
analyzeAlarmParam.setNumberForPeople(byteBuf.readUnsignedByte());
analyzeAlarmParam.setFatigueThreshold(byteBuf.readUnsignedByte());
return analyzeAlarmParam;
}
}

View File

@ -0,0 +1,270 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import com.genersoft.iot.vmp.jt1078.util.BCDUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 终端休眠唤醒模式设置
*/
@Setter
@Getter
public class JTAwakenParam implements JTDeviceSubConfig{
/**
* 休眠唤醒模式-条件唤醒
*/
private boolean wakeUpModeByCondition;
/**
* 休眠唤醒模式-定时唤醒
*/
private boolean wakeUpModeByTime;
/**
* 休眠唤醒模式-手动唤醒
*/
private boolean wakeUpModeByManual;
/**
* 唤醒条件类型-紧急报警
*/
private boolean wakeUpConditionsByAlarm;
/**
* 唤醒条件类型-碰撞侧翻报警
*/
private boolean wakeUpConditionsByRollover;
/**
* 唤醒条件类型-车辆开门
*/
private boolean wakeUpConditionsByOpenTheDoor;
/**
* 定时唤醒日设置-周一
*/
private boolean awakeningDayForMonday;
/**
* 定时唤醒日设置-周二
*/
private boolean awakeningDayForTuesday;
/**
* 定时唤醒日设置-周三
*/
private boolean awakeningDayForWednesday;
/**
* 定时唤醒日设置-周四
*/
private boolean awakeningDayForThursday;
/**
* 定时唤醒日设置-周五
*/
private boolean awakeningDayForFriday;
/**
* 定时唤醒日设置-周六
*/
private boolean awakeningDayForSaturday;
/**
* 定时唤醒日设置-周日
*/
private boolean awakeningDayForSunday;
/**
* 日定时唤醒-启用时间段1
*/
private boolean time1Enable;
/**
* 日定时唤醒-时间段1开始时间
*/
private String time1StartTime;
/**
* 日定时唤醒-时间段1结束时间
*/
private String time1EndTime;
/**
* 日定时唤醒-启用时间段2
*/
private boolean time2Enable;
/**
* 日定时唤醒-时间段2开始时间
*/
private String time2StartTime;
/**
* 日定时唤醒-时间段2结束时间
*/
private String time2EndTime;
/**
* 日定时唤醒-启用时间段3
*/
private boolean time3Enable;
/**
* 日定时唤醒-时间段3开始时间
*/
private String time3StartTime;
/**
* 日定时唤醒-时间段3结束时间
*/
private String time3EndTime;
/**
* 日定时唤醒-启用时间段4
*/
private boolean time4Enable;
/**
* 日定时唤醒-时间段4开始时间
*/
private String time4StartTime;
/**
* 日定时唤醒-时间段4结束时间
*/
private String time4EndTime;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte wakeUpTypeByte = 0;
byte wakeUpConditionsByte = 0;
byte wakeDayByte = 0;
if (wakeUpModeByCondition) {
wakeUpTypeByte = (byte)(wakeUpTypeByte | 1);
}
if (wakeUpModeByTime) {
wakeUpTypeByte = (byte)(wakeUpTypeByte | (1 << 1));
}
if (wakeUpModeByManual) {
wakeUpTypeByte = (byte)(wakeUpTypeByte | (1 << 2));
}
byteBuf.writeByte(wakeUpTypeByte);
if (wakeUpConditionsByAlarm) {
wakeUpConditionsByte = (byte)(wakeUpConditionsByte | 1);
}
if (wakeUpConditionsByRollover) {
wakeUpConditionsByte = (byte)(wakeUpConditionsByte | (1 << 1));
}
if (wakeUpConditionsByOpenTheDoor) {
wakeUpConditionsByte = (byte)(wakeUpConditionsByte | (1 << 2));
}
byteBuf.writeByte(wakeUpConditionsByte);
if (awakeningDayForMonday) {
wakeDayByte = (byte)(wakeDayByte | 1);
}
if (awakeningDayForTuesday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 1));
}
if (awakeningDayForWednesday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 2));
}
if (awakeningDayForThursday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 3));
}
if (awakeningDayForFriday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 4));
}
if (awakeningDayForSaturday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 5));
}
if (awakeningDayForSunday) {
wakeDayByte = (byte)(wakeDayByte | (1 << 6));
}
byteBuf.writeByte(wakeDayByte);
byte enableByte = 0;
if (time1Enable) {
enableByte = (byte)(enableByte | 1);
}
if (time2Enable) {
enableByte = (byte)(enableByte | (1 << 1));
}
if (time3Enable) {
enableByte = (byte)(enableByte | (1 << 2));
}
if (time4Enable) {
enableByte = (byte)(enableByte | (1 << 3));
}
byteBuf.writeByte(enableByte);
byteBuf.writeBytes(transportTime(time1StartTime));
byteBuf.writeBytes(transportTime(time1EndTime));
byteBuf.writeBytes(transportTime(time2StartTime));
byteBuf.writeBytes(transportTime(time2EndTime));
byteBuf.writeBytes(transportTime(time3StartTime));
byteBuf.writeBytes(transportTime(time3EndTime));
byteBuf.writeBytes(transportTime(time4StartTime));
byteBuf.writeBytes(transportTime(time4EndTime));
return byteBuf;
}
private byte[] transportTime(String time) {
return BCDUtil.strToBcd(time.replace(":", ""));
}
public static JTAwakenParam decode(ByteBuf byteBuf) {
JTAwakenParam awakenParam = new JTAwakenParam();
short wakeUpTypeByte = byteBuf.readUnsignedByte();
awakenParam.wakeUpModeByCondition = ((wakeUpTypeByte & 1) == 1);
awakenParam.wakeUpModeByTime = ((wakeUpTypeByte >>> 1 & 1) == 1);
awakenParam.wakeUpModeByManual = ((wakeUpTypeByte >>> 2 & 1) == 1);
short wakeUpConditionsByte = byteBuf.readUnsignedByte();
awakenParam.wakeUpConditionsByAlarm = ((wakeUpConditionsByte & 1) == 1);
awakenParam.wakeUpConditionsByRollover = ((wakeUpConditionsByte >>> 1 & 1) == 1);
awakenParam.wakeUpConditionsByOpenTheDoor = ((wakeUpConditionsByte >>> 2 & 1) == 1);
short wakeDayByte = byteBuf.readUnsignedByte();
awakenParam.awakeningDayForMonday = ((wakeDayByte & 1) == 1);
awakenParam.awakeningDayForTuesday = ((wakeDayByte >>> 1 & 1) == 1);
awakenParam.awakeningDayForWednesday = ((wakeDayByte >>> 2 & 1) == 1);
awakenParam.awakeningDayForThursday = ((wakeDayByte >>> 3 & 1) == 1);
awakenParam.awakeningDayForFriday = ((wakeDayByte >>> 4 & 1) == 1);
awakenParam.awakeningDayForSaturday = ((wakeDayByte >>> 5 & 1) == 1);
awakenParam.awakeningDayForSunday = ((wakeDayByte >>> 6 & 1) == 1);
short enableByte = byteBuf.readUnsignedByte();
awakenParam.time1Enable = ((enableByte & 1) == 1);
awakenParam.time2Enable = ((enableByte >>> 1 & 1) == 1);
awakenParam.time3Enable = ((enableByte >>> 2 & 1) == 1);
awakenParam.time4Enable = ((enableByte >>> 3 & 1) == 1);
byte[] timeBytes = new byte[2];
byteBuf.readBytes(timeBytes);
awakenParam.time1StartTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time1EndTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time2StartTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time2EndTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time3StartTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time3EndTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time4StartTime = transportTime(timeBytes);
byteBuf.readBytes(timeBytes);
awakenParam.time4EndTime = transportTime(timeBytes);
return awakenParam;
}
private static String transportTime(byte[] timeBytes) {
String time1Str = BCDUtil.transform(timeBytes);
return time1Str.replace(time1Str.substring(0, 2), time1Str.substring(0, 2) + ":");
}
}

View File

@ -0,0 +1,113 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 定时拍照控制
*/
@Setter
@Getter
public class JTCameraTimer implements JTDeviceSubConfig{
/**
* 摄像通道1 定时拍照开关标志
*/
private boolean switchForChannel1;
/**
* 摄像通道2 定时拍照开关标志
*/
private boolean switchForChannel2;
/**
* 摄像通道3 定时拍照开关标志
*/
private boolean switchForChannel3;
/**
* 摄像通道4 定时拍照开关标志
*/
private boolean switchForChannel4;
/**
* 摄像通道5 定时拍照开关标志
*/
private boolean switchForChannel5;
/**
* 摄像通道1 定时拍照存储标志, true: 上传 false 存储
*/
private boolean storageFlagsForChannel1;
/**
* 摄像通道2 定时拍照存储标志 true: 上传 false 存储
*/
private boolean storageFlagsForChannel2;
/**
* 摄像通道3 定时拍照存储标志 true: 上传 false 存储
*/
private boolean storageFlagsForChannel3;
/**
* 摄像通道4 定时拍照存储标志 true: 上传 false 存储
*/
private boolean storageFlagsForChannel4;
/**
* 摄像通道5 定时拍照存储标志 true: 上传 false 存储
*/
private boolean storageFlagsForChannel5;
/**
* 定时时间单位,true: false 当数值小于5s时终端按5s处理
*/
private boolean timeUnit;
/**
* 定时时间间隔
*/
private Integer timeInterval;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte[] bytes = new byte[4];
bytes[0] = 0;
if (switchForChannel1) {
bytes[0] = (byte)(bytes[0] | 1);
}
if (switchForChannel2) {
bytes[0] = (byte)(bytes[0] | 2);
}
if (switchForChannel3) {
bytes[0] = (byte)(bytes[0] | 4);
}
if (switchForChannel4) {
bytes[0] = (byte)(bytes[0] | 8);
}
if (switchForChannel5) {
bytes[0] = (byte)(bytes[0] | 16);
}
bytes[1] = 0;
if (storageFlagsForChannel1) {
bytes[1] = (byte)(bytes[1] | 1);
}
if (storageFlagsForChannel2) {
bytes[1] = (byte)(bytes[1] | 2);
}
if (storageFlagsForChannel3) {
bytes[1] = (byte)(bytes[1] | 4);
}
if (storageFlagsForChannel4) {
bytes[1] = (byte)(bytes[1] | 8);
}
if (storageFlagsForChannel5) {
bytes[1] = (byte)(bytes[1] | 16);
}
bytes[3] = (byte)(timeInterval & 0xfe);
if (timeUnit) {
bytes[3] = (byte)(bytes[3] | 1);
}
byteBuf.writeBytes(bytes);
return byteBuf;
}
}

View File

@ -0,0 +1,56 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 音视频通道
*/
@Setter
@Getter
public class JTChanelConfig implements JTDeviceSubConfig{
/**
* 物理通道号 单独
*/
private int physicalChannelId;
/**
* 逻辑通道号
*/
private int logicChannelId;
/**
* 通道类型:
* 0:音视频;
* 1:音频
* 2:视频
*/
private int channelType;
/**
* 是否连接云台: 通道类型为 0 2 ,此字段有效
* 0:未连接;1:连接
*/
private int ptzEnable;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(physicalChannelId);
byteBuf.writeByte(logicChannelId);
byteBuf.writeByte(channelType);
byteBuf.writeByte(ptzEnable);
return byteBuf;
}
public static JTChanelConfig decode(ByteBuf byteBuf) {
JTChanelConfig jtChanel = new JTChanelConfig();
jtChanel.setPhysicalChannelId(byteBuf.readUnsignedByte());
jtChanel.setLogicChannelId(byteBuf.readUnsignedByte());
jtChanel.setChannelType(byteBuf.readUnsignedByte());
jtChanel.setPtzEnable(byteBuf.readUnsignedByte());
return jtChanel;
}
}

View File

@ -0,0 +1,61 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
/**
* 音视频通道列表设置
*/
@Setter
@Getter
public class JTChannelListParam implements JTDeviceSubConfig{
/**
* 音视频通道总数
*/
private int videoAndAudioCount;
/**
* 音频通道总数
*/
private int audioCount;
/**
* 视频通道总数
*/
private int videoCount;
private List<JTChanelConfig> chanelList;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(videoAndAudioCount);
byteBuf.writeByte(audioCount);
byteBuf.writeByte(videoCount);
for (JTChanelConfig jtChanel : chanelList) {
byteBuf.writeBytes(jtChanel.encode());
}
return byteBuf;
}
public static JTChannelListParam decode(ByteBuf byteBuf) {
JTChannelListParam channelListParam = new JTChannelListParam();
channelListParam.setVideoAndAudioCount(byteBuf.readUnsignedByte());
channelListParam.setAudioCount(byteBuf.readUnsignedByte());
channelListParam.setVideoCount(byteBuf.readUnsignedByte());
int total = channelListParam.getVideoAndAudioCount() + channelListParam.getVideoCount() + channelListParam.getAudioCount();
List<JTChanelConfig> chanelList = new ArrayList<>(total);
for (int i = 0; i < total; i++) {
chanelList.add(JTChanelConfig.decode(byteBuf));
}
channelListParam.setChanelList(chanelList);
return channelListParam;
}
}

View File

@ -0,0 +1,46 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
/**
* 单独视频通道参数设置
*/
@Setter
@Getter
public class JTChannelParam implements JTDeviceSubConfig {
/**
* 单独通道视频参数设置列表
*/
private List<JTAloneChanel> jtAloneChanelList;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(jtAloneChanelList.size());
for (JTAloneChanel jtAloneChanel : jtAloneChanelList) {
if (jtAloneChanel == null) {
continue;
}
byteBuf.writeBytes(jtAloneChanel.encode());
}
return byteBuf;
}
public static JTChannelParam decode(ByteBuf byteBuf) {
JTChannelParam channelParam = new JTChannelParam();
int length = byteBuf.readUnsignedByte();
List<JTAloneChanel> jtAloneChanelList = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
jtAloneChanelList.add(JTAloneChanel.decode(byteBuf));
}
channelParam.setJtAloneChanelList(jtAloneChanelList);
return channelParam;
}
}

View File

@ -0,0 +1,34 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 碰撞报警参数设置
*/
@Setter
@Getter
public class JTCollisionAlarmParams implements JTDeviceSubConfig{
/**
* 碰撞时间 单位为毫秒(ms)
*/
private int collisionAlarmTime;
/**
* 碰撞加速度 单位为0.1g,设置范围为0~79,默认为10
*/
private int collisionAcceleration;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte[] bytes = new byte[2];
bytes[0] = (byte) (collisionAlarmTime & 0xff);
bytes[1] = (byte) (collisionAcceleration & 0xff);
byteBuf.writeBytes(bytes);
return byteBuf;
}
}

View File

@ -0,0 +1,7 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
public interface JTDeviceSubConfig {
ByteBuf encode();
}

View File

@ -0,0 +1,52 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* GNSS 定位模式
*/
@Setter
@Getter
public class JTGnssPositioningMode implements JTDeviceSubConfig{
/**
* GPS 定位 true: 开启 false 关闭
*/
private boolean gps;
/**
* 北斗定位 true: 开启 false 关闭
*/
private boolean beidou;
/**
* GLONASS定位 true: 开启 false 关闭
*/
private boolean glonass;
/**
* GaLiLeo定位 true: 开启 false 关闭
*/
private boolean gaLiLeo;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte[] bytes = new byte[1];
bytes[0] = 0;
if (gps) {
bytes[0] = (byte)(bytes[0] | 1);
}
if (beidou) {
bytes[0] = (byte)(bytes[0] | 2);
}
if (glonass) {
bytes[0] = (byte)(bytes[0] | 4);
}
if (gaLiLeo) {
bytes[0] = (byte)(bytes[0] | 8);
}
byteBuf.writeBytes(bytes);
return byteBuf;
}
}

View File

@ -0,0 +1,37 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* 违规行驶时段范围 ,精确到分
*/
@Setter
@Getter
public class JTIllegalDrivingPeriods implements JTDeviceSubConfig{
/**
* 违规行驶时段-开始时间 HH:mm
*/
private String startTime;
/**
* 违规行驶时段-结束时间 HH:mm
*/
private String endTime;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte[] bytes = new byte[4];
String[] startTimeArray = startTime.split(":");
String[] endTimeArray = endTime.split(":");
bytes[0] = (byte)Integer.parseInt(startTimeArray[0]);
bytes[1] = (byte)Integer.parseInt(startTimeArray[1]);
bytes[2] = (byte)Integer.parseInt(endTimeArray[0]);
bytes[3] = (byte)Integer.parseInt(endTimeArray[1]);
byteBuf.writeBytes(bytes);
return byteBuf;
}
}

View File

@ -0,0 +1,92 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
/**
* OSD字幕叠加设置
*/
@Setter
@Getter
public class JTOSDConfig {
/**
* 日期和时间
*/
private boolean time;
/**
* 车牌号码
*/
private boolean licensePlate;
/**
* 逻辑通道号
*/
private boolean channelId;
/**
* 经纬度
*/
private boolean position;
/**
* 行驶记录速度
*/
private boolean speed;
/**
* 卫星定位速度
*/
private boolean speedForGPS;
/**
* 连续驾驶时间
*/
private boolean drivingTime;
public ByteBuf encode(){
ByteBuf byteBuf = Unpooled.buffer();
byte content = 0;
if (time) {
content = (byte)(content | 1);
}
if (licensePlate) {
content = (byte)(content | (1 << 1));
}
if (channelId) {
content = (byte)(content | (1 << 2));
}
if (position) {
content = (byte)(content | (1 << 3));
}
if (speed) {
content = (byte)(content | (1 << 4));
}
if (speedForGPS) {
content = (byte)(content | (1 << 5));
}
if (drivingTime) {
content = (byte)(content | (1 << 6));
}
byteBuf.writeByte(content);
byteBuf.writeByte(0);
return byteBuf;
}
public static JTOSDConfig decode(ByteBuf buf) {
JTOSDConfig config = new JTOSDConfig();
int content = buf.readUnsignedShort();
config.setTime((content & 1) == 1);
config.setLicensePlate((content >>> 1 & 1) == 1);
config.setChannelId((content >>> 2 & 1) == 1);
config.setPosition((content >>> 3 & 1) == 1);
config.setSpeed((content >>> 4 & 1) == 1);
config.setSpeedForGPS((content >>> 5 & 1) == 1);
config.setDrivingTime((content >>> 6 & 1) == 1);
return config;
}
}

View File

@ -0,0 +1,143 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
/**
* 视频报警标志位
*/
public class JTVideoAlarmBit implements JTDeviceSubConfig{
/**
* 视频信号丢失报警
*/
private boolean lossSignal;
/**
* 视频信号遮挡报警
*/
private boolean occlusionSignal;
/**
* 存储单元故障报警
*/
private boolean storageFault;
/**
* 其他视频设备故障报警
*/
private boolean otherDeviceFailure;
/**
* 客车超员报警
*/
private boolean overcrowding;
/**
* 异常驾驶行为报警
*/
private boolean abnormalDriving;
/**
* 特殊报警录像达到存储阈值报警
*/
private boolean storageLimit;
public boolean isLossSignal() {
return lossSignal;
}
public void setLossSignal(boolean lossSignal) {
this.lossSignal = lossSignal;
}
public boolean isOcclusionSignal() {
return occlusionSignal;
}
public void setOcclusionSignal(boolean occlusionSignal) {
this.occlusionSignal = occlusionSignal;
}
public boolean isStorageFault() {
return storageFault;
}
public void setStorageFault(boolean storageFault) {
this.storageFault = storageFault;
}
public boolean isOtherDeviceFailure() {
return otherDeviceFailure;
}
public void setOtherDeviceFailure(boolean otherDeviceFailure) {
this.otherDeviceFailure = otherDeviceFailure;
}
public boolean isOvercrowding() {
return overcrowding;
}
public void setOvercrowding(boolean overcrowding) {
this.overcrowding = overcrowding;
}
public boolean isAbnormalDriving() {
return abnormalDriving;
}
public void setAbnormalDriving(boolean abnormalDriving) {
this.abnormalDriving = abnormalDriving;
}
public boolean isStorageLimit() {
return storageLimit;
}
public void setStorageLimit(boolean storageLimit) {
this.storageLimit = storageLimit;
}
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byte content = 0;
if (lossSignal) {
content = content |= 1;
}
if (occlusionSignal) {
content = content |= (1 << 1);
}
if (storageFault) {
content = content |= (1 << 2);
}
if (otherDeviceFailure) {
content = content |= (1 << 3);
}
if (overcrowding) {
content = content |= (1 << 4);
}
if (abnormalDriving) {
content = content |= (1 << 5);
}
if (storageLimit) {
content = content |= (1 << 6);
}
byteBuf.writeByte(content);
byteBuf.writeByte(0);
byteBuf.writeByte(0);
byteBuf.writeByte(0);
return byteBuf;
}
public static JTVideoAlarmBit decode(ByteBuf byteBuf) {
JTVideoAlarmBit videoAlarmBit = new JTVideoAlarmBit();
byte content = byteBuf.readByte();
videoAlarmBit.setLossSignal((content & 1) == 1);
videoAlarmBit.setOcclusionSignal((content >>> 1 & 1) == 1);
videoAlarmBit.setStorageFault((content >>> 2 & 1) == 1);
videoAlarmBit.setOtherDeviceFailure((content >>> 3 & 1) == 1);
videoAlarmBit.setOvercrowding((content >>> 4 & 1) == 1);
videoAlarmBit.setAbnormalDriving((content >>> 5 & 1) == 1);
videoAlarmBit.setStorageLimit((content >>> 6 & 1) == 1);
byteBuf.readByte();
byteBuf.readByte();
byteBuf.readByte();
return videoAlarmBit;
}
}

View File

@ -0,0 +1,133 @@
package com.genersoft.iot.vmp.jt1078.bean.config;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Data;
/**
* 违规行驶时段范围 ,精确到分
*/
@Data
public class JTVideoParam implements JTDeviceSubConfig{
/**
* 实时流编码模式
* 0:CBR( 固定码率) ;
* 1:VBR( 可变码率) ;
* 2:ABR( 平均码率) ;
* 100 ~ 127:自定义
*/
private int liveStreamCodeRateType;
/**
* 实时流分辨率
* 0:QCIF;
* 1:CIF;
* 2:WCIF;
* 3:D1;
* 4:WD1;
* 5:720P;
* 6:1 080P;
* 100 ~ 127:自定义
*/
private int liveStreamResolving;
/**
* 实时流关键帧间隔, 范围(1 ~ 1 000)
*/
private int liveStreamIInterval;
/**
* 实时流目标帧率,范围(1 ~ 120) / s
*/
private int liveStreamFrameRate;
/**
* 实时流目标码率,单位为千位每秒( kbps)
*/
private long liveStreamCodeRate;
/**
* 存储流编码模式
* 0:CBR( 固定码率)
* 1:VBR( 可变码率)
* 2:ABR( 平均码率)
* 100 ~ 127:自定义
*/
private int storageStreamCodeRateType;
/**
* 存储流分辨率
* 0:QCIF;
* 1:CIF;
* 2:WCIF;
* 3:D1;
* 4:WD1;
* 5:720P;
* 6:1 080P;
* 100 ~ 127:自定义
*/
private int storageStreamResolving;
/**
* 存储流关键帧间隔, 范围(1 ~ 1 000)
*/
private int storageStreamIInterval;
/**
* 存储流目标帧率,范围(1 ~ 120) / s
*/
private int storageStreamFrameRate;
/**
* 存储流目标码率,单位为千位每秒( kbps)
*/
private long storageStreamCodeRate;
/**
* 字幕叠加设置
*/
private JTOSDConfig osd;
/**
* 是否启用音频输出, 0:不启用;1:启用
*/
private int audioEnable;
@Override
public ByteBuf encode() {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeByte(liveStreamCodeRateType);
byteBuf.writeByte(liveStreamResolving);
byteBuf.writeShort((short)(liveStreamIInterval & 0xffff));
byteBuf.writeByte(liveStreamFrameRate);
byteBuf.writeInt((int) (liveStreamCodeRate & 0xffffffffL));
byteBuf.writeByte(storageStreamCodeRateType);
byteBuf.writeByte(storageStreamResolving);
byteBuf.writeShort((short)(storageStreamIInterval & 0xffff));
byteBuf.writeByte(storageStreamFrameRate);
byteBuf.writeInt((int) (storageStreamCodeRate & 0xffffffffL));
byteBuf.writeBytes(osd.encode());
byteBuf.writeByte(audioEnable);
return byteBuf;
}
public static JTVideoParam decode(ByteBuf buf) {
JTVideoParam videoParam = new JTVideoParam();
videoParam.setLiveStreamCodeRateType(buf.readByte());
videoParam.setLiveStreamResolving(buf.readByte());
videoParam.setLiveStreamIInterval(buf.readUnsignedShort());
videoParam.setLiveStreamFrameRate(buf.readByte());
videoParam.setLiveStreamCodeRate(buf.readUnsignedInt());
videoParam.setStorageStreamCodeRateType(buf.readByte());
videoParam.setStorageStreamResolving(buf.readByte());
videoParam.setStorageStreamIInterval(buf.readUnsignedShort());
videoParam.setStorageStreamFrameRate(buf.readByte());
videoParam.setStorageStreamCodeRate(buf.readUnsignedInt());
videoParam.setOsd(JTOSDConfig.decode(buf));
videoParam.setAudioEnable(buf.readByte());
return null;
}
}

View File

@ -1,8 +1,11 @@
package com.genersoft.iot.vmp.jt1078.cmd;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd;
import com.genersoft.iot.vmp.jt1078.proc.response.*;
import com.genersoft.iot.vmp.jt1078.session.SessionManager;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.springframework.stereotype.Component;
import java.util.Random;
@ -11,28 +14,83 @@ import java.util.Random;
* @date 2023/4/27 18:58
* @email qingtaij@163.com
*/
@Component
public class JT1078Template {
private final Random random = new Random();
private static final String H8103 = "8103";
private static final String H8104 = "8104";
private static final String H8105 = "8105";
private static final String H8106 = "8106";
private static final String H8107 = "8107";
private static final String H8201 = "8201";
private static final String H8202 = "8202";
private static final String H8203 = "8203";
private static final String H8204 = "8204";
private static final String H8300 = "8300";
private static final String H8400 = "8400";
private static final String H8401 = "8401";
private static final String H8500 = "8500";
private static final String H8600 = "8600";
private static final String H8601 = "8601";
private static final String H8602 = "8602";
private static final String H8603 = "8603";
private static final String H8604 = "8604";
private static final String H8605 = "8605";
private static final String H8606 = "8606";
private static final String H8607 = "8607";
private static final String H8608 = "8608";
private static final String H8702 = "8702";
private static final String H8801 = "8801";
private static final String H8802 = "8802";
private static final String H8803 = "8803";
private static final String H8804 = "8804";
private static final String H8805 = "8805";
private static final String H9003 = "9003";
private static final String H9101 = "9101";
private static final String H9102 = "9102";
private static final String H9201 = "9201";
private static final String H9202 = "9202";
private static final String H9205 = "9205";
private static final String H9206 = "9206";
private static final String H9207 = "9207";
private static final String H9301 = "9301";
private static final String H9302 = "9302";
private static final String H9303 = "9303";
private static final String H9304 = "9304";
private static final String H9305 = "9305";
private static final String H9306 = "9306";
private static final String H0001 = "0001";
private static final String H0104 = "0104";
private static final String H0107 = "0107";
private static final String H0201 = "0201";
private static final String H0500 = "0500";
private static final String H0608 = "0608";
private static final String H0702 = "0702";
private static final String H0801 = "0801";
private static final String H0802 = "0802";
private static final String H0805 = "0805";
private static final String H1003 = "1003";
private static final String H1205 = "1205";
public void checkTerminalStatus(String devId){
if (SessionManager.INSTANCE.get(devId) == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "终端不在线");
}
}
/**
* 开启直播视频
*
* @param devId 设备号
* @param j9101 开启视频参数
*/
public String startLive(String devId, J9101 j9101, Integer timeOut) {
public Object startLive(String devId, J9101 j9101, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setDevId(devId)
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9101)
.setRespId(H0001)
@ -47,9 +105,10 @@ public class JT1078Template {
* @param devId 设备号
* @param j9102 关闭视频参数
*/
public String stopLive(String devId, J9102 j9102, Integer timeOut) {
public Object stopLive(String devId, J9102 j9102, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setDevId(devId)
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9102)
.setRespId(H0001)
@ -64,9 +123,10 @@ public class JT1078Template {
* @param devId 设备号
* @param j9205 查询音视频列表
*/
public String queryBackTime(String devId, J9205 j9205, Integer timeOut) {
public Object queryBackTime(String devId, J9205 j9205, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setDevId(devId)
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9205)
.setRespId(H1205)
@ -81,9 +141,10 @@ public class JT1078Template {
* @param devId 设备号
* @param j9201 视频回放参数
*/
public String startBackLive(String devId, J9201 j9201, Integer timeOut) {
public Object startBackLive(String devId, J9201 j9201, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setDevId(devId)
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9201)
.setRespId(H1205)
@ -98,9 +159,10 @@ public class JT1078Template {
* @param devId 设备号
* @param j9202 控制视频回放参数
*/
public String controlBackLive(String devId, J9202 j9202, Integer timeOut) {
public Object controlBackLive(String devId, J9202 j9202, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setDevId(devId)
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9202)
.setRespId(H0001)
@ -109,7 +171,523 @@ public class JT1078Template {
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 文件上传
*
* @param devId 设备号
* @param j9206 文件上传参数
*/
public Object fileUpload(String devId, J9206 j9206, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9206)
.setRespId(H0001)
.setRs(j9206)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 文件上传控制
*
* @param devId 设备号
* @param j9207 文件上传控制参数
*/
public Object fileUploadControl(String devId, J9207 j9207, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9207)
.setRespId(H0001)
.setRs(j9207)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-云台旋转
*
* @param devId 设备号
* @param j9301 云台旋转参数
*/
public Object ptzRotate(String devId, J9301 j9301, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9301)
.setRespId(H0001)
.setRs(j9301)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-云台调整焦距控制
*
* @param devId 设备号
* @param j9302 云台焦距控制参数
*/
public Object ptzFocal(String devId, J9302 j9302, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9302)
.setRespId(H0001)
.setRs(j9302)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-云台调整光圈控制
*
* @param devId 设备号
* @param j9303 云台光圈控制参数
*/
public Object ptzIris(String devId, J9303 j9303, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9303)
.setRespId(H0001)
.setRs(j9303)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-云台雨刷控制
*
* @param devId 设备号
* @param j9304 云台雨刷控制参数
*/
public Object ptzWiper(String devId, J9304 j9304, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9304)
.setRespId(H0001)
.setRs(j9304)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-红外补光控制
*
* @param devId 设备号
* @param j9305 云台红外补光控制参数
*/
public Object ptzSupplementaryLight(String devId, J9305 j9305, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9305)
.setRespId(H0001)
.setRs(j9305)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 云台控制指令-变倍控制
*
* @param devId 设备号
* @param j9306 云台变倍控制参数
*/
public Object ptzZoom(String devId, J9306 j9306, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9306)
.setRespId(H0001)
.setRs(j9306)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 查询终端参数
*
* @param devId 设备号
*/
public Object getDeviceConfig(String devId, J8104 j8104, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8104)
.setRespId(H0104)
.setRs(j8104)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 查询指定终端参数
*
* @param devId 设备号
*/
public Object getDeviceSpecifyConfig(String devId, J8106 j8106, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8106)
.setRespId(H0104)
.setRs(j8106)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 设置终端参数
*
* @param devId 设备号
*/
public Object setDeviceSpecifyConfig(String devId, J8103 j8103, Integer timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8103)
.setRespId(H0001)
.setRs(j8103)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
private Long randomInt() {
return (long) random.nextInt(1000) + 1;
}
/**
* 设备控制
*/
public Object deviceControl(String devId, J8105 j8105, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8105)
.setRespId(H0001)
.setRs(j8105)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 查询终端属性
*/
public Object deviceAttribute(String devId, J8107 j8107, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8107)
.setRespId(H0107)
.setRs(j8107)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
/**
* 位置信息查询
*/
public Object queryPositionInfo(String devId, J8201 j8201, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8201)
.setRespId(H0201)
.setRs(j8201)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object tempPositionTrackingControl(String devId, J8202 j8202, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8202)
.setRespId(H0001)
.setRs(j8202)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object confirmationAlarmMessage(String devId, J8203 j8203, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8203)
.setRespId(H0001)
.setRs(j8203)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object linkDetection(String devId, J8204 j8204, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8204)
.setRespId(H0001)
.setRs(j8204)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object textMessage(String devId, J8300 j8300, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8300)
.setRespId(H0001)
.setRs(j8300)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object telephoneCallback(String devId, J8400 j8400, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8400)
.setRespId(H0001)
.setRs(j8400)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object setPhoneBook(String devId, J8401 j8401, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8401)
.setRespId(H0001)
.setRs(j8401)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object vehicleControl(String devId, J8500 j8500, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8500)
.setRespId(H0500)
.setRs(j8500)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object setAreaForCircle(String devId, J8600 j8600, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8600)
.setRespId(H0001)
.setRs(j8600)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object deleteAreaForCircle(String devId, J8601 j8601, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8601)
.setRespId(H0001)
.setRs(j8601)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object setAreaForRectangle(String devId, J8602 j8602, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8602)
.setRespId(H0001)
.setRs(j8602)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object deleteAreaForRectangle(String devId, J8603 j8603, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8603)
.setRespId(H0001)
.setRs(j8603)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object setAreaForPolygon(String devId, J8604 j8604, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8604)
.setRespId(H0001)
.setRs(j8604)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object deleteAreaForPolygon(String devId, J8605 j8605, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8605)
.setRespId(H0001)
.setRs(j8605)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object setRoute(String devId, J8606 j8606, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8606)
.setRespId(H0001)
.setRs(j8606)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object deleteRoute(String devId, J8607 j8607, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8607)
.setRespId(H0001)
.setRs(j8607)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object queryAreaOrRoute(String devId, J8608 j8608, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8608)
.setRespId(H0608)
.setRs(j8608)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object queryDriverInformation(String devId, J8702 j8702, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8702)
.setRespId(H0702)
.setRs(j8702)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object shooting(String devId, J8801 j8801, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8801)
.setRespId(H0805)
.setRs(j8801)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object queryMediaData(String devId, J8802 j8802, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8802)
.setRespId(H0802)
.setRs(j8802)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object uploadMediaData(String devId, J8803 j8803, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8803)
.setRespId(H0801)
.setRs(j8803)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object record(String devId, J8804 j8804, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8804)
.setRespId(H0001)
.setRs(j8804)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object uploadMediaDataForSingle(String devId, J8805 j8805, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H8805)
.setRespId(H0801)
.setRs(j8805)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
public Object queryMediaAttribute(String devId, J9003 j9003, int timeOut) {
checkTerminalStatus(devId);
Cmd cmd = new Cmd.Builder()
.setPhoneNumber(devId)
.setPackageNo(randomInt())
.setMsgId(H9003)
.setRespId(H1003)
.setRs(j9003)
.build();
return SessionManager.INSTANCE.request(cmd, timeOut);
}
}

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.jt1078.proc.Header;
import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory;
import com.genersoft.iot.vmp.jt1078.proc.request.Re;
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 io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
@ -11,10 +12,17 @@ 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 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
@ -24,40 +32,64 @@ import java.util.List;
@Slf4j
public class Jt808Decoder extends ByteToMessageDecoder {
private ApplicationEventPublisher applicationEventPublisher = null;
private Ijt1078Service service = null;
public Jt808Decoder(ApplicationEventPublisher applicationEventPublisher, Ijt1078Service service ) {
this.applicationEventPublisher = applicationEventPublisher;
this.service = service;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
Session session = ctx.channel().attr(Session.KEY).get();
log.info("> {} hex:{}", session, ByteBufUtil.hexDump(in));
log.info("> {} hex: 7e{}7e", session, ByteBufUtil.hexDump(in));
try {
// 按照部标定义执行校验和转义
ByteBuf buf = unEscapeAndCheck(in);
buf.retain();
Header header = new Header();
header.setMsgId(ByteBufUtil.hexDump(buf.readSlice(2)));
header.setMsgPro(buf.readUnsignedShort());
// 从消息属性中读取是否存在分包
boolean isSubpackage = (header.getMsgPro() >>> 13 & 1) == 1;
if (header.is2019Version()) {
header.setVersion(buf.readUnsignedByte());
String devId = ByteBufUtil.hexDump(buf.readSlice(10));
header.setDevId(devId.replaceFirst("^0*", ""));
header.setPhoneNumber(devId.replaceFirst("^0*", ""));
} else {
header.setDevId(ByteBufUtil.hexDump(buf.readSlice(6)).replaceFirst("^0*", ""));
header.setPhoneNumber(ByteBufUtil.hexDump(buf.readSlice(6)).replaceFirst("^0*", ""));
}
header.setSn(buf.readUnsignedShort());
if (isSubpackage) {
int packageCount = buf.readUnsignedShort();
int packageNumber = buf.readUnsignedShort();
log.debug("[分包消息] header: {}, 序号: {}, 总数: {}", header, packageNumber, packageCount);
// 缓存带合并的分包消息
ByteBuf intactBuf = MultiPacketManager.INSTANCE.add(header, packageCount, buf);
if (intactBuf == null) {
return;
}
buf = intactBuf;
}
Re handler = CodecFactory.getHandler(header.getMsgId());
if (handler == null) {
log.error("get msgId is null {}", header.getMsgId());
buf.release();
return;
}
Rs decode = handler.decode(buf, header, session);
Rs decode = handler.decode(buf, header, session, service);
ApplicationEvent applicationEvent = handler.getEvent();
if (applicationEvent != null) {
applicationEventPublisher.publishEvent(applicationEvent);
}
if (decode != null) {
out.add(decode);
}
} finally {
in.skipBytes(in.readableBytes());
}
}
@ -121,7 +153,7 @@ public class Jt808Decoder extends ByteToMessageDecoder {
}
if (calculationCheckSum == checkSum) {
if (bufList.size() == 0) {
if (bufList.isEmpty()) {
return byteBuf.slice(low, high);
} else {
bufList.add(byteBuf.slice(low, high - low));

View File

@ -0,0 +1,59 @@
package com.genersoft.iot.vmp.jt1078.codec.decode;
import com.genersoft.iot.vmp.jt1078.proc.Header;
import io.netty.buffer.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public enum MultiPacketManager {
INSTANCE;
// 用与消息的缓存
private final Map<String, CompositeByteBuf> packetMap = new ConcurrentHashMap<>();
private final Map<String, Long> packetTimeMap = new ConcurrentHashMap<>();
MultiPacketManager() {
startLister();
}
/**
* 增加待合并的分包如果分包接受完毕会返回完整的数据包
*/
public ByteBuf add(Header header, Integer count, ByteBuf byteBuf) {
String key = header.getMsgId() + "/" + header.getPhoneNumber();
CompositeByteBuf compositeBuf = packetMap.computeIfAbsent(key, k -> new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, count));
// compositeBuf.addComponent(true, byteBuf.readSlice(byteBuf.readableBytes()));
compositeBuf.addComponent(true, byteBuf);
packetTimeMap.put(key, System.currentTimeMillis());
if (count == compositeBuf.numComponents()) {
packetMap.remove(key);
packetTimeMap.remove(key);
compositeBuf.retain();
return compositeBuf;
}
return null;
}
private void startLister(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
long expireTime = System.currentTimeMillis() - 20 * 1000;
if (!packetTimeMap.isEmpty()) {
for (String key : packetTimeMap.keySet()) {
if (packetTimeMap.get(key) < expireTime) {
log.info("分包消息超时 key: {}", key);
packetTimeMap.remove(key);
packetMap.remove(key);
}
}
}
}
}, 2000L, 2000L);
}
}

View File

@ -9,6 +9,8 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* @author QingtaiJiang
* @date 2023/4/27 18:10
@ -21,12 +23,12 @@ public class Jt808Encoder extends MessageToByteEncoder<Rs> {
protected void encode(ChannelHandlerContext ctx, Rs msg, ByteBuf out) throws Exception {
Session session = ctx.channel().attr(Session.KEY).get();
ByteBuf encode = Jt808EncoderCmd.encode(msg, session, session.nextSerialNo());
if(encode!=null){
log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode));
out.writeBytes(encode);
List<ByteBuf> encodeList = Jt808EncoderCmd.encode(msg, session, session.nextSerialNo());
if(encodeList!=null && !encodeList.isEmpty()){
for (ByteBuf byteBuf : encodeList) {
log.debug("< {} hex:{}", session, ByteBufUtil.hexDump(byteBuf));
out.writeBytes(byteBuf);
}
}
}
}

View File

@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.util.LinkedList;
import java.util.List;
/**
* @author QingtaiJiang
@ -30,51 +31,84 @@ public class Jt808EncoderCmd extends MessageToByteEncoder<Cmd> {
protected void encode(ChannelHandlerContext ctx, Cmd cmd, ByteBuf out) throws Exception {
Session session = ctx.channel().attr(Session.KEY).get();
Rs msg = cmd.getRs();
ByteBuf encode = encode(msg, session, cmd.getPackageNo().intValue());
if (encode != null) {
log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode));
out.writeBytes(encode);
List<ByteBuf> encodeList = encode(msg, session, cmd.getPackageNo().intValue());
if (encodeList != null && !encodeList.isEmpty()) {
for (ByteBuf byteBuf : encodeList) {
log.debug("< {} hex:{}", session, ByteBufUtil.hexDump(byteBuf));
out.writeBytes(byteBuf);
}
}
}
public static ByteBuf encode(Rs msg, Session session, Integer packageNo) {
public static List<ByteBuf> encode(Rs msg, Session session, Integer packageNo) {
String id = msg.getClass().getAnnotation(MsgId.class).id();
if (!StringUtils.hasLength(id)) {
log.error("Not find msgId");
return null;
}
ByteBuf encode = msg.encode();
Header header = msg.getHeader();
List<ByteBuf> byteBufList = new LinkedList<>();
if (encode.readableBytes() > 1000) {
int index = 1;
int total = encode.readableBytes()%1000 == 0 ? encode.readableBytes()/1000 : (encode.readableBytes()/1000 + 1);
while (encode.isReadable()) {
ByteBuf byteBuf;
if (index == total) {
byteBuf = buildMsgByte(header, id, session, packageNo, encode.readRetainedSlice(encode.readableBytes()), index, total);
}else {
byteBuf = buildMsgByte(header, id, session, packageNo, encode.readRetainedSlice(1000), index, total);
}
byteBufList.add(byteBuf);
index ++;
}
}else {
byteBufList.add(buildMsgByte(header, id, session, packageNo, encode, 0, 0));
}
return byteBufList;
}
// 分包
private static ByteBuf buildMsgByte(Header header, String id, Session session, Integer packageNo, ByteBuf encode, Integer packetIndex, Integer packetTotal) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(ByteBufUtil.decodeHexDump(id));
ByteBuf encode = msg.encode();
Header header = msg.getHeader();
if (header == null) {
header = session.getHeader();
}
if (header.is2019Version()) {
int msgBody = encode.readableBytes() | 1 << 14;
if (packetIndex > 0) {
msgBody = msgBody | 1 << 13;
}
// 消息体属性
byteBuf.writeShort(encode.readableBytes() | 1 << 14);
byteBuf.writeShort(msgBody);
// 版本号
byteBuf.writeByte(header.getVersion());
// 终端手机号
byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 20)));
byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getPhoneNumber(), 20)));
} else {
// 消息体属性
byteBuf.writeShort(encode.readableBytes());
byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 12)));
byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getPhoneNumber(), 12)));
}
// 消息体流水号
byteBuf.writeShort(packageNo);
if (packetIndex > 0) {
byteBuf.writeShort(packetTotal);
byteBuf.writeShort(packetIndex);
}
// 写入消息体
byteBuf.writeBytes(encode);

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.jt1078.codec.netty;
import com.genersoft.iot.vmp.jt1078.event.ConnectChangeEvent;
import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
import com.genersoft.iot.vmp.jt1078.session.Session;
import com.genersoft.iot.vmp.jt1078.session.SessionManager;
@ -8,6 +9,10 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import lombok.extern.slf4j.Slf4j;
/**
@ -18,6 +23,12 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Jt808Handler extends ChannelInboundHandlerAdapter {
private ApplicationEventPublisher applicationEventPublisher = null;
public Jt808Handler(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Rs) {
@ -25,6 +36,8 @@ public class Jt808Handler extends ChannelInboundHandlerAdapter {
} else {
ctx.fireChannelRead(msg);
}
// 读取完成后的消息释放
ReferenceCountUtil.release(msg);
}
@Override
@ -33,6 +46,13 @@ public class Jt808Handler extends ChannelInboundHandlerAdapter {
Session session = SessionManager.INSTANCE.newSession(channel);
channel.attr(Session.KEY).set(session);
log.info("> Tcp connect {}", session);
if (session.getPhoneNumber() == null) {
return;
}
ConnectChangeEvent event = new ConnectChangeEvent(this);
event.setConnected(true);
event.setPhoneNumber(session.getPhoneNumber());
applicationEventPublisher.publishEvent(event);
}
@Override
@ -40,6 +60,14 @@ public class Jt808Handler extends ChannelInboundHandlerAdapter {
Session session = ctx.channel().attr(Session.KEY).get();
log.info("< Tcp disconnect {}", session);
ctx.close();
if (session.getPhoneNumber() == null) {
return;
}
ConnectChangeEvent event = new ConnectChangeEvent(this);
event.setConnected(false);
event.setPhoneNumber(session.getPhoneNumber());
applicationEventPublisher.publishEvent(event);
}
@Override

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.jt1078.codec.decode.Jt808Decoder;
import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808Encoder;
import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808EncoderCmd;
import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@ -17,6 +18,13 @@ import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@ -34,11 +42,15 @@ public class TcpServer {
private boolean isRunning = false;
private EventLoopGroup bossGroup = null;
private EventLoopGroup workerGroup = null;
private ApplicationEventPublisher applicationEventPublisher = null;
private Ijt1078Service service = null;
private final ByteBuf DECODER_JT808 = Unpooled.wrappedBuffer(new byte[]{0x7e});
public TcpServer(Integer port) {
public TcpServer(Integer port, ApplicationEventPublisher applicationEventPublisher, Ijt1078Service service) {
this.port = port;
this.applicationEventPublisher = applicationEventPublisher;
this.service = service;
}
private void startTcpServer() {
@ -59,10 +71,10 @@ public class TcpServer {
channel.pipeline()
.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.MINUTES))
.addLast(new DelimiterBasedFrameDecoder(1024 * 2, DECODER_JT808))
.addLast(new Jt808Decoder())
.addLast(new Jt808Decoder(applicationEventPublisher, service))
.addLast(new Jt808Encoder())
.addLast(new Jt808EncoderCmd())
.addLast(new Jt808Handler());
.addLast(new Jt808Handler(applicationEventPublisher));
}
});
ChannelFuture channelFuture = bootstrap.bind(port).sync();

View File

@ -1,9 +1,11 @@
package com.genersoft.iot.vmp.jt1078.config;
import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
import com.genersoft.iot.vmp.jt1078.codec.netty.TcpServer;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
@ -18,13 +20,14 @@ import org.springframework.core.annotation.Order;
@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
public class JT1078AutoConfiguration {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private Ijt1078Service service;
@Bean(initMethod = "start", destroyMethod = "stop")
public TcpServer jt1078Server(@Value("${jt1078.port}") Integer port) {
return new TcpServer(port);
}
@Bean
public JT1078Template jt1078Template() {
return new JT1078Template();
return new TcpServer(port, applicationEventPublisher, service);
}
}

View File

@ -0,0 +1,18 @@
package com.genersoft.iot.vmp.jt1078.config;
import com.genersoft.iot.vmp.jt1078.bean.common.ConfigAttribute;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "jt1078", ignoreInvalidFields = true)
@Order(3)
public class JT1078Config {
private Integer port;
private String password;
}

View File

@ -1,51 +0,0 @@
package com.genersoft.iot.vmp.jt1078.config;
import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
import com.genersoft.iot.vmp.jt1078.proc.response.*;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* curl http://localhost:18080/api/jt1078/start/live/18864197066/1
*
* @author QingtaiJiang
* @date 2023/4/27 18:12
* @email qingtaij@163.com
*/
@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
@RestController
@RequestMapping("/api/jt1078")
public class JT1078Controller {
@Resource
JT1078Template jt1078Template;
/**
* jt1078Template 调用示例
*/
@GetMapping("/start/live/{deviceId}/{channelId}")
public WVPResult<?> startLive(@PathVariable String deviceId, @PathVariable String channelId) {
J9101 j9101 = new J9101();
j9101.setChannel(Integer.valueOf(channelId));
j9101.setIp("192.168.1.1");
j9101.setRate(1);
j9101.setTcpPort(7618);
j9101.setUdpPort(7618);
j9101.setType(0);
// TODO 分配ZLM,获取IP端口
String s = jt1078Template.startLive(deviceId, j9101, 6);
// TODO 设备响应成功后,封装拉流结果集
WVPResult<String> wvpResult = new WVPResult<>();
wvpResult.setCode(200);
wvpResult.setData(String.format("http://192.168.1.1/rtp/%s_%s.live.mp4", deviceId, channelId));
return wvpResult;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,119 @@
package com.genersoft.iot.vmp.jt1078.controller;
import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.jt1078.bean.*;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Slf4j
@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
@RestController
@Tag(name = "部标终端以及通道管理")
@RequestMapping("/api/jt1078/terminal")
public class JT1078TerminalController {
@Resource
Ijt1078Service service;
@Operation(summary = "JT-分页查询部标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "page", description = "当前页", required = true)
@Parameter(name = "count", description = "每页查询数量", required = true)
@Parameter(name = "query", description = "查询内容")
@Parameter(name = "online", description = "是否在线")
@GetMapping("/list")
public PageInfo<JTDevice> getDevices(int page, int count,
@RequestParam(required = false) String query,
@RequestParam(required = false) Boolean online) {
return service.getDeviceList(page, count, query, online);
}
@Operation(summary = "更新设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "device", description = "设备", required = true)
@PostMapping("/update")
public void updateDevice(JTDevice device){
assert device.getId() > 0;
assert device.getPhoneNumber() != null;
service.updateDevice(device);
}
@Operation(summary = "JT-新增设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "device", description = "设备", required = true)
@PostMapping("/add")
public void addDevice(JTDevice device){
assert device.getPhoneNumber() != null;
String phoneNumber = device.getPhoneNumber().replaceFirst("^0*", "");
device.setPhoneNumber(phoneNumber);
service.addDevice(device);
}
@Operation(summary = "删除设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "phoneNumber", description = "设备手机号", required = true)
@DeleteMapping("/delete")
public void addDevice(String phoneNumber){
assert phoneNumber != null;
service.deleteDeviceByPhoneNumber(phoneNumber);
}
@Operation(summary = "查询设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "phoneNumber", description = "设备手机号", required = true)
@GetMapping("/query")
public JTDevice getDevice(Integer deviceId){
return service.getDeviceById(deviceId);
}
@Operation(summary = "JT-查询部标通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "page", description = "当前页", required = true)
@Parameter(name = "count", description = "每页查询数量", required = true)
@Parameter(name = "deviceId", description = "设备ID", required = true)
@Parameter(name = "query", description = "查询内容")
@GetMapping("/channel/list")
public PageInfo<JTChannel> getChannels(int page, int count,
@RequestParam(required = true) Integer deviceId,
@RequestParam(required = false) String query) {
assert deviceId != null;
return service.getChannelList(page, count, deviceId, query);
}
@Operation(summary = "JT-查询单个部标通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "id", description = "通道数据库ID", required = true)
@GetMapping("/channel/one")
public JTChannel getChannel(Integer id) {
assert id != null;
return service.getChannelByDbId(id);
}
@Operation(summary = "JT-更新通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "channel", description = "通道", required = true)
@PostMapping("/channel/update")
public void updateChannel(@RequestBody JTChannel channel){
assert channel.getId() > 0;
assert channel.getChannelId() != null;
service.updateChannel(channel);
}
@Operation(summary = "JT-新增通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "channel", description = "通道", required = true)
@PostMapping("/channel/add")
public JTChannel addChannel(@RequestBody JTChannel channel){
assert channel.getChannelId() != null;
assert channel.getTerminalDbId() != 0;
service.addChannel(channel);
return channel;
}
@Operation(summary = "JT-删除通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "id", description = "通道的数据库ID", required = true)
@DeleteMapping("/channel/delete")
public void deleteChannel(Integer id){
service.deleteChannelById(id);
}
}

View File

@ -0,0 +1,31 @@
package com.genersoft.iot.vmp.jt1078.controller.bean;
import com.genersoft.iot.vmp.jt1078.bean.JTConfirmationAlarmMessageType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* 人工确认报警消息参数
*/
@Setter
@Getter
@Schema(description = "人工确认报警消息参数")
public class ConfirmationAlarmMessageParam {
@Schema(description = "终端手机号")
private String phoneNumber;
@Schema(description = "报警消息流水号")
private int alarmPackageNo;
@Schema(description = "人工确认报警类型")
private JTConfirmationAlarmMessageType alarmMessageType;
@Override
public String toString() {
return "ConfirmationAlarmMessageParam{" +
"PhoneNumber='" + phoneNumber + '\'' +
", alarmPackageNo=" + alarmPackageNo +
", alarmMessageType=" + alarmMessageType +
'}';
}
}

View File

@ -0,0 +1,23 @@
package com.genersoft.iot.vmp.jt1078.controller.bean;
import com.genersoft.iot.vmp.jt1078.bean.JTDeviceConnectionControl;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class ConnectionControlParam {
@Schema(description = "终端手机号")
private String phoneNumber;
private JTDeviceConnectionControl control;
@Override
public String toString() {
return "ConnectionControlParam{" +
"deviceId='" + phoneNumber + '\'' +
", control=" + control +
'}';
}
}

View File

@ -0,0 +1,34 @@
package com.genersoft.iot.vmp.jt1078.controller.bean;
import com.genersoft.iot.vmp.jt1078.bean.JTQueryMediaDataCommand;
import com.genersoft.iot.vmp.jt1078.bean.JTShootingCommand;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Schema(description = "存储多媒体数据参数")
public class QueryMediaDataParam {
@Schema(description = "终端手机号")
private String phoneNumber;
@Schema(description = "多媒体 ID, 单条存储多媒体数据检索上传时有效")
private Long mediaId;
@Schema(description = "删除标志, 单条存储多媒体数据检索上传时有效")
private int delete;
@Schema(description = "存储多媒体数据参数")
private JTQueryMediaDataCommand queryMediaDataCommand;
@Override
public String toString() {
return "QueryMediaDataParam{" +
"设备手机号='" + phoneNumber + '\'' +
", mediaId=" + mediaId +
", queryMediaDataCommand=" + queryMediaDataCommand +
'}';
}
}

View File

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.jt1078.controller.bean;
import com.genersoft.iot.vmp.jt1078.bean.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Setter
@Getter
@Schema(description = "设置区域参数")
public class SetAreaParam {
@Schema(description = "终端手机号")
private String phoneNumber;
@Schema(description = "圆形区域项")
private List<JTCircleArea> circleAreaList;
@Schema(description = "矩形区域项")
private List<JTRectangleArea> rectangleAreas;
@Schema(description = "多边形区域")
private JTPolygonArea polygonArea;
@Schema(description = "路线")
private JTRoute route;
@Override
public String toString() {
return "SetAreaParam{" +
"设备手机号='" + phoneNumber + '\'' +
", circleAreaList=" + circleAreaList +
", rectangleAreas=" + rectangleAreas +
", polygonArea=" + polygonArea +
", route=" + route +
'}';
}
}

Some files were not shown because too many files have changed in this diff Show More