...
|
...
|
@@ -53,6 +53,7 @@ import java.util.ArrayList; |
53
|
53
|
import java.util.List;
|
54
|
54
|
import java.util.Map;
|
55
|
55
|
import java.util.concurrent.ConcurrentHashMap;
|
|
56
|
+import java.util.concurrent.ConcurrentMap;
|
56
|
57
|
|
57
|
58
|
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.*;
|
58
|
59
|
import static io.netty.handler.codec.mqtt.MqttMessageType.*;
|
...
|
...
|
@@ -77,12 +78,12 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
77
|
78
|
private final RelationService relationService;
|
78
|
79
|
private final QuotaService quotaService;
|
79
|
80
|
private final SslHandler sslHandler;
|
|
81
|
+ private final ConcurrentMap<String, Integer> mqttQoSMap;
|
|
82
|
+
|
80
|
83
|
private volatile boolean connected;
|
81
|
84
|
private volatile InetSocketAddress address;
|
82
|
85
|
private volatile GatewaySessionCtx gatewaySessionCtx;
|
83
|
86
|
|
84
|
|
- private Map<String,MqttQoS> mqttQoSMap = new ConcurrentHashMap<>();
|
85
|
|
-
|
86
|
87
|
public MqttTransportHandler(SessionMsgProcessor processor, DeviceService deviceService, DeviceAuthService authService, RelationService relationService,
|
87
|
88
|
MqttTransportAdaptor adaptor, SslHandler sslHandler, QuotaService quotaService) {
|
88
|
89
|
this.processor = processor;
|
...
|
...
|
@@ -90,7 +91,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
90
|
91
|
this.relationService = relationService;
|
91
|
92
|
this.authService = authService;
|
92
|
93
|
this.adaptor = adaptor;
|
93
|
|
- this.deviceSessionCtx = new DeviceSessionCtx(processor, authService, adaptor);
|
|
94
|
+ this.mqttQoSMap = new ConcurrentHashMap<>();
|
|
95
|
+ this.deviceSessionCtx = new DeviceSessionCtx(processor, authService, adaptor, mqttQoSMap);
|
94
|
96
|
this.sessionId = deviceSessionCtx.getSessionId().toUidStr();
|
95
|
97
|
this.sslHandler = sslHandler;
|
96
|
98
|
this.quotaService = quotaService;
|
...
|
...
|
@@ -170,18 +172,25 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
170
|
172
|
|
171
|
173
|
private void handleMqttPublishMsg(String topicName, int msgId, MqttPublishMessage mqttMsg) {
|
172
|
174
|
try {
|
173
|
|
- if (topicName.equals(GATEWAY_TELEMETRY_TOPIC)) {
|
174
|
|
- gatewaySessionCtx.onDeviceTelemetry(mqttMsg);
|
175
|
|
- } else if (topicName.equals(GATEWAY_ATTRIBUTES_TOPIC)) {
|
176
|
|
- gatewaySessionCtx.onDeviceAttributes(mqttMsg);
|
177
|
|
- } else if (topicName.equals(GATEWAY_ATTRIBUTES_REQUEST_TOPIC)) {
|
178
|
|
- gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg);
|
179
|
|
- } else if (topicName.equals(GATEWAY_RPC_TOPIC)) {
|
180
|
|
- gatewaySessionCtx.onDeviceRpcResponse(mqttMsg);
|
181
|
|
- } else if (topicName.equals(GATEWAY_CONNECT_TOPIC)) {
|
182
|
|
- gatewaySessionCtx.onDeviceConnect(mqttMsg);
|
183
|
|
- } else if (topicName.equals(GATEWAY_DISCONNECT_TOPIC)) {
|
184
|
|
- gatewaySessionCtx.onDeviceDisconnect(mqttMsg);
|
|
175
|
+ switch (topicName) {
|
|
176
|
+ case GATEWAY_TELEMETRY_TOPIC:
|
|
177
|
+ gatewaySessionCtx.onDeviceTelemetry(mqttMsg);
|
|
178
|
+ break;
|
|
179
|
+ case GATEWAY_ATTRIBUTES_TOPIC:
|
|
180
|
+ gatewaySessionCtx.onDeviceAttributes(mqttMsg);
|
|
181
|
+ break;
|
|
182
|
+ case GATEWAY_ATTRIBUTES_REQUEST_TOPIC:
|
|
183
|
+ gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg);
|
|
184
|
+ break;
|
|
185
|
+ case GATEWAY_RPC_TOPIC:
|
|
186
|
+ gatewaySessionCtx.onDeviceRpcResponse(mqttMsg);
|
|
187
|
+ break;
|
|
188
|
+ case GATEWAY_CONNECT_TOPIC:
|
|
189
|
+ gatewaySessionCtx.onDeviceConnect(mqttMsg);
|
|
190
|
+ break;
|
|
191
|
+ case GATEWAY_DISCONNECT_TOPIC:
|
|
192
|
+ gatewaySessionCtx.onDeviceDisconnect(mqttMsg);
|
|
193
|
+ break;
|
185
|
194
|
}
|
186
|
195
|
} catch (RuntimeException | AdaptorException e) {
|
187
|
196
|
log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
|
...
|
...
|
@@ -229,40 +238,53 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
229
|
238
|
log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId());
|
230
|
239
|
List<Integer> grantedQoSList = new ArrayList<>();
|
231
|
240
|
for (MqttTopicSubscription subscription : mqttMsg.payload().topicSubscriptions()) {
|
232
|
|
- String topicName = subscription.topicName();
|
233
|
|
- //TODO: handle this qos level.
|
|
241
|
+ String topic = subscription.topicName();
|
234
|
242
|
MqttQoS reqQoS = subscription.qualityOfService();
|
235
|
|
- mqttQoSMap.put(topicName, reqQoS);
|
236
|
243
|
try {
|
237
|
|
- if (topicName.equals(DEVICE_ATTRIBUTES_TOPIC)) {
|
238
|
|
- AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
239
|
|
- processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
240
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
241
|
|
- } else if (topicName.equals(DEVICE_RPC_REQUESTS_SUB_TOPIC)) {
|
242
|
|
- AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
243
|
|
- processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
244
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
245
|
|
- } else if (topicName.equals(DEVICE_RPC_RESPONSE_SUB_TOPIC)) {
|
246
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
247
|
|
- } else if (topicName.equals(DEVICE_ATTRIBUTES_RESPONSES_TOPIC)) {
|
248
|
|
- deviceSessionCtx.setAllowAttributeResponses();
|
249
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
250
|
|
- } else if (topicName.equals(GATEWAY_ATTRIBUTES_TOPIC)) {
|
251
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
252
|
|
- }else if (topicName.equals(GATEWAY_RPC_TOPIC)) {
|
253
|
|
- grantedQoSList.add(getMinSupportedQos(reqQoS));
|
254
|
|
- } else {
|
255
|
|
- log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topicName, reqQoS);
|
256
|
|
- grantedQoSList.add(FAILURE.value());
|
|
244
|
+ switch (topic) {
|
|
245
|
+ case DEVICE_ATTRIBUTES_TOPIC: {
|
|
246
|
+ AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
|
247
|
+ processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
248
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
249
|
+ break;
|
|
250
|
+ }
|
|
251
|
+ case DEVICE_RPC_REQUESTS_SUB_TOPIC: {
|
|
252
|
+ AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
|
253
|
+ processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
254
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
255
|
+ break;
|
|
256
|
+ }
|
|
257
|
+ case DEVICE_RPC_RESPONSE_SUB_TOPIC:
|
|
258
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
259
|
+ break;
|
|
260
|
+ case DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
|
|
261
|
+ deviceSessionCtx.setAllowAttributeResponses();
|
|
262
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
263
|
+ break;
|
|
264
|
+ case GATEWAY_ATTRIBUTES_TOPIC:
|
|
265
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
266
|
+ break;
|
|
267
|
+ case GATEWAY_RPC_TOPIC:
|
|
268
|
+ registerSubQoS(topic, grantedQoSList, reqQoS);
|
|
269
|
+ break;
|
|
270
|
+ default:
|
|
271
|
+ log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS);
|
|
272
|
+ grantedQoSList.add(FAILURE.value());
|
|
273
|
+ break;
|
257
|
274
|
}
|
258
|
275
|
} catch (AdaptorException e) {
|
259
|
|
- log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topicName, reqQoS);
|
|
276
|
+ log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS);
|
260
|
277
|
grantedQoSList.add(FAILURE.value());
|
261
|
278
|
}
|
262
|
279
|
}
|
263
|
280
|
ctx.writeAndFlush(createSubAckMessage(mqttMsg.variableHeader().messageId(), grantedQoSList));
|
264
|
281
|
}
|
265
|
282
|
|
|
283
|
+ private void registerSubQoS(String topic, List<Integer> grantedQoSList, MqttQoS reqQoS) {
|
|
284
|
+ grantedQoSList.add(getMinSupportedQos(reqQoS));
|
|
285
|
+ mqttQoSMap.put(topic, getMinSupportedQos(reqQoS));
|
|
286
|
+ }
|
|
287
|
+
|
266
|
288
|
private void processUnsubscribe(ChannelHandlerContext ctx, MqttUnsubscribeMessage mqttMsg) {
|
267
|
289
|
if (!checkConnected(ctx)) {
|
268
|
290
|
return;
|
...
|
...
|
@@ -271,14 +293,20 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
271
|
293
|
for (String topicName : mqttMsg.payload().topics()) {
|
272
|
294
|
mqttQoSMap.remove(topicName);
|
273
|
295
|
try {
|
274
|
|
- if (topicName.equals(DEVICE_ATTRIBUTES_TOPIC)) {
|
275
|
|
- AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
276
|
|
- processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
277
|
|
- } else if (topicName.equals(DEVICE_RPC_REQUESTS_SUB_TOPIC)) {
|
278
|
|
- AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
279
|
|
- processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
280
|
|
- } else if (topicName.equals(DEVICE_ATTRIBUTES_RESPONSES_TOPIC)) {
|
281
|
|
- deviceSessionCtx.setDisallowAttributeResponses();
|
|
296
|
+ switch (topicName) {
|
|
297
|
+ case DEVICE_ATTRIBUTES_TOPIC: {
|
|
298
|
+ AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg);
|
|
299
|
+ processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
300
|
+ break;
|
|
301
|
+ }
|
|
302
|
+ case DEVICE_RPC_REQUESTS_SUB_TOPIC: {
|
|
303
|
+ AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg);
|
|
304
|
+ processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));
|
|
305
|
+ break;
|
|
306
|
+ }
|
|
307
|
+ case DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
|
|
308
|
+ deviceSessionCtx.setDisallowAttributeResponses();
|
|
309
|
+ break;
|
282
|
310
|
}
|
283
|
311
|
} catch (AdaptorException e) {
|
284
|
312
|
log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName);
|
...
|
...
|
|