Commit 5a80d75584d09b33a88b25fd63d9e41e95e2eafc
1 parent
2637babf
Added support of attribute update notifications
Showing
11 changed files
with
204 additions
and
128 deletions
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -216,12 +216,16 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -216,12 +216,16 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
216 | 216 | ||
217 | void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { | 217 | void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { |
218 | TransportToDeviceActorMsg msg = wrapper.getMsg(); | 218 | TransportToDeviceActorMsg msg = wrapper.getMsg(); |
219 | -// processSubscriptionCommands(context, msg); | ||
220 | // processRpcResponses(context, msg); | 219 | // processRpcResponses(context, msg); |
221 | if (msg.hasSessionEvent()) { | 220 | if (msg.hasSessionEvent()) { |
222 | processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); | 221 | processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); |
223 | } | 222 | } |
224 | - | 223 | + if (msg.hasSubscribeToAttributes()) { |
224 | + processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToAttributes()); | ||
225 | + } | ||
226 | + if (msg.hasSubscribeToRPC()) { | ||
227 | + processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToRPC()); | ||
228 | + } | ||
225 | if (msg.hasPostAttributes()) { | 229 | if (msg.hasPostAttributes()) { |
226 | handlePostAttributesRequest(context, msg.getSessionInfo(), msg.getPostAttributes()); | 230 | handlePostAttributesRequest(context, msg.getSessionInfo(), msg.getPostAttributes()); |
227 | reportActivity(); | 231 | reportActivity(); |
@@ -236,9 +240,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -236,9 +240,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
236 | // SessionMsgType sessionMsgType = msg.getPayload().getMsgType(); | 240 | // SessionMsgType sessionMsgType = msg.getPayload().getMsgType(); |
237 | // if (sessionMsgType.requiresRulesProcessing()) { | 241 | // if (sessionMsgType.requiresRulesProcessing()) { |
238 | // switch (sessionMsgType) { | 242 | // switch (sessionMsgType) { |
239 | -// case GET_ATTRIBUTES_REQUEST: | ||
240 | -// handleGetAttributesRequest(msg); | ||
241 | -// break; | ||
242 | // case TO_SERVER_RPC_REQUEST: | 243 | // case TO_SERVER_RPC_REQUEST: |
243 | // handleClientSideRPCRequest(context, msg); | 244 | // handleClientSideRPCRequest(context, msg); |
244 | // reportActivity(); | 245 | // reportActivity(); |
@@ -262,7 +263,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -262,7 +263,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
262 | private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { | 263 | private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { |
263 | ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, toOptionalSet(request.getClientAttributeNamesList())); | 264 | ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, toOptionalSet(request.getClientAttributeNamesList())); |
264 | ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, toOptionalSet(request.getSharedAttributeNamesList())); | 265 | ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, toOptionalSet(request.getSharedAttributeNamesList())); |
265 | - UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
266 | int requestId = request.getRequestId(); | 266 | int requestId = request.getRequestId(); |
267 | Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() { | 267 | Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() { |
268 | @Override | 268 | @Override |
@@ -272,7 +272,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -272,7 +272,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
272 | .addAllClientAttributeList(toTsKvProtos(result.get(0))) | 272 | .addAllClientAttributeList(toTsKvProtos(result.get(0))) |
273 | .addAllSharedAttributeList(toTsKvProtos(result.get(1))) | 273 | .addAllSharedAttributeList(toTsKvProtos(result.get(1))) |
274 | .build(); | 274 | .build(); |
275 | - sendToTransport(responseMsg, sessionId, sessionInfo); | 275 | + sendToTransport(responseMsg, sessionInfo); |
276 | } | 276 | } |
277 | 277 | ||
278 | @Override | 278 | @Override |
@@ -280,7 +280,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -280,7 +280,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
280 | GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() | 280 | GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() |
281 | .setError(t.getMessage()) | 281 | .setError(t.getMessage()) |
282 | .build(); | 282 | .build(); |
283 | - sendToTransport(responseMsg, sessionId, sessionInfo); | 283 | + sendToTransport(responseMsg, sessionInfo); |
284 | } | 284 | } |
285 | }); | 285 | }); |
286 | } | 286 | } |
@@ -353,28 +353,37 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -353,28 +353,37 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
353 | 353 | ||
354 | void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { | 354 | void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { |
355 | if (attributeSubscriptions.size() > 0) { | 355 | if (attributeSubscriptions.size() > 0) { |
356 | - ToDeviceMsg notification = null; | 356 | + boolean hasNotificationData = false; |
357 | + AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder(); | ||
357 | if (msg.isDeleted()) { | 358 | if (msg.isDeleted()) { |
358 | - List<AttributeKey> sharedKeys = msg.getDeletedKeys().stream() | 359 | + List<String> sharedKeys = msg.getDeletedKeys().stream() |
359 | .filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope())) | 360 | .filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope())) |
361 | + .map(AttributeKey::getAttributeKey) | ||
360 | .collect(Collectors.toList()); | 362 | .collect(Collectors.toList()); |
361 | - notification = new AttributesUpdateNotification(BasicAttributeKVMsg.fromDeleted(sharedKeys)); | 363 | + if (!sharedKeys.isEmpty()) { |
364 | + notification.addAllSharedDeleted(sharedKeys); | ||
365 | + hasNotificationData = true; | ||
366 | + } | ||
362 | } else { | 367 | } else { |
363 | if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { | 368 | if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { |
364 | List<AttributeKvEntry> attributes = new ArrayList<>(msg.getValues()); | 369 | List<AttributeKvEntry> attributes = new ArrayList<>(msg.getValues()); |
365 | if (attributes.size() > 0) { | 370 | if (attributes.size() > 0) { |
366 | - notification = new AttributesUpdateNotification(BasicAttributeKVMsg.fromShared(attributes)); | 371 | + List<TsKvProto> sharedUpdated = msg.getValues().stream().map(this::toTsKvProto) |
372 | + .collect(Collectors.toList()); | ||
373 | + if (!sharedUpdated.isEmpty()) { | ||
374 | + notification.addAllSharedUpdated(sharedUpdated); | ||
375 | + hasNotificationData = true; | ||
376 | + } | ||
367 | } else { | 377 | } else { |
368 | logger.debug("[{}] No public server side attributes changed!", deviceId); | 378 | logger.debug("[{}] No public server side attributes changed!", deviceId); |
369 | } | 379 | } |
370 | } | 380 | } |
371 | } | 381 | } |
372 | - if (notification != null) { | ||
373 | - ToDeviceMsg finalNotification = notification; | ||
374 | -// attributeSubscriptions.entrySet().forEach(sub -> { | ||
375 | -// ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(finalNotification, sub.getKey()); | ||
376 | -// sendMsgToSessionActor(response, sub.getValue().getServer()); | ||
377 | -// }); | 382 | + if (hasNotificationData) { |
383 | + AttributeUpdateNotificationMsg finalNotification = notification.build(); | ||
384 | + attributeSubscriptions.entrySet().forEach(sub -> { | ||
385 | + sendToTransport(finalNotification, sub.getKey(), sub.getValue()); | ||
386 | + }); | ||
378 | } | 387 | } |
379 | } else { | 388 | } else { |
380 | logger.debug("[{}] No registered attributes subscriptions to process!", deviceId); | 389 | logger.debug("[{}] No registered attributes subscriptions to process!", deviceId); |
@@ -414,25 +423,35 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -414,25 +423,35 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
414 | // } | 423 | // } |
415 | } | 424 | } |
416 | 425 | ||
417 | -// private void processSubscriptionCommands(ActorContext context, DeviceToDeviceActorMsg msg) { | ||
418 | -// SessionId sessionId = msg.getSessionId(); | ||
419 | -// SessionType sessionType = msg.getSessionType(); | ||
420 | -// FromDeviceMsg inMsg = msg.getPayload(); | ||
421 | -// if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) { | ||
422 | -// logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId); | ||
423 | -// attributeSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); | ||
424 | -// } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST) { | ||
425 | -// logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); | ||
426 | -// attributeSubscriptions.remove(sessionId); | ||
427 | -// } else if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST) { | ||
428 | -// logger.debug("[{}] Registering rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); | ||
429 | -// rpcSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); | ||
430 | -// sendPendingRequests(context, sessionId, sessionType, msg.getServerAddress()); | ||
431 | -// } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST) { | ||
432 | -// logger.debug("[{}] Canceling rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); | ||
433 | -// rpcSubscriptions.remove(sessionId); | ||
434 | -// } | ||
435 | -// } | 426 | + private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { |
427 | + UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
428 | + if (subscribeCmd.getUnsubscribe()) { | ||
429 | + logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); | ||
430 | + attributeSubscriptions.remove(sessionId); | ||
431 | + } else { | ||
432 | + SessionInfo session = sessions.get(sessionId); | ||
433 | + if (session == null) { | ||
434 | + session = new SessionInfo(TransportProtos.SessionType.SYNC, sessionInfo.getNodeId()); | ||
435 | + } | ||
436 | + logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId); | ||
437 | + attributeSubscriptions.put(sessionId, session); | ||
438 | + } | ||
439 | + } | ||
440 | + | ||
441 | + private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) { | ||
442 | + UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
443 | + if (subscribeCmd.getUnsubscribe()) { | ||
444 | + logger.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId); | ||
445 | + rpcSubscriptions.remove(sessionId); | ||
446 | + } else { | ||
447 | + SessionInfo session = sessions.get(sessionId); | ||
448 | + if (session == null) { | ||
449 | + session = new SessionInfo(TransportProtos.SessionType.SYNC, sessionInfo.getNodeId()); | ||
450 | + } | ||
451 | + logger.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId); | ||
452 | + rpcSubscriptions.put(sessionId, session); | ||
453 | + } | ||
454 | + } | ||
436 | 455 | ||
437 | private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { | 456 | private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { |
438 | UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | 457 | UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); |
@@ -521,11 +540,19 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -521,11 +540,19 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
521 | } | 540 | } |
522 | } | 541 | } |
523 | 542 | ||
524 | - private void sendToTransport(GetAttributeResponseMsg responseMsg, UUID sessionId, SessionInfoProto sessionInfo) { | 543 | + private void sendToTransport(GetAttributeResponseMsg responseMsg, SessionInfoProto sessionInfo) { |
544 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
545 | + .setSessionIdMSB(sessionInfo.getSessionIdMSB()) | ||
546 | + .setSessionIdLSB(sessionInfo.getSessionIdLSB()) | ||
547 | + .setGetAttributesResponse(responseMsg).build(); | ||
548 | + systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); | ||
549 | + } | ||
550 | + | ||
551 | + private void sendToTransport(AttributeUpdateNotificationMsg notificationMsg, UUID sessionId, SessionInfo sessionInfo) { | ||
525 | DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | 552 | DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() |
526 | .setSessionIdMSB(sessionId.getMostSignificantBits()) | 553 | .setSessionIdMSB(sessionId.getMostSignificantBits()) |
527 | .setSessionIdLSB(sessionId.getLeastSignificantBits()) | 554 | .setSessionIdLSB(sessionId.getLeastSignificantBits()) |
528 | - .setGetAttributesResponse(responseMsg).build(); | 555 | + .setAttributeUpdateNotification(notificationMsg).build(); |
529 | systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); | 556 | systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); |
530 | } | 557 | } |
531 | 558 |
@@ -25,5 +25,4 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | @@ -25,5 +25,4 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; | ||
25 | public class SessionInfo { | 25 | public class SessionInfo { |
26 | private final SessionType type; | 26 | private final SessionType type; |
27 | private final String nodeId; | 27 | private final String nodeId; |
28 | - | ||
29 | } | 28 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.transport; | 16 | package org.thingsboard.server.common.transport; |
17 | 17 | ||
18 | +import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | ||
18 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; | 19 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; |
19 | 20 | ||
20 | /** | 21 | /** |
@@ -23,4 +24,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse | @@ -23,4 +24,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse | ||
23 | public interface SessionMsgListener { | 24 | public interface SessionMsgListener { |
24 | 25 | ||
25 | void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse); | 26 | void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse); |
27 | + | ||
28 | + void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification); | ||
26 | } | 29 | } |
@@ -15,6 +15,8 @@ | @@ -15,6 +15,8 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.transport; | 16 | package org.thingsboard.server.common.transport; |
17 | 17 | ||
18 | +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; | ||
19 | +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; | ||
18 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 20 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
19 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | 21 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
20 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | 22 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; |
@@ -43,6 +45,10 @@ public interface TransportService { | @@ -43,6 +45,10 @@ public interface TransportService { | ||
43 | 45 | ||
44 | void process(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback); | 46 | void process(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback); |
45 | 47 | ||
48 | + void process(SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback); | ||
49 | + | ||
50 | + void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback); | ||
51 | + | ||
46 | void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener); | 52 | void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener); |
47 | 53 | ||
48 | void deregisterSession(SessionInfoProto sessionInfo); | 54 | void deregisterSession(SessionInfoProto sessionInfo); |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg; | @@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg; | ||
39 | import org.thingsboard.server.common.msg.core.ToServerRpcRequestMsg; | 39 | import org.thingsboard.server.common.msg.core.ToServerRpcRequestMsg; |
40 | import org.thingsboard.server.common.msg.core.ToServerRpcResponseMsg; | 40 | import org.thingsboard.server.common.msg.core.ToServerRpcResponseMsg; |
41 | import org.thingsboard.server.common.msg.kv.AttributesKVMsg; | 41 | import org.thingsboard.server.common.msg.kv.AttributesKVMsg; |
42 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
42 | import org.thingsboard.server.gen.transport.TransportProtos.*; | 43 | import org.thingsboard.server.gen.transport.TransportProtos.*; |
43 | 44 | ||
44 | import java.util.ArrayList; | 45 | import java.util.ArrayList; |
@@ -153,20 +154,6 @@ public class JsonConverter { | @@ -153,20 +154,6 @@ public class JsonConverter { | ||
153 | return result; | 154 | return result; |
154 | } | 155 | } |
155 | 156 | ||
156 | - private static void parseNumericProto(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { | ||
157 | - if (value.getAsString().contains(".")) { | ||
158 | - result.add(new DoubleDataEntry(valueEntry.getKey(), value.getAsDouble())); | ||
159 | - } else { | ||
160 | - try { | ||
161 | - long longValue = Long.parseLong(value.getAsString()); | ||
162 | - result.add(new LongDataEntry(valueEntry.getKey(), longValue)); | ||
163 | - } catch (NumberFormatException e) { | ||
164 | - throw new JsonSyntaxException("Big integer values are not supported!"); | ||
165 | - } | ||
166 | - } | ||
167 | - } | ||
168 | - | ||
169 | - | ||
170 | private static TelemetryUploadRequest convertToTelemetry(JsonElement jsonObject, long systemTs, int requestId) throws JsonSyntaxException { | 157 | private static TelemetryUploadRequest convertToTelemetry(JsonElement jsonObject, long systemTs, int requestId) throws JsonSyntaxException { |
171 | BasicTelemetryUploadRequest request = new BasicTelemetryUploadRequest(requestId); | 158 | BasicTelemetryUploadRequest request = new BasicTelemetryUploadRequest(requestId); |
172 | if (jsonObject.isJsonObject()) { | 159 | if (jsonObject.isJsonObject()) { |
@@ -283,6 +270,19 @@ public class JsonConverter { | @@ -283,6 +270,19 @@ public class JsonConverter { | ||
283 | return result; | 270 | return result; |
284 | } | 271 | } |
285 | 272 | ||
273 | + public static JsonElement toJson(AttributeUpdateNotificationMsg payload) { | ||
274 | + JsonObject result = new JsonObject(); | ||
275 | + if (payload.getSharedUpdatedCount() > 0) { | ||
276 | + payload.getSharedUpdatedList().forEach(addToObjectFromProto(result)); | ||
277 | + } | ||
278 | + if (payload.getSharedDeletedCount() > 0) { | ||
279 | + JsonArray attrObject = new JsonArray(); | ||
280 | + payload.getSharedDeletedList().forEach(attrObject::add); | ||
281 | + result.add("deleted", attrObject); | ||
282 | + } | ||
283 | + return result; | ||
284 | + } | ||
285 | + | ||
286 | public static JsonObject toJson(AttributesKVMsg payload, boolean asMap) { | 286 | public static JsonObject toJson(AttributesKVMsg payload, boolean asMap) { |
287 | JsonObject result = new JsonObject(); | 287 | JsonObject result = new JsonObject(); |
288 | if (asMap) { | 288 | if (asMap) { |
@@ -377,4 +377,5 @@ public class JsonConverter { | @@ -377,4 +377,5 @@ public class JsonConverter { | ||
377 | error.addProperty("error", errorMsg); | 377 | error.addProperty("error", errorMsg); |
378 | return error; | 378 | return error; |
379 | } | 379 | } |
380 | + | ||
380 | } | 381 | } |
@@ -108,6 +108,11 @@ message GetAttributeResponseMsg { | @@ -108,6 +108,11 @@ message GetAttributeResponseMsg { | ||
108 | string error = 5; | 108 | string error = 5; |
109 | } | 109 | } |
110 | 110 | ||
111 | +message AttributeUpdateNotificationMsg { | ||
112 | + repeated TsKvProto sharedUpdated = 1; | ||
113 | + repeated string sharedDeleted = 2; | ||
114 | +} | ||
115 | + | ||
111 | message ValidateDeviceTokenRequestMsg { | 116 | message ValidateDeviceTokenRequestMsg { |
112 | string token = 1; | 117 | string token = 1; |
113 | } | 118 | } |
@@ -124,12 +129,22 @@ message SessionCloseNotificationProto { | @@ -124,12 +129,22 @@ message SessionCloseNotificationProto { | ||
124 | string message = 1; | 129 | string message = 1; |
125 | } | 130 | } |
126 | 131 | ||
132 | +message SubscribeToAttributeUpdatesMsg { | ||
133 | + bool unsubscribe = 1; | ||
134 | +} | ||
135 | + | ||
136 | +message SubscribeToRPCMsg { | ||
137 | + bool unsubscribe = 1; | ||
138 | +} | ||
139 | + | ||
127 | message TransportToDeviceActorMsg { | 140 | message TransportToDeviceActorMsg { |
128 | SessionInfoProto sessionInfo = 1; | 141 | SessionInfoProto sessionInfo = 1; |
129 | SessionEventMsg sessionEvent = 2; | 142 | SessionEventMsg sessionEvent = 2; |
130 | PostTelemetryMsg postTelemetry = 3; | 143 | PostTelemetryMsg postTelemetry = 3; |
131 | PostAttributeMsg postAttributes = 4; | 144 | PostAttributeMsg postAttributes = 4; |
132 | GetAttributeRequestMsg getAttributes = 5; | 145 | GetAttributeRequestMsg getAttributes = 5; |
146 | + SubscribeToAttributeUpdatesMsg subscribeToAttributes = 6; | ||
147 | + SubscribeToRPCMsg subscribeToRPC= 7; | ||
133 | } | 148 | } |
134 | 149 | ||
135 | message DeviceActorToTransportMsg { | 150 | message DeviceActorToTransportMsg { |
@@ -137,6 +152,7 @@ message DeviceActorToTransportMsg { | @@ -137,6 +152,7 @@ message DeviceActorToTransportMsg { | ||
137 | int64 sessionIdLSB = 2; | 152 | int64 sessionIdLSB = 2; |
138 | SessionCloseNotificationProto sessionCloseNotification = 3; | 153 | SessionCloseNotificationProto sessionCloseNotification = 3; |
139 | GetAttributeResponseMsg getAttributesResponse = 4; | 154 | GetAttributeResponseMsg getAttributesResponse = 4; |
155 | + AttributeUpdateNotificationMsg attributeUpdateNotification = 5; | ||
140 | } | 156 | } |
141 | 157 | ||
142 | /** | 158 | /** |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -71,6 +71,7 @@ import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEP | @@ -71,6 +71,7 @@ import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEP | ||
71 | import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; | 71 | import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; |
72 | import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; | 72 | import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; |
73 | import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK; | 73 | import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK; |
74 | +import static io.netty.handler.codec.mqtt.MqttMessageType.PINGRESP; | ||
74 | import static io.netty.handler.codec.mqtt.MqttMessageType.PUBACK; | 75 | import static io.netty.handler.codec.mqtt.MqttMessageType.PUBACK; |
75 | import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK; | 76 | import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK; |
76 | import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; | 77 | import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; |
@@ -148,16 +149,17 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -148,16 +149,17 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
148 | case UNSUBSCRIBE: | 149 | case UNSUBSCRIBE: |
149 | processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg); | 150 | processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg); |
150 | break; | 151 | break; |
151 | -// case PINGREQ: | ||
152 | -// if (checkConnected(ctx)) { | ||
153 | -// ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); | ||
154 | -// } | ||
155 | -// break; | ||
156 | -// case DISCONNECT: | ||
157 | -// if (checkConnected(ctx)) { | ||
158 | -// processDisconnect(ctx); | ||
159 | -// } | ||
160 | -// break; | 152 | + case PINGREQ: |
153 | + //TODO: should we push the notification to the rule engine? | ||
154 | + if (checkConnected(ctx)) { | ||
155 | + ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); | ||
156 | + } | ||
157 | + break; | ||
158 | + case DISCONNECT: | ||
159 | + if (checkConnected(ctx)) { | ||
160 | + processDisconnect(ctx); | ||
161 | + } | ||
162 | + break; | ||
161 | default: | 163 | default: |
162 | break; | 164 | break; |
163 | } | 165 | } |
@@ -289,25 +291,20 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -289,25 +291,20 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
289 | MqttQoS reqQoS = subscription.qualityOfService(); | 291 | MqttQoS reqQoS = subscription.qualityOfService(); |
290 | try { | 292 | try { |
291 | switch (topic) { | 293 | switch (topic) { |
292 | -// case MqttTopics.DEVICE_ATTRIBUTES_TOPIC: { | ||
293 | -// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg); | ||
294 | -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); | ||
295 | -// registerSubQoS(topic, grantedQoSList, reqQoS); | ||
296 | -// break; | ||
297 | -// } | ||
298 | -// case DEVICE_RPC_REQUESTS_SUB_TOPIC: { | ||
299 | -// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, SUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg); | ||
300 | -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); | ||
301 | -// registerSubQoS(topic, grantedQoSList, reqQoS); | ||
302 | -// break; | ||
303 | -// } | ||
304 | -// case DEVICE_RPC_RESPONSE_SUB_TOPIC: | ||
305 | -// case GATEWAY_ATTRIBUTES_TOPIC: | ||
306 | -// case GATEWAY_RPC_TOPIC: | ||
307 | -// registerSubQoS(topic, grantedQoSList, reqQoS); | ||
308 | -// break; | 294 | + case MqttTopics.DEVICE_ATTRIBUTES_TOPIC: { |
295 | + transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); | ||
296 | + registerSubQoS(topic, grantedQoSList, reqQoS); | ||
297 | + break; | ||
298 | + } | ||
299 | + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC: { | ||
300 | + transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); | ||
301 | + registerSubQoS(topic, grantedQoSList, reqQoS); | ||
302 | + break; | ||
303 | + } | ||
304 | + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC: | ||
305 | + case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC: | ||
306 | + case MqttTopics.GATEWAY_RPC_TOPIC: | ||
309 | case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC: | 307 | case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC: |
310 | - deviceSessionCtx.setAllowAttributeResponses(); | ||
311 | registerSubQoS(topic, grantedQoSList, reqQoS); | 308 | registerSubQoS(topic, grantedQoSList, reqQoS); |
312 | break; | 309 | break; |
313 | default: | 310 | default: |
@@ -337,19 +334,14 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -337,19 +334,14 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
337 | mqttQoSMap.remove(topicName); | 334 | mqttQoSMap.remove(topicName); |
338 | try { | 335 | try { |
339 | switch (topicName) { | 336 | switch (topicName) { |
340 | -// case DEVICE_ATTRIBUTES_TOPIC: { | ||
341 | -// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_ATTRIBUTES_REQUEST, mqttMsg); | ||
342 | -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); | ||
343 | -// break; | ||
344 | -// } | ||
345 | -// case DEVICE_RPC_REQUESTS_SUB_TOPIC: { | ||
346 | -// AdaptorToSessionActorMsg msg = adaptor.convertToActorMsg(deviceSessionCtx, UNSUBSCRIBE_RPC_COMMANDS_REQUEST, mqttMsg); | ||
347 | -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg)); | ||
348 | -// break; | ||
349 | -// } | ||
350 | - case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC: | ||
351 | - deviceSessionCtx.setDisallowAttributeResponses(); | 337 | + case MqttTopics.DEVICE_ATTRIBUTES_TOPIC: { |
338 | + transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setUnsubscribe(true).build(), null); | ||
339 | + break; | ||
340 | + } | ||
341 | + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC: { | ||
342 | + transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().setUnsubscribe(true).build(), null); | ||
352 | break; | 343 | break; |
344 | + } | ||
353 | } | 345 | } |
354 | } catch (Exception e) { | 346 | } catch (Exception e) { |
355 | log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName); | 347 | log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName); |
@@ -551,7 +543,16 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -551,7 +543,16 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
551 | try { | 543 | try { |
552 | adaptor.convertToPublish(deviceSessionCtx, response).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); | 544 | adaptor.convertToPublish(deviceSessionCtx, response).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
553 | } catch (Exception e) { | 545 | } catch (Exception e) { |
554 | - log.trace("[{}] Failed to convert device attributes to MQTT msg", sessionId, e); | 546 | + log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e); |
547 | + } | ||
548 | + } | ||
549 | + | ||
550 | + @Override | ||
551 | + public void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg notification) { | ||
552 | + try { | ||
553 | + adaptor.convertToPublish(deviceSessionCtx, notification).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); | ||
554 | + } catch (Exception e) { | ||
555 | + log.trace("[{}] Failed to convert device attributes update to MQTT msg", sessionId, e); | ||
555 | } | 556 | } |
556 | } | 557 | } |
557 | } | 558 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -114,6 +114,13 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | @@ -114,6 +114,13 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | ||
114 | } | 114 | } |
115 | 115 | ||
116 | @Override | 116 | @Override |
117 | + public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException { | ||
118 | + return Optional.of(createMqttPublishMsg(ctx, | ||
119 | + MqttTopics.DEVICE_ATTRIBUTES_TOPIC, | ||
120 | + JsonConverter.toJson(notificationMsg))); | ||
121 | + } | ||
122 | + | ||
123 | + @Override | ||
117 | public AdaptorToSessionActorMsg convertToActorMsg(DeviceSessionCtx ctx, SessionMsgType type, MqttMessage inbound) throws AdaptorException { | 124 | public AdaptorToSessionActorMsg convertToActorMsg(DeviceSessionCtx ctx, SessionMsgType type, MqttMessage inbound) throws AdaptorException { |
118 | FromDeviceMsg msg; | 125 | FromDeviceMsg msg; |
119 | switch (type) { | 126 | switch (type) { |
@@ -36,4 +36,8 @@ public interface MqttTransportAdaptor extends TransportAdaptor<DeviceSessionCtx, | @@ -36,4 +36,8 @@ public interface MqttTransportAdaptor extends TransportAdaptor<DeviceSessionCtx, | ||
36 | TransportProtos.GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; | 36 | TransportProtos.GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; |
37 | 37 | ||
38 | Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException; | 38 | Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException; |
39 | + | ||
40 | + Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; | ||
41 | + | ||
42 | + | ||
39 | } | 43 | } |
@@ -44,7 +44,6 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -44,7 +44,6 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
44 | private final MqttSessionId sessionId; | 44 | private final MqttSessionId sessionId; |
45 | @Getter | 45 | @Getter |
46 | private ChannelHandlerContext channel; | 46 | private ChannelHandlerContext channel; |
47 | - private volatile boolean allowAttributeResponses; | ||
48 | private AtomicInteger msgIdSeq = new AtomicInteger(0); | 47 | private AtomicInteger msgIdSeq = new AtomicInteger(0); |
49 | 48 | ||
50 | public DeviceSessionCtx(ConcurrentMap<String, Integer> mqttQoSMap) { | 49 | public DeviceSessionCtx(ConcurrentMap<String, Integer> mqttQoSMap) { |
@@ -103,14 +102,6 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -103,14 +102,6 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
103 | this.channel = channel; | 102 | this.channel = channel; |
104 | } | 103 | } |
105 | 104 | ||
106 | - public void setAllowAttributeResponses() { | ||
107 | - allowAttributeResponses = true; | ||
108 | - } | ||
109 | - | ||
110 | - public void setDisallowAttributeResponses() { | ||
111 | - allowAttributeResponses = false; | ||
112 | - } | ||
113 | - | ||
114 | public int nextMsgId() { | 105 | public int nextMsgId() { |
115 | return msgIdSeq.incrementAndGet(); | 106 | return msgIdSeq.incrementAndGet(); |
116 | } | 107 | } |
transport/mqtt-transport/src/main/java/org/thingsboard/server/mqtt/service/MqttTransportService.java
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -161,6 +161,9 @@ public class MqttTransportService implements TransportService { | @@ -161,6 +161,9 @@ public class MqttTransportService implements TransportService { | ||
161 | if (toSessionMsg.hasGetAttributesResponse()) { | 161 | if (toSessionMsg.hasGetAttributesResponse()) { |
162 | listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse()); | 162 | listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse()); |
163 | } | 163 | } |
164 | + if (toSessionMsg.hasAttributeUpdateNotification()) { | ||
165 | + listener.onAttributeUpdate(toSessionMsg.getAttributeUpdateNotification()); | ||
166 | + } | ||
164 | }); | 167 | }); |
165 | } else { | 168 | } else { |
166 | //TODO: should we notify the device actor about missed session? | 169 | //TODO: should we notify the device actor about missed session? |
@@ -252,6 +255,24 @@ public class MqttTransportService implements TransportService { | @@ -252,6 +255,24 @@ public class MqttTransportService implements TransportService { | ||
252 | } | 255 | } |
253 | 256 | ||
254 | @Override | 257 | @Override |
258 | + public void process(SessionInfoProto sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) { | ||
259 | + ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg( | ||
260 | + TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
261 | + .setSubscribeToAttributes(msg).build() | ||
262 | + ).build(); | ||
263 | + send(sessionInfo, toRuleEngineMsg, callback); | ||
264 | + } | ||
265 | + | ||
266 | + @Override | ||
267 | + public void process(SessionInfoProto sessionInfo, TransportProtos.SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) { | ||
268 | + ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg( | ||
269 | + TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
270 | + .setSubscribeToRPC(msg).build() | ||
271 | + ).build(); | ||
272 | + send(sessionInfo, toRuleEngineMsg, callback); | ||
273 | + } | ||
274 | + | ||
275 | + @Override | ||
255 | public void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener) { | 276 | public void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener) { |
256 | sessions.putIfAbsent(toId(sessionInfo), listener); | 277 | sessions.putIfAbsent(toId(sessionInfo), listener); |
257 | //TODO: monitor sessions periodically: PING REQ/RESP, etc. | 278 | //TODO: monitor sessions periodically: PING REQ/RESP, etc. |