Browse Source

项目上传

master
黎工 1 year ago
commit
d2d6e406a6
  1. 103
      pom.xml
  2. 18
      src/main/java/com/whhj/Application.java
  3. 25
      src/main/java/com/whhj/config/ChannelInitializerImpl.java
  4. 10
      src/main/java/com/whhj/constant/CommonConstant.java
  5. 13
      src/main/java/com/whhj/dao/YlSmartMattressMapper.java
  6. 41
      src/main/java/com/whhj/entity/DeviceInfo.java
  7. 35
      src/main/java/com/whhj/entity/YlSmartMattress.java
  8. 60
      src/main/java/com/whhj/handler/NettyServerHandler.java
  9. 67
      src/main/java/com/whhj/handler/QuantumDecoder.java
  10. 52
      src/main/java/com/whhj/server/IotServer.java
  11. 15
      src/main/java/com/whhj/service/YlSmartMattressService.java
  12. 25
      src/main/java/com/whhj/util/ApplicationContextUtil.java
  13. 20
      src/main/java/com/whhj/util/HexUtil.java
  14. 26
      src/main/resources/application-test.yml
  15. 3
      src/main/resources/application.yml
  16. 47
      src/main/resources/logback-spring.xml
  17. 5
      src/main/resources/mapper/YlSmartMattressMapper.xml
  18. 30
      src/test/java/ApplicationTest.java

103
pom.xml

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whhz</groupId>
<artifactId>quantum-iot</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<netty.version>4.1.42.Final</netty.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.7.16</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.whhj.Application</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.whhj.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

18
src/main/java/com/whhj/Application.java

@ -0,0 +1,18 @@
package com.whhj;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author lxg
* @date 2024/10/20 17:35
**/
@MapperScan("com.whhj.dao")
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

25
src/main/java/com/whhj/config/ChannelInitializerImpl.java

@ -0,0 +1,25 @@
package com.whhj.config;
import com.whhj.handler.NettyServerHandler;
import com.whhj.handler.QuantumDecoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringEncoder;
/**
* @author lxg
* @date 2024/10/20 19:33
**/
public class ChannelInitializerImpl extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast( new QuantumDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new NettyServerHandler()); // 自定义处理器
}
}

10
src/main/java/com/whhj/constant/CommonConstant.java

@ -0,0 +1,10 @@
package com.whhj.constant;
/**
* @author lxg
* @date 2024/10/30 23:26
**/
public interface CommonConstant {
String DEVICE_BRAND_CODE = "4";
}

13
src/main/java/com/whhj/dao/YlSmartMattressMapper.java

@ -0,0 +1,13 @@
package com.whhj.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whhj.entity.YlSmartMattress;
import org.apache.ibatis.annotations.Mapper;
/**
* @author lxg
* @date 2024/10/22 23:28
**/
@Mapper
public interface YlSmartMattressMapper extends BaseMapper<YlSmartMattress> {
}

41
src/main/java/com/whhj/entity/DeviceInfo.java

@ -0,0 +1,41 @@
package com.whhj.entity;
import lombok.Getter;
import lombok.Setter;
/**
* @author lxg
* @date 2024/10/20 22:08
**/
@Getter
@Setter
public class DeviceInfo{
/**
* 命令类型
*/
private Integer commandType;
/**
* 设备sn
*/
private String sn;
/**
* 上报时间
*/
private Integer reportTime;
/**
* 心率
*/
private Integer heartRate;
/**
* 呼吸值
*/
private Integer breath;
/**
* 状态
*/
private Integer status;
/**
* 电量
*/
private Integer electricity;
}

35
src/main/java/com/whhj/entity/YlSmartMattress.java

@ -0,0 +1,35 @@
package com.whhj.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("yl_smart_mattress")
public class YlSmartMattress {
@TableId(type = IdType.AUTO)
private Long id;
private String deviceId;
private Integer heart;
private Integer breathe;
private String leaveBed;
private Boolean move;
private Boolean wifi;
private Boolean m4g;
private Date createTime;
private String brand;
}

60
src/main/java/com/whhj/handler/NettyServerHandler.java

@ -0,0 +1,60 @@
package com.whhj.handler;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whhj.constant.CommonConstant;
import com.whhj.entity.DeviceInfo;
import com.whhj.entity.YlSmartMattress;
import com.whhj.service.YlSmartMattressService;
import com.whhj.util.ApplicationContextUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
/**
* @author lxg
* @date 2024/10/20 19:34
**/
@Slf4j
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof DeviceInfo) {
DeviceInfo reportInfo = (DeviceInfo) msg;
log.info("Received info: {}", JSON.toJSONString(reportInfo));
YlSmartMattressService service = ApplicationContextUtil.getBean(YlSmartMattressService.class);
QueryWrapper<YlSmartMattress> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_id", reportInfo.getSn());
queryWrapper.eq("brand", CommonConstant.DEVICE_BRAND_CODE);
YlSmartMattress originInfo = service.getOne(queryWrapper);
YlSmartMattress ylSmartMattress = new YlSmartMattress();
if (originInfo != null) {
ylSmartMattress.setId(originInfo.getId());
}
ylSmartMattress.setBrand(CommonConstant.DEVICE_BRAND_CODE);
ylSmartMattress.setDeviceId(reportInfo.getSn());
ylSmartMattress.setHeart(reportInfo.getHeartRate());
ylSmartMattress.setBreathe(reportInfo.getBreath());
ylSmartMattress.setLeaveBed(reportInfo.getStatus() == 4 ? "1" : "0");
ylSmartMattress.setCreateTime(DateUtil.date(Long.valueOf(reportInfo.getReportTime()) * 1000));
service.saveOrUpdate(ylSmartMattress);
ctx.writeAndFlush("received data");
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
log.info("Client:{} connected",ctx.channel().remoteAddress());
}
}

67
src/main/java/com/whhj/handler/QuantumDecoder.java

@ -0,0 +1,67 @@
package com.whhj.handler;
import cn.hutool.core.util.StrUtil;
import com.whhj.entity.DeviceInfo;
import com.whhj.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author lxg
* @date 2024/10/20 22:04
**/
public class QuantumDecoder extends ByteToMessageDecoder {
private static final Logger log = LoggerFactory.getLogger(QuantumDecoder.class);
private static final int FRAME_LENGTH = 16;
private static final String START_MARKER = "cd";
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) {
// 检查是否有足够的字节来读取一个完整的消息
if (in.readableBytes() < FRAME_LENGTH) {
return;
}
in.markReaderIndex();
String frameHeader = Integer.toHexString(0xFF & in.readByte());
// 检查起始标识是否匹配
if (!StrUtil.equals(frameHeader, START_MARKER)) {
in.resetReaderIndex();
byte[] data = new byte[in.readableBytes()];
in.readBytes(data);
try {
log.info("invalid data:{}",HexUtil.bytesToHexStr(data));
}catch (Exception e){
e.printStackTrace();
}
return;
}
DeviceInfo deviceInfo = new DeviceInfo();
int cmdType = in.readByte();
deviceInfo.setCommandType(cmdType);
byte[] sn = new byte[6];
in.readBytes(sn);
deviceInfo.setSn(HexUtil.bytesToHexStr(sn));
byte[] reportTime = new byte[4];
in.readBytes(reportTime);
deviceInfo.setReportTime(ByteBuffer.wrap(reportTime).order(ByteOrder.BIG_ENDIAN).getInt());
int heartRate = in.readByte();
deviceInfo.setHeartRate(heartRate);
int breath = in.readByte();
deviceInfo.setBreath(breath);
int status = in.readByte();
deviceInfo.setStatus(status);
int electricity = in.readByte();
deviceInfo.setElectricity(electricity);
list.add(deviceInfo);
}
}

52
src/main/java/com/whhj/server/IotServer.java

@ -0,0 +1,52 @@
package com.whhj.server;
import com.whhj.config.ChannelInitializerImpl;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;
/**
* @author lxg
* @date 2024/10/20 17:36
**/
@Slf4j
@Component
public class IotServer implements ApplicationListener<ContextClosedEvent> {
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private final ServerBootstrap bootstrap = new ServerBootstrap();
@Override
public void onApplicationEvent(ContextClosedEvent event) {
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializerImpl())
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
ChannelFuture channelFuture = bootstrap.bind(8080).sync();
log.info("服务启动:{}", channelFuture.channel().localAddress());
channelFuture.channel().closeFuture().sync();
log.info("服务关闭");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("资源已释放");
}
}
}

15
src/main/java/com/whhj/service/YlSmartMattressService.java

@ -0,0 +1,15 @@
package com.whhj.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whhj.dao.YlSmartMattressMapper;
import com.whhj.entity.YlSmartMattress;
import org.springframework.stereotype.Service;
/**
* @author lxg
* @date 2024/10/22 23:32
**/
@Service
public class YlSmartMattressService extends ServiceImpl<YlSmartMattressMapper, YlSmartMattress> {
}

25
src/main/java/com/whhj/util/ApplicationContextUtil.java

@ -0,0 +1,25 @@
package com.whhj.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author lxg
* @date 2024/10/23 22:09
**/
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
}

20
src/main/java/com/whhj/util/HexUtil.java

@ -0,0 +1,20 @@
package com.whhj.util;
/**
* @author lxg
* @date 2024/10/21 22:43
**/
public class HexUtil {
public static String bytesToHexStr(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}

26
src/main/resources/application-test.yml

@ -0,0 +1,26 @@
# 服务端口配置
server:
port: 8088
spring:
datasource:
url: jdbc:mysql://119.23.39.166:3306/jjyl_test?useUnicode=true&&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitlsBoolean=true
username: root
password: rootWHJ2018
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
connection-timeout: 30000 # 连接超时时间(毫秒)
maximum-pool-size: 10 # 最大连接池大小
minimum-idle: 5 # 最小空闲连接数
idle-timeout: 600000 # 空闲连接超时时间(毫秒)
max-lifetime: 1800000 # 连接的最大生命周期(毫秒)
pool-name: HikariCPDemoPool # 连接池名称
auto-commit: true # 是否自动提交
connection-test-query: SELECT 1 # 连接测试查询
validation-timeout: 5000 # 连接验证超时时间(毫秒)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml

3
src/main/resources/application.yml

@ -0,0 +1,3 @@
spring:
profiles:
active: test

47
src/main/resources/logback-spring.xml

@ -0,0 +1,47 @@
<configuration>
<!-- 定义日志文件的存储路径 -->
<property name="LOG_PATH" value="logs" />
<property name="LOG_FILE" value="${LOG_PATH}/quantum-iot.log" />
<property name="LOG_FILE_MAX_HISTORY" value="7" />
<property name="LOG_FILE_MAX_SIZE" value="100MB" />
<!-- 控制台输出格式 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 文件输出格式 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天滚动 -->
<fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 保留7天的日志文件 -->
<maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory>
<!-- 单个日志文件的最大大小 -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 配置根日志级别 -->
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<!-- 配置特定包的日志级别 -->
<logger name="com.example" level="debug" additivity="false">
<appender-ref ref="FILE" />
</logger>
<!-- 配置Spring Boot的日志级别 -->
<logger name="org.springframework" level="info" />
<logger name="org.hibernate" level="info" />
</configuration>

5
src/main/resources/mapper/YlSmartMattressMapper.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.whhz.dao.YlSmartMattressMapper">
</mapper>

30
src/test/java/ApplicationTest.java

@ -0,0 +1,30 @@
import com.whhj.Application;
import com.whhj.service.YlSmartMattressService;
import com.whhj.util.ApplicationContextUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author lxg
* @date 2024/10/23 21:34
**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private YlSmartMattressService ylSmartMattressService;
@Autowired
private ApplicationContextUtil applicationContextUtil;
@Test
public void test_01() {
Integer cnt = ylSmartMattressService.count();
System.out.println(cnt);
}
}
Loading…
Cancel
Save