Commit 950ec8d622cd5c0c851de63f715959e1a3a4e168

Authored by Andrew Shvayka
1 parent 5a80d755

MQTT API implementation

1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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.
@@ -32,7 +32,6 @@ import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; @@ -32,7 +32,6 @@ import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor;
32 import org.thingsboard.server.common.data.DataConstants; 32 import org.thingsboard.server.common.data.DataConstants;
33 import org.thingsboard.server.common.data.Device; 33 import org.thingsboard.server.common.data.Device;
34 import org.thingsboard.server.common.data.id.DeviceId; 34 import org.thingsboard.server.common.data.id.DeviceId;
35 -import org.thingsboard.server.common.data.id.SessionId;  
36 import org.thingsboard.server.common.data.id.TenantId; 35 import org.thingsboard.server.common.data.id.TenantId;
37 import org.thingsboard.server.common.data.kv.AttributeKey; 36 import org.thingsboard.server.common.data.kv.AttributeKey;
38 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 37 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@@ -44,18 +43,33 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -44,18 +43,33 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
44 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 43 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
45 import org.thingsboard.server.common.msg.cluster.ServerAddress; 44 import org.thingsboard.server.common.msg.cluster.ServerAddress;
46 import org.thingsboard.server.common.msg.core.ActorSystemToDeviceSessionActorMsg; 45 import org.thingsboard.server.common.msg.core.ActorSystemToDeviceSessionActorMsg;
47 -import org.thingsboard.server.common.msg.core.AttributesUpdateNotification;  
48 import org.thingsboard.server.common.msg.core.RuleEngineError; 46 import org.thingsboard.server.common.msg.core.RuleEngineError;
49 import org.thingsboard.server.common.msg.core.RuleEngineErrorMsg; 47 import org.thingsboard.server.common.msg.core.RuleEngineErrorMsg;
50 -import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg;  
51 -import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg;  
52 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; 48 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
53 import org.thingsboard.server.common.msg.session.SessionMsgType; 49 import org.thingsboard.server.common.msg.session.SessionMsgType;
54 -import org.thingsboard.server.common.msg.session.SessionType;  
55 import org.thingsboard.server.common.msg.session.ToDeviceMsg; 50 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
56 import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; 51 import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg;
57 import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; 52 import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg;
58 import org.thingsboard.server.gen.transport.TransportProtos; 53 import org.thingsboard.server.gen.transport.TransportProtos;
  54 +import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
  55 +import org.thingsboard.server.gen.transport.TransportProtos.DeviceActorToTransportMsg;
  56 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
  57 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
  58 +import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto;
  59 +import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType;
  60 +import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
  61 +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
  62 +import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
  63 +import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;
  64 +import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg;
  65 +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
  66 +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
  67 +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg;
  68 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
  69 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
  70 +import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
  71 +import org.thingsboard.server.gen.transport.TransportProtos.TsKvListProto;
  72 +import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
59 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; 73 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
60 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; 74 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg;
61 import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; 75 import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg;
@@ -76,8 +90,6 @@ import java.util.UUID; @@ -76,8 +90,6 @@ import java.util.UUID;
76 import java.util.function.Consumer; 90 import java.util.function.Consumer;
77 import java.util.stream.Collectors; 91 import java.util.stream.Collectors;
78 92
79 -import org.thingsboard.server.gen.transport.TransportProtos.*;  
80 -  
81 /** 93 /**
82 * @author Andrew Shvayka 94 * @author Andrew Shvayka
83 */ 95 */
@@ -123,11 +135,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -123,11 +135,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
123 void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) { 135 void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) {
124 ToDeviceRpcRequest request = msg.getMsg(); 136 ToDeviceRpcRequest request = msg.getMsg();
125 ToDeviceRpcRequestBody body = request.getBody(); 137 ToDeviceRpcRequestBody body = request.getBody();
126 - ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(  
127 - rpcSeq++,  
128 - body.getMethod(),  
129 - body.getParams()  
130 - ); 138 + ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId(
  139 + rpcSeq++).setMethodName(body.getMethod()).setParams(body.getParams()).build();
131 140
132 long timeout = request.getExpirationTime() - System.currentTimeMillis(); 141 long timeout = request.getExpirationTime() - System.currentTimeMillis();
133 if (timeout <= 0) { 142 if (timeout <= 0) {
@@ -136,13 +145,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -136,13 +145,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
136 } 145 }
137 146
138 boolean sent = rpcSubscriptions.size() > 0; 147 boolean sent = rpcSubscriptions.size() > 0;
139 - Set<SessionId> syncSessionSet = new HashSet<>(); 148 + Set<UUID> syncSessionSet = new HashSet<>();
140 rpcSubscriptions.entrySet().forEach(sub -> { 149 rpcSubscriptions.entrySet().forEach(sub -> {
141 -// ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(rpcRequest, sub.getKey());  
142 -// sendMsgToSessionActor(response, sub.getValue().getServer());  
143 -// if (SessionType.SYNC == sub.getValue().getType()) {  
144 -// syncSessionSet.add(sub.getKey());  
145 -// } 150 + sendToTransport(rpcRequest, sub.getKey(), sub.getValue().getNodeId());
  151 + if (TransportProtos.SessionType.SYNC == sub.getValue().getType()) {
  152 + syncSessionSet.add(sub.getKey());
  153 + }
146 }); 154 });
147 syncSessionSet.forEach(rpcSubscriptions::remove); 155 syncSessionSet.forEach(rpcSubscriptions::remove);
148 156
@@ -175,10 +183,11 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -175,10 +183,11 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
175 } 183 }
176 } 184 }
177 185
178 - private void sendPendingRequests(ActorContext context, SessionId sessionId, SessionType type, Optional<ServerAddress> server) { 186 + private void sendPendingRequests(ActorContext context, UUID sessionId, SessionInfoProto sessionInfo) {
  187 + TransportProtos.SessionType sessionType = getSessionType(sessionId);
179 if (!toDeviceRpcPendingMap.isEmpty()) { 188 if (!toDeviceRpcPendingMap.isEmpty()) {
180 logger.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId); 189 logger.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId);
181 - if (type == SessionType.SYNC) { 190 + if (sessionType == TransportProtos.SessionType.SYNC) {
182 logger.debug("[{}] Cleanup sync rpc session [{}]", deviceId, sessionId); 191 logger.debug("[{}] Cleanup sync rpc session [{}]", deviceId, sessionId);
183 rpcSubscriptions.remove(sessionId); 192 rpcSubscriptions.remove(sessionId);
184 } 193 }
@@ -186,16 +195,16 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -186,16 +195,16 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
186 logger.debug("[{}] No pending RPC messages for new async session [{}]", deviceId, sessionId); 195 logger.debug("[{}] No pending RPC messages for new async session [{}]", deviceId, sessionId);
187 } 196 }
188 Set<Integer> sentOneWayIds = new HashSet<>(); 197 Set<Integer> sentOneWayIds = new HashSet<>();
189 - if (type == SessionType.ASYNC) {  
190 - toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, server, sentOneWayIds)); 198 + if (sessionType == TransportProtos.SessionType.ASYNC) {
  199 + toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
191 } else { 200 } else {
192 - toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, server, sentOneWayIds)); 201 + toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
193 } 202 }
194 203
195 sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); 204 sentOneWayIds.forEach(toDeviceRpcPendingMap::remove);
196 } 205 }
197 206
198 - private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(ActorContext context, SessionId sessionId, Optional<ServerAddress> server, Set<Integer> sentOneWayIds) { 207 + private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(ActorContext context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) {
199 return entry -> { 208 return entry -> {
200 ToDeviceRpcRequestActorMsg requestActorMsg = entry.getValue().getMsg(); 209 ToDeviceRpcRequestActorMsg requestActorMsg = entry.getValue().getMsg();
201 ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); 210 ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg();
@@ -204,19 +213,14 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -204,19 +213,14 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
204 sentOneWayIds.add(entry.getKey()); 213 sentOneWayIds.add(entry.getKey());
205 systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(request.getId(), requestActorMsg.getServerAddress(), null, null)); 214 systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(request.getId(), requestActorMsg.getServerAddress(), null, null));
206 } 215 }
207 - ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(  
208 - entry.getKey(),  
209 - body.getMethod(),  
210 - body.getParams()  
211 - );  
212 -// ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(rpcRequest, sessionId);  
213 -// sendMsgToSessionActor(response, server); 216 + ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId(
  217 + entry.getKey()).setMethodName(body.getMethod()).setParams(body.getParams()).build();
  218 + sendToTransport(rpcRequest, sessionId, nodeId);
214 }; 219 };
215 } 220 }
216 221
217 void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { 222 void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) {
218 TransportToDeviceActorMsg msg = wrapper.getMsg(); 223 TransportToDeviceActorMsg msg = wrapper.getMsg();
219 -// processRpcResponses(context, msg);  
220 if (msg.hasSessionEvent()) { 224 if (msg.hasSessionEvent()) {
221 processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); 225 processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent());
222 } 226 }
@@ -237,15 +241,13 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -237,15 +241,13 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
237 if (msg.hasGetAttributes()) { 241 if (msg.hasGetAttributes()) {
238 handleGetAttributesRequest(context, msg.getSessionInfo(), msg.getGetAttributes()); 242 handleGetAttributesRequest(context, msg.getSessionInfo(), msg.getGetAttributes());
239 } 243 }
240 -// SessionMsgType sessionMsgType = msg.getPayload().getMsgType();  
241 -// if (sessionMsgType.requiresRulesProcessing()) {  
242 -// switch (sessionMsgType) {  
243 -// case TO_SERVER_RPC_REQUEST:  
244 -// handleClientSideRPCRequest(context, msg);  
245 -// reportActivity();  
246 -// break;  
247 -// }  
248 -// } 244 + if (msg.hasToDeviceRPCCallResponse()) {
  245 + processRpcResponses(context, msg.getSessionInfo(), msg.getToDeviceRPCCallResponse());
  246 + }
  247 + if (msg.hasToServerRPCCallRequest()) {
  248 + handleClientSideRPCRequest(context, msg.getSessionInfo(), msg.getToServerRPCCallRequest());
  249 + reportActivity();
  250 + }
249 } 251 }
250 252
251 private void reportActivity() { 253 private void reportActivity() {
@@ -314,36 +316,42 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -314,36 +316,42 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
314 } 316 }
315 } 317 }
316 318
317 -// private void handleClientSideRPCRequest(ActorContext context, DeviceToDeviceActorMsg src) {  
318 -// ToServerRpcRequestMsg request = (ToServerRpcRequestMsg) src.getPayload();  
319 -//  
320 -// JsonObject json = new JsonObject();  
321 -// json.addProperty("method", request.getMethod());  
322 -// json.add("params", jsonParser.parse(request.getParams()));  
323 -//  
324 -// TbMsgMetaData requestMetaData = defaultMetaData.copy();  
325 -// requestMetaData.putValue("requestId", Integer.toString(request.getRequestId()));  
326 -// TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.TO_SERVER_RPC_REQUEST.name(), deviceId, requestMetaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L);  
327 -// PendingSessionMsgData msgData = new PendingSessionMsgData(src.getSessionId(), src.getServerAddress(), SessionMsgType.TO_SERVER_RPC_REQUEST, request.getRequestId(), false, 1);  
328 -// pushToRuleEngineWithTimeout(context, tbMsg, msgData);  
329 -//  
330 -// scheduleMsgWithDelay(context, new DeviceActorClientSideRpcTimeoutMsg(request.getRequestId(), systemContext.getClientSideRpcTimeout()), systemContext.getClientSideRpcTimeout());  
331 -// toServerRpcPendingMap.put(request.getRequestId(), new ToServerRpcRequestMetadata(src.getSessionId(), src.getSessionType(), src.getServerAddress()));  
332 -// } 319 + private void handleClientSideRPCRequest(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg request) {
  320 + UUID sessionId = getSessionId(sessionInfo);
  321 + JsonObject json = new JsonObject();
  322 + json.addProperty("method", request.getMethodName());
  323 + json.add("params", jsonParser.parse(request.getParams()));
  324 +
  325 + TbMsgMetaData requestMetaData = defaultMetaData.copy();
  326 + requestMetaData.putValue("requestId", Integer.toString(request.getRequestId()));
  327 + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.TO_SERVER_RPC_REQUEST.name(), deviceId, requestMetaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L);
  328 + context.parent().tell(new DeviceActorToRuleEngineMsg(context.self(), tbMsg), context.self());
  329 +
  330 + scheduleMsgWithDelay(context, new DeviceActorClientSideRpcTimeoutMsg(request.getRequestId(), systemContext.getClientSideRpcTimeout()), systemContext.getClientSideRpcTimeout());
  331 + toServerRpcPendingMap.put(request.getRequestId(), new ToServerRpcRequestMetadata(sessionId, getSessionType(sessionId), sessionInfo.getNodeId()));
  332 + }
333 333
334 - public void processClientSideRpcTimeout(ActorContext context, DeviceActorClientSideRpcTimeoutMsg msg) { 334 + private TransportProtos.SessionType getSessionType(UUID sessionId) {
  335 + return sessions.containsKey(sessionId) ? TransportProtos.SessionType.ASYNC : TransportProtos.SessionType.SYNC;
  336 + }
  337 +
  338 + void processClientSideRpcTimeout(ActorContext context, DeviceActorClientSideRpcTimeoutMsg msg) {
335 ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getId()); 339 ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getId());
336 if (data != null) { 340 if (data != null) {
337 logger.debug("[{}] Client side RPC request [{}] timeout detected!", deviceId, msg.getId()); 341 logger.debug("[{}] Client side RPC request [{}] timeout detected!", deviceId, msg.getId());
338 - ToDeviceMsg toDeviceMsg = new RuleEngineErrorMsg(SessionMsgType.TO_SERVER_RPC_REQUEST, RuleEngineError.TIMEOUT);  
339 -// sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServer()); 342 + sendToTransport(TransportProtos.ToServerRpcResponseMsg.newBuilder()
  343 + .setRequestId(msg.getId()).setError("timeout").build()
  344 + , data.getSessionId(), data.getNodeId());
340 } 345 }
341 } 346 }
342 347
343 void processToServerRPCResponse(ActorContext context, ToServerRpcResponseActorMsg msg) { 348 void processToServerRPCResponse(ActorContext context, ToServerRpcResponseActorMsg msg) {
344 - ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getMsg().getRequestId()); 349 + int requestId = msg.getMsg().getRequestId();
  350 + ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(requestId);
345 if (data != null) { 351 if (data != null) {
346 -// sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(msg.getMsg(), data.getSessionId()), data.getServer()); 352 + sendToTransport(TransportProtos.ToServerRpcResponseMsg.newBuilder()
  353 + .setRequestId(requestId).setPayload(msg.getMsg().getData()).build()
  354 + , data.getSessionId(), data.getNodeId());
347 } 355 }
348 } 356 }
349 357
@@ -382,7 +390,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -382,7 +390,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
382 if (hasNotificationData) { 390 if (hasNotificationData) {
383 AttributeUpdateNotificationMsg finalNotification = notification.build(); 391 AttributeUpdateNotificationMsg finalNotification = notification.build();
384 attributeSubscriptions.entrySet().forEach(sub -> { 392 attributeSubscriptions.entrySet().forEach(sub -> {
385 - sendToTransport(finalNotification, sub.getKey(), sub.getValue()); 393 + sendToTransport(finalNotification, sub.getKey(), sub.getValue().getNodeId());
386 }); 394 });
387 } 395 }
388 } else { 396 } else {
@@ -390,6 +398,19 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -390,6 +398,19 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
390 } 398 }
391 } 399 }
392 400
  401 + private void processRpcResponses(ActorContext context, SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg responseMsg) {
  402 + UUID sessionId = getSessionId(sessionInfo);
  403 + logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId);
  404 + ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId());
  405 + boolean success = requestMd != null;
  406 + if (success) {
  407 + systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(),
  408 + requestMd.getMsg().getServerAddress(), responseMsg.getPayload(), null));
  409 + } else {
  410 + logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
  411 + }
  412 + }
  413 +
393 // private void processRpcResponses(ActorContext context, DeviceToDeviceActorMsg msg) { 414 // private void processRpcResponses(ActorContext context, DeviceToDeviceActorMsg msg) {
394 // SessionId sessionId = msg.getSessionId(); 415 // SessionId sessionId = msg.getSessionId();
395 // FromDeviceMsg inMsg = msg.getPayload(); 416 // FromDeviceMsg inMsg = msg.getPayload();
@@ -424,7 +445,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -424,7 +445,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
424 } 445 }
425 446
426 private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { 447 private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) {
427 - UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); 448 + UUID sessionId = getSessionId(sessionInfo);
428 if (subscribeCmd.getUnsubscribe()) { 449 if (subscribeCmd.getUnsubscribe()) {
429 logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); 450 logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId);
430 attributeSubscriptions.remove(sessionId); 451 attributeSubscriptions.remove(sessionId);
@@ -438,8 +459,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -438,8 +459,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
438 } 459 }
439 } 460 }
440 461
  462 + private UUID getSessionId(SessionInfoProto sessionInfo) {
  463 + return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());
  464 + }
  465 +
441 private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) { 466 private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) {
442 - UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); 467 + UUID sessionId = getSessionId(sessionInfo);
443 if (subscribeCmd.getUnsubscribe()) { 468 if (subscribeCmd.getUnsubscribe()) {
444 logger.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId); 469 logger.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId);
445 rpcSubscriptions.remove(sessionId); 470 rpcSubscriptions.remove(sessionId);
@@ -450,11 +475,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -450,11 +475,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
450 } 475 }
451 logger.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId); 476 logger.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId);
452 rpcSubscriptions.put(sessionId, session); 477 rpcSubscriptions.put(sessionId, session);
  478 + sendPendingRequests(context, sessionId, sessionInfo);
453 } 479 }
454 } 480 }
455 481
456 private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { 482 private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) {
457 - UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); 483 + UUID sessionId = getSessionId(sessionInfo);
458 if (msg.getEvent() == SessionEvent.OPEN) { 484 if (msg.getEvent() == SessionEvent.OPEN) {
459 logger.debug("[{}] Processing new session [{}]", deviceId, sessionId); 485 logger.debug("[{}] Processing new session [{}]", deviceId, sessionId);
460 if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) { 486 if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) {
@@ -548,14 +574,31 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -548,14 +574,31 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
548 systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); 574 systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg);
549 } 575 }
550 576
551 - private void sendToTransport(AttributeUpdateNotificationMsg notificationMsg, UUID sessionId, SessionInfo sessionInfo) { 577 + private void sendToTransport(AttributeUpdateNotificationMsg notificationMsg, UUID sessionId, String nodeId) {
552 DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() 578 DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder()
553 .setSessionIdMSB(sessionId.getMostSignificantBits()) 579 .setSessionIdMSB(sessionId.getMostSignificantBits())
554 .setSessionIdLSB(sessionId.getLeastSignificantBits()) 580 .setSessionIdLSB(sessionId.getLeastSignificantBits())
555 .setAttributeUpdateNotification(notificationMsg).build(); 581 .setAttributeUpdateNotification(notificationMsg).build();
556 - systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); 582 + systemContext.getRuleEngineTransportService().process(nodeId, msg);
557 } 583 }
558 584
  585 + private void sendToTransport(ToDeviceRpcRequestMsg rpcMsg, UUID sessionId, String nodeId) {
  586 + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder()
  587 + .setSessionIdMSB(sessionId.getMostSignificantBits())
  588 + .setSessionIdLSB(sessionId.getLeastSignificantBits())
  589 + .setToDeviceRequest(rpcMsg).build();
  590 + systemContext.getRuleEngineTransportService().process(nodeId, msg);
  591 + }
  592 +
  593 + private void sendToTransport(TransportProtos.ToServerRpcResponseMsg rpcMsg, UUID sessionId, String nodeId) {
  594 + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder()
  595 + .setSessionIdMSB(sessionId.getMostSignificantBits())
  596 + .setSessionIdLSB(sessionId.getLeastSignificantBits())
  597 + .setToServerResponse(rpcMsg).build();
  598 + systemContext.getRuleEngineTransportService().process(nodeId, msg);
  599 + }
  600 +
  601 +
559 private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) { 602 private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) {
560 List<TsKvProto> clientAttributes; 603 List<TsKvProto> clientAttributes;
561 if (result == null || result.isEmpty()) { 604 if (result == null || result.isEmpty()) {
1 -/**  
2 - * Copyright © 2016-2018 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (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  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.actors.device;  
17 -  
18 -import lombok.AllArgsConstructor;  
19 -import lombok.Data;  
20 -import org.thingsboard.server.common.data.id.SessionId;  
21 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
22 -import org.thingsboard.server.common.msg.session.SessionMsgType;  
23 -  
24 -import java.util.Optional;  
25 -import java.util.UUID;  
26 -  
27 -/**  
28 - * Created by ashvayka on 17.04.18.  
29 - */  
30 -@Data  
31 -@AllArgsConstructor  
32 -public final class PendingSessionMsgData {  
33 -  
34 - private final UUID sessionId;  
35 - private final Optional<ServerAddress> serverAddress;  
36 - private final SessionMsgType sessionMsgType;  
37 - private final int requestId;  
38 - private final boolean replyOnQueueAck;  
39 - private int ackMsgCount;  
40 -  
41 -}  
@@ -16,18 +16,16 @@ @@ -16,18 +16,16 @@
16 package org.thingsboard.server.actors.device; 16 package org.thingsboard.server.actors.device;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 -import org.thingsboard.server.common.data.id.SessionId;  
20 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
21 -import org.thingsboard.server.common.msg.session.SessionType; 19 +import org.thingsboard.server.gen.transport.TransportProtos;
22 20
23 -import java.util.Optional; 21 +import java.util.UUID;
24 22
25 /** 23 /**
26 * @author Andrew Shvayka 24 * @author Andrew Shvayka
27 */ 25 */
28 @Data 26 @Data
29 public class ToServerRpcRequestMetadata { 27 public class ToServerRpcRequestMetadata {
30 - private final SessionId sessionId;  
31 - private final SessionType type;  
32 - private final Optional<ServerAddress> server; 28 + private final UUID sessionId;
  29 + private final TransportProtos.SessionType type;
  30 + private final String nodeId;
33 } 31 }
1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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,8 +15,11 @@ @@ -15,8 +15,11 @@
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.ToServerRpcResponseMsg;
18 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; 19 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
19 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; 20 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
  21 +import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
  22 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
20 23
21 /** 24 /**
22 * Created by ashvayka on 04.10.18. 25 * Created by ashvayka on 04.10.18.
@@ -26,4 +29,10 @@ public interface SessionMsgListener { @@ -26,4 +29,10 @@ public interface SessionMsgListener {
26 void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse); 29 void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse);
27 30
28 void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification); 31 void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification);
  32 +
  33 + void onRemoteSessionCloseCommand(SessionCloseNotificationProto sessionCloseNotification);
  34 +
  35 + void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest);
  36 +
  37 + void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse);
29 } 38 }
@@ -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.ToServerRpcRequestMsg;
  19 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
18 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; 20 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
19 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; 21 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg;
20 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; 22 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
@@ -49,6 +51,10 @@ public interface TransportService { @@ -49,6 +51,10 @@ public interface TransportService {
49 51
50 void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback); 52 void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback);
51 53
  54 + void process(SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback);
  55 +
  56 + void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback);
  57 +
52 void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener); 58 void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener);
53 59
54 void deregisterSession(SessionInfoProto sessionInfo); 60 void deregisterSession(SessionInfoProto sessionInfo);
1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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.
@@ -22,6 +22,7 @@ import com.google.gson.JsonObject; @@ -22,6 +22,7 @@ import com.google.gson.JsonObject;
22 import com.google.gson.JsonParser; 22 import com.google.gson.JsonParser;
23 import com.google.gson.JsonPrimitive; 23 import com.google.gson.JsonPrimitive;
24 import com.google.gson.JsonSyntaxException; 24 import com.google.gson.JsonSyntaxException;
  25 +import org.springframework.util.StringUtils;
25 import org.thingsboard.server.common.data.kv.AttributeKey; 26 import org.thingsboard.server.common.data.kv.AttributeKey;
26 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 27 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
27 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; 28 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
@@ -95,6 +96,15 @@ public class JsonConverter { @@ -95,6 +96,15 @@ public class JsonConverter {
95 } 96 }
96 } 97 }
97 98
  99 + public static JsonElement toJson(TransportProtos.ToDeviceRpcRequestMsg msg, boolean includeRequestId) {
  100 + JsonObject result = new JsonObject();
  101 + if (includeRequestId) {
  102 + result.addProperty("id", msg.getRequestId());
  103 + }
  104 + result.addProperty("method", msg.getMethodName());
  105 + result.add("params", new JsonParser().parse(msg.getParams()));
  106 + return result;
  107 + }
98 108
99 private static void parseObject(PostTelemetryMsg.Builder builder, long systemTs, JsonElement jsonObject) { 109 private static void parseObject(PostTelemetryMsg.Builder builder, long systemTs, JsonElement jsonObject) {
100 JsonObject jo = jsonObject.getAsJsonObject(); 110 JsonObject jo = jsonObject.getAsJsonObject();
@@ -112,14 +122,14 @@ public class JsonConverter { @@ -112,14 +122,14 @@ public class JsonConverter {
112 request.addTsKvList(builder.build()); 122 request.addTsKvList(builder.build());
113 } 123 }
114 124
115 - public static void parseWithTs(PostTelemetryMsg.Builder request, JsonObject jo) { 125 + private static void parseWithTs(PostTelemetryMsg.Builder request, JsonObject jo) {
116 TsKvListProto.Builder builder = TsKvListProto.newBuilder(); 126 TsKvListProto.Builder builder = TsKvListProto.newBuilder();
117 builder.setTs(jo.get("ts").getAsLong()); 127 builder.setTs(jo.get("ts").getAsLong());
118 builder.addAllKv(parseProtoValues(jo.get("values").getAsJsonObject())); 128 builder.addAllKv(parseProtoValues(jo.get("values").getAsJsonObject()));
119 request.addTsKvList(builder.build()); 129 request.addTsKvList(builder.build());
120 } 130 }
121 131
122 - public static List<KeyValueProto> parseProtoValues(JsonObject valuesObject) { 132 + private static List<KeyValueProto> parseProtoValues(JsonObject valuesObject) {
123 List<KeyValueProto> result = new ArrayList<>(); 133 List<KeyValueProto> result = new ArrayList<>();
124 for (Entry<String, JsonElement> valueEntry : valuesObject.entrySet()) { 134 for (Entry<String, JsonElement> valueEntry : valuesObject.entrySet()) {
125 JsonElement element = valueEntry.getValue(); 135 JsonElement element = valueEntry.getValue();
@@ -172,9 +182,9 @@ public class JsonConverter { @@ -172,9 +182,9 @@ public class JsonConverter {
172 return request; 182 return request;
173 } 183 }
174 184
175 - public static ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException { 185 + public static TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException {
176 JsonObject object = json.getAsJsonObject(); 186 JsonObject object = json.getAsJsonObject();
177 - return new ToServerRpcRequestMsg(requestId, object.get("method").getAsString(), GSON.toJson(object.get("params"))); 187 + return TransportProtos.ToServerRpcRequestMsg.newBuilder().setRequestId(requestId).setMethodName(object.get("method").getAsString()).setParams(GSON.toJson(object.get("params"))).build();
178 } 188 }
179 189
180 private static void parseObject(BasicTelemetryUploadRequest request, long systemTs, JsonElement jsonObject) { 190 private static void parseObject(BasicTelemetryUploadRequest request, long systemTs, JsonElement jsonObject) {
@@ -368,8 +378,14 @@ public class JsonConverter { @@ -368,8 +378,14 @@ public class JsonConverter {
368 return result; 378 return result;
369 } 379 }
370 380
371 - public static JsonElement toJson(ToServerRpcResponseMsg msg) {  
372 - return new JsonParser().parse(msg.getData()); 381 + public static JsonElement toJson(TransportProtos.ToServerRpcResponseMsg msg) {
  382 + if (StringUtils.isEmpty(msg.getError())) {
  383 + return new JsonParser().parse(msg.getPayload());
  384 + } else {
  385 + JsonObject errorMsg = new JsonObject();
  386 + errorMsg.addProperty("error", msg.getError());
  387 + return errorMsg;
  388 + }
373 } 389 }
374 390
375 public static JsonElement toErrorJson(String errorMsg) { 391 public static JsonElement toErrorJson(String errorMsg) {
@@ -137,6 +137,29 @@ message SubscribeToRPCMsg { @@ -137,6 +137,29 @@ message SubscribeToRPCMsg {
137 bool unsubscribe = 1; 137 bool unsubscribe = 1;
138 } 138 }
139 139
  140 +message ToDeviceRpcRequestMsg {
  141 + int32 requestId = 1;
  142 + string methodName = 2;
  143 + string params = 3;
  144 +}
  145 +
  146 +message ToDeviceRpcResponseMsg {
  147 + int32 requestId = 1;
  148 + string payload = 2;
  149 +}
  150 +
  151 +message ToServerRpcRequestMsg {
  152 + int32 requestId = 1;
  153 + string methodName = 2;
  154 + string params = 3;
  155 +}
  156 +
  157 +message ToServerRpcResponseMsg {
  158 + int32 requestId = 1;
  159 + string payload = 2;
  160 + string error = 3;
  161 +}
  162 +
140 message TransportToDeviceActorMsg { 163 message TransportToDeviceActorMsg {
141 SessionInfoProto sessionInfo = 1; 164 SessionInfoProto sessionInfo = 1;
142 SessionEventMsg sessionEvent = 2; 165 SessionEventMsg sessionEvent = 2;
@@ -144,7 +167,9 @@ message TransportToDeviceActorMsg { @@ -144,7 +167,9 @@ message TransportToDeviceActorMsg {
144 PostAttributeMsg postAttributes = 4; 167 PostAttributeMsg postAttributes = 4;
145 GetAttributeRequestMsg getAttributes = 5; 168 GetAttributeRequestMsg getAttributes = 5;
146 SubscribeToAttributeUpdatesMsg subscribeToAttributes = 6; 169 SubscribeToAttributeUpdatesMsg subscribeToAttributes = 6;
147 - SubscribeToRPCMsg subscribeToRPC= 7; 170 + SubscribeToRPCMsg subscribeToRPC = 7;
  171 + ToDeviceRpcResponseMsg toDeviceRPCCallResponse = 8;
  172 + ToServerRpcRequestMsg toServerRPCCallRequest = 9;
148 } 173 }
149 174
150 message DeviceActorToTransportMsg { 175 message DeviceActorToTransportMsg {
@@ -153,6 +178,8 @@ message DeviceActorToTransportMsg { @@ -153,6 +178,8 @@ message DeviceActorToTransportMsg {
153 SessionCloseNotificationProto sessionCloseNotification = 3; 178 SessionCloseNotificationProto sessionCloseNotification = 3;
154 GetAttributeResponseMsg getAttributesResponse = 4; 179 GetAttributeResponseMsg getAttributesResponse = 4;
155 AttributeUpdateNotificationMsg attributeUpdateNotification = 5; 180 AttributeUpdateNotificationMsg attributeUpdateNotification = 5;
  181 + ToDeviceRpcRequestMsg toDeviceRequest = 6;
  182 + ToServerRpcResponseMsg toServerResponse = 7;
156 } 183 }
157 184
158 /** 185 /**
@@ -98,7 +98,8 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { @@ -98,7 +98,8 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
98 98
99 String payload = validatePayload(ctx, inbound); 99 String payload = validatePayload(ctx, inbound);
100 100
101 - return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), 0); 101 +// return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), 0);
  102 + return null;
102 } 103 }
103 104
104 @Override 105 @Override
@@ -225,8 +226,8 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { @@ -225,8 +226,8 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
225 private Response convertToServerRpcResponse(SessionContext ctx, ToServerRpcResponseMsg msg) { 226 private Response convertToServerRpcResponse(SessionContext ctx, ToServerRpcResponseMsg msg) {
226 if (msg.isSuccess()) { 227 if (msg.isSuccess()) {
227 Response response = new Response(ResponseCode.CONTENT); 228 Response response = new Response(ResponseCode.CONTENT);
228 - JsonElement result = JsonConverter.toJson(msg);  
229 - response.setPayload(result.toString()); 229 +// JsonElement result = JsonConverter.toJson(msg);
  230 +// response.setPayload(result.toString());
230 return response; 231 return response;
231 } else { 232 } else {
232 return convertError(Optional.of(new RuntimeException("Server RPC response is empty!"))); 233 return convertError(Optional.of(new RuntimeException("Server RPC response is empty!")));
@@ -114,7 +114,7 @@ public class HttpSessionCtx extends DeviceAwareSessionContext { @@ -114,7 +114,7 @@ public class HttpSessionCtx extends DeviceAwareSessionContext {
114 } 114 }
115 115
116 private void reply(ToServerRpcResponseMsg msg) { 116 private void reply(ToServerRpcResponseMsg msg) {
117 - responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); 117 +// responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK));
118 } 118 }
119 119
120 private void reply(AttributesUpdateNotification msg) { 120 private void reply(AttributesUpdateNotification msg) {
1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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.
@@ -223,43 +223,18 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -223,43 +223,18 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
223 } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) { 223 } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {
224 TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg); 224 TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg);
225 transportService.process(sessionInfo, getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg)); 225 transportService.process(sessionInfo, getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
  226 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC)){
  227 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = adaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg);
  228 + transportService.process(sessionInfo, rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
  229 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)){
  230 + TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = adaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg);
  231 + transportService.process(sessionInfo, rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
226 } 232 }
227 } catch (AdaptorException e) { 233 } catch (AdaptorException e) {
228 log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e); 234 log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
229 log.info("[{}] Closing current session due to invalid publish msg [{}][{}]", sessionId, topicName, msgId); 235 log.info("[{}] Closing current session due to invalid publish msg [{}][{}]", sessionId, topicName, msgId);
230 ctx.close(); 236 ctx.close();
231 } 237 }
232 -// AdaptorToSessionActorMsg msg = null;  
233 -// try {  
234 -// if (topicName.equals(DEVICE_TELEMETRY_TOPIC)) {  
235 -// msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_TELEMETRY_REQUEST, mqttMsg);  
236 -// } else if (topicName.equals(DEVICE_ATTRIBUTES_TOPIC)) {  
237 -// msg = adaptor.convertToActorMsg(deviceSessionCtx, POST_ATTRIBUTES_REQUEST, mqttMsg);  
238 -// } else if (topicName.startsWith(DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {  
239 -// msg = adaptor.convertToActorMsg(deviceSessionCtx, GET_ATTRIBUTES_REQUEST, mqttMsg);  
240 -// if (msgId >= 0) {  
241 -// ctx.writeAndFlush(createMqttPubAckMsg(msgId));  
242 -// }  
243 -// } else if (topicName.startsWith(DEVICE_RPC_RESPONSE_TOPIC)) {  
244 -// msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_DEVICE_RPC_RESPONSE, mqttMsg);  
245 -// if (msgId >= 0) {  
246 -// ctx.writeAndFlush(createMqttPubAckMsg(msgId));  
247 -// }  
248 -// } else if (topicName.startsWith(DEVICE_RPC_REQUESTS_TOPIC)) {  
249 -// msg = adaptor.convertToActorMsg(deviceSessionCtx, TO_SERVER_RPC_REQUEST, mqttMsg);  
250 -// if (msgId >= 0) {  
251 -// ctx.writeAndFlush(createMqttPubAckMsg(msgId));  
252 -// }  
253 -// }  
254 -// } catch (AdaptorException e) {  
255 -// log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);  
256 -// }  
257 -// if (msg != null) {  
258 -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(), msg));  
259 -// } else {  
260 -// log.info("[{}] Closing current session due to invalid publish msg [{}][{}]", sessionId, topicName, msgId);  
261 -// ctx.close();  
262 -// }  
263 } 238 }
264 239
265 private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final int msgId, final T msg) { 240 private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final int msgId, final T msg) {
@@ -555,4 +530,30 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -555,4 +530,30 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
555 log.trace("[{}] Failed to convert device attributes update to MQTT msg", sessionId, e); 530 log.trace("[{}] Failed to convert device attributes update to MQTT msg", sessionId, e);
556 } 531 }
557 } 532 }
  533 +
  534 + @Override
  535 + public void onRemoteSessionCloseCommand(TransportProtos.SessionCloseNotificationProto sessionCloseNotification) {
  536 + log.trace("[{}] Received the remote command to close the session", sessionId);
  537 + processDisconnect(deviceSessionCtx.getChannel());
  538 + }
  539 +
  540 + @Override
  541 + public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg rpcRequest) {
  542 + log.trace("[{}] Received RPC command to device", sessionId);
  543 + try {
  544 + adaptor.convertToPublish(deviceSessionCtx, rpcRequest).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
  545 + } catch (Exception e) {
  546 + log.trace("[{}] Failed to convert device RPC commandto MQTT msg", sessionId, e);
  547 + }
  548 + }
  549 +
  550 + @Override
  551 + public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg rpcResponse) {
  552 + log.trace("[{}] Received RPC command to device", sessionId);
  553 + try {
  554 + adaptor.convertToPublish(deviceSessionCtx, rpcResponse).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
  555 + } catch (Exception e) {
  556 + log.trace("[{}] Failed to convert device RPC commandto MQTT msg", sessionId, e);
  557 + }
  558 + }
558 } 559 }
1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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.
@@ -17,7 +17,6 @@ package org.thingsboard.server.transport.mqtt.adaptors; @@ -17,7 +17,6 @@ package org.thingsboard.server.transport.mqtt.adaptors;
17 17
18 import com.google.gson.Gson; 18 import com.google.gson.Gson;
19 import com.google.gson.JsonElement; 19 import com.google.gson.JsonElement;
20 -import com.google.gson.JsonObject;  
21 import com.google.gson.JsonParser; 20 import com.google.gson.JsonParser;
22 import com.google.gson.JsonSyntaxException; 21 import com.google.gson.JsonSyntaxException;
23 import io.netty.buffer.ByteBuf; 22 import io.netty.buffer.ByteBuf;
@@ -99,6 +98,31 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -99,6 +98,31 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
99 } 98 }
100 99
101 @Override 100 @Override
  101 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  102 + String topicName = inbound.variableHeader().topicName();
  103 + try {
  104 + Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC.length()));
  105 + String payload = inbound.payload().toString(UTF8);
  106 + return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build();
  107 + } catch (RuntimeException e) {
  108 + log.warn("Failed to decode get attributes request", e);
  109 + throw new AdaptorException(e);
  110 + }
  111 + }
  112 +
  113 + @Override
  114 + public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  115 + String topicName = inbound.variableHeader().topicName();
  116 + String payload = validatePayload(ctx.getSessionId(), inbound.payload());
  117 + try {
  118 + Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC.length()));
  119 + return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), requestId);
  120 + } catch (IllegalStateException | JsonSyntaxException ex) {
  121 + throw new AdaptorException(ex);
  122 + }
  123 + }
  124 +
  125 + @Override
102 public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { 126 public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
103 if (!StringUtils.isEmpty(responseMsg.getError())) { 127 if (!StringUtils.isEmpty(responseMsg.getError())) {
104 throw new AdaptorException(responseMsg.getError()); 128 throw new AdaptorException(responseMsg.getError());
@@ -115,9 +139,17 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -115,9 +139,17 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
115 139
116 @Override 140 @Override
117 public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException { 141 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))); 142 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, JsonConverter.toJson(notificationMsg)));
  143 + }
  144 +
  145 + @Override
  146 + public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException {
  147 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), JsonConverter.toJson(rpcRequest, false)));
  148 + }
  149 +
  150 + @Override
  151 + public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse) {
  152 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(), JsonConverter.toJson(rpcResponse)));
121 } 153 }
122 154
123 @Override 155 @Override
@@ -149,7 +181,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -149,7 +181,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
149 msg = convertToRpcCommandResponse(ctx, (MqttPublishMessage) inbound); 181 msg = convertToRpcCommandResponse(ctx, (MqttPublishMessage) inbound);
150 break; 182 break;
151 case TO_SERVER_RPC_REQUEST: 183 case TO_SERVER_RPC_REQUEST:
152 - msg = convertToServerRpcRequest(ctx, (MqttPublishMessage) inbound); 184 + msg = null;//convertToServerRpcRequest(ctx, (MqttPublishMessage) inbound);
153 break; 185 break;
154 default: 186 default:
155 log.warn("[{}] Unsupported msg type: {}!", ctx.getSessionId(), type); 187 log.warn("[{}] Unsupported msg type: {}!", ctx.getSessionId(), type);
@@ -181,13 +213,12 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -181,13 +213,12 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
181 break; 213 break;
182 case TO_DEVICE_RPC_REQUEST: 214 case TO_DEVICE_RPC_REQUEST:
183 ToDeviceRpcRequestMsg rpcRequest = (ToDeviceRpcRequestMsg) msg; 215 ToDeviceRpcRequestMsg rpcRequest = (ToDeviceRpcRequestMsg) msg;
184 - result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(),  
185 - rpcRequest); 216 + result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), rpcRequest);
186 break; 217 break;
187 case TO_SERVER_RPC_RESPONSE: 218 case TO_SERVER_RPC_RESPONSE:
188 - ToServerRpcResponseMsg rpcResponse = (ToServerRpcResponseMsg) msg;  
189 - result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(),  
190 - rpcResponse); 219 +// ToServerRpcResponseMsg rpcResponse = (ToServerRpcResponseMsg) msg;
  220 +// result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(),
  221 +// rpcResponse);
191 break; 222 break;
192 case RULE_ENGINE_ERROR: 223 case RULE_ENGINE_ERROR:
193 RuleEngineErrorMsg errorMsg = (RuleEngineErrorMsg) msg; 224 RuleEngineErrorMsg errorMsg = (RuleEngineErrorMsg) msg;
@@ -232,7 +263,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -232,7 +263,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
232 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg, false)); 263 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg, false));
233 } 264 }
234 265
235 - private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, ToServerRpcResponseMsg msg) { 266 + private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, TransportProtos.ToServerRpcResponseMsg msg) {
236 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg)); 267 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg));
237 } 268 }
238 269
@@ -290,7 +321,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -290,7 +321,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
290 private AttributesUpdateRequest convertToUpdateAttributesRequest(SessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { 321 private AttributesUpdateRequest convertToUpdateAttributesRequest(SessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
291 String payload = validatePayload(ctx.getSessionId(), inbound.payload()); 322 String payload = validatePayload(ctx.getSessionId(), inbound.payload());
292 try { 323 try {
293 - return JsonConverter.convertToAttributes(new JsonParser().parse(payload), inbound.variableHeader().messageId()); 324 + return JsonConverter.convertToAttributes(new JsonParser().parse(payload), inbound.variableHeader().packetId());
294 } catch (IllegalStateException | JsonSyntaxException ex) { 325 } catch (IllegalStateException | JsonSyntaxException ex) {
295 throw new AdaptorException(ex); 326 throw new AdaptorException(ex);
296 } 327 }
@@ -299,18 +330,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { @@ -299,18 +330,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
299 private TelemetryUploadRequest convertToTelemetryUploadRequest(SessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { 330 private TelemetryUploadRequest convertToTelemetryUploadRequest(SessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
300 String payload = validatePayload(ctx.getSessionId(), inbound.payload()); 331 String payload = validatePayload(ctx.getSessionId(), inbound.payload());
301 try { 332 try {
302 - return JsonConverter.convertToTelemetry(new JsonParser().parse(payload), inbound.variableHeader().messageId());  
303 - } catch (IllegalStateException | JsonSyntaxException ex) {  
304 - throw new AdaptorException(ex);  
305 - }  
306 - }  
307 -  
308 - private FromDeviceMsg convertToServerRpcRequest(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {  
309 - String topicName = inbound.variableHeader().topicName();  
310 - String payload = validatePayload(ctx.getSessionId(), inbound.payload());  
311 - try {  
312 - Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC.length()));  
313 - return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), requestId); 333 + return JsonConverter.convertToTelemetry(new JsonParser().parse(payload), inbound.variableHeader().packetId());
314 } catch (IllegalStateException | JsonSyntaxException ex) { 334 } catch (IllegalStateException | JsonSyntaxException ex) {
315 throw new AdaptorException(ex); 335 throw new AdaptorException(ex);
316 } 336 }
@@ -19,7 +19,15 @@ import io.netty.handler.codec.mqtt.MqttMessage; @@ -19,7 +19,15 @@ import io.netty.handler.codec.mqtt.MqttMessage;
19 import io.netty.handler.codec.mqtt.MqttPublishMessage; 19 import io.netty.handler.codec.mqtt.MqttPublishMessage;
20 import org.thingsboard.server.common.transport.TransportAdaptor; 20 import org.thingsboard.server.common.transport.TransportAdaptor;
21 import org.thingsboard.server.common.transport.adaptor.AdaptorException; 21 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
22 -import org.thingsboard.server.gen.transport.TransportProtos; 22 +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
  23 +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
  24 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
  25 +import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
  28 +import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
  29 +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
  30 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
23 import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; 31 import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
24 32
25 import java.util.Optional; 33 import java.util.Optional;
@@ -29,15 +37,21 @@ import java.util.Optional; @@ -29,15 +37,21 @@ import java.util.Optional;
29 */ 37 */
30 public interface MqttTransportAdaptor extends TransportAdaptor<DeviceSessionCtx, MqttMessage, MqttMessage> { 38 public interface MqttTransportAdaptor extends TransportAdaptor<DeviceSessionCtx, MqttMessage, MqttMessage> {
31 39
32 - TransportProtos.PostTelemetryMsg convertToPostTelemetry(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; 40 + PostTelemetryMsg convertToPostTelemetry(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
33 41
34 - TransportProtos.PostAttributeMsg convertToPostAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; 42 + PostAttributeMsg convertToPostAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
35 43
36 - TransportProtos.GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; 44 + GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
37 45
38 - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException; 46 + ToDeviceRpcResponseMsg convertToDeviceRpcResponse(DeviceSessionCtx ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
39 47
40 - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; 48 + ToServerRpcRequestMsg convertToServerRpcRequest(DeviceSessionCtx ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
41 49
  50 + Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, GetAttributeResponseMsg responseMsg) throws AdaptorException;
42 51
  52 + Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
  53 +
  54 + Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
  55 +
  56 + Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, ToServerRpcResponseMsg rpcResponse);
43 } 57 }
1 /** 1 /**
2 * Copyright © 2016-2018 The Thingsboard Authors 2 * Copyright © 2016-2018 The Thingsboard Authors
3 - * <p> 3 + *
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 - * <p>  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - * <p> 7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
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.
@@ -164,6 +164,15 @@ public class MqttTransportService implements TransportService { @@ -164,6 +164,15 @@ public class MqttTransportService implements TransportService {
164 if (toSessionMsg.hasAttributeUpdateNotification()) { 164 if (toSessionMsg.hasAttributeUpdateNotification()) {
165 listener.onAttributeUpdate(toSessionMsg.getAttributeUpdateNotification()); 165 listener.onAttributeUpdate(toSessionMsg.getAttributeUpdateNotification());
166 } 166 }
  167 + if (toSessionMsg.hasSessionCloseNotification()) {
  168 + listener.onRemoteSessionCloseCommand(toSessionMsg.getSessionCloseNotification());
  169 + }
  170 + if (toSessionMsg.hasToDeviceRequest()) {
  171 + listener.onToDeviceRpcRequest(toSessionMsg.getToDeviceRequest());
  172 + }
  173 + if (toSessionMsg.hasToServerResponse()) {
  174 + listener.onToServerRpcResponse(toSessionMsg.getToServerResponse());
  175 + }
167 }); 176 });
168 } else { 177 } else {
169 //TODO: should we notify the device actor about missed session? 178 //TODO: should we notify the device actor about missed session?
@@ -273,6 +282,24 @@ public class MqttTransportService implements TransportService { @@ -273,6 +282,24 @@ public class MqttTransportService implements TransportService {
273 } 282 }
274 283
275 @Override 284 @Override
  285 + public void process(SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) {
  286 + ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
  287 + TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  288 + .setToDeviceRPCCallResponse(msg).build()
  289 + ).build();
  290 + send(sessionInfo, toRuleEngineMsg, callback);
  291 + }
  292 +
  293 + @Override
  294 + public void process(SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) {
  295 + ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
  296 + TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  297 + .setToServerRPCCallRequest(msg).build()
  298 + ).build();
  299 + send(sessionInfo, toRuleEngineMsg, callback);
  300 + }
  301 +
  302 + @Override
276 public void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener) { 303 public void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener) {
277 sessions.putIfAbsent(toId(sessionInfo), listener); 304 sessions.putIfAbsent(toId(sessionInfo), listener);
278 //TODO: monitor sessions periodically: PING REQ/RESP, etc. 305 //TODO: monitor sessions periodically: PING REQ/RESP, etc.