Showing
13 changed files
with
333 additions
and
212 deletions
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()) { |
application/src/main/java/org/thingsboard/server/actors/device/PendingSessionMsgData.java
deleted
100644 → 0
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 | } |
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 | - * <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. |