├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── iot
│ │ ├── ClientApplication.java
│ │ ├── device
│ │ ├── entity
│ │ │ └── Device.java
│ │ ├── mapper
│ │ │ └── DeviceMapper.java
│ │ └── service
│ │ │ ├── DeviceService.java
│ │ │ └── serviceImpl
│ │ │ └── DeviceServiceImpl.java
│ │ └── mqtt
│ │ ├── InitCallback.java
│ │ ├── MQTTConnect.java
│ │ └── MQTTListener.java
└── resources
│ ├── config
│ ├── application-dev.yml
│ ├── application-prod.yml
│ └── application.yml
│ ├── logback
│ ├── logback-dev.xml
│ └── logback-prod.xml
│ └── mapper
│ └── DeviceMapper.xml
└── test
└── java
└── com
└── iot
└── ClientApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IoT
2 | 物联网平台
3 | 采用emq x作为mqtt服务器,运行代码时,注意修改配置文件中mysql参数、mqtt参数.
4 |
5 | [link]: https://blog.csdn.net/qq_37949192
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.2.6.RELEASE
10 |
11 |
12 | com.iot
13 | AM
14 | 1.0.0
15 | AM
16 | mqtt client
17 |
18 |
19 | 1.8
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-web
26 |
27 |
28 | org.mybatis.spring.boot
29 | mybatis-spring-boot-starter
30 | 2.1.2
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter
35 |
36 |
37 | org.mybatis.spring.boot
38 | mybatis-spring-boot-starter
39 | 2.1.2
40 |
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-devtools
45 | runtime
46 | true
47 |
48 |
49 | mysql
50 | mysql-connector-java
51 | runtime
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-configuration-processor
56 | true
57 |
58 |
59 | org.projectlombok
60 | lombok
61 | true
62 |
63 |
64 | org.springframework.boot
65 | spring-boot-starter-test
66 | test
67 |
68 |
69 | org.junit.vintage
70 | junit-vintage-engine
71 |
72 |
73 |
74 |
75 |
76 |
77 | org.springframework.integration
78 | spring-integration-mqtt
79 |
80 |
81 |
82 |
83 | com.alibaba
84 | fastjson
85 | 1.2.62
86 |
87 |
88 |
89 |
90 |
91 |
92 | org.springframework.boot
93 | spring-boot-maven-plugin
94 |
95 |
96 |
97 |
98 |
99 |
100 | src/main/resources
101 | true
102 |
103 |
104 | application.yml
105 | application-dev.yml
106 | application-prod.yml
107 |
108 |
109 |
110 |
111 | src/main/resources
112 | true
113 |
114 |
115 | application.yml
116 | application-${spring.profiles.active}.yml
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | dev
125 |
126 |
127 | true
128 |
129 |
130 | dev
131 |
132 |
133 |
134 |
135 |
136 | prod
137 |
138 | prod
139 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/ClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.iot;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | @SpringBootApplication
8 | @MapperScan({"com.iot.**.mapper"})
9 | public class ClientApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ClientApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/device/entity/Device.java:
--------------------------------------------------------------------------------
1 | package com.iot.device.entity;
2 |
3 | import java.io.Serializable;
4 | import lombok.Data;
5 | import lombok.experimental.Accessors;
6 |
7 | /**
8 | * TODO
9 | *
10 | * @author Mr.Qu
11 | * @title: Device
12 | * @since 2020/11/17 15:42
13 | */
14 | @Data
15 | @Accessors(chain = true)
16 | public class Device implements Serializable {
17 |
18 | private String username;
19 |
20 | private long ts;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/device/mapper/DeviceMapper.java:
--------------------------------------------------------------------------------
1 | package com.iot.device.mapper;
2 |
3 | import com.iot.device.entity.Device;
4 | import org.springframework.stereotype.Repository;
5 |
6 | /**
7 | * TODO
8 | *
9 | * @author Mr.Qu
10 | * @title: DeviceMapper
11 | * @since 2020/11/17 15:56
12 | */
13 | @Repository
14 | public interface DeviceMapper {
15 |
16 | boolean updateDeviceStatus(Device param);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/device/service/DeviceService.java:
--------------------------------------------------------------------------------
1 | package com.iot.device.service;
2 |
3 | import com.iot.device.entity.Device;
4 |
5 | /**
6 | * TODO
7 | *
8 | * @author Mr.Qu
9 | * @title: DeviceService
10 | * @since 2020/11/17 15:35
11 | */
12 | public interface DeviceService {
13 |
14 | boolean updateDeviceStatus(Device param);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/device/service/serviceImpl/DeviceServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.iot.device.service.serviceImpl;
2 |
3 | import com.iot.device.entity.Device;
4 | import com.iot.device.mapper.DeviceMapper;
5 | import com.iot.device.service.DeviceService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | * TODO
11 | *
12 | * @author Mr.Qu
13 | * @title: DeviceServiceImpl
14 | * @since 2020/11/17 15:55
15 | */
16 | @Service
17 | public class DeviceServiceImpl implements DeviceService {
18 |
19 | @Autowired
20 | private DeviceMapper deviceMapper;
21 |
22 | @Override
23 | public boolean updateDeviceStatus(Device param) {
24 | return deviceMapper.updateDeviceStatus(param);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/mqtt/InitCallback.java:
--------------------------------------------------------------------------------
1 | package com.iot.mqtt;
2 |
3 | import com.iot.device.entity.Device;
4 | import com.iot.device.service.DeviceService;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
7 | import org.eclipse.paho.client.mqttv3.MqttCallback;
8 | import org.eclipse.paho.client.mqttv3.MqttMessage;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Component;
11 |
12 | /**
13 | * MQTT回调函数
14 | *
15 | * @author Mr.Qu
16 | * @since 2020/11/18
17 | */
18 | @Slf4j
19 | @Component
20 | public class InitCallback implements MqttCallback {
21 |
22 | @Autowired
23 | private DeviceService deviceService;
24 |
25 | /**
26 | * MQTT 断开连接会执行此方法
27 | */
28 | @Override
29 | public void connectionLost(Throwable cause) {
30 | log.error(cause.getMessage(), cause);
31 | }
32 |
33 | /**
34 | * publish发布成功后会执行到这里
35 | */
36 | @Override
37 | public void deliveryComplete(IMqttDeliveryToken token) {
38 | }
39 |
40 | /**
41 | * subscribe订阅后得到的消息会执行到这里
42 | */
43 | @Override
44 | public void messageArrived(String topic, MqttMessage message) {
45 | log.info("[{}] : {}", topic, new String(message.getPayload()));
46 | deviceService
47 | .updateDeviceStatus(new Device().setUsername("qbb").setTs(System.currentTimeMillis()));
48 | /*try {
49 | JSONObject jsonObject = JSON.parseObject(msg);
50 | String clientId = String.valueOf(jsonObject.get("clientid"));
51 | if (topic.endsWith("/disconnected")) {
52 | log.info("客户端已掉线:{}", clientId);
53 | } else {
54 | log.info("客户端已上线:{}", clientId);
55 | }
56 | } catch (JSONException e) {
57 | log.error("JSON Format Parsing Exception : {}", msg);
58 | }*/
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/mqtt/MQTTConnect.java:
--------------------------------------------------------------------------------
1 | package com.iot.mqtt;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.eclipse.paho.client.mqttv3.*;
5 | import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.stereotype.Component;
8 |
9 | /**
10 | * MQTT工具类操作
11 | *
12 | * @author Mr.Qu
13 | * @since 2020/11/18
14 | */
15 | @Slf4j
16 | @Component
17 | public class MQTTConnect {
18 |
19 | @Value("${mqtt.host}")
20 | private String HOST;
21 | private final String clientId = "Client" + (int) (Math.random() * 100000000);
22 | private MqttClient mqttClient;
23 |
24 | /**
25 | * 客户端connect连接mqtt服务器
26 | *
27 | * @param username 用户名
28 | * @param password 密码
29 | * @param mqttCallback 回调函数
30 | **/
31 | public void setMqttClient(String username, String password, MqttCallback mqttCallback)
32 | throws MqttException {
33 | MqttConnectOptions options = mqttConnectOptions(username, password);
34 | /*if (mqttCallback == null) {
35 | mqttClient.setCallback(new Callback());
36 | } else {
37 | }*/
38 | mqttClient.setCallback(mqttCallback);
39 | mqttClient.connect(options);
40 | }
41 |
42 | /**
43 | * MQTT连接参数设置
44 | */
45 | private MqttConnectOptions mqttConnectOptions(String userName, String passWord)
46 | throws MqttException {
47 | mqttClient = new MqttClient(HOST, clientId, new MemoryPersistence());
48 | MqttConnectOptions options = new MqttConnectOptions();
49 | options.setUserName(userName);
50 | options.setPassword(passWord.toCharArray());
51 | options.setConnectionTimeout(10);///默认:30
52 | options.setAutomaticReconnect(true);//默认:false
53 | options.setCleanSession(false);//默认:true
54 | //options.setKeepAliveInterval(20);//默认:60
55 | return options;
56 | }
57 |
58 | /**
59 | * 关闭MQTT连接
60 | */
61 | public void close() throws MqttException {
62 | mqttClient.close();
63 | mqttClient.disconnect();
64 | }
65 |
66 | /**
67 | * 向某个主题发布消息 默认qos:1
68 | */
69 | public void pub(String topic, String msg) throws MqttException {
70 | MqttMessage mqttMessage = new MqttMessage();
71 | //mqttMessage.setQos(2);
72 | mqttMessage.setPayload(msg.getBytes());
73 | MqttTopic mqttTopic = mqttClient.getTopic(topic);
74 | MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
75 | token.waitForCompletion();
76 | }
77 |
78 | /**
79 | * 向某个主题发布消息
80 | *
81 | * @param topic: 发布的主题
82 | * @param msg: 发布的消息
83 | * @param qos: 消息质量 Qos:0、1、2
84 | */
85 | public void pub(String topic, String msg, int qos) throws MqttException {
86 | MqttMessage mqttMessage = new MqttMessage();
87 | mqttMessage.setQos(qos);
88 | mqttMessage.setPayload(msg.getBytes());
89 | MqttTopic mqttTopic = mqttClient.getTopic(topic);
90 | MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
91 | token.waitForCompletion();
92 | }
93 |
94 | /**
95 | * 订阅某一个主题 ,此方法默认的的Qos等级为:1
96 | *
97 | * @param topic 主题
98 | */
99 | public void sub(String topic) throws MqttException {
100 | mqttClient.subscribe(topic);
101 | }
102 |
103 | /**
104 | * 订阅某一个主题,可携带Qos
105 | *
106 | * @param topic 所要订阅的主题
107 | * @param qos 消息质量:0、1、2
108 | */
109 | public void sub(String topic, int qos) throws MqttException {
110 | mqttClient.subscribe(topic, qos);
111 | }
112 |
113 | public static void main(String[] args) throws MqttException {
114 | MQTTConnect mqttConnect = new MQTTConnect();
115 | String msg = "Mr.Qu" + (int) (Math.random() * 100000000);
116 | mqttConnect.setMqttClient("admin", "public", new InitCallback());
117 | mqttConnect.sub("com/iot/init");
118 | mqttConnect.pub("com/iot/init", msg);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/com/iot/mqtt/MQTTListener.java:
--------------------------------------------------------------------------------
1 | package com.iot.mqtt;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.eclipse.paho.client.mqttv3.MqttException;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.ApplicationListener;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.stereotype.Component;
10 |
11 | /**
12 | * 项目启动 监听主题
13 | *
14 | * @author Mr.Qu
15 | * @since 2020/11/18 0018
16 | */
17 | @Slf4j
18 | @Component
19 | public class MQTTListener implements ApplicationListener {
20 |
21 | @Value("${mqtt.username}")
22 | private String username;
23 | @Value("${mqtt.password}")
24 | private String password;
25 | private final MQTTConnect server;
26 | private final InitCallback initCallback;
27 |
28 | @Autowired
29 | public MQTTListener(MQTTConnect server, InitCallback initCallback) {
30 | this.server = server;
31 | this.initCallback = initCallback;
32 | }
33 |
34 | @Override
35 | public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
36 | try {
37 | server.setMqttClient(username, password, initCallback);
38 | server.sub("com/iot/init");
39 | } catch (MqttException e) {
40 | log.error(e.getMessage(), e);
41 | }
42 | }
43 | }
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/main/resources/config/application-dev.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: jdbc:mysql://localhost:3306/iotdb?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
4 | username: root
5 | password: root
6 |
7 | server:
8 | port: 8082
9 |
10 | mqtt:
11 | host: tcp://broker.emqx.io:1883
12 | username: admin
13 | password: public
14 |
--------------------------------------------------------------------------------
/src/main/resources/config/application-prod.yml:
--------------------------------------------------------------------------------
1 | logging:
2 | path: /opt/iot/logs
3 |
4 | server:
5 | port: 8084
6 |
7 | mqtt:
8 | host: tcp://broker.emqx.io:1883
9 | username: admin
10 | password: public
--------------------------------------------------------------------------------
/src/main/resources/config/application.yml:
--------------------------------------------------------------------------------
1 | logging:
2 | config: classpath:logback/logback-@spring.profiles.active@.xml
3 |
4 | spring:
5 | application:
6 | name: DC
7 | profiles:
8 | active: @spring.profiles.active@
9 |
10 | datasource:
11 | driver-class-name: com.mysql.cj.jdbc.Driver
12 | type: com.zaxxer.hikari.HikariDataSource
13 | hikari:
14 | minimum-idle: 5
15 | maximum-pool-size: 15
16 | auto-commit: true
17 | idle-timeout: 30000
18 | pool-name: DatebookHikariCP
19 | max-lifetime: 1800000
20 | connection-timeout: 30000
21 | connection-test-query: SELECT 1 FROM DUAL
22 |
23 | jackson:
24 | default-property-inclusion: non_null
25 |
26 | mybatis:
27 | mapper-locations: mapper/**/*.xml
--------------------------------------------------------------------------------
/src/main/resources/logback/logback-dev.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 | logback
9 |
10 |
11 |
12 |
13 |
15 |
17 |
18 |
20 |
21 |
22 |
23 | ${CONSOLE_LOG_PATTERN}
24 | UTF-8
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/resources/logback/logback-prod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 | logback
9 |
10 |
11 |
12 |
13 |
14 |
15 | ${log.path}/log_info.log
16 |
17 |
18 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
19 | UTF-8
20 |
21 |
22 |
23 |
24 | ${log.path}/web-info-%d{yyyy-MM-dd}.%i.log
25 |
26 | 60MB
27 |
28 |
29 | 15
30 |
31 |
32 |
33 | info
34 | ACCEPT
35 | DENY
36 |
37 |
38 |
39 |
40 |
41 | ${log.path}/log_warn.log
42 |
43 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
44 | UTF-8
45 |
46 |
47 | ${log.path}/web-warn-%d{yyyy-MM-dd}.%i.log
48 |
49 | 60MB
50 |
51 | 15
52 |
53 |
54 | warn
55 | ACCEPT
56 | DENY
57 |
58 |
59 |
60 |
61 |
62 | ${log.path}/log_error.log
63 |
64 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
65 | UTF-8
66 |
67 |
68 | ${log.path}/web-error-%d{yyyy-MM-dd}.%i.log
69 |
70 | 60MB
71 |
72 | 15
73 |
74 |
75 | ERROR
76 | ACCEPT
77 | DENY
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/DeviceMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | insert into device
8 | values (#{username}, #{ts})
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/test/java/com/iot/ClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.iot;
2 |
3 | import com.iot.device.entity.Device;
4 | import com.iot.device.service.DeviceService;
5 | import org.junit.jupiter.api.Test;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 |
9 | @SpringBootTest
10 | class ClientApplicationTests {
11 |
12 | @Autowired
13 | private DeviceService deviceService;
14 |
15 | @Test
16 | void contextLoads() {
17 | deviceService
18 | .updateDeviceStatus(new Device().setUsername("qbb").setTs(System.currentTimeMillis()));
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------