2026-06-24 f4bd1f3c89d906131495a0aca5aaf82966378510
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package cn.iocoder.yudao.module.iot.gateway.protocol.emqx;
 
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
 
import java.util.List;
 
/**
 * IoT EMQX 协议配置
 *
 * @author 芋道源码
 */
@Data
public class IotEmqxConfig {
 
    // ========== MQTT Client 配置(连接 EMQX Broker) ==========
 
    /**
     * MQTT 服务器地址
     */
    @NotEmpty(message = "MQTT 服务器地址不能为空")
    private String mqttHost;
 
    /**
     * MQTT 服务器端口(默认:1883)
     */
    @NotNull(message = "MQTT 服务器端口不能为空")
    private Integer mqttPort = 1883;
 
    /**
     * MQTT 用户名
     */
    @NotEmpty(message = "MQTT 用户名不能为空")
    private String mqttUsername;
 
    /**
     * MQTT 密码
     */
    @NotEmpty(message = "MQTT 密码不能为空")
    private String mqttPassword;
 
    /**
     * MQTT 客户端的 SSL 开关
     */
    @NotNull(message = "MQTT 是否开启 SSL 不能为空")
    private Boolean mqttSsl = false;
 
    /**
     * MQTT 客户端 ID
     */
    @NotEmpty(message = "MQTT 客户端 ID 不能为空")
    private String mqttClientId;
 
    /**
     * MQTT 订阅的主题
     */
    @NotEmpty(message = "MQTT 主题不能为空")
    private List<@NotEmpty(message = "MQTT 主题不能为空") String> mqttTopics;
 
    /**
     * 默认 QoS 级别
     * <p>
     * 0 - 最多一次
     * 1 - 至少一次
     * 2 - 刚好一次
     */
    @NotNull(message = "MQTT QoS 不能为空")
    @Min(value = 0, message = "MQTT QoS 不能小于 0")
    @Max(value = 2, message = "MQTT QoS 不能大于 2")
    private Integer mqttQos = 1;
 
    /**
     * 连接超时时间(秒)
     */
    @NotNull(message = "连接超时时间不能为空")
    @Min(value = 1, message = "连接超时时间不能小于 1 秒")
    private Integer connectTimeoutSeconds = 10;
 
    /**
     * 重连延迟时间(毫秒)
     */
    @NotNull(message = "重连延迟时间不能为空")
    @Min(value = 0, message = "重连延迟时间不能小于 0 毫秒")
    private Long reconnectDelayMs = 5000L;
 
    /**
     * 是否启用 Clean Session (清理会话)
     * true: 每次连接都是新会话,Broker 不保留离线消息和订阅关系。
     * 对于网关这类“永远在线”且会主动重新订阅的应用,建议为 true。
     */
    @NotNull(message = "是否启用 Clean Session 不能为空")
    private Boolean cleanSession = true;
 
    /**
     * 心跳间隔(秒)
     * 用于保持连接活性,及时发现网络中断。
     */
    @NotNull(message = "心跳间隔不能为空")
    @Min(value = 1, message = "心跳间隔不能小于 1 秒")
    private Integer keepAliveIntervalSeconds = 60;
 
    /**
     * 最大未确认消息队列大小
     * 限制已发送但未收到 Broker 确认的 QoS 1/2 消息数量,用于流量控制。
     */
    @NotNull(message = "最大未确认消息队列大小不能为空")
    @Min(value = 1, message = "最大未确认消息队列大小不能小于 1")
    private Integer maxInflightQueue = 10000;
 
    /**
     * 是否信任所有 SSL 证书
     * 警告:此配置会绕过证书验证,仅建议在开发和测试环境中使用!
     * 在生产环境中,应设置为 false,并配置正确的信任库。
     */
    @NotNull(message = "是否信任所有 SSL 证书不能为空")
    private Boolean trustAll = false;
 
    // ========== MQTT Will / SSL 高级配置 ==========
 
    /**
     * 遗嘱消息配置 (用于网关异常下线时通知其他系统)
     */
    @Valid
    private Will will = new Will();
 
    /**
     * 高级 SSL/TLS 配置 (用于生产环境)
     */
    @Valid
    private Ssl sslOptions = new Ssl();
 
    // ========== HTTP Hook 配置(网关提供给 EMQX 调用) ==========
 
    /**
     * HTTP Hook 服务配置(用于 /mqtt/auth、/mqtt/event)
     */
    @Valid
    private Http http = new Http();
 
    /**
     * 遗嘱消息 (Last Will and Testament)
     */
    @Data
    public static class Will {
 
        /**
         * 是否启用遗嘱消息
         */
        private boolean enabled = false;
        /**
         * 遗嘱消息主题
         */
        private String topic;
        /**
         * 遗嘱消息内容
         */
        private String payload;
        /**
         * 遗嘱消息 QoS 等级
         */
        @Min(value = 0, message = "遗嘱消息 QoS 不能小于 0")
        @Max(value = 2, message = "遗嘱消息 QoS 不能大于 2")
        private Integer qos = 1;
        /**
         * 遗嘱消息是否作为保留消息发布
         */
        private boolean retain = true;
 
    }
 
    /**
     * 高级 SSL/TLS 配置
     */
    @Data
    public static class Ssl {
 
        /**
         * 密钥库(KeyStore)路径,例如:classpath:certs/client.jks
         * 包含客户端自己的证书和私钥,用于向服务端证明身份(双向认证)。
         */
        private String keyStorePath;
        /**
         * 密钥库密码
         */
        private String keyStorePassword;
        /**
         * 信任库(TrustStore)路径,例如:classpath:certs/trust.jks
         * 包含服务端信任的 CA 证书,用于验证服务端的身份,防止中间人攻击。
         */
        private String trustStorePath;
        /**
         * 信任库密码
         */
        private String trustStorePassword;
 
    }
 
    /**
     * HTTP Hook 服务 SSL 配置
     */
    @Data
    public static class Http {
 
        /**
         * 是否启用 SSL
         */
        private Boolean sslEnabled = false;
 
        /**
         * SSL 证书路径
         */
        private String sslCertPath;
 
        /**
         * SSL 私钥路径
         */
        private String sslKeyPath;
 
    }
 
}