Commit 2af9f9ee0e3034b5a72cc315645eca25b895f9a8
1 parent
5598699e
feat: 设备指令下发
Showing
74 changed files
with
3596 additions
and
2 deletions
Bsth-admin/pom.xml
| @@ -74,6 +74,12 @@ | @@ -74,6 +74,12 @@ | ||
| 74 | <artifactId>mysql-connector-j</artifactId> | 74 | <artifactId>mysql-connector-j</artifactId> |
| 75 | <version>8.0.33</version> | 75 | <version>8.0.33</version> |
| 76 | </dependency> | 76 | </dependency> |
| 77 | + <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> | ||
| 78 | + <dependency> | ||
| 79 | + <groupId>io.netty</groupId> | ||
| 80 | + <artifactId>netty-all</artifactId> | ||
| 81 | + <version>4.1.101.Final</version> | ||
| 82 | + </dependency> | ||
| 77 | 83 | ||
| 78 | <!-- 核心模块--> | 84 | <!-- 核心模块--> |
| 79 | <dependency> | 85 | <dependency> |
Bsth-admin/src/main/java/com/ruoyi/common/global/IDeviceException.java
0 → 100644
| 1 | +package com.ruoyi.common.global; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import lombok.NoArgsConstructor; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 设备异常 | ||
| 8 | + * @author 20412 | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +@NoArgsConstructor | ||
| 12 | +public class IDeviceException extends RuntimeException{ | ||
| 13 | + private String msg; | ||
| 14 | + private ResultCode code; | ||
| 15 | + | ||
| 16 | + public IDeviceException(ResultCode code, String msg) { | ||
| 17 | + this.msg = msg; | ||
| 18 | + this.code = code; | ||
| 19 | + } | ||
| 20 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/client/ClientHandler.java
0 → 100644
| 1 | +package com.ruoyi.system.client; | ||
| 2 | + | ||
| 3 | +import io.netty.buffer.ByteBuf; | ||
| 4 | +import io.netty.buffer.Unpooled; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import io.netty.channel.ChannelInboundHandlerAdapter; | ||
| 7 | +import io.netty.util.CharsetUtil; | ||
| 8 | + | ||
| 9 | +import java.util.Scanner; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 测试类 模拟手表设备 | ||
| 13 | + */ | ||
| 14 | +public class ClientHandler extends ChannelInboundHandlerAdapter { | ||
| 15 | +// @Override | ||
| 16 | +// public void channelRegistered(ChannelHandlerContext ctx) throws Exception { | ||
| 17 | +// ctx.writeAndFlush(Unpooled.copiedBuffer("IWAP00353456789012345#", CharsetUtil.UTF_8)); | ||
| 18 | +//// super.channelRegistered(ctx); | ||
| 19 | +// } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | ||
| 23 | + ByteBuf byteBuf = (ByteBuf) msg; | ||
| 24 | + String str = byteBuf.toString(CharsetUtil.UTF_8); | ||
| 25 | + System.out.println("收到服务端" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); | ||
| 26 | + | ||
| 27 | + // 判断是否需要发送 | ||
| 28 | + if (str.startsWith("IWBP12")) { | ||
| 29 | + String replace = str.replace(",353456789012345","").replace("IWBP12", "IWAP12"); | ||
| 30 | + System.out.println("客户端响应" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); | ||
| 31 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(replace, CharsetUtil.UTF_8)); | ||
| 32 | + } | ||
| 33 | + if (str.startsWith("IWBP15")) { | ||
| 34 | + String replace = str.replace(",353456789012345","").replace("IWBP15", "IWAP15"); | ||
| 35 | + System.out.println("客户端响应" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); | ||
| 36 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(replace, CharsetUtil.UTF_8)); | ||
| 37 | + } | ||
| 38 | +// else { | ||
| 39 | +// Scanner sc = new Scanner(System.in); | ||
| 40 | +// String line = sc.nextLine(); | ||
| 41 | +// ctx.channel().writeAndFlush(Unpooled.copiedBuffer(line, CharsetUtil.UTF_8)); | ||
| 42 | +// } | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + | ||
| 46 | +// @Override | ||
| 47 | +// public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { | ||
| 48 | +// ctx.writeAndFlush(Unpooled.copiedBuffer("歪比巴卜~茉莉~Are you good~马来西亚~", CharsetUtil.UTF_8)); | ||
| 49 | +// } | ||
| 50 | + | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public void channelActive(ChannelHandlerContext ctx) throws Exception { | ||
| 54 | + ctx.writeAndFlush(Unpooled.copiedBuffer("IWAP00353456789012345#", CharsetUtil.UTF_8)); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | ||
| 59 | + System.out.println(cause.getMessage()); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + | ||
| 63 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/client/NettyClientDemoMain.java
0 → 100644
| 1 | +package com.ruoyi.system.client; | ||
| 2 | + | ||
| 3 | +import io.netty.bootstrap.Bootstrap; | ||
| 4 | +import io.netty.channel.ChannelFuture; | ||
| 5 | +import io.netty.channel.ChannelInitializer; | ||
| 6 | +import io.netty.channel.nio.NioEventLoopGroup; | ||
| 7 | +import io.netty.channel.socket.SocketChannel; | ||
| 8 | +import io.netty.channel.socket.nio.NioSocketChannel; | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +public class NettyClientDemoMain { | ||
| 12 | + public static void main(String[] args) throws Exception { | ||
| 13 | + NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); | ||
| 14 | + ChannelFuture channelFuture = null; | ||
| 15 | + try { | ||
| 16 | + //创建bootstrap对象,配置参数 | ||
| 17 | + Bootstrap bootstrap = new Bootstrap(); | ||
| 18 | + //设置线程组 | ||
| 19 | + bootstrap.group(eventExecutors) | ||
| 20 | + //设置客户端的通道实现类型 | ||
| 21 | + .channel(NioSocketChannel.class) | ||
| 22 | + //使用匿名内部类初始化通道 | ||
| 23 | + .handler(new ChannelInitializer<SocketChannel>() { | ||
| 24 | + @Override | ||
| 25 | + protected void initChannel(SocketChannel ch) throws Exception { | ||
| 26 | + //添加客户端通道的处理器 | ||
| 27 | + ch.pipeline().addLast(new ClientHandler()); | ||
| 28 | + } | ||
| 29 | + }); | ||
| 30 | + System.out.println("客户端准备就绪,随时可以起飞~"); | ||
| 31 | + //连接服务端 | ||
| 32 | + channelFuture = bootstrap.connect("127.0.0.1", 8989).sync(); | ||
| 33 | + channelFuture.channel().closeFuture().sync(); | ||
| 34 | + | ||
| 35 | + } finally { | ||
| 36 | + //关闭线程组 | ||
| 37 | + eventExecutors.shutdownGracefully(); | ||
| 38 | + } | ||
| 39 | + } | ||
| 40 | +} | ||
| 41 | + |
Bsth-admin/src/main/java/com/ruoyi/system/controller/DeviceCommandController.java
0 → 100644
| 1 | +package com.ruoyi.system.controller; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.global.Result; | ||
| 4 | +import com.ruoyi.system.domain.active.Sos; | ||
| 5 | +import com.ruoyi.system.domain.active.UploadGpsTime; | ||
| 6 | +import com.ruoyi.system.domain.active.WhiteListPeople; | ||
| 7 | +import com.ruoyi.system.service.IDeviceService; | ||
| 8 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 9 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 10 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 11 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 12 | +import org.springframework.web.bind.annotation.RestController; | ||
| 13 | + | ||
| 14 | +@RestController | ||
| 15 | +@RequestMapping("/command/send") | ||
| 16 | +public class DeviceCommandController { | ||
| 17 | + @Autowired | ||
| 18 | + private IDeviceService deviceService; | ||
| 19 | + | ||
| 20 | + @PostMapping("/settingSos") | ||
| 21 | + public Result<?> settingSos(@RequestBody Sos sos) { | ||
| 22 | + return deviceService.settingSos(sos); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + @PostMapping("/settingWhiteList") | ||
| 27 | + public Result<?> settingWhiteList(@RequestBody WhiteListPeople wlp) { | ||
| 28 | + return deviceService.settingWhiteList(wlp); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @PostMapping("/settingGpsUploadTime") | ||
| 32 | + public Result<?> settingGpsUploadTime(@RequestBody UploadGpsTime ugt) { | ||
| 33 | + return deviceService.settingGpsUploadTime(ugt); | ||
| 34 | + } | ||
| 35 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/active/ActiveBase.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/domain/active/Sos.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/domain/active/UploadGpsTime.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/domain/active/WhiteListPeople.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.active; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.List; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 联系人白名单 | ||
| 9 | + * @author 20412 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class WhiteListPeople extends ActiveBase { | ||
| 13 | + private List<Contact> contacts; | ||
| 14 | + @Data | ||
| 15 | + public static class Contact { | ||
| 16 | + private String name; | ||
| 17 | + private String tell; | ||
| 18 | + } | ||
| 19 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/Bluetooth.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.NoArgsConstructor; | ||
| 6 | + | ||
| 7 | +@Data | ||
| 8 | +@AllArgsConstructor | ||
| 9 | +@NoArgsConstructor | ||
| 10 | +public class Bluetooth { | ||
| 11 | + /** 蓝牙名称 */ | ||
| 12 | + private String name; | ||
| 13 | + /** mac 地址 */ | ||
| 14 | + private String mac; | ||
| 15 | + /** 信号强度 */ | ||
| 16 | + private String signalStrong; | ||
| 17 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/BluetoothInfo.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/DeviceAlarm.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | +import java.util.List; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 设备报警 | ||
| 10 | + * @author 20412 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class DeviceAlarm { | ||
| 14 | + private String imei; | ||
| 15 | + private Date createTime; | ||
| 16 | + private String deviceDate; | ||
| 17 | + private String gpsLabel; | ||
| 18 | + /** 地址是否有效 A 还是V */ | ||
| 19 | + private String addressCheck; | ||
| 20 | + /** ddmm.mmmm维度 */ | ||
| 21 | + private String gpsN; | ||
| 22 | + /** dddmm.mmmm 经度 */ | ||
| 23 | + private String gpsE; | ||
| 24 | + private String speed; | ||
| 25 | + private String deviceTime; | ||
| 26 | + private String direction; | ||
| 27 | + private String gms; | ||
| 28 | + /** 参与定位的卫星数 */ | ||
| 29 | + private String gpsSatelliteCount; | ||
| 30 | + private String power; | ||
| 31 | + private String placeholder; | ||
| 32 | + /** 是否设防 01 设防 00 未设置 */ | ||
| 33 | + private String isSafety; | ||
| 34 | + /** 是否为工作模式 02 工作模式 */ | ||
| 35 | + private String isWork; | ||
| 36 | + private String mcc; | ||
| 37 | + private String mnc; | ||
| 38 | + private String lac; | ||
| 39 | + private String cid; | ||
| 40 | + /** 告警值 | ||
| 41 | + * 01 SOS 02 低电 03 摘除手表 | ||
| 42 | + * 04 预留 05 防拆表带打开 06 跌倒 | ||
| 43 | + * 07 无效的心率值 08 心率过高 09 心率过低 | ||
| 44 | + * 10 舒张压过高 11 舒张压过低 12 收缩压过高 | ||
| 45 | + * 13 收缩压过低 14 久坐 15 预留 | ||
| 46 | + * 16 防拆表带锁上 17 体温过高 18 体温过低 | ||
| 47 | + * 19 关机 20 离开电子围栏 21 进入电子围栏 | ||
| 48 | + * 22 消息已阅读 */ | ||
| 49 | + private String alarmValue; | ||
| 50 | + /** 设备语言 */ | ||
| 51 | + private String deviceLanguage; | ||
| 52 | + /** 设备标志位 */ | ||
| 53 | + private String alarmInfoLabel; | ||
| 54 | + private List<WifiInfo> wifiInfo; | ||
| 55 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/GpsInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | +import java.util.List; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * gps信息 | ||
| 10 | + * @author 20412 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class GpsInfo { | ||
| 14 | + private String imei; | ||
| 15 | + private String commandLabel; | ||
| 16 | + /** 地址是否有效 A 还是V */ | ||
| 17 | + private String addressCheck; | ||
| 18 | + private Date createTime; | ||
| 19 | + private String deviceDate; | ||
| 20 | + private String gpsLabel; | ||
| 21 | + /** ddmm.mmmm维度 */ | ||
| 22 | + private String gpsN; | ||
| 23 | + /** dddmm.mmmm 经度 */ | ||
| 24 | + private String gpsE; | ||
| 25 | + /** 速度 */ | ||
| 26 | + private String speed; | ||
| 27 | + private String deviceTime; | ||
| 28 | + private String direction; | ||
| 29 | + private String gms; | ||
| 30 | + /** 参与定位的卫星数 */ | ||
| 31 | + private String gpsSatelliteCount; | ||
| 32 | + private String power; | ||
| 33 | + private String placeholder; | ||
| 34 | + /** 是否设防 01 设防 00 未设置 */ | ||
| 35 | + private String isSafety; | ||
| 36 | + /** 是否为工作模式 02 工作模式 */ | ||
| 37 | + private String isWork; | ||
| 38 | + private String mcc; | ||
| 39 | + private String mnc; | ||
| 40 | + private String lac; | ||
| 41 | + private String cid; | ||
| 42 | + /** 网络识别码 */ | ||
| 43 | + private String sid; | ||
| 44 | + /** 网络识别码 */ | ||
| 45 | + private String nid; | ||
| 46 | + /** 小区唯一识别码 */ | ||
| 47 | + private String bid; | ||
| 48 | + /** 信号强度 */ | ||
| 49 | + private Integer signal; | ||
| 50 | + private List<WifiInfo> wifiInfoList; | ||
| 51 | + | ||
| 52 | + private String languageLabel; | ||
| 53 | + private String replyLabel; | ||
| 54 | + /** 基站组数 */ | ||
| 55 | + private Integer baseStationGroups; | ||
| 56 | + /** 基站集合 */ | ||
| 57 | + private List<BaseStation> baseStations; | ||
| 58 | + /** wifi组数 */ | ||
| 59 | + private Integer wifiGroups; | ||
| 60 | + | ||
| 61 | + private String remark; | ||
| 62 | + | ||
| 63 | + @Data | ||
| 64 | + public static class BaseStation { | ||
| 65 | + private String lac; | ||
| 66 | + private String cid; | ||
| 67 | + /** 信号强度 */ | ||
| 68 | + private String dbm; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/HealthInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * @author 20412 | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +public class HealthInfo { | ||
| 12 | + private String imei; | ||
| 13 | + private String commandLabel; | ||
| 14 | + private String power; | ||
| 15 | + private String uploadTime; | ||
| 16 | + /** 1:健康数据类型,取值1表示血压,取值2表示心率,取值3表示体温,4表示血氧 */ | ||
| 17 | + private String healthType; | ||
| 18 | + // 691120:健康数值,根据类型不同数据内容有不同。691120表示,舒张压(低压)69,收缩压(高 压)120,中间的1为多个参数分隔符。 | ||
| 19 | + // 当健康数据类型为3时,后面的健康数值是体温,36.19是具体的温度值,单位为摄氏度 | ||
| 20 | + // 若只有一个参数则无需分隔符,例如心率:80,则包为:WAPJK,2021-05-29100:00,2,80# | ||
| 21 | + private String heartRate; | ||
| 22 | + /** 高压 */ | ||
| 23 | + private Integer highPressure; | ||
| 24 | + /** 低压 */ | ||
| 25 | + private Integer lowPressure; | ||
| 26 | + /** 体温 */ | ||
| 27 | + private Float temperature; | ||
| 28 | + /** 血氧 */ | ||
| 29 | + private String bloodOxygen; | ||
| 30 | + /** 血糖 */ | ||
| 31 | + private String bloodSugar; | ||
| 32 | + /** 手腕温度 */ | ||
| 33 | + private String handTemperature; | ||
| 34 | + private Date createTime; | ||
| 35 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/ImageInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * @author 20412 | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +public class ImageInfo { | ||
| 12 | + private String imei; | ||
| 13 | + private String imageUrl; | ||
| 14 | + private String uploadTime; | ||
| 15 | + private Date createTime; | ||
| 16 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/KeepLiveInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 心跳包 | ||
| 9 | + * @author 20412 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class KeepLiveInfo { | ||
| 13 | + private String imei; | ||
| 14 | + private String commandLabel; | ||
| 15 | + private Date createTime; | ||
| 16 | + private String gsm; | ||
| 17 | + private String satelliteCount; | ||
| 18 | + private String power; | ||
| 19 | + private String placeholder; | ||
| 20 | + private String isSafety; | ||
| 21 | + private String isWork; | ||
| 22 | + /** 计步数 */ | ||
| 23 | + private String step; | ||
| 24 | + /** 翻滚次数 */ | ||
| 25 | + private String rollingCount; | ||
| 26 | + /** 定位间隔 */ | ||
| 27 | + private String gpsInterval; | ||
| 28 | + private String remark; | ||
| 29 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/PowerAlarm.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/SpeechInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 语音包 | ||
| 9 | + * @author 20412 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class SpeechInfo { | ||
| 13 | + private String imei; | ||
| 14 | + private String speechUrl; | ||
| 15 | + private String uploadTime; | ||
| 16 | + private Date createTime; | ||
| 17 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/WearingState.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 佩戴状态 | ||
| 9 | + * @author 20412 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class WearingState { | ||
| 13 | + private String imei; | ||
| 14 | + private String state; | ||
| 15 | + private Long timestamp; | ||
| 16 | + private Date createTime; | ||
| 17 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/command/WifiInfo.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.command; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.NoArgsConstructor; | ||
| 6 | + | ||
| 7 | +@Data | ||
| 8 | +@AllArgsConstructor | ||
| 9 | +@NoArgsConstructor | ||
| 10 | +public class WifiInfo { | ||
| 11 | + private String ssid; | ||
| 12 | + private String mac; | ||
| 13 | + private String signal; | ||
| 14 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/entity/Device.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.entity; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +@Data | ||
| 8 | +public class Device { | ||
| 9 | + /** | ||
| 10 | + * 设备号 | ||
| 11 | + */ | ||
| 12 | + private String imei; | ||
| 13 | + | ||
| 14 | + private String ip; | ||
| 15 | + | ||
| 16 | + private String version; | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * MCC 标识移动通信网络所属国家或地区的代码 | ||
| 20 | + */ | ||
| 21 | + private String mcc; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * MNC 标识移动网络运营商的代码 | ||
| 25 | + */ | ||
| 26 | + private String mnc; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * APN 建立移动网络数据连接的配置信息 | ||
| 30 | + */ | ||
| 31 | + private String apn; | ||
| 32 | + | ||
| 33 | + //,通过将 IMSI 存储在 SIM 卡中,并将 ICCID 与 IMSI 关联,可以实现对移动网络用户和 SIM 卡的管理和追踪 | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * ICCID 用于唯一标识 SIM 卡 可以用于激活、注册、识别和管理 SIM 卡 | ||
| 37 | + */ | ||
| 38 | + private String iccId; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * IMSI 用于唯一标识移动网络用户 | ||
| 42 | + */ | ||
| 43 | + private String imsi; | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + private Date createTime; | ||
| 47 | + | ||
| 48 | + private Date updateTime; | ||
| 49 | + private String id; | ||
| 50 | + | ||
| 51 | + private String remark; | ||
| 52 | + private Integer state; | ||
| 53 | + | ||
| 54 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/response/BaseStationResponse.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.response; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import javax.xml.bind.annotation.XmlAccessType; | ||
| 6 | +import javax.xml.bind.annotation.XmlAccessorType; | ||
| 7 | +import javax.xml.bind.annotation.XmlElement; | ||
| 8 | +import javax.xml.bind.annotation.XmlRootElement; | ||
| 9 | + | ||
| 10 | +@Data | ||
| 11 | +@XmlRootElement(name = "response") | ||
| 12 | +@XmlAccessorType(value = XmlAccessType.FIELD) | ||
| 13 | +public class BaseStationResponse { | ||
| 14 | + @XmlElement(name="errcode") | ||
| 15 | + private String errcode; | ||
| 16 | + @XmlElement(name="lat") | ||
| 17 | + private String lat = "00.000000"; | ||
| 18 | + @XmlElement(name="lon") | ||
| 19 | + private String lon = "000.000000"; | ||
| 20 | + @XmlElement(name="radius") | ||
| 21 | + private String radius; | ||
| 22 | + @XmlElement(name="address") | ||
| 23 | + private String address; | ||
| 24 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/domain/response/WeatherResponse.java
0 → 100644
| 1 | +package com.ruoyi.system.domain.response; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.List; | ||
| 6 | + | ||
| 7 | +@Data | ||
| 8 | +public class WeatherResponse { | ||
| 9 | + private String code; | ||
| 10 | + | ||
| 11 | + private String updateTime; | ||
| 12 | + | ||
| 13 | + private String fxLink; | ||
| 14 | + | ||
| 15 | + private List<Daily> daily; | ||
| 16 | + | ||
| 17 | + private Refer refer; | ||
| 18 | + @Data | ||
| 19 | + public static class Daily | ||
| 20 | + { | ||
| 21 | + private String fxDate; | ||
| 22 | + | ||
| 23 | + private String sunrise; | ||
| 24 | + | ||
| 25 | + private String sunset; | ||
| 26 | + | ||
| 27 | + private String moonrise; | ||
| 28 | + | ||
| 29 | + private String moonset; | ||
| 30 | + | ||
| 31 | + private String moonPhase; | ||
| 32 | + | ||
| 33 | + private String moonPhaseIcon; | ||
| 34 | + | ||
| 35 | + private String tempMax; | ||
| 36 | + | ||
| 37 | + private String tempMin; | ||
| 38 | + | ||
| 39 | + private String iconDay; | ||
| 40 | + | ||
| 41 | + private String textDay; | ||
| 42 | + | ||
| 43 | + private String iconNight; | ||
| 44 | + | ||
| 45 | + private String textNight; | ||
| 46 | + | ||
| 47 | + private String wind360Day; | ||
| 48 | + | ||
| 49 | + private String windDirDay; | ||
| 50 | + | ||
| 51 | + private String windScaleDay; | ||
| 52 | + | ||
| 53 | + private String windSpeedDay; | ||
| 54 | + | ||
| 55 | + private String wind360Night; | ||
| 56 | + | ||
| 57 | + private String windDirNight; | ||
| 58 | + | ||
| 59 | + private String windScaleNight; | ||
| 60 | + | ||
| 61 | + private String windSpeedNight; | ||
| 62 | + | ||
| 63 | + private String humidity; | ||
| 64 | + | ||
| 65 | + private String precip; | ||
| 66 | + | ||
| 67 | + private String pressure; | ||
| 68 | + | ||
| 69 | + private String vis; | ||
| 70 | + | ||
| 71 | + private String cloud; | ||
| 72 | + | ||
| 73 | + private String uvIndex; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Data | ||
| 77 | + public static class Refer | ||
| 78 | + { | ||
| 79 | + private List<String> sources; | ||
| 80 | + | ||
| 81 | + private List<String> license; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + | ||
| 85 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/handler/DeviceExceptionHandler.java
0 → 100644
| 1 | +package com.ruoyi.system.handler; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.global.IDeviceException; | ||
| 4 | +import com.ruoyi.common.global.Result; | ||
| 5 | +import org.slf4j.Logger; | ||
| 6 | +import org.slf4j.LoggerFactory; | ||
| 7 | +import org.springframework.web.bind.annotation.ExceptionHandler; | ||
| 8 | +import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * @author 20412 | ||
| 12 | + */ | ||
| 13 | +@RestControllerAdvice | ||
| 14 | +public class DeviceExceptionHandler { | ||
| 15 | + private static final Logger log = LoggerFactory.getLogger(DeviceExceptionHandler.class); | ||
| 16 | + | ||
| 17 | + @ExceptionHandler(IDeviceException.class) | ||
| 18 | + public Result<?> handlerDeviceException(IDeviceException e) { | ||
| 19 | + log.error(e.getMsg()); | ||
| 20 | + return Result.ERROR(e.getCode(), e.getMsg()); | ||
| 21 | + } | ||
| 22 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/handler/SocketServerHandler.java
0 → 100644
| 1 | +package com.ruoyi.system.handler; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.strategy.CommandStrategy; | ||
| 5 | +import io.netty.buffer.ByteBuf; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import io.netty.channel.ChannelInboundHandlerAdapter; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.slf4j.Logger; | ||
| 11 | +import org.slf4j.LoggerFactory; | ||
| 12 | + | ||
| 13 | +public class SocketServerHandler extends ChannelInboundHandlerAdapter { | ||
| 14 | + CommandStrategy strategy; | ||
| 15 | + private static final Logger log = LoggerFactory.getLogger(SocketServerHandler.class); | ||
| 16 | + | ||
| 17 | + public SocketServerHandler() { | ||
| 18 | + this.strategy = new CommandStrategy(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | ||
| 24 | + ByteBuf buf = (ByteBuf) msg; | ||
| 25 | + // 处理指令 | ||
| 26 | + strategy.handler(buf.toString(CharsetUtil.UTF_8), ctx); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { | ||
| 31 | +// System.out.println(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).get()); | ||
| 32 | + super.channelReadComplete(ctx); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | ||
| 38 | + String imei = AttributeKey.valueOf(ThinkraceUtil.IMEI).toString(); | ||
| 39 | + // 发生异常触发 | ||
| 40 | + ThinkraceUtil.removeDevice(imei); | ||
| 41 | + log.info("发生未知错误,设备:{}将关闭连接,原因:{}", imei, cause.getMessage()); | ||
| 42 | + ctx.close(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public void channelActive(ChannelHandlerContext ctx) throws Exception { | ||
| 48 | +// ctx.channel().close(); | ||
| 49 | + super.channelActive(ctx); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public void channelInactive(ChannelHandlerContext ctx) throws Exception { | ||
| 54 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 55 | + log.info("设备断开连接了,设备号为:{}", imei); | ||
| 56 | + } | ||
| 57 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/mapper/DeviceMapper.java
0 → 100644
| 1 | +package com.ruoyi.system.mapper; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 4 | +import com.ruoyi.system.domain.entity.Device; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * deviceMapper接口 | ||
| 8 | + * | ||
| 9 | + * @author bsth | ||
| 10 | + * @date 2024-04-17 | ||
| 11 | + */ | ||
| 12 | +public interface DeviceMapper extends BaseMapper<Device> | ||
| 13 | +{ | ||
| 14 | + | ||
| 15 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/mapper/system/DeviceMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
| 2 | +<!DOCTYPE mapper | ||
| 3 | +PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
| 4 | +"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 5 | +<mapper namespace="com.ruoyi.system.mapper.DeviceMapper"> | ||
| 6 | + | ||
| 7 | + <resultMap type="Device" id="DeviceResult"> | ||
| 8 | + <result property="id" column="id" /> | ||
| 9 | + <result property="imei" column="imei" /> | ||
| 10 | + <result property="ip" column="ip" /> | ||
| 11 | + <result property="version" column="version" /> | ||
| 12 | + <result property="mcc" column="mcc" /> | ||
| 13 | + <result property="mnc" column="mnc" /> | ||
| 14 | + <result property="apn" column="apn" /> | ||
| 15 | + <result property="iccId" column="iccId" /> | ||
| 16 | + <result property="imsi" column="imsi" /> | ||
| 17 | + <result property="createTime" column="create_time" /> | ||
| 18 | + <result property="updateTime" column="update_time" /> | ||
| 19 | + <result property="remark" column="remark" /> | ||
| 20 | + <result property="state" column="state" /> | ||
| 21 | + </resultMap> | ||
| 22 | + | ||
| 23 | +</mapper> | ||
| 0 | \ No newline at end of file | 24 | \ No newline at end of file |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/ThinkraceUtil.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.core.redis.RedisCache; | ||
| 4 | +import com.ruoyi.common.global.IDeviceException; | ||
| 5 | +import com.ruoyi.common.global.ResultCode; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.Channel; | ||
| 9 | +import io.netty.channel.ChannelHandlerContext; | ||
| 10 | +import io.netty.util.AttributeKey; | ||
| 11 | +import io.netty.util.CharsetUtil; | ||
| 12 | +import org.slf4j.Logger; | ||
| 13 | +import org.slf4j.LoggerFactory; | ||
| 14 | + | ||
| 15 | +import java.util.HashMap; | ||
| 16 | +import java.util.Map; | ||
| 17 | +import java.util.Objects; | ||
| 18 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 19 | +import java.util.concurrent.TimeUnit; | ||
| 20 | + | ||
| 21 | +public class ThinkraceUtil { | ||
| 22 | + // 命令过期时间 | ||
| 23 | + private static final Integer COMMAND_TTL = 300; | ||
| 24 | + | ||
| 25 | + private static final String COMMAND_SN = "command:sn"; | ||
| 26 | + private static final String COMMAND_SEND = "command:send:"; | ||
| 27 | + public static final Integer COMMAND_LABEL_SURE = 1; | ||
| 28 | + public static final Integer COMMAND_LABEL_INIT = 0; | ||
| 29 | + private static final Long SN_LENGTH = 1000000L; | ||
| 30 | + private static RedisCache REDIS_CACHE; | ||
| 31 | + /** | ||
| 32 | + * 指令列表 | ||
| 33 | + */ | ||
| 34 | + private static final Map<String, ICommandAdapter> REGEX_MAP = new HashMap<>(); | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 时区 | ||
| 38 | + */ | ||
| 39 | + public static String UTC_8 = "8"; | ||
| 40 | + /** | ||
| 41 | + * 命令结束符 | ||
| 42 | + */ | ||
| 43 | + public static String END_SYMBOL = "#"; | ||
| 44 | + /** | ||
| 45 | + * 设备号 | ||
| 46 | + */ | ||
| 47 | + public static String IMEI = "IMEI"; | ||
| 48 | + | ||
| 49 | + public static String generatorSn() { | ||
| 50 | + Long commandSn; | ||
| 51 | + // 防止出现线程安全 重复覆盖值的情况 | ||
| 52 | + synchronized (ThinkraceUtil.class) { | ||
| 53 | + // 指令流水号是6位的 不足补0 | ||
| 54 | + commandSn = REDIS_CACHE.increment(COMMAND_SN); | ||
| 55 | + if (commandSn == null || commandSn > SN_LENGTH) { | ||
| 56 | + commandSn = 0L; | ||
| 57 | + REDIS_CACHE.setCacheObject(COMMAND_SN, commandSn.intValue()); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + String commandSnStr = commandSn.toString(); | ||
| 61 | + int snLen = (SN_LENGTH.toString().length() - 1) - commandSnStr.length(); | ||
| 62 | + StringBuilder sb = new StringBuilder(); | ||
| 63 | + //长度不足6位补零 | ||
| 64 | + for (int i = 0; i < snLen; i++) { | ||
| 65 | + sb.append("0"); | ||
| 66 | + } | ||
| 67 | + return sb + commandSnStr; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public static String commandLabelInit(String imei, String sn) { | ||
| 71 | + // 存入redis处理会有网络io的消耗 所以redis和服务器最好是在同一台服务器 原则是30s 增加容错 | ||
| 72 | + String key = getCommandKey(imei, sn); | ||
| 73 | + REDIS_CACHE.expire(key, COMMAND_LABEL_INIT, COMMAND_TTL, TimeUnit.SECONDS); | ||
| 74 | + return key; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + private static String getCommandKey(String imei, String sn) { | ||
| 78 | + return COMMAND_SEND + imei + ":" + sn; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public static Integer getCommandSn(String key) { | ||
| 82 | + return REDIS_CACHE.getCacheObject(key); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + | ||
| 86 | + public static class REQ { | ||
| 87 | + /** | ||
| 88 | + * 登陆包 | ||
| 89 | + */ | ||
| 90 | + public static final String LOGIN_REQ = "IWAP00"; | ||
| 91 | + public static final String GPS_REQ = "IWAP01"; | ||
| 92 | + public static final String MORE_GPS_REQ = "IWAP02"; | ||
| 93 | + public static final String KEEPLIVE_REQ = "IWAP03"; | ||
| 94 | + /** | ||
| 95 | + * 电量报警 | ||
| 96 | + */ | ||
| 97 | + public static final String POWER_REQ = "IWAP04"; | ||
| 98 | + /** | ||
| 99 | + * 这个可能在文档内是被划线了的可能没有启用过 语音传输没有在设备找到按钮 | ||
| 100 | + */ | ||
| 101 | + @Deprecated | ||
| 102 | + public static final String SPEECH_REQ = "IWAP05"; | ||
| 103 | + /** | ||
| 104 | + * 语音上行 | ||
| 105 | + */ | ||
| 106 | + public static final String SPEECH_UP_REQ = "IWAP07"; | ||
| 107 | + /** | ||
| 108 | + * 设备报警与地址回复包 | ||
| 109 | + */ | ||
| 110 | + public static final String ALARM_REQ = "IWAP10"; | ||
| 111 | + public static final String IMAGE_REQ = "IWAP42"; | ||
| 112 | + public static final String HEART_REQ = "IWAP49"; | ||
| 113 | + public static final String TEMPERATURE_50_REQ = "IWAP50"; | ||
| 114 | + public static final String QUERY_BLUETOOTH_REQ = "IWAP51"; | ||
| 115 | + public static final String CDMA_GPS_REQ = "IWAP91"; | ||
| 116 | + public static final String CDMA_WIFI_GPS_REQ = "IWAP92"; | ||
| 117 | + public static final String BLUETOOTH_REQ = "IWAPBL"; | ||
| 118 | + public static final String HEART_BLOOD_REQ = "IWAPHT"; | ||
| 119 | + public static final String HEALTH_REQ = "IWAPJK"; | ||
| 120 | + public static final String TEMPERATURE_REQ = "IWAPTP"; | ||
| 121 | + public static final String VERSION_REQ = "IWAPVR"; | ||
| 122 | + public static final String WEARING_REQ = "IWAPWR"; | ||
| 123 | + /** | ||
| 124 | + * 12 上传心率、血压、血氧、血糖 | ||
| 125 | + */ | ||
| 126 | + public static final String HEART_RATE_BLOOD_PRESSURE_OXYGEN_SUGAR_REQ = "IWAPHP"; | ||
| 127 | + public static final String BASE_STATION_TIMING_GPS_REQ = "IWAPTM"; | ||
| 128 | + /** | ||
| 129 | + * 14 同步天气 | ||
| 130 | + */ | ||
| 131 | + public static final String WEATHER_REQ = "IWAPWT"; | ||
| 132 | + /** | ||
| 133 | + * 确认已读文字 | ||
| 134 | + */ | ||
| 135 | + public static final String SURE_TEXT_REQ = "IWAP94"; | ||
| 136 | + public static final String ECG_DATA_REQ = "IWAPHD"; | ||
| 137 | + /** | ||
| 138 | + * 设备响应 | ||
| 139 | + */ | ||
| 140 | + public static final String CONTACT_REQ = "IWAP14"; | ||
| 141 | + public static final String SOS_REQ = "IWAP12"; | ||
| 142 | + | ||
| 143 | + | ||
| 144 | + public static final String UPLOAD_GPS_TIME_REQ = "IWAP15"; | ||
| 145 | + | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + public static class RES { | ||
| 149 | + /** | ||
| 150 | + * 登陆包 | ||
| 151 | + */ | ||
| 152 | + public static final String LOGIN_RES = "IWBP00"; | ||
| 153 | + /** | ||
| 154 | + * 定位 | ||
| 155 | + */ | ||
| 156 | + public static final String GPS_RES = "IWBP01"; | ||
| 157 | + /** | ||
| 158 | + * 多基站GPS定位 | ||
| 159 | + */ | ||
| 160 | + public static final String MORE_GPS_RES = "IWBP02"; | ||
| 161 | + /** | ||
| 162 | + * 心跳 | ||
| 163 | + */ | ||
| 164 | + public static final String KEEPLIVE_RES = "IWBP03"; | ||
| 165 | + public static final String HEART_RES = "IWBP49"; | ||
| 166 | + public static final String TEMPERATURE_50_RES = "IWBP50"; | ||
| 167 | + public static final String QUERY_BLUETOOTH_RES = "IWBP51"; | ||
| 168 | + public static final String CDMA_GPS_RES = "IWBP91"; | ||
| 169 | + | ||
| 170 | + public static final String CDMA_WIFI_GPS_RES = "IWBP92"; | ||
| 171 | + /** | ||
| 172 | + * 电源报警 | ||
| 173 | + */ | ||
| 174 | + public static final String POWER_RES = "IWBP04"; | ||
| 175 | + /** | ||
| 176 | + * 设备报警与地址回复包 | ||
| 177 | + */ | ||
| 178 | + public static final String ALARM_RES = "IWBP10"; | ||
| 179 | + public static final String IMAGE_RES = "IWBP42"; | ||
| 180 | + public static final String BLUETOOTH_RES = "IWBPBL"; | ||
| 181 | + public static final String HEART_BLOOD_RES = "IWBPHT"; | ||
| 182 | + public static final String HEALTH_RES = "IWBPJK"; | ||
| 183 | + public static final String TEMPERATURE_RES = "IWBPTP"; | ||
| 184 | + public static final String HEART_RATE_BLOOD_PRESSURE_OXYGEN_SUGAR_RES = "IWBPHP"; | ||
| 185 | + /** | ||
| 186 | + * 基站校时并获取经纬度协议 | ||
| 187 | + */ | ||
| 188 | + public static final String BASE_STATION_TIMING_GPS_RES = "IWBPTM"; | ||
| 189 | + ; | ||
| 190 | + /** | ||
| 191 | + * 确认已读文字 | ||
| 192 | + */ | ||
| 193 | + public static final String SURE_TEXT_RES = "IWBP94"; | ||
| 194 | + public static final String ECG_DATA_RES = "IWBPHD"; | ||
| 195 | + @Deprecated | ||
| 196 | + public static final String SPEECH_RES = "IWBP05"; | ||
| 197 | + public static final String SPEECH_UP_RES = "IWBP07"; | ||
| 198 | + public static final String WEATHER_RES = "IWBPWT"; | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + /** | ||
| 202 | + * 下发指令集 | ||
| 203 | + */ | ||
| 204 | + public static class ACTIVE { | ||
| 205 | + public static final String CONTACT_ACTIVE = "IWBP14"; | ||
| 206 | + public static final String UPLOAD_GPS_TIME_ACTIVE = "IWBP15"; | ||
| 207 | + public static final String SOS_ACTIVE = "IWBP12"; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + | ||
| 211 | + public static ICommandAdapter getAdapter(String key) { | ||
| 212 | + return REGEX_MAP.get(key); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + public static void addAdapter(String key, ICommandAdapter adapter) { | ||
| 216 | + REGEX_MAP.put(key, adapter); | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + public static void removeDevice(String imei) { | ||
| 220 | + DeviceManager.removeDevice(imei); | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + public static boolean hasDevice(Channel channel) { | ||
| 224 | + return DeviceManager.hasDevice(channel); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + public static void sendCommand(String imei, String command) { | ||
| 228 | + DeviceManager.sendCommand(imei, command); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + public static boolean askCommand(String txt, String imei, String command, String commandSn, ICommandAdapter adapter) { | ||
| 232 | + return DeviceManager.askCommand(txt, imei, command, commandSn, adapter); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + public static void setDevice(String imei, ChannelHandlerContext ctx) { | ||
| 236 | + DeviceManager.onlineDevice(imei, ctx); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + | ||
| 240 | + /** | ||
| 241 | + * 管理设备 | ||
| 242 | + * | ||
| 243 | + * @author 20412 | ||
| 244 | + */ | ||
| 245 | + protected static class DeviceManager { | ||
| 246 | + | ||
| 247 | + private static final Logger log = LoggerFactory.getLogger(DeviceManager.class); | ||
| 248 | + private static final ConcurrentHashMap<String, Channel> DEVICE_MAP = new ConcurrentHashMap<>(); | ||
| 249 | + | ||
| 250 | + /** | ||
| 251 | + * 设备上线 | ||
| 252 | + * | ||
| 253 | + * @param imei 设备号 | ||
| 254 | + * @param ctx 当前连接的处理器上下文 | ||
| 255 | + */ | ||
| 256 | + public static void onlineDevice(String imei, ChannelHandlerContext ctx) { | ||
| 257 | + if (DEVICE_MAP.containsKey(imei)) { | ||
| 258 | + // 关闭之前的连接 | ||
| 259 | + Channel channel = DEVICE_MAP.get(imei); | ||
| 260 | + channel.close(); | ||
| 261 | + } | ||
| 262 | + // 为当前连接设置id | ||
| 263 | + Channel channel = ctx.channel(); | ||
| 264 | + channel.attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).set(imei); | ||
| 265 | + // 继续传递事件给下一个 ChannelHandler | ||
| 266 | + ctx.fireChannelActive(); | ||
| 267 | + init(imei, channel); | ||
| 268 | + log.info("设备上线:设备号为:{}", imei); | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + /** | ||
| 272 | + * 移除设备 以及资源管理器 | ||
| 273 | + * | ||
| 274 | + * @param imei 设备号 | ||
| 275 | + */ | ||
| 276 | + public static void removeDevice(String imei) { | ||
| 277 | + if (DEVICE_MAP.containsKey(imei)) { | ||
| 278 | + clean(imei); | ||
| 279 | + log.info("设备离线,设备号为:{}", imei); | ||
| 280 | + } | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + /** | ||
| 284 | + * 向设备发送指令 | ||
| 285 | + * | ||
| 286 | + * @param imei 设备号 | ||
| 287 | + * @param command 指令 | ||
| 288 | + * @return obj 处理结果 | ||
| 289 | + */ | ||
| 290 | + public static void sendCommand(String imei, String command) { | ||
| 291 | + log.info("服务器发起:{}", command); | ||
| 292 | + Channel channel = DEVICE_MAP.get(imei); | ||
| 293 | + if (Objects.isNull(channel)) { | ||
| 294 | + throw new IDeviceException(ResultCode.CODE_207, "设备" + imei + "不在线"); | ||
| 295 | + } | ||
| 296 | + channel.writeAndFlush(Unpooled.copiedBuffer(command, CharsetUtil.UTF_8)); | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + /** | ||
| 300 | + * 判断信道内是否有设备注册 | ||
| 301 | + * | ||
| 302 | + * @param channel 通道 | ||
| 303 | + * @return result 如果存在返回 --true 如果不存在返回 --false | ||
| 304 | + */ | ||
| 305 | + public static boolean hasDevice(Channel channel) { | ||
| 306 | + AttributeKey<String> key = AttributeKey.valueOf(ThinkraceUtil.IMEI); | ||
| 307 | + //netty移除了这个map的remove方法,这里的判断谨慎一点 | ||
| 308 | + return (channel.hasAttr(key) || channel.attr(key).get() != null); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + | ||
| 312 | + // 设备上线 创建资源管理器 | ||
| 313 | + private static void init(String imei, Channel channel) { | ||
| 314 | + // 设备上线 | ||
| 315 | + DEVICE_MAP.put(imei, channel); | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + // 离线删除创建的资源管理器 | ||
| 319 | + private static void clean(String imei) { | ||
| 320 | + DEVICE_MAP.remove(imei); | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + /** | ||
| 324 | + * 指令响应 | ||
| 325 | + * | ||
| 326 | + * @param imei 设备号 可以为 -- null | ||
| 327 | + * @param command 指令 | ||
| 328 | + * @param commandSn 指令流水号 | ||
| 329 | + * @param adapter 适配器 -- 调用适配器的更新方法 | ||
| 330 | + * @return obj 处理结果 | ||
| 331 | + */ | ||
| 332 | + public static boolean askCommand(String txt, String imei, String command, String commandSn, ICommandAdapter adapter) { | ||
| 333 | + log.info("{}:设备:{},命令流水号:{},响应命令:{}", txt, imei, commandSn, command); | ||
| 334 | + // 通过事件通知 另外单独一个类通知 | ||
| 335 | + String key = getCommandKey(imei, commandSn); | ||
| 336 | + REDIS_CACHE.expire(key, COMMAND_LABEL_SURE, COMMAND_TTL, TimeUnit.SECONDS); | ||
| 337 | + return true; | ||
| 338 | + } | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + | ||
| 342 | + public static void initRedisThinkraceCommandParam(RedisCache redisCache) { | ||
| 343 | + REDIS_CACHE = redisCache; | ||
| 344 | + REDIS_CACHE.setNx(COMMAND_SN, 0); | ||
| 345 | + } | ||
| 346 | + | ||
| 347 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/ICommandAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.device.ILoginPacketAdapter; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import org.slf4j.Logger; | ||
| 7 | +import org.slf4j.LoggerFactory; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 命令适配器基类 | ||
| 11 | + * | ||
| 12 | + * @author 20412 | ||
| 13 | + */ | ||
| 14 | +public abstract class ICommandAdapter { | ||
| 15 | + protected static final Logger log = LoggerFactory.getLogger(ICommandAdapter.class); | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 指令解析 | ||
| 20 | + * | ||
| 21 | + * @param command 指令 | ||
| 22 | + * @param ctx netty处理器上下文 | ||
| 23 | + * @return obj 处理结果 | ||
| 24 | + */ | ||
| 25 | + public abstract Object resolveCommand(String command, ChannelHandlerContext ctx); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 指令下发 | ||
| 29 | + * | ||
| 30 | + * @return obj 处理结果 | ||
| 31 | + */ | ||
| 32 | + public abstract CommandListen sendCommand(Object params); | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 生成命令序列号 | ||
| 37 | + * | ||
| 38 | + * @return commandSn | ||
| 39 | + */ | ||
| 40 | + protected String generatorSn() { | ||
| 41 | + return ThinkraceUtil.generatorSn(); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 设置命令 | ||
| 46 | + * | ||
| 47 | + * @param sn 命令流水号 | ||
| 48 | + * @param imei 设备号 | ||
| 49 | + * @return | ||
| 50 | + */ | ||
| 51 | + private CommandListen syncCommandSnAsk(String imei, String sn) { | ||
| 52 | + String key = ThinkraceUtil.commandLabelInit(imei, sn); | ||
| 53 | + return new CommandListenImpl(key); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + protected CommandListen syncSendCommand(String imei, String sn, String command) { | ||
| 57 | + ThinkraceUtil.sendCommand(imei, command); | ||
| 58 | + return syncCommandSnAsk(imei, sn); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + public interface CommandListen { | ||
| 63 | + /** | ||
| 64 | + * 监听应答 | ||
| 65 | + * | ||
| 66 | + * @return 应答结果 | ||
| 67 | + */ | ||
| 68 | + boolean listenAsk(); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + protected class CommandListenImpl implements CommandListen { | ||
| 72 | + private String key; | ||
| 73 | + | ||
| 74 | + protected CommandListenImpl(String key) { | ||
| 75 | + this.key = key; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + @Override | ||
| 79 | + public boolean listenAsk() { | ||
| 80 | + // 循环读取 | ||
| 81 | + try { | ||
| 82 | + Thread.sleep(100); | ||
| 83 | + Integer val = ThinkraceUtil.getCommandSn(this.key); | ||
| 84 | + while (val != null) { | ||
| 85 | + if (!val.equals(ThinkraceUtil.COMMAND_LABEL_SURE)) { | ||
| 86 | + return true; | ||
| 87 | + } | ||
| 88 | + Thread.sleep(100); | ||
| 89 | + val = ThinkraceUtil.getCommandSn(this.key); | ||
| 90 | + } | ||
| 91 | + return false; | ||
| 92 | + } catch (Exception e) { | ||
| 93 | + System.out.println("等待命令响应出现异常:" + e.getMessage()); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + protected void responseLog(String imei, String response) { | ||
| 100 | + log.info("设备:{},命令解析完毕,返回响应:{}", imei, response); | ||
| 101 | + } | ||
| 102 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/active/IActiveContactPeopleWhitePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.active; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.active.WhiteListPeople; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import com.ruoyi.utils.IUnicodeUtils; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * @author 20412 | ||
| 12 | + * 白名单 | ||
| 13 | + */ | ||
| 14 | +@Service(ThinkraceUtil.ACTIVE.CONTACT_ACTIVE) | ||
| 15 | +public class IActiveContactPeopleWhitePacketAdapter extends ICommandAdapter { | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 19 | + return null; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public CommandListen sendCommand(Object params) { | ||
| 24 | + // 设置10个联系人白名单 | ||
| 25 | + // IWBP14,IMEI,指令流水号,联系人1名称|联系人1电话,联系人2名称|联系人2电话,联系人3名称|联系人3电话,联系人4名称|联系人4电话,联系人5名称|联系人5电话,联系人6名称|联系人6电话,联系人7名称|联系人7电话,联系人8名称|联系人8电话,联系人9名称|联系人9电话,联系人10名称|联系人10电话# | ||
| 26 | + WhiteListPeople wlp = (WhiteListPeople) params; | ||
| 27 | + String commandSn = generatorSn(); | ||
| 28 | + StringBuilder command = new StringBuilder(); | ||
| 29 | + command.append(ThinkraceUtil.ACTIVE.CONTACT_ACTIVE).append(","); | ||
| 30 | + command.append(wlp.getImei()).append(","); | ||
| 31 | + command.append(commandSn).append(","); | ||
| 32 | + for (WhiteListPeople.Contact contact : wlp.getContacts()) { | ||
| 33 | + command.append(IUnicodeUtils.toUnicode(contact.getName())).append("|").append(contact.getTell()).append(","); | ||
| 34 | + } | ||
| 35 | + command.deleteCharAt(command.length() - 1).append(ThinkraceUtil.END_SYMBOL); | ||
| 36 | + // 发送指令 | ||
| 37 | + return syncSendCommand(wlp.getImei(), commandSn, command.toString()); | ||
| 38 | + } | ||
| 39 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/active/IActiveSettingSosPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.active; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.active.Sos; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +import java.util.ArrayList; | ||
| 10 | +import java.util.List; | ||
| 11 | +import java.util.stream.Collectors; | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 下发指令 设置sos联系方式 | ||
| 16 | + * | ||
| 17 | + * @author 20412 | ||
| 18 | + */ | ||
| 19 | +@Service(ThinkraceUtil.ACTIVE.SOS_ACTIVE) | ||
| 20 | +public class IActiveSettingSosPacketAdapter extends ICommandAdapter { | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 25 | + return null; | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public CommandListen sendCommand(Object params) { | ||
| 30 | + // 格式:IWBP12,IMEI,指令流水号,SOS1,SOS2,SOS3# | ||
| 31 | + // 示例:IWBP12,353456789012345,080835,1XXXXXXXX,2XXXXXXXX,3XXXXXXXX# | ||
| 32 | + Sos sos = (Sos) params; | ||
| 33 | + List<String> commands = new ArrayList<>(); | ||
| 34 | + commands.add(ThinkraceUtil.ACTIVE.SOS_ACTIVE); | ||
| 35 | + commands.add(sos.getImei()); | ||
| 36 | + commands.add(generatorSn()); | ||
| 37 | + commands.addAll(sos.getCalls()); | ||
| 38 | + String command = commands.stream().collect(Collectors.joining(",")) + ThinkraceUtil.END_SYMBOL; | ||
| 39 | + return syncSendCommand(sos.getImei(), commands.get(2), command); | ||
| 40 | + } | ||
| 41 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/active/IActiveUploadGpsTimePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.active; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.active.UploadGpsTime; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 下发指令 设置sos联系方式 | ||
| 12 | + * | ||
| 13 | + * @author 20412 | ||
| 14 | + */ | ||
| 15 | +@Service(ThinkraceUtil.ACTIVE.UPLOAD_GPS_TIME_ACTIVE) | ||
| 16 | +public class IActiveUploadGpsTimePacketAdapter extends ICommandAdapter { | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 21 | + return null; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public CommandListen sendCommand(Object params) { | ||
| 26 | + // 格式:IWBP15,IMEI,指令流水号,定位间隔# | ||
| 27 | + // 示例:IWBP15,353456789012345,080835,300# | ||
| 28 | + UploadGpsTime ugt = (UploadGpsTime) params; | ||
| 29 | + String sn = generatorSn(); | ||
| 30 | + StringBuilder command = new StringBuilder(); | ||
| 31 | + command.append(ThinkraceUtil.ACTIVE.UPLOAD_GPS_TIME_ACTIVE).append(","); | ||
| 32 | + command.append(ugt.getImei()).append(","); | ||
| 33 | + command.append(sn).append(","); | ||
| 34 | + command.append(ugt.getSeconds()); | ||
| 35 | + command.append(ThinkraceUtil.END_SYMBOL); | ||
| 36 | + return syncSendCommand(ugt.getImei(), sn, command.toString()); | ||
| 37 | + } | ||
| 38 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/callback/ICallbackContactPeopleWhitePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.callback; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import io.netty.util.AttributeKey; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author 20412 | ||
| 11 | + * 白名单 | ||
| 12 | + */ | ||
| 13 | +@Service(ThinkraceUtil.REQ.CONTACT_REQ) | ||
| 14 | +public class ICallbackContactPeopleWhitePacketAdapter extends ICommandAdapter { | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 18 | + // IWAP14,080835, D3590D54|135xxxxxxxxxx, | ||
| 19 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 20 | + String[] params = command.split(","); | ||
| 21 | + return ThinkraceUtil.askCommand("设置联系人白名单", imei, command, params[1], this); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public CommandListen sendCommand(Object params) { | ||
| 26 | + return null; | ||
| 27 | + } | ||
| 28 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/callback/ICallbackSettingSosPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.callback; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import io.netty.util.AttributeKey; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author 20412 | ||
| 11 | + */ | ||
| 12 | +@Service(ThinkraceUtil.REQ.SOS_REQ) | ||
| 13 | +public class ICallbackSettingSosPacketAdapter extends ICommandAdapter { | ||
| 14 | + | ||
| 15 | + @Override | ||
| 16 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 17 | + // IWAP12,指令流水号,SOS1,SOS2, SOS3# | ||
| 18 | + // IWAP12,080835, 1XXXXXXXX,2XXXXXXXX,3XXXXXXXX # | ||
| 19 | + // 080835: 终端响应的时候带上响应流水号 | ||
| 20 | + // 1XXXXXXXX,2XXXXXXXX,3XXXXXXXX | ||
| 21 | + String[] params = command.split(","); | ||
| 22 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 23 | + // 命令确认应答 | ||
| 24 | + return ThinkraceUtil.askCommand("设置sos命令响应",imei, command, params[1], this); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public CommandListen sendCommand(Object params) { | ||
| 29 | + return null; | ||
| 30 | + } | ||
| 31 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/callback/ICallbackUploadGpsTimePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.callback; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import io.netty.util.AttributeKey; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author 20412 | ||
| 11 | + */ | ||
| 12 | +@Service(ThinkraceUtil.REQ.UPLOAD_GPS_TIME_REQ) | ||
| 13 | +public class ICallbackUploadGpsTimePacketAdapter extends ICommandAdapter { | ||
| 14 | + | ||
| 15 | + @Override | ||
| 16 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 17 | + //IWAP15,指令流水号,定位间隔# | ||
| 18 | + String[] params = command.split(","); | ||
| 19 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 20 | + // 命令确认应答 | ||
| 21 | + return ThinkraceUtil.askCommand("GPS定位数据上传时间间隔命令响应", imei, command, params[1], this); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public CommandListen sendCommand(Object params) { | ||
| 26 | + return null; | ||
| 27 | + } | ||
| 28 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IBaseStationTimeGpsPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.response.BaseStationResponse; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import com.ruoyi.utils.ConstDateUtil; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.AttributeKey; | ||
| 10 | +import io.netty.util.CharsetUtil; | ||
| 11 | +import org.springframework.http.HttpMethod; | ||
| 12 | +import org.springframework.http.ResponseEntity; | ||
| 13 | +import org.springframework.stereotype.Service; | ||
| 14 | +import org.springframework.web.client.RestTemplate; | ||
| 15 | +import javax.xml.bind.JAXBContext; | ||
| 16 | +import javax.xml.bind.Unmarshaller; | ||
| 17 | +import java.io.StringReader; | ||
| 18 | +import java.time.ZoneOffset; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * 13 通过基站校时并获取经纬度命令 | ||
| 22 | + * | ||
| 23 | + * @author 20412 | ||
| 24 | + */ | ||
| 25 | +@Service(ThinkraceUtil.REQ.BASE_STATION_TIMING_GPS_REQ) | ||
| 26 | +public class IBaseStationTimeGpsPacketAdapter extends ICommandAdapter { | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 30 | + // IWAPTM,460,0,9750,3613# | ||
| 31 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 32 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 33 | + log.info("设备:{},通过基站校时并获取经纬度命令:{}", imei, command); | ||
| 34 | + // IWBPTM,20160225090909,22.123456,113.654321# | ||
| 35 | + //返回时间,格式为:yyyyMMddHHmmss ,为UTC0 时间 | ||
| 36 | + String mcc = params[1]; | ||
| 37 | + String mnc = params[2]; | ||
| 38 | + String lac = params[3]; | ||
| 39 | + String cid = params[4]; | ||
| 40 | + BaseStationResponse obs = getLocation(mcc, mnc, lac, cid); | ||
| 41 | + // 这个坐标解析 | ||
| 42 | + String response = ThinkraceUtil.RES.BASE_STATION_TIMING_GPS_RES + "," + ConstDateUtil.formatDate("yyyyMMddHHmmss", ZoneOffset.UTC) | ||
| 43 | + + "," + obs.getLat() + "," + obs.getLon() + ThinkraceUtil.END_SYMBOL; | ||
| 44 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 45 | + responseLog(imei, response); | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + private BaseStationResponse getLocation(String mcc, String mnc, String lac, String cid) { | ||
| 50 | + BaseStationResponse result = null; | ||
| 51 | + try { | ||
| 52 | + StringBuilder sb = new StringBuilder(); | ||
| 53 | + sb.append("http://api.cellocation.com:84/cell/?"); | ||
| 54 | + sb.append("mnc=").append(mnc); | ||
| 55 | + sb.append("&mcc=").append(mcc); | ||
| 56 | + sb.append("&lac=").append(lac); | ||
| 57 | + sb.append("&ci=").append(cid); | ||
| 58 | + sb.append("&output=xml"); | ||
| 59 | + RestTemplate restTemplate = new RestTemplate(); | ||
| 60 | + ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, String.class); | ||
| 61 | + String xmlData = response.getBody(); | ||
| 62 | + // 创建JAXB上下文对象,并指定要绑定的根类 | ||
| 63 | + JAXBContext jaxbContext = JAXBContext.newInstance(BaseStationResponse.class); | ||
| 64 | + // 创建Unmarshaller对象,用于将XML数据转换为Java对象 | ||
| 65 | + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); | ||
| 66 | + // 调用unmarshal方法将XML字符串转换为Java对象 | ||
| 67 | + result = (BaseStationResponse) unmarshaller.unmarshal(new StringReader(xmlData)); | ||
| 68 | + } catch (Exception e) { | ||
| 69 | + log.error("根据基站获取信息api调用异常:{}", e.getMessage()); | ||
| 70 | + //若没取到则返回 0 TODO | ||
| 71 | + return new BaseStationResponse(); | ||
| 72 | + } | ||
| 73 | + return result; | ||
| 74 | + | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public CommandListen sendCommand(Object params) { | ||
| 79 | + return null; | ||
| 80 | + } | ||
| 81 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ICdmaGpsPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.GpsInfo; | ||
| 4 | +import com.ruoyi.system.domain.command.WifiInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 8 | +import io.netty.buffer.Unpooled; | ||
| 9 | +import io.netty.channel.ChannelHandlerContext; | ||
| 10 | +import io.netty.util.AttributeKey; | ||
| 11 | +import io.netty.util.CharsetUtil; | ||
| 12 | +import org.springframework.stereotype.Service; | ||
| 13 | +import java.util.ArrayList; | ||
| 14 | +import java.util.List; | ||
| 15 | +import java.util.regex.Matcher; | ||
| 16 | +import java.util.regex.Pattern; | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * 3. CDMA GPS定位数据包 | ||
| 20 | + * | ||
| 21 | + * @author 20412 | ||
| 22 | + */ | ||
| 23 | +@Service(ThinkraceUtil.REQ.CDMA_GPS_REQ) | ||
| 24 | +public class ICdmaGpsPacketAdapter extends ICommandAdapter { | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 29 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 30 | + log.info("CDMA GPS定位数据包:{}", command); | ||
| 31 | + // 格式GPS+LBS+状态+基站+WIFI合并包 | ||
| 32 | + // 示例:IWAP91080524A2232.9806N11404.9355E000.1061830323.8700908000102, | ||
| 33 | + // 13824,1,1838,-52,Home|74-DE-2B-44-88-8C|97& Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97& Home3|74-DE-2B-44-88-8C|97# | ||
| 34 | + GpsInfo gpsCommand = resolveGpsCommand(command); | ||
| 35 | + // 返回响应 IWBP91# | ||
| 36 | + String response = ThinkraceUtil.RES.CDMA_GPS_RES + ThinkraceUtil.END_SYMBOL; | ||
| 37 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 38 | + // 响应log | ||
| 39 | + responseLog(imei, response); | ||
| 40 | + return gpsCommand; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public CommandListen sendCommand(Object params) { | ||
| 45 | + return null; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 格式GPS+LBS+状态+基站+WIFI合并包 | ||
| 50 | + * 示例:IWAP91080524A2232.9806N11404.9355E000.1061830323.8700908000102, | ||
| 51 | + * 13824,1,1838,-52,Home|74-DE-2B-44-88-8C|97& Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97& Home3|74-DE-2B-44-88-8C|97# | ||
| 52 | + * | ||
| 53 | + * @param command 指令 | ||
| 54 | + */ | ||
| 55 | + private GpsInfo resolveGpsCommand(String command) { | ||
| 56 | + String conditionRegex = ThinkraceUtil.REQ.CDMA_GPS_REQ + "([0-9]{6})([AV])"; | ||
| 57 | + // 数据分段 | ||
| 58 | + String[] sc = command.split(","); | ||
| 59 | + String str1 = sc[0]; | ||
| 60 | + // TODO 判断定位是否有效 匹配 "IWAP01" 后的数字,直到遇到大写字母 "A" 而是V的话 就是不合法 | ||
| 61 | + Pattern pattern = Pattern.compile(conditionRegex); | ||
| 62 | + Matcher matcher = pattern.matcher(str1); | ||
| 63 | + GpsInfo gps = new GpsInfo(); | ||
| 64 | + if (matcher.find()) { | ||
| 65 | + // 位置信息合法 todo | ||
| 66 | + String addressAndOtherRegex = conditionRegex + "([0-9]{4}.[0-9]{4}N)([0-9]{5}.[0-9]{4}E)(\\d+.[0-9]{1})([0-9]{6})(\\d+.[0-9]{2})([0-9]{3})([0-9]{3})([0-9]{1})([0-9]{2})([0-9]{2})"; | ||
| 67 | + pattern = Pattern.compile(addressAndOtherRegex); | ||
| 68 | + matcher = pattern.matcher(str1); | ||
| 69 | + if (matcher.find()) { | ||
| 70 | + // 设备时间 | ||
| 71 | + gps.setDeviceDate(matcher.group(1)); | ||
| 72 | + gps.setAddressCheck(matcher.group(2)); | ||
| 73 | + if (DeviceProperty.AddressProperty.INVALID.equals(gps.getAddressCheck())) { | ||
| 74 | + log.info("gps数据V无效,命令为:{}", command); | ||
| 75 | + } | ||
| 76 | + // ddmm.mmmm维度 | ||
| 77 | + gps.setGpsN(matcher.group(3)); | ||
| 78 | + // dddmm.mmmm 经度 | ||
| 79 | + gps.setGpsE(matcher.group(4)); | ||
| 80 | + gps.setSpeed(matcher.group(5)); | ||
| 81 | + gps.setDeviceTime(matcher.group(6)); | ||
| 82 | + gps.setDirection(matcher.group(7)); | ||
| 83 | +// gps.setGms(matcher.group(7)); | ||
| 84 | + // 参与定位的卫星数 | ||
| 85 | + gps.setGpsSatelliteCount(matcher.group(8)); | ||
| 86 | + gps.setPower(matcher.group(9)); | ||
| 87 | + gps.setPlaceholder(matcher.group(10)); | ||
| 88 | + // 是否设防 01 设防 00 未设置 | ||
| 89 | + gps.setIsSafety(matcher.group(11)); | ||
| 90 | + // 是否为工作模式 02 工作模式 | ||
| 91 | + gps.setIsWork(matcher.group(12)); | ||
| 92 | + gps.setSid(sc[1]); | ||
| 93 | + gps.setNid(sc[2]); | ||
| 94 | + gps.setBid(sc[3]); | ||
| 95 | + gps.setSignal(Integer.parseInt(sc[4])); | ||
| 96 | + // WIFI 信息 | ||
| 97 | + List<WifiInfo> wifiGroups = new ArrayList<>(); | ||
| 98 | + gps.setWifiInfoList(wifiGroups); | ||
| 99 | + if (sc.length > 5) { | ||
| 100 | + String[] wifiSpilt = sc[5].replace(ThinkraceUtil.END_SYMBOL, "") | ||
| 101 | + .replaceAll(" ", "") | ||
| 102 | + .split("&"); | ||
| 103 | + for (String wifi : wifiSpilt) { | ||
| 104 | + String[] wifiInfo = wifi.split("\\|"); | ||
| 105 | + wifiGroups.add(new WifiInfo(wifiInfo[0], wifiInfo[1], wifiInfo[2])); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + return gps; | ||
| 112 | + | ||
| 113 | + } | ||
| 114 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ICdmaWifiPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.GpsInfo; | ||
| 4 | +import com.ruoyi.system.domain.command.WifiInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.AttributeKey; | ||
| 10 | +import io.netty.util.CharsetUtil; | ||
| 11 | +import org.springframework.stereotype.Service; | ||
| 12 | + | ||
| 13 | +import java.util.ArrayList; | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * CDMA基站wifi定位数据包 | ||
| 18 | + * | ||
| 19 | + * @author 20412 | ||
| 20 | + */ | ||
| 21 | +@Service(ThinkraceUtil.REQ.CDMA_WIFI_GPS_REQ) | ||
| 22 | +public class ICdmaWifiPacketAdapter extends ICommandAdapter { | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 26 | + // IWAP92,zh_cn,0, 13824,1,1838,-52,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65# | ||
| 27 | + GpsInfo gi = new GpsInfo(); | ||
| 28 | + gi.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 29 | + log.info("设备:{},CDMA基站wifi定位数据包:{}", gi.getImei(), command); | ||
| 30 | + String sub = command.substring(0, command.length() - 1); | ||
| 31 | + String[] params = sub.split(","); | ||
| 32 | + gi.setCommandLabel(params[0]); | ||
| 33 | + gi.setLanguageLabel(params[1]); | ||
| 34 | + gi.setReplyLabel(params[2]); | ||
| 35 | + gi.setSid(params[3]); | ||
| 36 | + gi.setNid(params[4]); | ||
| 37 | + gi.setBid(params[5]); | ||
| 38 | + gi.setSignal(Integer.parseInt(params[6])); | ||
| 39 | + gi.setWifiGroups(Integer.parseInt(params[7])); | ||
| 40 | + List<WifiInfo> wifiInfoList = new ArrayList<>(); | ||
| 41 | + gi.setWifiInfoList(wifiInfoList); | ||
| 42 | + String[] wifiInfo = params[8].split("&"); | ||
| 43 | + for (String baseWifi : wifiInfo) { | ||
| 44 | + String[] param = baseWifi.split("\\|"); | ||
| 45 | + WifiInfo wi = new WifiInfo(param[0], param[1], param[2]); | ||
| 46 | + wifiInfoList.add(wi); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + // 响应 IWBP92# | ||
| 50 | + String response = ThinkraceUtil.RES.CDMA_WIFI_GPS_RES + ThinkraceUtil.END_SYMBOL; | ||
| 51 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 52 | + responseLog(gi.getImei(), response); | ||
| 53 | + return gi; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public CommandListen sendCommand(Object params) { | ||
| 58 | + return null; | ||
| 59 | + } | ||
| 60 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IDeviceAlarmPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.DeviceAlarm; | ||
| 4 | +import com.ruoyi.system.domain.command.WifiInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 8 | +import com.ruoyi.utils.IUnicodeUtils; | ||
| 9 | +import io.netty.buffer.Unpooled; | ||
| 10 | +import io.netty.channel.ChannelHandlerContext; | ||
| 11 | +import io.netty.util.AttributeKey; | ||
| 12 | +import io.netty.util.CharsetUtil; | ||
| 13 | +import org.springframework.stereotype.Service; | ||
| 14 | +import java.util.ArrayList; | ||
| 15 | +import java.util.List; | ||
| 16 | +import java.util.regex.Matcher; | ||
| 17 | +import java.util.regex.Pattern; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 报警与地址回复包 | ||
| 21 | + * | ||
| 22 | + * @author 20412 | ||
| 23 | + */ | ||
| 24 | +@Service(ThinkraceUtil.REQ.ALARM_REQ) | ||
| 25 | +public class IDeviceAlarmPacketAdapter extends ICommandAdapter { | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 29 | + | ||
| 30 | + // IWAP10+时间+GPS位置有效性标志+纬度+经度+速度+定位数据产生时间+方向角+参数,基站数据,报警值,终端语言,标志位,Wi-Fi信息# | ||
| 31 | + // 示例:IWAP10080524A2232.9806N11404.9355E000.1061830323.8706000908000502,460,0,9520,3671,00,zh-cn,00, | ||
| 32 | + String regex = ThinkraceUtil.REQ.ALARM_REQ + "([0-9]{6})([AV])"; | ||
| 33 | + // 数据分段 | ||
| 34 | + String[] sc = command.split(","); | ||
| 35 | + String str1 = sc[0]; | ||
| 36 | + // TODO 判断定位是否有效 匹配 "IWAP01" 后的数字,直到遇到大写字母 "A" 而是V的话 就是不合法 | ||
| 37 | + Pattern pattern = Pattern.compile(regex); | ||
| 38 | + Matcher matcher = pattern.matcher(str1); | ||
| 39 | + DeviceAlarm alarm = new DeviceAlarm(); | ||
| 40 | + alarm.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 41 | + log.info("设备:{},报警与地址回复:{}", alarm.getImei(), command); | ||
| 42 | + // 匹配是否有效 | ||
| 43 | + if (matcher.find()) { | ||
| 44 | + // 位置信息合法 todo | ||
| 45 | + String addressAndOtherRegex = regex + "([0-9]{4}.[0-9]{4}N)([0-9]{5}.[0-9]{4}E)(\\d+.[0-9]{1})([0-9]{6})(\\d+.[0-9]{2})([0-9]{3})([0-9]{3})([0-9]{3})([0-9]{1})([0-9]{2})([0-9]{2})"; | ||
| 46 | + pattern = Pattern.compile(addressAndOtherRegex); | ||
| 47 | + matcher = pattern.matcher(str1); | ||
| 48 | + if (matcher.find()) { | ||
| 49 | + // 设备时间 | ||
| 50 | + alarm.setDeviceDate(matcher.group(1)); | ||
| 51 | + alarm.setAddressCheck(matcher.group(2)); | ||
| 52 | + if (DeviceProperty.AddressProperty.INVALID.equals(alarm.getAddressCheck())) { | ||
| 53 | + log.info("gps数据V无效,命令为:{}", command); | ||
| 54 | + } | ||
| 55 | + // ddmm.mmmm维度 | ||
| 56 | + alarm.setGpsN(matcher.group(3)); | ||
| 57 | + // dddmm.mmmm 经度 | ||
| 58 | + alarm.setGpsE(matcher.group(4)); | ||
| 59 | + alarm.setSpeed(matcher.group(5)); | ||
| 60 | + alarm.setDeviceTime(matcher.group(6)); | ||
| 61 | + alarm.setDirection(matcher.group(7)); | ||
| 62 | + alarm.setGms(matcher.group(8)); | ||
| 63 | + // 参与定位的卫星数 | ||
| 64 | + alarm.setGpsSatelliteCount(matcher.group(9)); | ||
| 65 | + alarm.setPower(matcher.group(10)); | ||
| 66 | + alarm.setPlaceholder(matcher.group(11)); | ||
| 67 | + // 是否设防 01 设防 00 未设置 | ||
| 68 | + alarm.setIsSafety(matcher.group(12)); | ||
| 69 | + // 是否为工作模式 02 工作模式 | ||
| 70 | + alarm.setIsWork(matcher.group(13)); | ||
| 71 | + alarm.setMcc(sc[1]); | ||
| 72 | + alarm.setMnc(sc[2]); | ||
| 73 | + alarm.setLac(sc[3]); | ||
| 74 | + alarm.setCid(sc[4]); | ||
| 75 | + // 01 SOS 02 低电 03 摘除手表 | ||
| 76 | + // 04 预留 05 防拆表带打开 06 跌倒 | ||
| 77 | + // 07 无效的心率值 08 心率过高 09 心率过低 | ||
| 78 | + // 10 舒张压过高 11 舒张压过低 12 收缩压过高 | ||
| 79 | + // 13 收缩压过低 14 久坐 15 预留 | ||
| 80 | + // 16 防拆表带锁上 17 体温过高 18 体温过低 | ||
| 81 | + // 19 关机 20 离开电子围栏 21 进入电子围栏 | ||
| 82 | + // 22 消息已阅读 | ||
| 83 | + alarm.setAlarmValue(sc[5]); | ||
| 84 | + alarm.setDeviceLanguage(sc[6]); | ||
| 85 | + // 第一个0:是否需要回复地址信息标志,取值为0表示不需要回复,取值为1表示需要回复. | ||
| 86 | + // 第二个0:地址信息中是否包含手机超链接, 取值为0表示不包含,取值为1表示包含. TODO 什么手机超链接 | ||
| 87 | + alarm.setAlarmInfoLabel(sc[7]); | ||
| 88 | + // WIFI 信息 | ||
| 89 | + List<WifiInfo> infoList = new ArrayList<>(); | ||
| 90 | + alarm.setWifiInfo(infoList); | ||
| 91 | + String[] wifiSpilt = sc[sc.length - 1].replace(ThinkraceUtil.END_SYMBOL, "") | ||
| 92 | + .replaceAll(" ", "") | ||
| 93 | + .split("&"); | ||
| 94 | + for (String wifi : wifiSpilt) { | ||
| 95 | + String[] wifiInfo = wifi.split("\\|"); | ||
| 96 | + infoList.add(new WifiInfo(wifiInfo[0], wifiInfo[1], wifiInfo[2])); | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + // 返回响应 | ||
| 101 | + backCommand(ctx, alarm); | ||
| 102 | + return alarm; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + private void backCommand(ChannelHandlerContext ctx, DeviceAlarm alarm) { | ||
| 106 | + char isBackAddress = alarm.getAlarmInfoLabel().charAt(0); | ||
| 107 | + String response = ""; | ||
| 108 | + if (isBackAddress == '1') { | ||
| 109 | + // TODO 返回地址 判断是否需要返回超链接 地址是解析好的设备传过来的地址还是服务器预留的地址以及连接。 | ||
| 110 | + String unicode = IUnicodeUtils.toUnicode("深圳市南山区南海大道1079号http://www.gps.com/map.aspx?lat=23.123&lng=113.123"); | ||
| 111 | + response = ThinkraceUtil.RES.ALARM_RES + unicode + ThinkraceUtil.END_SYMBOL; | ||
| 112 | + } else { | ||
| 113 | + response = ThinkraceUtil.RES.ALARM_RES + ThinkraceUtil.END_SYMBOL; | ||
| 114 | + } | ||
| 115 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 116 | + // 打印日志 | ||
| 117 | + responseLog(alarm.getImei(), response); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @Override | ||
| 121 | + public CommandListen sendCommand(Object params) { | ||
| 122 | + return null; | ||
| 123 | + } | ||
| 124 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IEcgDatePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import io.netty.util.AttributeKey; | ||
| 8 | +import io.netty.util.CharsetUtil; | ||
| 9 | +import org.springframework.stereotype.Service; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * ECG 数据 | ||
| 13 | + * | ||
| 14 | + * @author 20412 | ||
| 15 | + */ | ||
| 16 | +@Service(ThinkraceUtil.REQ.ECG_DATA_REQ) | ||
| 17 | +public class IEcgDatePacketAdapter extends ICommandAdapter { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 21 | + // IWAPHD,20140818064408,6,1,1.3,20.2,1,1000,1024,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX# | ||
| 22 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 23 | + log.info("设备:{},ECG数据命令:{}", imei, command); | ||
| 24 | + | ||
| 25 | + // 响应IWBPHD,0, 98, 59, 156, 296, 369,7aa660275fc35f8b4e0d9f50|623f98a4 # | ||
| 26 | + String response = "IWBPHD,0, 98, 59, 156, 296, 369,7aa660275fc35f8b4e0d9f50|623f98a4 #"; | ||
| 27 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 28 | + responseLog(imei, response); | ||
| 29 | + return null; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public CommandListen sendCommand(Object params) { | ||
| 34 | + return null; | ||
| 35 | + } | ||
| 36 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IGpsPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.GpsInfo; | ||
| 4 | +import com.ruoyi.system.domain.command.WifiInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 8 | +import io.netty.buffer.Unpooled; | ||
| 9 | +import io.netty.channel.ChannelHandlerContext; | ||
| 10 | +import io.netty.util.AttributeKey; | ||
| 11 | +import io.netty.util.CharsetUtil; | ||
| 12 | +import org.springframework.stereotype.Service; | ||
| 13 | + | ||
| 14 | +import java.util.ArrayList; | ||
| 15 | +import java.util.List; | ||
| 16 | +import java.util.regex.Matcher; | ||
| 17 | +import java.util.regex.Pattern; | ||
| 18 | + | ||
| 19 | +@Service(ThinkraceUtil.REQ.GPS_REQ) | ||
| 20 | +public class IGpsPacketAdapter extends ICommandAdapter { | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 24 | + log.info("定位数据包:{}", command); | ||
| 25 | + // 处理指令 获取gps信息 | ||
| 26 | + GpsInfo gpsInfo = resolveGpsCommand(command); | ||
| 27 | + gpsInfo.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 28 | + // 返回响应 | ||
| 29 | + String response = ThinkraceUtil.RES.GPS_RES + ThinkraceUtil.END_SYMBOL; | ||
| 30 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 31 | + // 打印日志 | ||
| 32 | + responseLog(gpsInfo.getImei(), response); | ||
| 33 | + return gpsInfo; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public CommandListen sendCommand(Object params) { | ||
| 38 | + return null; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + private GpsInfo resolveGpsCommand(String command) { | ||
| 42 | + String conditionRegex = ThinkraceUtil.REQ.GPS_REQ + "([0-9]{6})([AV])"; | ||
| 43 | + // 数据分段 | ||
| 44 | + String[] sc = command.split(","); | ||
| 45 | + String str1 = sc[0]; | ||
| 46 | + // TODO 判断定位是否有效 匹配 "IWAP01" 后的数字,直到遇到大写字母 "A" 而是V的话 就是不合法 | ||
| 47 | + Pattern pattern = Pattern.compile(conditionRegex); | ||
| 48 | + Matcher matcher = pattern.matcher(str1); | ||
| 49 | + GpsInfo gps = new GpsInfo(); | ||
| 50 | + if (matcher.find()) { | ||
| 51 | + // 位置信息合法 todo | ||
| 52 | + String addressAndOtherRegex = conditionRegex + "([0-9]{4}.[0-9]{4}N)([0-9]{5}.[0-9]{4}E)(\\d+.[0-9]{1})([0-9]{6})(\\d+.[0-9]{2})([0-9]{3})([0-9]{3})([0-9]{3})([0-9]{1})([0-9]{2})([0-9]{2})"; | ||
| 53 | + pattern = Pattern.compile(addressAndOtherRegex); | ||
| 54 | + matcher = pattern.matcher(str1); | ||
| 55 | + if (matcher.find()) { | ||
| 56 | + // 设备时间 | ||
| 57 | + gps.setDeviceDate(matcher.group(1)); | ||
| 58 | + gps.setAddressCheck(matcher.group(2)); | ||
| 59 | + if (DeviceProperty.AddressProperty.INVALID.equals(gps.getAddressCheck())) { | ||
| 60 | + log.info("gps数据V无效,命令为:{}", command); | ||
| 61 | + } | ||
| 62 | + // ddmm.mmmm维度 | ||
| 63 | + gps.setGpsN(matcher.group(3)); | ||
| 64 | + // dddmm.mmmm 经度 | ||
| 65 | + gps.setGpsE(matcher.group(4)); | ||
| 66 | + gps.setSpeed(matcher.group(5)); | ||
| 67 | + gps.setDeviceTime(matcher.group(6)); | ||
| 68 | + gps.setDirection(matcher.group(7)); | ||
| 69 | + gps.setGms(matcher.group(8)); | ||
| 70 | + // 参与定位的卫星数 | ||
| 71 | + gps.setGpsSatelliteCount(matcher.group(9)); | ||
| 72 | + gps.setPower(matcher.group(10)); | ||
| 73 | + gps.setPlaceholder(matcher.group(11)); | ||
| 74 | + // 是否设防 01 设防 00 未设置 | ||
| 75 | + gps.setIsSafety(matcher.group(12)); | ||
| 76 | + // 是否为工作模式 02 工作模式 | ||
| 77 | + gps.setIsWork(matcher.group(13)); | ||
| 78 | + gps.setMcc(sc[1]); | ||
| 79 | + gps.setMnc(sc[2]); | ||
| 80 | + gps.setLac(sc[3]); | ||
| 81 | + gps.setCid(sc[4]); | ||
| 82 | + // WIFI 信息 | ||
| 83 | + List<WifiInfo> infoList = new ArrayList<>(); | ||
| 84 | + gps.setWifiInfoList(infoList); | ||
| 85 | + if (sc.length > 5) { | ||
| 86 | + String[] wifiSpilt = sc[5].replace(ThinkraceUtil.END_SYMBOL, "") | ||
| 87 | + .replaceAll(" ", "") | ||
| 88 | + .split("&"); | ||
| 89 | + for (String wifi : wifiSpilt) { | ||
| 90 | + String[] wifiInfo = wifi.split("\\|"); | ||
| 91 | + infoList.add(new WifiInfo(wifiInfo[0], wifiInfo[1], wifiInfo[2])); | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + return gps; | ||
| 97 | + | ||
| 98 | + } | ||
| 99 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IHealthPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.CharsetUtil; | ||
| 9 | +import org.springframework.stereotype.Service; | ||
| 10 | + | ||
| 11 | +import java.util.Date; | ||
| 12 | + | ||
| 13 | +import static com.ruoyi.system.protocol.property.DeviceProperty.HealthProperty.*; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * @author 20412健康 | ||
| 17 | + */ | ||
| 18 | +@Service(ThinkraceUtil.REQ.HEALTH_REQ) | ||
| 19 | +public class IHealthPacketAdapter extends ICommandAdapter { | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 23 | + // 格式:IWAPJK,产生健康数据的时间,健康数据类型,健康数值# | ||
| 24 | + // 示例:IWAPJK,2021-05-29 13:00:00,1,691120# 或 | ||
| 25 | + // IWAPJK,2024-03-28 14:21:09,3,36.19# | ||
| 26 | + String[] params = command.split(","); | ||
| 27 | + HealthInfo info = new HealthInfo(); | ||
| 28 | + info.setCreateTime(new Date()); | ||
| 29 | + info.setCommandLabel(params[0]); | ||
| 30 | + info.setUploadTime(params[1]); | ||
| 31 | + info.setHealthType(params[2]); | ||
| 32 | +// info.setHealthValue(params[3].replace(ThinkraceUtil.END_SYMBOL,"")); | ||
| 33 | + // 1:健康数据类型,取值1表示血压,取值2表示心率,取值3表示体温,4表示血氧。 | ||
| 34 | + //691120:健康数值,根据类型不同数据内容有不同。691120表示,舒张压(低压)69,收缩压(高 压)120,中间的1为多个参数分隔符。 | ||
| 35 | + //当健康数据类型为3时,后面的健康数值是体温,36.19是具体的温度值,单位为摄氏度。 | ||
| 36 | + //若只有一个参数则无需分隔符,例如心率:80,则包为:WAPJK,2021-05-29100:00,2,80# | ||
| 37 | + switch (info.getHealthType()) { | ||
| 38 | + case BLOOD_PRESSURE: | ||
| 39 | + info.setLowPressure(Integer.parseInt(params[3].substring(0, 2))); | ||
| 40 | + info.setHighPressure(Integer.parseInt(params[3].substring(3, 6))); | ||
| 41 | + break; | ||
| 42 | + case HEART_RATE: | ||
| 43 | + info.setHeartRate(params[3]); | ||
| 44 | + break; | ||
| 45 | + case TEMPERATURE: | ||
| 46 | + info.setTemperature(Float.parseFloat(params[3].replace(ThinkraceUtil.END_SYMBOL, ""))); | ||
| 47 | + break; | ||
| 48 | + case BLOOD_OXYGEN: | ||
| 49 | + info.setBloodOxygen(params[3]); | ||
| 50 | + break; | ||
| 51 | + } | ||
| 52 | + String response = ThinkraceUtil.RES.HEALTH_RES + "," + info.getHealthType() + ThinkraceUtil.END_SYMBOL; | ||
| 53 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 54 | + responseLog(info.getImei(), response); | ||
| 55 | + return null; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Override | ||
| 59 | + public CommandListen sendCommand(Object params) { | ||
| 60 | + return null; | ||
| 61 | + } | ||
| 62 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IHeartRateBloodPressureOxygenSugarResPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.ArrayList; | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 12 上传心率、血压、血氧、血糖 | ||
| 17 | + * | ||
| 18 | + * @author 20412 | ||
| 19 | + */ | ||
| 20 | +@Service(ThinkraceUtil.REQ.HEART_RATE_BLOOD_PRESSURE_OXYGEN_SUGAR_REQ) | ||
| 21 | +public class IHeartRateBloodPressureOxygenSugarResPacketAdapter extends ICommandAdapter { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 25 | + // IWAPHP,60,130,85,95,90,36.5,,,,,,,# | ||
| 26 | + // IWAPHP,83,119,80,,,,,,,,,,# | ||
| 27 | + // IWAPHP,,,,98,,,,,,,,,# | ||
| 28 | + //IW:标识符 | ||
| 29 | + //APHT : 命令字符 | ||
| 30 | + //60 : 表示心率 | ||
| 31 | + //130: 血压高压 [收缩压] | ||
| 32 | + //85 : 血压低压 [舒张压] | ||
| 33 | + //95:血氧 | ||
| 34 | + //90:血糖 | ||
| 35 | + //36.5: 体温 | ||
| 36 | + // ,分割 | ||
| 37 | + List<String> params = new ArrayList<>(); | ||
| 38 | + StringBuilder sb = new StringBuilder(); | ||
| 39 | + for (char ch : command.toCharArray()) { | ||
| 40 | + if (',' == ch) { | ||
| 41 | + params.add(sb.toString()); | ||
| 42 | + sb = new StringBuilder(); | ||
| 43 | + continue; | ||
| 44 | + } | ||
| 45 | + sb.append(ch); | ||
| 46 | + } | ||
| 47 | + HealthInfo health = new HealthInfo(); | ||
| 48 | + health.setCommandLabel(params.get(0)); | ||
| 49 | + health.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 50 | + log.info("设备:{},上传心率、血压、血氧、血糖命令:{}", health.getImei(), command); | ||
| 51 | + health.setHeartRate(params.get(1)); | ||
| 52 | + health.setHighPressure(params.get(2).length() != 0 ? Integer.parseInt(params.get(2)) : null); | ||
| 53 | + health.setLowPressure(params.get(3).length() != 0 ? Integer.parseInt(params.get(3)) : null); | ||
| 54 | + health.setBloodOxygen(params.get(4)); | ||
| 55 | + health.setBloodSugar(params.get(5)); | ||
| 56 | + health.setTemperature(params.get(6).length() != 0 ? Float.parseFloat(params.get(6)) : null); | ||
| 57 | + String response = ThinkraceUtil.RES.HEART_RATE_BLOOD_PRESSURE_OXYGEN_SUGAR_RES + ThinkraceUtil.END_SYMBOL; | ||
| 58 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 59 | + responseLog(health.getImei(), response); | ||
| 60 | + return null; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public CommandListen sendCommand(Object params) { | ||
| 65 | + return null; | ||
| 66 | + } | ||
| 67 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IHeartRatePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | + | ||
| 14 | +@Service(ThinkraceUtil.REQ.HEART_REQ) | ||
| 15 | +public class IHeartRatePacketAdapter extends ICommandAdapter { | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 19 | + // 格式:IWAP49,心率值# | ||
| 20 | + // 示例:IWAP49,68# | ||
| 21 | + HealthInfo rateInfo = new HealthInfo(); | ||
| 22 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 23 | + rateInfo.setCommandLabel(params[0]); | ||
| 24 | + rateInfo.setHeartRate(params[1]); | ||
| 25 | + rateInfo.setCreateTime(new Date()); | ||
| 26 | + rateInfo.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 27 | + log.info("设备:{},心率数据上传命令:{}", rateInfo.getImei(), command); | ||
| 28 | + // 返回响应 | ||
| 29 | + String response = ThinkraceUtil.RES.HEART_RES + ThinkraceUtil.END_SYMBOL; | ||
| 30 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 31 | + // 打印日志 | ||
| 32 | + responseLog(rateInfo.getImei(), response); | ||
| 33 | + return rateInfo; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public CommandListen sendCommand(Object params) { | ||
| 38 | + return null; | ||
| 39 | + } | ||
| 40 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IImagePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.ImageInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 7 | +import com.ruoyi.utils.PathToolUtil; | ||
| 8 | +import io.netty.buffer.Unpooled; | ||
| 9 | +import io.netty.channel.ChannelHandlerContext; | ||
| 10 | +import io.netty.util.AttributeKey; | ||
| 11 | +import io.netty.util.CharsetUtil; | ||
| 12 | +import org.springframework.beans.factory.annotation.Value; | ||
| 13 | +import org.springframework.stereotype.Service; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 设备图片指令 | ||
| 17 | + * | ||
| 18 | + * @author 20412 | ||
| 19 | + */ | ||
| 20 | +@Service(ThinkraceUtil.REQ.IMAGE_REQ) | ||
| 21 | +public class IImagePacketAdapter extends ICommandAdapter { | ||
| 22 | + | ||
| 23 | + @Value("${netty.socket.catalogue.image}") | ||
| 24 | + private String catalogue; | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 图片上行指令 | ||
| 29 | + * | ||
| 30 | + * @param command 指令 | ||
| 31 | + * @param ctx | ||
| 32 | + * @return | ||
| 33 | + */ | ||
| 34 | + @Override | ||
| 35 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 36 | + // TODO 记录表状态 给出耗时 给出当前上传进度 超时机制 重传机制 | ||
| 37 | + ImageInfo imageInfo = new ImageInfo(); | ||
| 38 | + imageInfo.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 39 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 40 | + String count = params[2]; | ||
| 41 | + String current = params[3]; | ||
| 42 | + log.info("设备:{},图片上传命令:{},共:{}个包,当前第:{}个包,字节数据:{}", imageInfo.getImei(), command, count, current, params[5]); | ||
| 43 | + boolean result = uploadImage(imageInfo.getImei(), params, ctx); | ||
| 44 | + // 响应示例 | ||
| 45 | + // IWBP42, 终端产生图片的时间+图片包总数+当前收到的包号+接收成功标志# | ||
| 46 | + // IWBP42,20140818064408,6,1,1# | ||
| 47 | + String response = ThinkraceUtil.RES.IMAGE_RES + "," + params[1] + "," + params[2] + "," + params[3] + "," + | ||
| 48 | + (result ? DeviceProperty.ImageProperty.UPLOAD_SUCCESS : DeviceProperty.ImageProperty.UPLOAD_FAIL) | ||
| 49 | + + ThinkraceUtil.END_SYMBOL; | ||
| 50 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 51 | + // TODO 更新写入日志 on key 可以使用mysql的key存在时更新操作把新的文件写入进去 | ||
| 52 | +// String count = params[2]; | ||
| 53 | + responseLog(imageInfo.getImei(), response); | ||
| 54 | + return imageInfo; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public CommandListen sendCommand(Object params) { | ||
| 59 | + return null; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + private boolean uploadImage(String imei, String[] params, ChannelHandlerContext ctx) { | ||
| 63 | + // IWAP42,终端产生图片的时间,图片包总数,当前包号,当前包长度,当前包图片数据# | ||
| 64 | + // IWAP42,20140818064408,6,1,1024,XXXXXXXXXXXXXXXXXXXXXXXXX# | ||
| 65 | + // 数据存入集合全部集齐后写入 | ||
| 66 | + String uploadTime = params[1]; | ||
| 67 | + // TODO 当前是否为第一个包 判断资源是否存在 | ||
| 68 | + String count = params[2]; | ||
| 69 | + String current = params[3]; | ||
| 70 | + String packetLength = params[4]; | ||
| 71 | + String data = params[5]; | ||
| 72 | + // TODO 写入数据库 | ||
| 73 | + // 追加数据包 | ||
| 74 | + boolean result = PathToolUtil.generateRelativeImagePath(catalogue, imei, uploadTime, data.getBytes()); | ||
| 75 | + return true; | ||
| 76 | + } | ||
| 77 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IKeepLivePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.KeepLiveInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.regex.Matcher; | ||
| 13 | +import java.util.regex.Pattern; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 心跳包处理 | ||
| 17 | + * | ||
| 18 | + * @author 20412 | ||
| 19 | + */ | ||
| 20 | +@Service(ThinkraceUtil.REQ.KEEPLIVE_REQ) | ||
| 21 | +public class IKeepLivePacketAdapter extends ICommandAdapter { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 25 | + KeepLiveInfo heart = handlerHeartPacket(command); | ||
| 26 | + heart.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 27 | + log.info("设备:{},心跳包:{}", heart.getImei(), command); | ||
| 28 | + // 返回响应 | ||
| 29 | + String response = ThinkraceUtil.RES.KEEPLIVE_RES + ThinkraceUtil.END_SYMBOL; | ||
| 30 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 31 | + return heart; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + private KeepLiveInfo handlerHeartPacket(String command) { | ||
| 35 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 36 | + KeepLiveInfo heart = new KeepLiveInfo(); | ||
| 37 | + heart.setCommandLabel(params[0]); | ||
| 38 | + // 处理指令 | ||
| 39 | + String regex = "([0-9]{3})([0-9]{3})([0-9]{3})([0-9]{1})([0-9]{2})([0-9]{2})"; | ||
| 40 | + Pattern pattern = Pattern.compile(regex); | ||
| 41 | + Matcher matcher = pattern.matcher(command); | ||
| 42 | + if (matcher.find()) { | ||
| 43 | + heart.setGsm(matcher.group(1)); | ||
| 44 | + heart.setSatelliteCount(matcher.group(2)); | ||
| 45 | + heart.setPower(matcher.group(3)); | ||
| 46 | + heart.setPlaceholder(matcher.group(4)); | ||
| 47 | + heart.setIsSafety(matcher.group(5)); | ||
| 48 | + heart.setIsWork(matcher.group(6)); | ||
| 49 | + } | ||
| 50 | + // TODO 判断是那种形式的心跳包 | ||
| 51 | + // IWAP03,06300706800008,0,00,8,600# | ||
| 52 | + // IWAP03,GSM信号值+定位卫星数+电池电量+保留位+设防状态+工作模式,计步数值,翻滚次数,工作模式,定位间隔# | ||
| 53 | + if (params.length == 6) { | ||
| 54 | + heart.setStep(params[2]); | ||
| 55 | + heart.setRollingCount(params[3]); | ||
| 56 | + heart.setGpsInterval(params[5]); | ||
| 57 | + } | ||
| 58 | + // IWAP03,06000908000102,5555,30# | ||
| 59 | + // IWAP03,GSM信号值+定位卫星数+电池电量+保留位+设防状态+工作模式,计步数,翻滚次数# | ||
| 60 | + else { | ||
| 61 | + heart.setStep(params[2]); | ||
| 62 | + heart.setRollingCount(params[3]); | ||
| 63 | + } | ||
| 64 | + return heart; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Override | ||
| 68 | + public CommandListen sendCommand(Object params) { | ||
| 69 | + return null; | ||
| 70 | + } | ||
| 71 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ILoginPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.entity.Device; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import com.ruoyi.utils.ConstDateUtil; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | +import java.util.regex.Matcher; | ||
| 14 | +import java.util.regex.Pattern; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * @author 20412 | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * 处理登录包 | ||
| 22 | + */ | ||
| 23 | +@Service(ThinkraceUtil.REQ.LOGIN_REQ) | ||
| 24 | +public class ILoginPacketAdapter extends ICommandAdapter { | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 29 | + Device device = getDeviceInfo(command); | ||
| 30 | + ThinkraceUtil.setDevice(device.getImei(), ctx); | ||
| 31 | + String response = ThinkraceUtil.RES.LOGIN_RES + "," + ConstDateUtil.formatDate("yyyyMMddHHmmss") + ThinkraceUtil.UTC_8 + ThinkraceUtil.END_SYMBOL; | ||
| 32 | + // 返回响应 | ||
| 33 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 34 | + responseLog(device.getImei(), response); | ||
| 35 | + return device; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * 返回响应 | ||
| 40 | + * | ||
| 41 | + * @return command 指令 | ||
| 42 | + */ | ||
| 43 | + @Override | ||
| 44 | + public CommandListen sendCommand(Object params) { | ||
| 45 | + return null; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + Device getDeviceInfo(String command) { | ||
| 50 | + String[] params = command.split(","); | ||
| 51 | + Device device = new Device(); | ||
| 52 | + device.setCreateTime(new Date()); | ||
| 53 | + String pattern = ThinkraceUtil.REQ.LOGIN_REQ + "([0-9]{15})"; | ||
| 54 | + Pattern regex = Pattern.compile(pattern); | ||
| 55 | + //格式IWAP00+IMEI# 或者 IWAP00+IMEI,MCC|MNC|APN名称# 或者 IWAP00+IMEI,ICCID,IMSI# | ||
| 56 | + if (params.length == 1) { | ||
| 57 | + Matcher matcher = regex.matcher(command); | ||
| 58 | + if (matcher.find()) { | ||
| 59 | + String imei = matcher.group(1); | ||
| 60 | + device.setImei(imei); | ||
| 61 | + } | ||
| 62 | + return device; | ||
| 63 | + } | ||
| 64 | + // 格式 IWAP00+IMEI,MCC|MNC|APN名称# | ||
| 65 | + else if (params.length == 2) { | ||
| 66 | + Matcher matcher = regex.matcher(params[0]); | ||
| 67 | + if (matcher.find()) { | ||
| 68 | + String imei = matcher.group(1); | ||
| 69 | + device.setImei(imei); | ||
| 70 | + } | ||
| 71 | + String[] mma = params[1].split("\\|"); | ||
| 72 | + device.setMcc(mma[0]); | ||
| 73 | + device.setMnc(mma[1]); | ||
| 74 | + device.setApn(mma[2].replace(ThinkraceUtil.END_SYMBOL, "")); | ||
| 75 | + return device; | ||
| 76 | + } | ||
| 77 | + // 格式 IWAP00+IMEI,ICCID,IMSI# | ||
| 78 | + else { | ||
| 79 | + Matcher matcher = regex.matcher(params[0]); | ||
| 80 | + if (matcher.find()) { | ||
| 81 | + String imei = matcher.group(1); | ||
| 82 | + device.setImei(imei); | ||
| 83 | + } | ||
| 84 | + device.setIccId(params[1]); | ||
| 85 | + device.setImsi(params[2].replace(ThinkraceUtil.END_SYMBOL, "")); | ||
| 86 | + return device; | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IMoreBaseGpsPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.GpsInfo; | ||
| 4 | +import com.ruoyi.system.domain.command.WifiInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.AttributeKey; | ||
| 10 | +import io.netty.util.CharsetUtil; | ||
| 11 | +import org.springframework.stereotype.Service; | ||
| 12 | + | ||
| 13 | +import java.util.ArrayList; | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 4. 多基站定位数据包 | ||
| 18 | + * | ||
| 19 | + * @author 20412 | ||
| 20 | + */ | ||
| 21 | +@Service(ThinkraceUtil.REQ.MORE_GPS_REQ) | ||
| 22 | +public class IMoreBaseGpsPacketAdapter extends ICommandAdapter { | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 26 | + GpsInfo mgi = new GpsInfo(); | ||
| 27 | + mgi.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 28 | + log.info("设备:{},基站定位数据包:{}", mgi.getImei(), command); | ||
| 29 | + // IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65# | ||
| 30 | + String sub = command.substring(0, command.length() - 1); | ||
| 31 | + String[] params = sub.split(","); | ||
| 32 | + mgi.setLanguageLabel(params[1]); | ||
| 33 | + // 回复标识:回复标识,为0时不回复地址,为 1 时,服务器回复地址信息(目前一定是0) | ||
| 34 | + mgi.setReplyLabel(params[2]); | ||
| 35 | + mgi.setBaseStationGroups(Integer.parseInt(params[3])); | ||
| 36 | + mgi.setMcc(params[4]); | ||
| 37 | + mgi.setMnc(params[5]); | ||
| 38 | + List<GpsInfo.BaseStation> bsList = new ArrayList<>(mgi.getBaseStationGroups()); | ||
| 39 | + mgi.setBaseStations(bsList); | ||
| 40 | + // 基站数据 | ||
| 41 | + for (int i = 0; i < mgi.getBaseStationGroups(); i++) { | ||
| 42 | + GpsInfo.BaseStation bs = new GpsInfo.BaseStation(); | ||
| 43 | + String baseParam = params[6 + i]; | ||
| 44 | + String[] param = baseParam.split("\\|"); | ||
| 45 | + bs.setLac(param[0]); | ||
| 46 | + bs.setCid(param[1]); | ||
| 47 | + bs.setDbm(param[2]); | ||
| 48 | + bsList.add(bs); | ||
| 49 | + } | ||
| 50 | + mgi.setWifiGroups(Integer.parseInt(params[6 + mgi.getBaseStationGroups()])); | ||
| 51 | + List<WifiInfo> wifiInfoList = new ArrayList<>(mgi.getWifiGroups()); | ||
| 52 | + mgi.setWifiInfoList(wifiInfoList); | ||
| 53 | + // WiFi数据 | ||
| 54 | + String baseParam = params[7 + mgi.getBaseStationGroups()]; | ||
| 55 | + String[] param = baseParam.split("&"); | ||
| 56 | + for (int i = 0; i < param.length; i++) { | ||
| 57 | + String[] baseWifi = param[i].split("\\|"); | ||
| 58 | + WifiInfo wi = new WifiInfo(); | ||
| 59 | + wi.setSsid(baseWifi[0]); | ||
| 60 | + wi.setMac(baseWifi[1]); | ||
| 61 | + wi.setSignal(baseWifi[2]); | ||
| 62 | + wifiInfoList.add(wi); | ||
| 63 | + } | ||
| 64 | + String response = ThinkraceUtil.RES.MORE_GPS_RES + ThinkraceUtil.END_SYMBOL; | ||
| 65 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 66 | + // 响应日志 | ||
| 67 | + responseLog(mgi.getImei(), response); | ||
| 68 | + return mgi; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @Override | ||
| 72 | + public CommandListen sendCommand(Object params) { | ||
| 73 | + return null; | ||
| 74 | + } | ||
| 75 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IPowerAlarmPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.PowerAlarm; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | +import java.util.regex.Matcher; | ||
| 14 | +import java.util.regex.Pattern; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 低电量报警上报 | ||
| 18 | + * | ||
| 19 | + * @author guzijian | ||
| 20 | + */ | ||
| 21 | +@Service(ThinkraceUtil.REQ.POWER_REQ) | ||
| 22 | +public class IPowerAlarmPacketAdapter extends ICommandAdapter { | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 26 | + // IWAP04+电池电量# | ||
| 27 | + // IWAP04075# | ||
| 28 | + PowerAlarm power = handlerPower(command, ctx); | ||
| 29 | + // 返回响应 | ||
| 30 | + String response = ThinkraceUtil.RES.POWER_RES + ThinkraceUtil.END_SYMBOL; | ||
| 31 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 32 | + return power; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + private PowerAlarm handlerPower(String command, ChannelHandlerContext ctx) { | ||
| 36 | + String regex = ThinkraceUtil.REQ.POWER_REQ + "(\\d+)"; | ||
| 37 | + Pattern pattern = Pattern.compile(regex); | ||
| 38 | + Matcher matcher = pattern.matcher(command); | ||
| 39 | + if (matcher.find()) { | ||
| 40 | + PowerAlarm pa = new PowerAlarm(); | ||
| 41 | + pa.setPower(matcher.group(1)); | ||
| 42 | + pa.setCreateTime(new Date()); | ||
| 43 | + pa.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).get().toString()); | ||
| 44 | + return pa; | ||
| 45 | + } | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + @Override | ||
| 50 | + public CommandListen sendCommand(Object params) { | ||
| 51 | + return null; | ||
| 52 | + } | ||
| 53 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IQueryBluetoothPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import io.netty.util.AttributeKey; | ||
| 8 | +import io.netty.util.CharsetUtil; | ||
| 9 | +import org.springframework.stereotype.Service; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 10 查询手表对应的蓝牙温度计SN | ||
| 13 | + * | ||
| 14 | + * @author 20412 | ||
| 15 | + */ | ||
| 16 | +@Service(ThinkraceUtil.REQ.QUERY_BLUETOOTH_REQ) | ||
| 17 | +public class IQueryBluetoothPacketAdapter extends ICommandAdapter { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 21 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 22 | + log.info("设备:{},查询手表对应的蓝牙温度计SN命令:{}", imei, command); | ||
| 23 | + // IWBP51,123456# | ||
| 24 | + String response = ThinkraceUtil.RES.QUERY_BLUETOOTH_RES + "," + 123456 + ThinkraceUtil.END_SYMBOL; | ||
| 25 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 26 | + responseLog(imei, response); | ||
| 27 | + return null; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public CommandListen sendCommand(Object params) { | ||
| 32 | + return null; | ||
| 33 | + } | ||
| 34 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ISpeechPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import io.netty.util.AttributeKey; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author 20412 | ||
| 11 | + */ | ||
| 12 | +@Service(ThinkraceUtil.REQ.SPEECH_REQ) | ||
| 13 | +@Deprecated | ||
| 14 | +public class ISpeechPacketAdapter extends ICommandAdapter { | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 18 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 19 | + log.info("设备:{},语音查询接收协议命令:{},未作处理。", imei, command); | ||
| 20 | + // TODO | ||
| 21 | + // 响应 IWBP05,6# | ||
| 22 | + String response = ThinkraceUtil.RES.SPEECH_RES + "," + 6 + ThinkraceUtil.END_SYMBOL; | ||
| 23 | + responseLog(imei, response); | ||
| 24 | + return null; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public CommandListen sendCommand(Object params) { | ||
| 29 | + return null; | ||
| 30 | + } | ||
| 31 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ISpeechUpPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 6 | +import com.ruoyi.utils.PathToolUtil; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.AttributeKey; | ||
| 10 | +import io.netty.util.CharsetUtil; | ||
| 11 | +import org.springframework.beans.factory.annotation.Value; | ||
| 12 | +import org.springframework.stereotype.Service; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 语音上行 | ||
| 16 | + * | ||
| 17 | + * @author 20412 | ||
| 18 | + */ | ||
| 19 | +@Service(ThinkraceUtil.REQ.SPEECH_UP_REQ) | ||
| 20 | +public class ISpeechUpPacketAdapter extends ICommandAdapter { | ||
| 21 | + | ||
| 22 | + @Value("${netty.socket.catalogue.speech}") | ||
| 23 | + private String catalogue; | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 28 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 29 | + // 传输的是字节流 需要处理字节流的数据 | ||
| 30 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 31 | + String count = params[2]; | ||
| 32 | + String current = params[3]; | ||
| 33 | + log.info("设备:{},图片上传命令:{},共:{}个包,当前第:{}个包,字节数据:{}", imei, command, count, current, params[5]); | ||
| 34 | + boolean result = uploadSpeech(imei, params, ctx); | ||
| 35 | + | ||
| 36 | + // 返回响应 IWBP07,20140818064408,6,1,1# | ||
| 37 | + String response = ThinkraceUtil.RES.SPEECH_UP_RES + "," + params[1] + "," + count + "," + current + "," + | ||
| 38 | + (result ? DeviceProperty.SpeechProperty.UPLOAD_SUCCESS : DeviceProperty.SpeechProperty.UPLOAD_FAIL) + ThinkraceUtil.END_SYMBOL; | ||
| 39 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 40 | + responseLog(imei, response); | ||
| 41 | + return null; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @Override | ||
| 45 | + public CommandListen sendCommand(Object params) { | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + private boolean uploadSpeech(String imei, String[] params, ChannelHandlerContext ctx) { | ||
| 50 | + // IWAP42,终端产生语音的时间,图片包总数,当前包号,当前包长度,当前包语音数据# | ||
| 51 | + // IWAP42,20140818064408,6,1,1024,XXXXXXXXXXXXXXXXXXXXXXXXX# | ||
| 52 | + // 数据存入集合全部集齐后写入 | ||
| 53 | + String uploadTime = params[1]; | ||
| 54 | + // TODO 当前是否为第一个包 判断资源是否存在 | ||
| 55 | + String count = params[2]; | ||
| 56 | + String current = params[3]; | ||
| 57 | + String packetLength = params[4]; | ||
| 58 | + String data = params[5]; | ||
| 59 | + // TODO 写入数据库 | ||
| 60 | + // 追加数据包 | ||
| 61 | + PathToolUtil.generateRelativeSpeechPath(catalogue, imei, uploadTime, data.getBytes()); | ||
| 62 | + return true; | ||
| 63 | + } | ||
| 64 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ISureReadTextPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 4 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import io.netty.util.AttributeKey; | ||
| 8 | +import io.netty.util.CharsetUtil; | ||
| 9 | +import org.springframework.stereotype.Service; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 确认已读文字 | ||
| 13 | + * | ||
| 14 | + * @author 20412 | ||
| 15 | + */ | ||
| 16 | +@Service(ThinkraceUtil.REQ.SURE_TEXT_REQ) | ||
| 17 | +public class ISureReadTextPacketAdapter extends ICommandAdapter { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 21 | + //TODO | ||
| 22 | + // IWAP94,123456,1# | ||
| 23 | + // IWAP94:标识符 | ||
| 24 | + // APHCI: 命令字符 | ||
| 25 | + // 123456: 文字来源系统流水号 | ||
| 26 | + // 1:确认阅读、0:取消阅读 | ||
| 27 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 28 | + log.info("设备:{},确认已读文字命令:{},未作处理。", imei, command); | ||
| 29 | + String response = ThinkraceUtil.RES.SURE_TEXT_RES + ThinkraceUtil.END_SYMBOL; | ||
| 30 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 31 | + responseLog(imei, response); | ||
| 32 | + return null; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public CommandListen sendCommand(Object params) { | ||
| 37 | + return null; | ||
| 38 | + } | ||
| 39 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ISyncWeatherPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.JSONObject; | ||
| 4 | +import com.ruoyi.system.domain.response.WeatherResponse; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import com.ruoyi.utils.ConstDateUtil; | ||
| 8 | +import com.ruoyi.utils.IUnicodeUtils; | ||
| 9 | +import io.netty.buffer.Unpooled; | ||
| 10 | +import io.netty.channel.ChannelHandlerContext; | ||
| 11 | +import io.netty.util.AttributeKey; | ||
| 12 | +import io.netty.util.CharsetUtil; | ||
| 13 | +import org.springframework.stereotype.Service; | ||
| 14 | + | ||
| 15 | +import java.io.*; | ||
| 16 | +import java.net.HttpURLConnection; | ||
| 17 | +import java.net.URL; | ||
| 18 | +import java.util.Comparator; | ||
| 19 | +import java.util.List; | ||
| 20 | +import java.util.zip.GZIPInputStream; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * 同步天气 | ||
| 24 | + * | ||
| 25 | + * @author 20412 | ||
| 26 | + */ | ||
| 27 | +@Service(ThinkraceUtil.REQ.WEATHER_REQ) | ||
| 28 | +public class ISyncWeatherPacketAdapter extends ICommandAdapter { | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 32 | + String imei = ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString(); | ||
| 33 | + log.info("设备:{},同步天气指令:{}", imei, command); | ||
| 34 | + // 三天api https://devapi.qweather.com/v7/weather/3d?{查询参数} | ||
| 35 | + // 天气api请求示例 'https://devapi.qweather.com/v7/weather/3d?location=116.41,39.92&key=9ee551aeac884cca8c68d70086708b44' | ||
| 36 | + // TODO 后续完善 没有获取设备位置 | ||
| 37 | + // 先从表中获取当前设备位置 获取指定位置的天气 响应示例 unicode | ||
| 38 | + String location = "116.41,39.92"; | ||
| 39 | + WeatherResponse weather = getWeather(location); | ||
| 40 | + // IWBPWT, 深圳, 2018-12-24 16:45:5, 2018-12-25,1, 3,1,晴, 2018-12-26, -1,4,2, 阴, 2018-12-27,3,7, 3,小雨# | ||
| 41 | + // IWBPWT, 6df15733, 2018-12-24 16:45:5, 2018-12-25,1, 3, 1, 6674, 2018-12-26, -1,4, 2,9634, 2018-12-27,3,7, 3, 5c0f96e8# | ||
| 42 | + String weatherStr = transString("深圳", weather); | ||
| 43 | + String response = ThinkraceUtil.RES.WEATHER_RES + weatherStr; | ||
| 44 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 45 | + responseLog(imei, response); | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + private String transString(String localName, WeatherResponse weather) { | ||
| 50 | + StringBuilder sb = new StringBuilder(); | ||
| 51 | + List<WeatherResponse.Daily> daily = weather.getDaily(); | ||
| 52 | + sb.append(",").append(IUnicodeUtils.toUnicode(localName)); | ||
| 53 | + sb.append(",").append(ConstDateUtil.formatDate("yyyy-MM-dd HH:mm:ss")); | ||
| 54 | + sb.append(",").append(daily.get(0).getFxDate()); | ||
| 55 | + sb.append(",").append(daily.get(0).getTempMin()); | ||
| 56 | + sb.append(",").append(daily.get(0).getTempMax()); | ||
| 57 | + sb.append(",").append(enumTrans(daily.get(0).getTextDay())); | ||
| 58 | + sb.append(",").append(IUnicodeUtils.toUnicode(daily.get(0).getTextDay())); | ||
| 59 | + | ||
| 60 | + sb.append(",").append(daily.get(1).getFxDate()); | ||
| 61 | + sb.append(",").append(daily.get(1).getTempMin()); | ||
| 62 | + sb.append(",").append(daily.get(1).getTempMax()); | ||
| 63 | + sb.append(",").append(enumTrans(daily.get(1).getTextDay())); | ||
| 64 | + sb.append(",").append(IUnicodeUtils.toUnicode(daily.get(1).getTextDay())); | ||
| 65 | + | ||
| 66 | + sb.append(",").append(daily.get(2).getFxDate()); | ||
| 67 | + sb.append(",").append(daily.get(2).getTempMin()); | ||
| 68 | + sb.append(",").append(daily.get(2).getTempMax()); | ||
| 69 | + sb.append(",").append(enumTrans(daily.get(2).getTextDay())); | ||
| 70 | + sb.append(",").append(IUnicodeUtils.toUnicode(daily.get(2).getTextDay())); | ||
| 71 | + | ||
| 72 | + sb.append(ThinkraceUtil.END_SYMBOL); | ||
| 73 | + return sb.toString(); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + private String enumTrans(String str) { | ||
| 77 | + switch (str) { | ||
| 78 | + case "晴": | ||
| 79 | + return "1"; | ||
| 80 | + case "多云": | ||
| 81 | + case "阴": | ||
| 82 | + return "2"; | ||
| 83 | + case "雨": | ||
| 84 | + return "3"; | ||
| 85 | + case "雪": | ||
| 86 | + return "4"; | ||
| 87 | + default: | ||
| 88 | + return "5"; | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + private WeatherResponse getWeather(String location) { | ||
| 93 | + WeatherResponse weather = null; | ||
| 94 | + try { | ||
| 95 | + String url = "https://devapi.qweather.com/v7/weather/3d?location=" + location + "&key=9ee551aeac884cca8c68d70086708b44"; | ||
| 96 | + weather = JSONObject.parseObject(sendGetRequest(url), WeatherResponse.class); | ||
| 97 | + weather.getDaily().sort(Comparator.comparing(WeatherResponse.Daily::getFxDate)); | ||
| 98 | + } catch (Exception e) { | ||
| 99 | + log.info(e.getMessage()); | ||
| 100 | + } | ||
| 101 | + return weather; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + // 发送GET请求并获取响应数据(包括Gzip解压缩) | ||
| 105 | + private static String sendGetRequest(String url) throws IOException { | ||
| 106 | + HttpURLConnection connection = null; | ||
| 107 | + try { | ||
| 108 | + URL requestUrl = new URL(url); | ||
| 109 | + connection = (HttpURLConnection) requestUrl.openConnection(); | ||
| 110 | + connection.setRequestMethod("GET"); | ||
| 111 | + // 请求Gzip压缩 | ||
| 112 | + connection.setRequestProperty("Accept-Encoding", "gzip"); | ||
| 113 | + | ||
| 114 | + int responseCode = connection.getResponseCode(); | ||
| 115 | + if (responseCode == HttpURLConnection.HTTP_OK) { | ||
| 116 | + InputStream inputStream = connection.getInputStream(); | ||
| 117 | + String contentEncoding = connection.getContentEncoding(); | ||
| 118 | + | ||
| 119 | + if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { | ||
| 120 | + inputStream = new GZIPInputStream(inputStream); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); | ||
| 124 | + StringBuilder response = new StringBuilder(); | ||
| 125 | + String line; | ||
| 126 | + while ((line = reader.readLine()) != null) { | ||
| 127 | + response.append(line); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + reader.close(); | ||
| 131 | + return response.toString(); | ||
| 132 | + } else { | ||
| 133 | + throw new IOException("GET request failed with response code: " + responseCode); | ||
| 134 | + } | ||
| 135 | + } finally { | ||
| 136 | + if (connection != null) { | ||
| 137 | + connection.disconnect(); | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + // 解压缩Gzip数据 | ||
| 143 | + private static byte[] decompressGzip(byte[] compressedData) throws IOException { | ||
| 144 | + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(compressedData); | ||
| 145 | + GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream); | ||
| 146 | + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | ||
| 147 | + | ||
| 148 | + byte[] buffer = new byte[1024]; | ||
| 149 | + int len; | ||
| 150 | + while ((len = gzipInputStream.read(buffer)) > 0) { | ||
| 151 | + byteArrayOutputStream.write(buffer, 0, len); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + gzipInputStream.close(); | ||
| 155 | + byteArrayOutputStream.close(); | ||
| 156 | + | ||
| 157 | + return byteArrayOutputStream.toByteArray(); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + @Override | ||
| 161 | + public CommandListen sendCommand(Object params) { | ||
| 162 | + return null; | ||
| 163 | + } | ||
| 164 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ITemperature50PacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 9 温度数据上传 | ||
| 14 | + * | ||
| 15 | + * @author 20412 | ||
| 16 | + */ | ||
| 17 | +@Service(ThinkraceUtil.REQ.TEMPERATURE_50_REQ) | ||
| 18 | +public class ITemperature50PacketAdapter extends ICommandAdapter { | ||
| 19 | + | ||
| 20 | + @Override | ||
| 21 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 22 | + // IWAP50,36.7,90# | ||
| 23 | + String sub = command.substring(0, command.length() - 1); | ||
| 24 | + String[] params = sub.split(","); | ||
| 25 | + HealthInfo hi = new HealthInfo(); | ||
| 26 | + hi.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 27 | + log.info("设备:{},温度数据上传命令:{}", hi.getImei(), command); | ||
| 28 | + hi.setTemperature(Float.parseFloat(params[1])); | ||
| 29 | + hi.setPower(params[2]); | ||
| 30 | + // IWBP50# | ||
| 31 | + String response = ThinkraceUtil.RES.TEMPERATURE_50_RES + ThinkraceUtil.END_SYMBOL; | ||
| 32 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 33 | + responseLog(hi.getImei(), response); | ||
| 34 | + return hi; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public CommandListen sendCommand(Object params) { | ||
| 39 | + return null; | ||
| 40 | + } | ||
| 41 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/ITemperaturePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import com.ruoyi.system.protocol.property.DeviceProperty; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.AttributeKey; | ||
| 10 | +import io.netty.util.CharsetUtil; | ||
| 11 | +import org.springframework.stereotype.Service; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 上报体温 | ||
| 15 | + * | ||
| 16 | + * @author 20412 | ||
| 17 | + */ | ||
| 18 | +@Service(ThinkraceUtil.REQ.TEMPERATURE_REQ) | ||
| 19 | +public class ITemperaturePacketAdapter extends ICommandAdapter { | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 23 | + // 格式:IWAPTP,体温,腕温# | ||
| 24 | + // 示例:IWAPTP,36.0,33,0# | ||
| 25 | + String[] params = command.split(","); | ||
| 26 | + HealthInfo health = new HealthInfo(); | ||
| 27 | + health.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 28 | + log.info("设备:{},上报体温命令:{}", health.getImei(), command); | ||
| 29 | + health.setHealthType(DeviceProperty.HealthProperty.TEMPERATURE); | ||
| 30 | + health.setCommandLabel(params[0]); | ||
| 31 | + health.setTemperature(Float.parseFloat(params[1])); | ||
| 32 | + health.setHandTemperature(params[2].replace(ThinkraceUtil.END_SYMBOL, "")); | ||
| 33 | + // 返回响应 | ||
| 34 | + String response = ThinkraceUtil.RES.TEMPERATURE_RES + ThinkraceUtil.END_SYMBOL; | ||
| 35 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 36 | + responseLog(health.getImei(), response); | ||
| 37 | + return health; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public CommandListen sendCommand(Object params) { | ||
| 42 | + return null; | ||
| 43 | + } | ||
| 44 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IUploadBluetoothAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.Bluetooth; | ||
| 4 | +import com.ruoyi.system.domain.command.BluetoothInfo; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import io.netty.buffer.Unpooled; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.ArrayList; | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * @author 20412 | ||
| 17 | + */ | ||
| 18 | +@Service(ThinkraceUtil.REQ.BLUETOOTH_REQ) | ||
| 19 | +public class IUploadBluetoothAdapter extends ICommandAdapter { | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 24 | + // 格式:IWAPBL,IMEI,周围的蓝牙参数,终端自身MAC地址,时间戳# | ||
| 25 | + // 示例:IWAPBL,355932600029362,TraxBean064|BF:0C:B8:3F:2F:37|-30&VG05|F0:49:32:83:F9:9E|-52,28:05:31:16:02:04,1711512576683# | ||
| 26 | + String[] params = command.split(","); | ||
| 27 | + BluetoothInfo bluetooth = new BluetoothInfo(); | ||
| 28 | + bluetooth.setImei(params[1]); | ||
| 29 | + bluetooth.setMac(params[3]); | ||
| 30 | + bluetooth.setTimestamp(params[4].replace(ThinkraceUtil.END_SYMBOL, "")); | ||
| 31 | + String[] btInfo = params[2].split("&"); | ||
| 32 | + List<Bluetooth> bluetoothList = new ArrayList<>(btInfo.length); | ||
| 33 | + for (String bti : btInfo) { | ||
| 34 | + String[] bts = bti.split("\\|"); | ||
| 35 | + Bluetooth bt = new Bluetooth(bts[0], bts[1], bts[2]); | ||
| 36 | + bluetoothList.add(bt); | ||
| 37 | + } | ||
| 38 | + bluetooth.setBluetoothList(bluetoothList); | ||
| 39 | + // TODO 信息入表 | ||
| 40 | + // 返回响应 | ||
| 41 | + // IWBPBL# | ||
| 42 | + String response = ThinkraceUtil.RES.BLUETOOTH_RES + ThinkraceUtil.END_SYMBOL; | ||
| 43 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 44 | + responseLog(bluetooth.getImei(), response); | ||
| 45 | + return null; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Override | ||
| 49 | + public CommandListen sendCommand(Object params) { | ||
| 50 | + return null; | ||
| 51 | + } | ||
| 52 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IUploadDeviceVersionPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.entity.Device; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 设备上传固件版本 | ||
| 11 | + * | ||
| 12 | + * @author 20412 | ||
| 13 | + */ | ||
| 14 | +@Service(ThinkraceUtil.REQ.VERSION_REQ) | ||
| 15 | +public class IUploadDeviceVersionPacketAdapter extends ICommandAdapter { | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + @Override | ||
| 19 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 20 | + // 格式:IWAPVR,IMEI,固件版本号# | ||
| 21 | + // 示例:IWAPVR,357653050858997,C42F-l005l005-EU-P1-V0.3.38.20210906.182655# | ||
| 22 | + String[] params = command.split(","); | ||
| 23 | + Device device = new Device(); | ||
| 24 | + device.setImei(params[1]); | ||
| 25 | + device.setVersion(params[2].replace(ThinkraceUtil.END_SYMBOL, "")); | ||
| 26 | + // 无需响应 | ||
| 27 | + return null; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public CommandListen sendCommand(Object params) { | ||
| 32 | + return null; | ||
| 33 | + } | ||
| 34 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IUploadHeartRateBloodOxygenPacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.HealthInfo; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.util.AttributeKey; | ||
| 9 | +import io.netty.util.CharsetUtil; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 处理血样血压 | ||
| 16 | + * | ||
| 17 | + * @author 20412 | ||
| 18 | + */ | ||
| 19 | +@Service(ThinkraceUtil.REQ.HEART_BLOOD_REQ) | ||
| 20 | +public class IUploadHeartRateBloodOxygenPacketAdapter extends ICommandAdapter { | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 25 | + // 格式:IWAPHT,心率值,收缩压值,舒张压值# | ||
| 26 | + // 示例:IWAPHT,60,130,85# | ||
| 27 | + String[] params = command.substring(0, command.length() - 1).split(","); | ||
| 28 | + HealthInfo info = new HealthInfo(); | ||
| 29 | + info.setImei(ctx.channel().attr(AttributeKey.valueOf(ThinkraceUtil.IMEI)).toString()); | ||
| 30 | + info.setCommandLabel(params[0]); | ||
| 31 | + info.setHeartRate(params[1]); | ||
| 32 | + info.setHighPressure(Integer.parseInt(params[2])); | ||
| 33 | + // 去掉结束符 | ||
| 34 | + info.setLowPressure(Integer.parseInt(params[3])); | ||
| 35 | + info.setCreateTime(new Date()); | ||
| 36 | + // TODO 记录表 info | ||
| 37 | + // 返回响应 | ||
| 38 | + // IWBPHT# | ||
| 39 | + String response = ThinkraceUtil.RES.HEART_BLOOD_RES + ThinkraceUtil.END_SYMBOL; | ||
| 40 | + ctx.channel().writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8)); | ||
| 41 | + responseLog(info.getImei(), response); | ||
| 42 | + return info; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Override | ||
| 46 | + public CommandListen sendCommand(Object params) { | ||
| 47 | + return null; | ||
| 48 | + } | ||
| 49 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/adapter/device/IWearingStatePacketAdapter.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.adapter.device; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.domain.command.WearingState; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import org.springframework.stereotype.Service; | ||
| 8 | +import java.util.Date; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 佩戴状态 | ||
| 12 | + * | ||
| 13 | + * @author 20412 | ||
| 14 | + */ | ||
| 15 | +@Service(ThinkraceUtil.REQ.WEARING_REQ) | ||
| 16 | +public class IWearingStatePacketAdapter extends ICommandAdapter { | ||
| 17 | + | ||
| 18 | + @Override | ||
| 19 | + public Object resolveCommand(String command, ChannelHandlerContext ctx) { | ||
| 20 | + // 格式:IWAPWR, IMEI,佩戴标志位,时间戳# | ||
| 21 | + // 示例:IWAPVR,357653050858997,1,xxxxxx# | ||
| 22 | + String[] params = command.split(","); | ||
| 23 | + WearingState ws = new WearingState(); | ||
| 24 | + ws.setImei(params[1]); | ||
| 25 | + ws.setState(params[2]); | ||
| 26 | + ws.setTimestamp(Long.parseLong(params[3].replace(ThinkraceUtil.END_SYMBOL, ""))); | ||
| 27 | + ws.setCreateTime(new Date()); | ||
| 28 | + // TODO 入表 | ||
| 29 | + // 无需响应 | ||
| 30 | + return null; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public CommandListen sendCommand(Object params) { | ||
| 35 | + return null; | ||
| 36 | + } | ||
| 37 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/protocol/property/DeviceProperty.java
0 → 100644
| 1 | +package com.ruoyi.system.protocol.property; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 设备配置 | ||
| 5 | + * @author 20412 | ||
| 6 | + */ | ||
| 7 | +public class DeviceProperty { | ||
| 8 | + public static class RedisProperty { | ||
| 9 | + public static String UPLOAD_IMAGE_PRE = "device:image:upload:"; | ||
| 10 | + } | ||
| 11 | + | ||
| 12 | + public static class ImageProperty { | ||
| 13 | + public static final String UPLOAD_SUCCESS = "1"; | ||
| 14 | + public static final String UPLOAD_FAIL = "0"; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + public static class SpeechProperty { | ||
| 18 | + public static final String UPLOAD_SUCCESS = "1"; | ||
| 19 | + public static final String UPLOAD_FAIL = "0"; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + public static class AddressProperty { | ||
| 23 | + public static final String VALID = "A"; | ||
| 24 | + public static final String INVALID = "V"; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + public static class HealthProperty { | ||
| 30 | + /** 血压 */ | ||
| 31 | + public static final String BLOOD_PRESSURE = "1"; | ||
| 32 | + /** 心率*/ | ||
| 33 | + public static final String HEART_RATE = "2"; | ||
| 34 | + /** 体温 */ | ||
| 35 | + public static final String TEMPERATURE = "3"; | ||
| 36 | + /** 血氧 */ | ||
| 37 | + public static final String BLOOD_OXYGEN = "4"; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public static class WearingState { | ||
| 41 | + /** 血压 */ | ||
| 42 | + public static final String HAND = "1"; | ||
| 43 | + /** 血压 */ | ||
| 44 | + public static final String NOT = "0"; | ||
| 45 | + } | ||
| 46 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/server/SocketServer.java
0 → 100644
| 1 | +package com.ruoyi.system.server; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.core.redis.RedisCache; | ||
| 4 | +import com.ruoyi.system.handler.SocketServerHandler; | ||
| 5 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 6 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 7 | +import io.netty.bootstrap.ServerBootstrap; | ||
| 8 | +import io.netty.channel.ChannelFuture; | ||
| 9 | +import io.netty.channel.ChannelInitializer; | ||
| 10 | +import io.netty.channel.ChannelOption; | ||
| 11 | +import io.netty.channel.EventLoopGroup; | ||
| 12 | +import io.netty.channel.nio.NioEventLoopGroup; | ||
| 13 | +import io.netty.channel.socket.SocketChannel; | ||
| 14 | +import io.netty.channel.socket.nio.NioServerSocketChannel; | ||
| 15 | +import org.slf4j.Logger; | ||
| 16 | +import org.slf4j.LoggerFactory; | ||
| 17 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 18 | +import org.springframework.beans.factory.annotation.Value; | ||
| 19 | +import org.springframework.boot.CommandLineRunner; | ||
| 20 | +import org.springframework.context.ApplicationContext; | ||
| 21 | +import org.springframework.stereotype.Component; | ||
| 22 | + | ||
| 23 | +import javax.annotation.PreDestroy; | ||
| 24 | +import java.util.Map; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * @author 20412 | ||
| 28 | + */ | ||
| 29 | +@Component | ||
| 30 | +public class SocketServer implements CommandLineRunner { | ||
| 31 | + @Autowired | ||
| 32 | + private ApplicationContext applicationContext; | ||
| 33 | + | ||
| 34 | + @Autowired | ||
| 35 | + private RedisCache redisCache; | ||
| 36 | + | ||
| 37 | + private static final Logger log = LoggerFactory.getLogger(SocketServer.class); | ||
| 38 | + EventLoopGroup bossGroup = null; | ||
| 39 | + EventLoopGroup workerGroup = null; | ||
| 40 | + @Value("${netty.socket.port:8989}") | ||
| 41 | + private Integer port; | ||
| 42 | + | ||
| 43 | + @Value("${netty.enabled:false}") | ||
| 44 | + private Boolean enabled; | ||
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public void run(String... args) throws Exception { | ||
| 48 | + if (enabled) { | ||
| 49 | + // 创建一个线程启动netty 这个CommandLineRunner 接口在主服务基本启动完后会调用使用的是主线程 netty启动会占用线程一直监听端口 | ||
| 50 | + Thread thread = new Thread(new NettyServer()); | ||
| 51 | + log.info("netty server active..."); | ||
| 52 | + thread.start(); | ||
| 53 | + // 初始化命令适配器 | ||
| 54 | + log.info("command adapter init..."); | ||
| 55 | + initCommandAdapter(); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + private void initCommandAdapter() { | ||
| 60 | + // 把所有适配器注入到工具类中管理 | ||
| 61 | + Map<String, ICommandAdapter> implementations = applicationContext.getBeansOfType(ICommandAdapter.class); | ||
| 62 | + for (Map.Entry<String, ICommandAdapter> entry : implementations.entrySet()) { | ||
| 63 | + ThinkraceUtil.addAdapter(entry.getKey(), entry.getValue()); | ||
| 64 | + } | ||
| 65 | + ThinkraceUtil.initRedisThinkraceCommandParam(redisCache); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * 销毁方法 | ||
| 70 | + * | ||
| 71 | + * @throws Exception | ||
| 72 | + */ | ||
| 73 | + @PreDestroy | ||
| 74 | + public void destroy() throws Exception { | ||
| 75 | + if (bossGroup != null) { | ||
| 76 | + bossGroup.shutdownGracefully(); | ||
| 77 | + } | ||
| 78 | + if (workerGroup != null) { | ||
| 79 | + workerGroup.shutdownGracefully(); | ||
| 80 | + } | ||
| 81 | + log.info("netty server destroy..."); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + class NettyServer implements Runnable { | ||
| 85 | + @Override | ||
| 86 | + public void run() { | ||
| 87 | + try { | ||
| 88 | + bossGroup = new NioEventLoopGroup(); | ||
| 89 | + workerGroup = new NioEventLoopGroup(); | ||
| 90 | + //创建服务端的启动对象,设置参数 | ||
| 91 | + ServerBootstrap bootstrap = new ServerBootstrap(); | ||
| 92 | + //设置两个线程组boosGroup和workerGroup | ||
| 93 | + bootstrap.group(bossGroup, workerGroup) | ||
| 94 | + //设置服务端通道实现类型 | ||
| 95 | + .channel(NioServerSocketChannel.class) | ||
| 96 | + //设置线程队列得到连接个数 | ||
| 97 | + .option(ChannelOption.SO_BACKLOG, 128) | ||
| 98 | + //设置保持活动连接状态 | ||
| 99 | + .childOption(ChannelOption.SO_KEEPALIVE, true) | ||
| 100 | + //使用匿名内部类的形式初始化通道对象 | ||
| 101 | + .childHandler(new ChannelInitializer<SocketChannel>() { | ||
| 102 | + @Override | ||
| 103 | + protected void initChannel(SocketChannel socketChannel) throws Exception { | ||
| 104 | + //给pipeline管道设置处理器 | ||
| 105 | + socketChannel.pipeline().addLast(new SocketServerHandler()); | ||
| 106 | + } | ||
| 107 | + });//给workerGroup的EventLoop对应的管道设置处理器 | ||
| 108 | + //绑定端口号,启动服务端 | ||
| 109 | + ChannelFuture channelFuture = bootstrap.bind(port).sync(); | ||
| 110 | + //对关闭通道进行监听 | ||
| 111 | + channelFuture.channel().closeFuture().sync(); | ||
| 112 | + } catch (InterruptedException e) { | ||
| 113 | + log.error("SocketServer at line 71:" + e.getMessage()); | ||
| 114 | + } | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/service/IDeviceService.java
0 → 100644
| 1 | +package com.ruoyi.system.service; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.extension.service.IService; | ||
| 4 | +import com.ruoyi.common.global.Result; | ||
| 5 | +import com.ruoyi.system.domain.active.Sos; | ||
| 6 | +import com.ruoyi.system.domain.active.UploadGpsTime; | ||
| 7 | +import com.ruoyi.system.domain.active.WhiteListPeople; | ||
| 8 | +import com.ruoyi.system.domain.entity.Device; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * deviceService接口 | ||
| 12 | + * | ||
| 13 | + * @author bsth | ||
| 14 | + * @date 2024-04-17 | ||
| 15 | + */ | ||
| 16 | +public interface IDeviceService extends IService<Device> | ||
| 17 | +{ | ||
| 18 | + | ||
| 19 | + Result<?> settingSos(Sos sos); | ||
| 20 | + | ||
| 21 | + Result<?> settingWhiteList(WhiteListPeople wlp); | ||
| 22 | + | ||
| 23 | + Result<?> settingGpsUploadTime(UploadGpsTime ugt); | ||
| 24 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/service/ITimedTaskService.java
0 → 100644
Bsth-admin/src/main/java/com/ruoyi/system/service/impl/DeviceServiceImpl.java
0 → 100644
| 1 | +package com.ruoyi.system.service.impl; | ||
| 2 | +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||
| 3 | + | ||
| 4 | +import com.ruoyi.common.global.Result; | ||
| 5 | +import com.ruoyi.system.domain.active.Sos; | ||
| 6 | +import com.ruoyi.system.domain.active.UploadGpsTime; | ||
| 7 | +import com.ruoyi.system.domain.active.WhiteListPeople; | ||
| 8 | +import com.ruoyi.system.domain.entity.Device; | ||
| 9 | +import com.ruoyi.system.mapper.DeviceMapper; | ||
| 10 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 11 | +import com.ruoyi.system.service.IDeviceService; | ||
| 12 | +import org.springframework.stereotype.Service; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * deviceService业务层处理 | ||
| 16 | + * | ||
| 17 | + * @author bsth | ||
| 18 | + * @date 2024-04-17 | ||
| 19 | + */ | ||
| 20 | +@Service | ||
| 21 | +public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService | ||
| 22 | +{ | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public Result<?> settingSos(Sos sos) { | ||
| 27 | + boolean result = ThinkraceUtil | ||
| 28 | + .getAdapter(ThinkraceUtil.ACTIVE.SOS_ACTIVE) | ||
| 29 | + .sendCommand(sos) | ||
| 30 | + .listenAsk(); | ||
| 31 | + return Result.OK((result ? "设备成功响应" :"设备无响应")); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + public Result<?> settingWhiteList(WhiteListPeople wlp) { | ||
| 36 | + boolean result = ThinkraceUtil | ||
| 37 | + .getAdapter(ThinkraceUtil.ACTIVE.CONTACT_ACTIVE) | ||
| 38 | + .sendCommand(wlp) | ||
| 39 | + .listenAsk(); | ||
| 40 | + return Result.OK((result ? "设备成功响应" :"设备无响应")); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public Result<?> settingGpsUploadTime(UploadGpsTime ugt) { | ||
| 45 | + boolean result = ThinkraceUtil | ||
| 46 | + .getAdapter(ThinkraceUtil.ACTIVE.UPLOAD_GPS_TIME_ACTIVE) | ||
| 47 | + .sendCommand(ugt) | ||
| 48 | + .listenAsk(); | ||
| 49 | + return Result.OK((result ? "设备成功响应" :"设备无响应")); | ||
| 50 | + } | ||
| 51 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/service/impl/ITimedTaskServiceImpl.java
0 → 100644
| 1 | +package com.ruoyi.system.service.impl; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.system.service.ITimedTaskService; | ||
| 4 | +import lombok.extern.slf4j.Slf4j; | ||
| 5 | +import org.springframework.stereotype.Service; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * @author 20412 | ||
| 9 | + */ | ||
| 10 | +@Service | ||
| 11 | +@Slf4j | ||
| 12 | +public class ITimedTaskServiceImpl implements ITimedTaskService { | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +} |
Bsth-admin/src/main/java/com/ruoyi/system/strategy/CommandStrategy.java
0 → 100644
| 1 | +package com.ruoyi.system.strategy; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.utils.StringUtils; | ||
| 4 | +import com.ruoyi.system.protocol.ThinkraceUtil; | ||
| 5 | +import com.ruoyi.system.protocol.adapter.ICommandAdapter; | ||
| 6 | +import io.netty.channel.ChannelHandlerContext; | ||
| 7 | +import org.slf4j.Logger; | ||
| 8 | +import org.slf4j.LoggerFactory; | ||
| 9 | + | ||
| 10 | +import static com.ruoyi.system.protocol.ThinkraceUtil.REQ.LOGIN_REQ; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 命令观察者模式 | ||
| 14 | + * | ||
| 15 | + * @author 20412 | ||
| 16 | + */ | ||
| 17 | +public class CommandStrategy { | ||
| 18 | + private static final Logger log = LoggerFactory.getLogger(CommandStrategy.class); | ||
| 19 | + | ||
| 20 | + public CommandStrategy() { | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + public void handler(String command, ChannelHandlerContext ctx) { | ||
| 24 | + processor(command, ctx); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + private void processor(String command, ChannelHandlerContext ctx) { | ||
| 28 | + if (StringUtils.isNotEmpty(command) && command.length() > 6) { | ||
| 29 | + String key = command.substring(0, 6); | ||
| 30 | + // 未上传登录包无法使用对应指令 | ||
| 31 | + ICommandAdapter adapter = ThinkraceUtil.getAdapter(key); | ||
| 32 | + if (filterCommand(key, ctx) && adapter != null) { | ||
| 33 | + adapter.resolveCommand(command, ctx); | ||
| 34 | + return; | ||
| 35 | + } | ||
| 36 | + log.error("设备传来未知指令:{}", command); | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + private boolean filterCommand(String key, ChannelHandlerContext ctx) { | ||
| 41 | + return LOGIN_REQ.equals(key) || ThinkraceUtil.hasDevice(ctx.channel()); | ||
| 42 | + } | ||
| 43 | +} |
Bsth-admin/src/main/java/com/ruoyi/utils/ConstDateUtil.java
| @@ -46,6 +46,11 @@ public class ConstDateUtil { | @@ -46,6 +46,11 @@ public class ConstDateUtil { | ||
| 46 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); | 46 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); |
| 47 | return simpleDateFormat.format(new Date()); | 47 | return simpleDateFormat.format(new Date()); |
| 48 | } | 48 | } |
| 49 | + public static String formatDate(String pattern,ZoneOffset utc){ | ||
| 50 | + LocalDateTime currentTime = LocalDateTime.now(utc); | ||
| 51 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); | ||
| 52 | + return formatter.format(currentTime); | ||
| 53 | + } | ||
| 49 | 54 | ||
| 50 | public static Date parseDate(String date){ | 55 | public static Date parseDate(String date){ |
| 51 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | 56 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
Bsth-admin/src/main/java/com/ruoyi/utils/IUnicodeUtils.java
0 → 100644
| 1 | +package com.ruoyi.utils; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.StringUtils; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * @author 20412 | ||
| 7 | + */ | ||
| 8 | +public class IUnicodeUtils { | ||
| 9 | + | ||
| 10 | + /** | ||
| 11 | + * @param str content | ||
| 12 | + * @return unicode | ||
| 13 | + */ | ||
| 14 | + public static String toUnicode(String str) { | ||
| 15 | + StringBuilder outStr = new StringBuilder(); | ||
| 16 | + if (StringUtils.isNotEmpty(str)) { | ||
| 17 | + for (int i = 0; i < str.length(); i++) { | ||
| 18 | + String outStr2 = Integer.toHexString(str.charAt(i)); | ||
| 19 | + outStr.append(StringUtils.leftPad(outStr2, 4, '0')); | ||
| 20 | + } | ||
| 21 | + } | ||
| 22 | + return outStr.toString(); | ||
| 23 | + } | ||
| 24 | +} |
Bsth-admin/src/main/java/com/ruoyi/utils/PathToolUtil.java
0 → 100644
| 1 | +package com.ruoyi.utils; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.utils.StringUtils; | ||
| 4 | +import org.slf4j.Logger; | ||
| 5 | +import org.slf4j.LoggerFactory; | ||
| 6 | + | ||
| 7 | +import java.io.File; | ||
| 8 | +import java.io.FileInputStream; | ||
| 9 | +import java.io.RandomAccessFile; | ||
| 10 | + | ||
| 11 | +public class PathToolUtil { | ||
| 12 | + | ||
| 13 | + private static final Logger log = LoggerFactory.getLogger(PathToolUtil.class); | ||
| 14 | + | ||
| 15 | + // 维护写入队列 不停的遍历队列内的任务来完成写入 提高指令的响应速度 | ||
| 16 | + | ||
| 17 | +// private static LinkedList<Runnable> runnableList = new LinkedList<>(); | ||
| 18 | + | ||
| 19 | + public static boolean generateRelativeImagePath(String catalogue, String imei, String uploadTime, byte[] bits) { | ||
| 20 | +// runnableList.push(); | ||
| 21 | + String resourceDirectory = "Bsth-admin/src/main/resources"; | ||
| 22 | + String path = StringUtils.format("{}/{}/{}/{}.{}", resourceDirectory, | ||
| 23 | + catalogue, imei, uploadTime, "jpg"); | ||
| 24 | + File file = new File(path); | ||
| 25 | + RandomAccessFile raf = null; | ||
| 26 | + if (!file.exists()) { | ||
| 27 | + if (!file.getParentFile().exists()) { | ||
| 28 | + file.getParentFile().mkdirs(); | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + try { | ||
| 32 | + // 创建RandomAccessFile对象,并以读写模式打开文件 | ||
| 33 | + raf = new RandomAccessFile(file, "rw"); | ||
| 34 | + | ||
| 35 | + // 将文件指针移动到文件末尾 | ||
| 36 | + raf.seek(file.length()); | ||
| 37 | + | ||
| 38 | + // 写入数据 | ||
| 39 | + raf.write(bits); | ||
| 40 | + | ||
| 41 | + } catch (Exception e) { | ||
| 42 | + log.error("图片写入出错:{}", e.getMessage()); | ||
| 43 | + // TODO 第三次返回true | ||
| 44 | + } finally { | ||
| 45 | + try { | ||
| 46 | + if (raf != null) { | ||
| 47 | + raf.close(); | ||
| 48 | + } | ||
| 49 | + } catch (Exception e) { | ||
| 50 | + log.info(e.getMessage()); | ||
| 51 | + } | ||
| 52 | + return true; | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + public static boolean generateRelativeSpeechPath(String catalogue, String imei, String uploadTime, byte[] bits) { | ||
| 58 | +// runnableList.push(); | ||
| 59 | + String resourceDirectory = "Bsth-admin/src/main/resources"; | ||
| 60 | + String path = StringUtils.format("{}/{}/{}/{}.{}", resourceDirectory, | ||
| 61 | + catalogue, imei, uploadTime, "mp3"); | ||
| 62 | + File file = new File(path); | ||
| 63 | + RandomAccessFile raf = null; | ||
| 64 | + if (!file.exists()) { | ||
| 65 | + if (!file.getParentFile().exists()) { | ||
| 66 | + file.getParentFile().mkdirs(); | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + try { | ||
| 70 | + // 创建RandomAccessFile对象,并以读写模式打开文件 | ||
| 71 | + raf = new RandomAccessFile(file, "rw"); | ||
| 72 | + | ||
| 73 | + // 将文件指针移动到文件末尾 | ||
| 74 | + raf.seek(file.length()); | ||
| 75 | + | ||
| 76 | + // 写入数据 | ||
| 77 | + raf.write(bits); | ||
| 78 | + | ||
| 79 | + } catch (Exception e) { | ||
| 80 | + log.error("图片写入出错:{}", e.getMessage()); | ||
| 81 | + // TODO 第三次返回true | ||
| 82 | + } finally { | ||
| 83 | + try { | ||
| 84 | + if (raf != null) { | ||
| 85 | + raf.close(); | ||
| 86 | + } | ||
| 87 | + } catch (Exception e) { | ||
| 88 | + log.info(e.getMessage()); | ||
| 89 | + } | ||
| 90 | + return true; | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + | ||
| 95 | + | ||
| 96 | + public static void main(String[] args) { | ||
| 97 | + | ||
| 98 | + try { | ||
| 99 | + int count = 0; | ||
| 100 | + FileInputStream fis = new FileInputStream("C:\\Users\\20412\\Desktop\\Bsth\\岗前检查\\Bsth\\Bsth-admin\\src\\main\\resources\\564.jpg"); | ||
| 101 | + byte[] bits = new byte[1024]; | ||
| 102 | + int len; | ||
| 103 | + while ((len = fis.read(bits)) != -1) { | ||
| 104 | + count++; | ||
| 105 | + for (int i = 0; i < len; i++) { | ||
| 106 | + System.out.print(bits[i]); | ||
| 107 | + } | ||
| 108 | + System.out.println("分片"); | ||
| 109 | + } | ||
| 110 | + System.out.println("共" + count + "片"); | ||
| 111 | + } catch (Exception e) { | ||
| 112 | + throw new RuntimeException(e); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + | ||
| 118 | +} |
Bsth-admin/src/main/resources/application-druid-dev.yml
| @@ -97,7 +97,7 @@ spring: | @@ -97,7 +97,7 @@ spring: | ||
| 97 | redis: | 97 | redis: |
| 98 | # 地址 | 98 | # 地址 |
| 99 | # host: 121.41.83.61 | 99 | # host: 121.41.83.61 |
| 100 | - host: 192.168.168.124 | 100 | + host: localhost |
| 101 | database: 14 | 101 | database: 14 |
| 102 | # password: "guzijian" | 102 | # password: "guzijian" |
| 103 | port: 6379 | 103 | port: 6379 |
| @@ -182,3 +182,12 @@ log: | @@ -182,3 +182,12 @@ log: | ||
| 182 | path: D:/ruoyi/logs | 182 | path: D:/ruoyi/logs |
| 183 | server: | 183 | server: |
| 184 | port: 8100 | 184 | port: 8100 |
| 185 | +netty: | ||
| 186 | + # 是否开启netty服务 | ||
| 187 | + enabled: false | ||
| 188 | + socket: | ||
| 189 | + # 相对路径 classpath | ||
| 190 | + catalogue: | ||
| 191 | + image: device/image | ||
| 192 | + speech: device/speech | ||
| 193 | + port: 8989 | ||
| 185 | \ No newline at end of file | 194 | \ No newline at end of file |
Bsth-admin/src/main/resources/application-druid-prd.yml
| @@ -206,3 +206,13 @@ api: | @@ -206,3 +206,13 @@ api: | ||
| 206 | people: | 206 | people: |
| 207 | url: https://api.dingtalk.com/v1.0/yida/forms/instances/search | 207 | url: https://api.dingtalk.com/v1.0/yida/forms/instances/search |
| 208 | 208 | ||
| 209 | + | ||
| 210 | +netty: | ||
| 211 | + # 是否开启netty服务 | ||
| 212 | + enabled: false | ||
| 213 | + socket: | ||
| 214 | + # 相对路径 classpath | ||
| 215 | + catalogue: | ||
| 216 | + image: device/image | ||
| 217 | + speech: device/speech | ||
| 218 | + port: 8989 | ||
| 209 | \ No newline at end of file | 219 | \ No newline at end of file |
Bsth-admin/src/main/resources/application-druid-uat.yml
| @@ -198,4 +198,13 @@ api: | @@ -198,4 +198,13 @@ api: | ||
| 198 | people: | 198 | people: |
| 199 | url: https://api.dingtalk.com/v1.0/yida/forms/instances/search | 199 | url: https://api.dingtalk.com/v1.0/yida/forms/instances/search |
| 200 | log: | 200 | log: |
| 201 | - path: /home/sign/logs | ||
| 202 | \ No newline at end of file | 201 | \ No newline at end of file |
| 202 | + path: /home/sign/logs | ||
| 203 | +netty: | ||
| 204 | + # 是否开启netty服务 | ||
| 205 | + enabled: false | ||
| 206 | + socket: | ||
| 207 | + # 相对路径 classpath | ||
| 208 | + catalogue: | ||
| 209 | + image: device/image | ||
| 210 | + speech: device/speech | ||
| 211 | + port: 8989 | ||
| 203 | \ No newline at end of file | 212 | \ No newline at end of file |
Bsth-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
| @@ -69,6 +69,18 @@ public class RedisCache { | @@ -69,6 +69,18 @@ public class RedisCache { | ||
| 69 | * @param unit 时间单位 | 69 | * @param unit 时间单位 |
| 70 | * @return true=设置成功;false=设置失败 | 70 | * @return true=设置成功;false=设置失败 |
| 71 | */ | 71 | */ |
| 72 | + public void expire(final String key,Object val ,final long timeout, final TimeUnit unit) { | ||
| 73 | + redisTemplate.opsForValue().set(key, val,timeout, unit); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 设置有效时间 | ||
| 78 | + * | ||
| 79 | + * @param key Redis键 | ||
| 80 | + * @param timeout 超时时间 | ||
| 81 | + * @param unit 时间单位 | ||
| 82 | + * @return true=设置成功;false=设置失败 | ||
| 83 | + */ | ||
| 72 | public boolean expire(final String key, final long timeout, final TimeUnit unit) { | 84 | public boolean expire(final String key, final long timeout, final TimeUnit unit) { |
| 73 | return redisTemplate.expire(key, timeout, unit); | 85 | return redisTemplate.expire(key, timeout, unit); |
| 74 | } | 86 | } |
| @@ -283,4 +295,14 @@ public class RedisCache { | @@ -283,4 +295,14 @@ public class RedisCache { | ||
| 283 | public <T> Set<T> getHashKeys(String key){ | 295 | public <T> Set<T> getHashKeys(String key){ |
| 284 | return redisTemplate.opsForHash().keys(key); | 296 | return redisTemplate.opsForHash().keys(key); |
| 285 | } | 297 | } |
| 298 | + | ||
| 299 | + public boolean setNx(String key, Object val) { | ||
| 300 | + Boolean result = redisTemplate.opsForValue().setIfAbsent(key, val); | ||
| 301 | + return result != null && result; | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + public Long increment(String key) { | ||
| 305 | + Long increment = redisTemplate.opsForValue().increment(key); | ||
| 306 | + return increment; | ||
| 307 | + } | ||
| 286 | } | 308 | } |