Commit a4869b2b05d6f45f73c317d7a23aacf7954ac4c5
Merge branch '20230705' into 'master_dev'
20230705 See merge request yunteng/thingskit!203
Showing
2 changed files
with
463 additions
and
398 deletions
1 | /** | 1 | /** |
2 | * Copyright © 2016-2022 The Thingsboard Authors | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | * | 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 | 4 | + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
5 | + * except in compliance with the License. You may obtain a copy of the License at | ||
7 | * | 6 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | 7 | + * <p>http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | 8 | * |
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 | 9 | + * <p>Unless required by applicable law or agreed to in writing, software distributed under the |
10 | + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
11 | + * express or implied. See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | 12 | * limitations under the License. |
15 | */ | 13 | */ |
16 | package org.thingsboard.server.transport.udp; | 14 | package org.thingsboard.server.transport.udp; |
17 | 15 | ||
18 | - | ||
19 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; | 16 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; |
20 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN; | 17 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN; |
21 | 18 | ||
@@ -25,9 +22,11 @@ import com.google.common.util.concurrent.Futures; | @@ -25,9 +22,11 @@ import com.google.common.util.concurrent.Futures; | ||
25 | import com.google.common.util.concurrent.ListenableFuture; | 22 | import com.google.common.util.concurrent.ListenableFuture; |
26 | import com.google.common.util.concurrent.MoreExecutors; | 23 | import com.google.common.util.concurrent.MoreExecutors; |
27 | import io.netty.buffer.ByteBuf; | 24 | import io.netty.buffer.ByteBuf; |
25 | +import io.netty.buffer.ByteBufUtil; | ||
28 | import io.netty.buffer.Unpooled; | 26 | import io.netty.buffer.Unpooled; |
29 | import io.netty.channel.ChannelFuture; | 27 | import io.netty.channel.ChannelFuture; |
30 | import io.netty.channel.ChannelHandlerContext; | 28 | import io.netty.channel.ChannelHandlerContext; |
29 | +import io.netty.channel.socket.DatagramPacket; | ||
31 | import io.netty.handler.codec.mqtt.*; | 30 | import io.netty.handler.codec.mqtt.*; |
32 | import io.netty.util.concurrent.Future; | 31 | import io.netty.util.concurrent.Future; |
33 | import io.netty.util.concurrent.GenericFutureListener; | 32 | import io.netty.util.concurrent.GenericFutureListener; |
@@ -73,411 +72,472 @@ import org.thingsboard.server.transport.tcp.session.TcpGatewaySessionHandler; | @@ -73,411 +72,472 @@ import org.thingsboard.server.transport.tcp.session.TcpGatewaySessionHandler; | ||
73 | * @author Andrew Shvayka | 72 | * @author Andrew Shvayka |
74 | */ | 73 | */ |
75 | @Slf4j | 74 | @Slf4j |
76 | - public class UdpDatagramDataHandler implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | ||
77 | - | ||
78 | - private final UUID sessionId; | ||
79 | - private final TcpTransportContext context; | ||
80 | - private final TransportService transportService; | ||
81 | - | ||
82 | - | ||
83 | - /** | ||
84 | - * 需要处理的消息队列,例如:需要下发给设备的,设备上传的。 | ||
85 | - */ | ||
86 | - final TcpDeviceSessionCtx deviceSessionCtx; | ||
87 | - volatile InetSocketAddress address; | ||
88 | - | ||
89 | - volatile TcpGatewaySessionHandler gatewaySessionHandler; | ||
90 | - private final AtomicInteger authedCounter = new AtomicInteger(); | ||
91 | - | ||
92 | - | ||
93 | - UdpDatagramDataHandler(ChannelHandlerContext ctx,TcpTransportContext context, InetSocketAddress devAddress) { | ||
94 | - super(); | ||
95 | - this.sessionId = UUID.randomUUID(); | ||
96 | - this.context = context; | ||
97 | - this.address = devAddress; | ||
98 | - this.transportService = context.getTransportService(); | ||
99 | - this.deviceSessionCtx = new TcpDeviceSessionCtx(sessionId, context); | 75 | +public class UdpDatagramDataHandler |
76 | + implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | ||
77 | + | ||
78 | + private final UUID sessionId; | ||
79 | + private final TcpTransportContext context; | ||
80 | + private final TransportService transportService; | ||
81 | + | ||
82 | + /** 需要处理的消息队列,例如:需要下发给设备的,设备上传的。 */ | ||
83 | + final TcpDeviceSessionCtx deviceSessionCtx; | ||
84 | + | ||
85 | + volatile InetSocketAddress address; | ||
86 | + | ||
87 | + volatile TcpGatewaySessionHandler gatewaySessionHandler; | ||
88 | + private final AtomicInteger authedCounter = new AtomicInteger(); | ||
89 | + | ||
90 | + UdpDatagramDataHandler( | ||
91 | + ChannelHandlerContext ctx, TcpTransportContext context, InetSocketAddress devAddress) { | ||
92 | + super(); | ||
93 | + this.sessionId = UUID.randomUUID(); | ||
94 | + this.context = context; | ||
95 | + this.address = devAddress; | ||
96 | + this.transportService = context.getTransportService(); | ||
97 | + this.deviceSessionCtx = new TcpDeviceSessionCtx(sessionId, context); | ||
98 | + } | ||
99 | + | ||
100 | + public void dealDeviceMsg(ChannelHandlerContext ctx, String msg) { | ||
101 | + deviceSessionCtx.setChannel(ctx); | ||
102 | + if (deviceSessionCtx.getDeviceInfo() == null || deviceSessionCtx.getDeviceProfile() == null) { | ||
103 | + processConnect(ctx, msg); | ||
104 | + return; | ||
100 | } | 105 | } |
101 | - | ||
102 | - | ||
103 | - | ||
104 | - | ||
105 | - | ||
106 | - | ||
107 | - public void dealDeviceMsg(ChannelHandlerContext ctx, String msg) { | ||
108 | - deviceSessionCtx.setChannel(ctx); | ||
109 | - if (deviceSessionCtx.getDeviceInfo() == null || deviceSessionCtx.getDeviceProfile() == null) { | ||
110 | - processConnect(ctx, msg); | ||
111 | - return; | ||
112 | - } | ||
113 | - final int queueSize = deviceSessionCtx.getMsgQueueSize(); | ||
114 | - if (queueSize >= context.getMessageQueueSizePerDeviceLimit()) { | ||
115 | - log.info("Closing current session because msq queue size for device {} exceed limit {} with msgQueueSize counter {} and actual queue size {}", | ||
116 | - deviceSessionCtx.getDeviceId(), context.getMessageQueueSizePerDeviceLimit(), queueSize, deviceSessionCtx.getMsgQueueSize()); | ||
117 | -// ctx.close(); | ||
118 | - return; | ||
119 | - } | ||
120 | - deviceSessionCtx.addToQueue(msg); | ||
121 | - processQueueMessage(ctx); //Under the normal conditions the msg queue will contain 0 messages. Many messages will be processed on device connect event in separate thread pool | ||
122 | - | 106 | + final int queueSize = deviceSessionCtx.getMsgQueueSize(); |
107 | + if (queueSize >= context.getMessageQueueSizePerDeviceLimit()) { | ||
108 | + log.info( | ||
109 | + "Closing current session because msq queue size for device {} exceed limit {} with msgQueueSize counter {} and actual queue size {}", | ||
110 | + deviceSessionCtx.getDeviceId(), | ||
111 | + context.getMessageQueueSizePerDeviceLimit(), | ||
112 | + queueSize, | ||
113 | + deviceSessionCtx.getMsgQueueSize()); | ||
114 | + // ctx.close(); | ||
115 | + return; | ||
123 | } | 116 | } |
124 | - | ||
125 | - | ||
126 | - void processQueueMessage(ChannelHandlerContext ctx) { | ||
127 | - if (!deviceSessionCtx.isConnected()) { | ||
128 | - log.trace("[{}][{}] Postpone processing msg due to device is not connected. Msg queue size is {}", sessionId, deviceSessionCtx.getDeviceId(), deviceSessionCtx.getMsgQueueSize()); | ||
129 | - return; | ||
130 | - } | ||
131 | - deviceSessionCtx.tryProcessQueuedMsgs(msg -> processDeviceSessionMsg(ctx, msg)); | 117 | + deviceSessionCtx.addToQueue(msg); |
118 | + processQueueMessage( | ||
119 | + ctx); // Under the normal conditions the msg queue will contain 0 messages. Many messages | ||
120 | + // will be processed on device connect event in separate thread pool | ||
121 | + } | ||
122 | + | ||
123 | + void processQueueMessage(ChannelHandlerContext ctx) { | ||
124 | + if (!deviceSessionCtx.isConnected()) { | ||
125 | + log.trace( | ||
126 | + "[{}][{}] Postpone processing msg due to device is not connected. Msg queue size is {}", | ||
127 | + sessionId, | ||
128 | + deviceSessionCtx.getDeviceId(), | ||
129 | + deviceSessionCtx.getMsgQueueSize()); | ||
130 | + return; | ||
132 | } | 131 | } |
132 | + deviceSessionCtx.tryProcessQueuedMsgs(msg -> processDeviceSessionMsg(ctx, msg)); | ||
133 | + } | ||
133 | 134 | ||
134 | - | ||
135 | - private void processDeviceSessionMsg(ChannelHandlerContext ctx, String tcpMessage) { | ||
136 | - if (!checkConnected(ctx, tcpMessage)) { | ||
137 | - return; | ||
138 | - } | ||
139 | - deviceSessionCtx.doUpScript(tcpMessage, r -> { | ||
140 | - if (gatewaySessionHandler != null) { | ||
141 | - processGatewayDeviceMsg(ctx, r); | ||
142 | - } | ||
143 | - processDirectDeviceMsg(ctx, r); | 135 | + private void processDeviceSessionMsg(ChannelHandlerContext ctx, String tcpMessage) { |
136 | + if (!checkConnected(ctx, tcpMessage)) { | ||
137 | + return; | ||
138 | + } | ||
139 | + deviceSessionCtx.doUpScript( | ||
140 | + tcpMessage, | ||
141 | + r -> { | ||
142 | + if (gatewaySessionHandler != null) { | ||
143 | + processGatewayDeviceMsg(ctx, r); | ||
144 | + } | ||
145 | + processDirectDeviceMsg(ctx, r); | ||
144 | }); | 146 | }); |
145 | - | 147 | + } |
148 | + | ||
149 | + /** | ||
150 | + * 上行脚本解析结果是否包含数据 | ||
151 | + * | ||
152 | + * @param datas 数据集合 | ||
153 | + * @return | ||
154 | + */ | ||
155 | + private boolean hasDatas(Map<String, Object> datas) { | ||
156 | + if (datas == null || datas.isEmpty()) { | ||
157 | + return false; | ||
146 | } | 158 | } |
147 | - | ||
148 | - | ||
149 | - /** | ||
150 | - * 上行脚本解析结果是否包含数据 | ||
151 | - * @param datas 数据集合 | ||
152 | - * @return | ||
153 | - */ | ||
154 | - private boolean hasDatas(Map<String, Object> datas) { | ||
155 | - if (datas == null || datas.isEmpty()) { | ||
156 | - return false; | ||
157 | - } | ||
158 | - return true; | 159 | + return true; |
160 | + } | ||
161 | + | ||
162 | + private void processGatewayDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | ||
163 | + log.trace( | ||
164 | + "[{}][{}] Processing publish msg [{}]!", | ||
165 | + sessionId, | ||
166 | + deviceSessionCtx.getDeviceId(), | ||
167 | + tcpMessage); | ||
168 | + try { | ||
169 | + Map<String, Object> datas = tcpMessage.getDatas(); | ||
170 | + if (hasDatas(datas)) { | ||
171 | + datas.forEach( | ||
172 | + (devName, param) -> { | ||
173 | + if (TkScriptFactory.ORIGINAL_DATA_FILED.equals(devName)) { | ||
174 | + return; | ||
175 | + } | ||
176 | + if (tcpMessage.getTelemetry()) { | ||
177 | + gatewaySessionHandler.onDeviceTelemetry( | ||
178 | + devName, tcpMessage.getRequestId(), param.toString()); | ||
179 | + } else { | ||
180 | + // gatewaySessionHandler.onDeviceRpcResponse(devName, | ||
181 | + // tcpMessage.getRequestId(), param.toString()); | ||
182 | + } | ||
183 | + }); | ||
184 | + } else { | ||
185 | + transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | ||
186 | + pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | ||
187 | + } | ||
188 | + } catch (Exception e) { | ||
189 | + log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); | ||
190 | + // ctx.close(); | ||
159 | } | 191 | } |
160 | - | ||
161 | - | ||
162 | - private void processGatewayDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | ||
163 | - log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage); | ||
164 | - try { | ||
165 | - Map<String, Object> datas = tcpMessage.getDatas(); | ||
166 | - if (hasDatas(datas)) { | ||
167 | - datas.forEach((devName, param) -> { | ||
168 | - if (TkScriptFactory.ORIGINAL_DATA_FILED.equals(devName)) { | ||
169 | - return; | ||
170 | - } | ||
171 | - if (tcpMessage.getTelemetry()) { | ||
172 | - gatewaySessionHandler.onDeviceTelemetry(devName, tcpMessage.getRequestId(), param.toString()); | ||
173 | - } else { | ||
174 | -// gatewaySessionHandler.onDeviceRpcResponse(devName, tcpMessage.getRequestId(), param.toString()); | ||
175 | - } | ||
176 | - | ||
177 | - }); | ||
178 | - } else { | ||
179 | - transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | ||
180 | - pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | ||
181 | - } | ||
182 | - } catch (Exception e) { | ||
183 | - log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); | ||
184 | -// ctx.close(); | 192 | + } |
193 | + | ||
194 | + private void processDirectDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | ||
195 | + log.trace( | ||
196 | + "[{}][{}] Processing publish msg [{}]!", | ||
197 | + sessionId, | ||
198 | + deviceSessionCtx.getDeviceId(), | ||
199 | + tcpMessage); | ||
200 | + try { | ||
201 | + TcpTransportAdaptor payloadAdaptor = deviceSessionCtx.getPayloadAdaptor(); | ||
202 | + Map<String, Object> datas = tcpMessage.getDatas(); | ||
203 | + if (hasDatas(datas)) { | ||
204 | + String dataStr = JacksonUtil.toString(datas); | ||
205 | + if (tcpMessage.getTelemetry()) { | ||
206 | + TransportProtos.PostTelemetryMsg postTelemetryMsg = | ||
207 | + payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, dataStr); | ||
208 | + transportService.process( | ||
209 | + deviceSessionCtx.getSessionInfo(), | ||
210 | + postTelemetryMsg, | ||
211 | + getPubAckCallback(ctx, tcpMessage)); | ||
212 | + } else { | ||
213 | + TransportProtos.ToDeviceRpcResponseMsg postRpcMsg = | ||
214 | + payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, tcpMessage); | ||
215 | + transportService.process( | ||
216 | + deviceSessionCtx.getSessionInfo(), postRpcMsg, getPubAckCallback(ctx, tcpMessage)); | ||
185 | } | 217 | } |
218 | + } else { | ||
219 | + transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | ||
220 | + pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | ||
221 | + } | ||
222 | + } catch (AdaptorException e) { | ||
223 | + log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); | ||
224 | + // ctx.close(); | ||
186 | } | 225 | } |
187 | - | ||
188 | - private void processDirectDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | ||
189 | - log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage); | ||
190 | - try { | ||
191 | - TcpTransportAdaptor payloadAdaptor = deviceSessionCtx.getPayloadAdaptor(); | ||
192 | - Map<String, Object> datas = tcpMessage.getDatas(); | ||
193 | - if (hasDatas(datas)) { | ||
194 | - String dataStr = JacksonUtil.toString(datas); | ||
195 | - if (tcpMessage.getTelemetry()) { | ||
196 | - TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, dataStr); | ||
197 | - transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, tcpMessage)); | ||
198 | - } else { | ||
199 | - TransportProtos.ToDeviceRpcResponseMsg postRpcMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, tcpMessage); | ||
200 | - transportService.process(deviceSessionCtx.getSessionInfo(), postRpcMsg, getPubAckCallback(ctx, tcpMessage)); | ||
201 | - } | ||
202 | - } else { | ||
203 | - transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | ||
204 | - pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | ||
205 | - } | ||
206 | - } catch (AdaptorException e) { | ||
207 | - log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); | ||
208 | -// ctx.close(); | 226 | + } |
227 | + | ||
228 | + private <T> TransportServiceCallback<Void> getPubAckCallback( | ||
229 | + final ChannelHandlerContext ctx, final TcpUpEntry msg) { | ||
230 | + return new TransportServiceCallback<>() { | ||
231 | + @Override | ||
232 | + public void onSuccess(Void dummy) { | ||
233 | + log.trace("[{}] Published msg: {}", sessionId, msg); | ||
234 | + if (StringUtils.isNotEmpty(msg.getAckMsg())) { | ||
235 | + pushDeviceMsg(ctx, msg.getAckMsg()); | ||
209 | } | 236 | } |
237 | + } | ||
238 | + | ||
239 | + @Override | ||
240 | + public void onError(Throwable e) { | ||
241 | + log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e); | ||
242 | + // ctx.close(); | ||
243 | + } | ||
244 | + }; | ||
245 | + } | ||
246 | + | ||
247 | + void processConnect(ChannelHandlerContext ctx, String accessToken) { | ||
248 | + log.debug("[{}][{}] Processing connect msg for client: {}!", address, sessionId, accessToken); | ||
249 | + | ||
250 | + if (DataConstants.PROVISION.equals(accessToken) | ||
251 | + || DataConstants.PROVISION.equals(accessToken)) { | ||
252 | + deviceSessionCtx.setProvisionOnly(true); | ||
253 | + pushDeviceMsg(ctx, "CONNECTION_ACCEPTED"); | ||
254 | + } else { | ||
255 | + TkScriptInvokeService.authScripts.forEach( | ||
256 | + id -> { | ||
257 | + ListenableFuture item = context.getJsEngine().invokeFunction(id, accessToken); | ||
258 | + Futures.addCallback( | ||
259 | + item, | ||
260 | + new FutureCallback<String>() { | ||
261 | + @Override | ||
262 | + public void onSuccess(@Nullable String result) { | ||
263 | + processAuthTokenConnect( | ||
264 | + ctx, | ||
265 | + id, | ||
266 | + JacksonUtil.fromString(result.replace("\\", "\\\\"), TcpAuthEntry.class)); | ||
267 | + } | ||
268 | + | ||
269 | + @Override | ||
270 | + public void onFailure(Throwable t) { | ||
271 | + onValidateFailed( | ||
272 | + ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | ||
273 | + } | ||
274 | + }, | ||
275 | + MoreExecutors.directExecutor()); | ||
276 | + }); | ||
210 | } | 277 | } |
211 | - | ||
212 | - | ||
213 | - private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final TcpUpEntry msg) { | ||
214 | - return new TransportServiceCallback<>() { | 278 | + } |
279 | + | ||
280 | + private void processAuthTokenConnect( | ||
281 | + ChannelHandlerContext ctx, UUID scriptId, TcpAuthEntry accessToken) { | ||
282 | + | ||
283 | + log.debug( | ||
284 | + "[{}][{}] Processing connect msg for client with user name: {}!", | ||
285 | + address, | ||
286 | + sessionId, | ||
287 | + accessToken); | ||
288 | + if (null != accessToken.getClientId()) {} | ||
289 | + if (null != accessToken.getUserName()) {} | ||
290 | + String token = accessToken.getPassword(); | ||
291 | + if (StringUtils.isNotEmpty(token)) { | ||
292 | + TransportProtos.ValidateDeviceTokenRequestMsg.Builder request = | ||
293 | + TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder(); | ||
294 | + request.setToken(token); | ||
295 | + transportService.process( | ||
296 | + DeviceTransportType.TCP, | ||
297 | + request.build(), | ||
298 | + new TransportServiceCallback<>() { | ||
215 | @Override | 299 | @Override |
216 | - public void onSuccess(Void dummy) { | ||
217 | - log.trace("[{}] Published msg: {}", sessionId, msg); | ||
218 | - if (StringUtils.isNotEmpty(msg.getAckMsg())) { | ||
219 | - pushDeviceMsg(ctx, msg.getAckMsg()); | ||
220 | - } | 300 | + public void onSuccess(ValidateDeviceCredentialsResponse msg) { |
301 | + onValidateDeviceResponse(msg, ctx, accessToken, scriptId); | ||
221 | } | 302 | } |
222 | 303 | ||
223 | @Override | 304 | @Override |
224 | public void onError(Throwable e) { | 305 | public void onError(Throwable e) { |
225 | - log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e); | ||
226 | -// ctx.close(); | 306 | + log.trace("[{}] Failed to process credentials: {}", address, accessToken, e); |
307 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | ||
227 | } | 308 | } |
228 | - }; | 309 | + }); |
310 | + } else { | ||
311 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | ||
229 | } | 312 | } |
230 | - | ||
231 | - | ||
232 | - void processConnect(ChannelHandlerContext ctx, String accessToken) { | ||
233 | - log.debug("[{}][{}] Processing connect msg for client: {}!", address, sessionId, accessToken); | ||
234 | - | ||
235 | - if (DataConstants.PROVISION.equals(accessToken) || DataConstants.PROVISION.equals(accessToken)) { | ||
236 | - deviceSessionCtx.setProvisionOnly(true); | ||
237 | - pushDeviceMsg(ctx,"CONNECTION_ACCEPTED"); | ||
238 | - } else { | ||
239 | - TkScriptInvokeService.authScripts.forEach(id -> { | ||
240 | - ListenableFuture item = context.getJsEngine().invokeFunction(id, accessToken); | ||
241 | - Futures.addCallback(item, new FutureCallback<String>() { | ||
242 | - @Override | ||
243 | - public void onSuccess(@Nullable String result) { | ||
244 | - processAuthTokenConnect(ctx, id, JacksonUtil.fromString(result.replace("\\","\\\\"), TcpAuthEntry.class)); | ||
245 | - } | ||
246 | - | ||
247 | - @Override | ||
248 | - public void onFailure(Throwable t) { | ||
249 | - onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | ||
250 | - } | ||
251 | - }, MoreExecutors.directExecutor()); | ||
252 | - | ||
253 | - }); | ||
254 | - } | 313 | + } |
314 | + | ||
315 | + private boolean checkConnected(ChannelHandlerContext ctx, String msg) { | ||
316 | + if (deviceSessionCtx.isConnected()) { | ||
317 | + return true; | ||
318 | + } else { | ||
319 | + log.info("[{}] Closing current session due to invalid msg order: {}", sessionId, msg); | ||
320 | + return false; | ||
255 | } | 321 | } |
256 | - | ||
257 | - private void processAuthTokenConnect(ChannelHandlerContext ctx, UUID scriptId, TcpAuthEntry accessToken) { | ||
258 | - | ||
259 | - log.debug("[{}][{}] Processing connect msg for client with user name: {}!", address, sessionId, accessToken); | ||
260 | - if (null != accessToken.getClientId()) { | ||
261 | - } | ||
262 | - if (null != accessToken.getUserName()) { | ||
263 | - } | ||
264 | - String token = accessToken.getPassword(); | ||
265 | - if(StringUtils.isNotEmpty(token)){ | ||
266 | - TransportProtos.ValidateDeviceTokenRequestMsg.Builder request = TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder(); | ||
267 | - request.setToken(token); | ||
268 | - transportService.process(DeviceTransportType.TCP, request.build(), | ||
269 | - new TransportServiceCallback<>() { | ||
270 | - @Override | ||
271 | - public void onSuccess(ValidateDeviceCredentialsResponse msg) { | ||
272 | - onValidateDeviceResponse(msg, ctx, accessToken, scriptId); | ||
273 | - } | ||
274 | - | ||
275 | - @Override | ||
276 | - public void onError(Throwable e) { | ||
277 | - log.trace("[{}] Failed to process credentials: {}", address, accessToken, e); | ||
278 | - onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | ||
279 | - } | ||
280 | - }); | ||
281 | - }else{ | ||
282 | - onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | 322 | + } |
323 | + | ||
324 | + private void checkGatewaySession(SessionMetaData sessionMetaData) { | ||
325 | + TransportDeviceInfo device = deviceSessionCtx.getDeviceInfo(); | ||
326 | + try { | ||
327 | + JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); | ||
328 | + if (infoNode != null) { | ||
329 | + JsonNode gatewayNode = infoNode.get("gateway"); | ||
330 | + if (gatewayNode != null && gatewayNode.asBoolean()) { | ||
331 | + gatewaySessionHandler = new TcpGatewaySessionHandler(deviceSessionCtx, sessionId); | ||
332 | + if (infoNode.has(DefaultTransportService.OVERWRITE_ACTIVITY_TIME) | ||
333 | + && infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).isBoolean()) { | ||
334 | + sessionMetaData.setOverwriteActivityTime( | ||
335 | + infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).asBoolean()); | ||
336 | + } | ||
283 | } | 337 | } |
338 | + } | ||
339 | + } catch (IOException e) { | ||
340 | + log.trace( | ||
341 | + "[{}][{}] Failed to fetch device additional info", sessionId, device.getDeviceName(), e); | ||
284 | } | 342 | } |
285 | - | ||
286 | - | ||
287 | - | ||
288 | - | ||
289 | - | ||
290 | - | ||
291 | - | ||
292 | - | ||
293 | - | ||
294 | - private boolean checkConnected(ChannelHandlerContext ctx, String msg) { | ||
295 | - if (deviceSessionCtx.isConnected()) { | ||
296 | - return true; | ||
297 | - } else { | ||
298 | - log.info("[{}] Closing current session due to invalid msg order: {}", sessionId, msg); | ||
299 | - return false; | ||
300 | - } | ||
301 | - } | ||
302 | - | ||
303 | - private void checkGatewaySession(SessionMetaData sessionMetaData) { | ||
304 | - TransportDeviceInfo device = deviceSessionCtx.getDeviceInfo(); | ||
305 | - try { | ||
306 | - JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); | ||
307 | - if (infoNode != null) { | ||
308 | - JsonNode gatewayNode = infoNode.get("gateway"); | ||
309 | - if (gatewayNode != null && gatewayNode.asBoolean()) { | ||
310 | - gatewaySessionHandler = new TcpGatewaySessionHandler(deviceSessionCtx, sessionId); | ||
311 | - if (infoNode.has(DefaultTransportService.OVERWRITE_ACTIVITY_TIME) && infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).isBoolean()) { | ||
312 | - sessionMetaData.setOverwriteActivityTime(infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).asBoolean()); | ||
313 | - } | ||
314 | - } | ||
315 | - } | ||
316 | - } catch (IOException e) { | ||
317 | - log.trace("[{}][{}] Failed to fetch device additional info", sessionId, device.getDeviceName(), e); | ||
318 | - } | 343 | + } |
344 | + | ||
345 | + @Override | ||
346 | + public void operationComplete(Future<? super Void> future) throws Exception { | ||
347 | + log.trace("[{}] Channel closed!", sessionId); | ||
348 | + doDisconnect(); | ||
349 | + } | ||
350 | + | ||
351 | + public void doDisconnect() { | ||
352 | + if (deviceSessionCtx.isConnected()) { | ||
353 | + log.debug("[{}] Client disconnected!", sessionId); | ||
354 | + transportService.process(deviceSessionCtx.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); | ||
355 | + transportService.deregisterSession(deviceSessionCtx.getSessionInfo()); | ||
356 | + if (gatewaySessionHandler != null) { | ||
357 | + gatewaySessionHandler.onGatewayDisconnect(); | ||
358 | + } | ||
359 | + deviceSessionCtx.setDisconnected(); | ||
319 | } | 360 | } |
320 | - | ||
321 | - @Override | ||
322 | - public void operationComplete(Future<? super Void> future) throws Exception { | ||
323 | - log.trace("[{}] Channel closed!", sessionId); | ||
324 | - doDisconnect(); | ||
325 | - } | ||
326 | - | ||
327 | - public void doDisconnect() { | ||
328 | - if (deviceSessionCtx.isConnected()) { | ||
329 | - log.debug("[{}] Client disconnected!", sessionId); | ||
330 | - transportService.process(deviceSessionCtx.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); | ||
331 | - transportService.deregisterSession(deviceSessionCtx.getSessionInfo()); | ||
332 | - if (gatewaySessionHandler != null) { | ||
333 | - gatewaySessionHandler.onGatewayDisconnect(); | 361 | + deviceSessionCtx.release(); |
362 | + } | ||
363 | + | ||
364 | + private void onValidateDeviceResponse( | ||
365 | + ValidateDeviceCredentialsResponse msg, | ||
366 | + ChannelHandlerContext ctx, | ||
367 | + TcpAuthEntry authEntry, | ||
368 | + UUID scriptId) { | ||
369 | + if (!msg.hasDeviceInfo()) { | ||
370 | + context.onAuthFailure(address); | ||
371 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED); | ||
372 | + } else { | ||
373 | + DeviceProfile profile = msg.getDeviceProfile(); | ||
374 | + TkTcpDeviceProfileTransportConfiguration tcpConfig = | ||
375 | + (TkTcpDeviceProfileTransportConfiguration) | ||
376 | + profile.getProfileData().getTransportConfiguration(); | ||
377 | + if (scriptId != null && !tcpConfig.getAuthScriptId().equals(scriptId.toString())) { | ||
378 | + authedCounter.incrementAndGet(); | ||
379 | + return; | ||
380 | + } | ||
381 | + context.onAuthSuccess(address); | ||
382 | + deviceSessionCtx.setDeviceInfo(msg.getDeviceInfo()); | ||
383 | + deviceSessionCtx.setDeviceProfile(profile); | ||
384 | + deviceSessionCtx.setSessionInfo(SessionInfoCreator.create(msg, context, sessionId)); | ||
385 | + transportService.process( | ||
386 | + deviceSessionCtx.getSessionInfo(), | ||
387 | + SESSION_EVENT_MSG_OPEN, | ||
388 | + new TransportServiceCallback<Void>() { | ||
389 | + @Override | ||
390 | + public void onSuccess(Void msg) { | ||
391 | + SessionMetaData sessionMetaData = | ||
392 | + transportService.registerAsyncSession( | ||
393 | + deviceSessionCtx.getSessionInfo(), UdpDatagramDataHandler.this); | ||
394 | + checkGatewaySession(sessionMetaData); | ||
395 | + pushDeviceMsg(ctx, authEntry.getSuccess()); | ||
396 | + deviceSessionCtx.setConnected(true); | ||
397 | + log.debug("[{}] Client connected!", sessionId); | ||
398 | + | ||
399 | + transportService.process( | ||
400 | + deviceSessionCtx.getSessionInfo(), | ||
401 | + TransportProtos.SubscribeToRPCMsg.newBuilder().build(), | ||
402 | + null); | ||
403 | + transportService | ||
404 | + .getCallbackExecutor() | ||
405 | + .execute( | ||
406 | + () -> | ||
407 | + processQueueMessage( | ||
408 | + ctx)); // this callback will execute in Producer worker thread and | ||
409 | + // hard or blocking work have to be submitted to the separate | ||
410 | + // thread. | ||
334 | } | 411 | } |
335 | - deviceSessionCtx.setDisconnected(); | ||
336 | - } | ||
337 | - deviceSessionCtx.release(); | ||
338 | - } | ||
339 | 412 | ||
340 | - | ||
341 | - private void onValidateDeviceResponse(ValidateDeviceCredentialsResponse msg, ChannelHandlerContext ctx, TcpAuthEntry authEntry, UUID scriptId) { | ||
342 | - if (!msg.hasDeviceInfo()) { | ||
343 | - context.onAuthFailure(address); | ||
344 | - onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED); | ||
345 | - } else { | ||
346 | - DeviceProfile profile = msg.getDeviceProfile(); | ||
347 | - TkTcpDeviceProfileTransportConfiguration tcpConfig = (TkTcpDeviceProfileTransportConfiguration) profile.getProfileData().getTransportConfiguration(); | ||
348 | - if (scriptId != null && !tcpConfig.getAuthScriptId().equals(scriptId.toString())) { | ||
349 | - authedCounter.incrementAndGet(); | ||
350 | - return; | 413 | + @Override |
414 | + public void onError(Throwable e) { | ||
415 | + if (e instanceof TbRateLimitsException) { | ||
416 | + log.trace("[{}] Failed to submit session event: {}", sessionId, e.getMessage()); | ||
417 | + } else { | ||
418 | + log.warn("[{}] Failed to submit session event", sessionId, e); | ||
419 | + } | ||
420 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | ||
351 | } | 421 | } |
352 | - context.onAuthSuccess(address); | ||
353 | - deviceSessionCtx.setDeviceInfo(msg.getDeviceInfo()); | ||
354 | - deviceSessionCtx.setDeviceProfile(profile); | ||
355 | - deviceSessionCtx.setSessionInfo(SessionInfoCreator.create(msg, context, sessionId)); | ||
356 | - transportService.process(deviceSessionCtx.getSessionInfo(), SESSION_EVENT_MSG_OPEN, new TransportServiceCallback<Void>() { | ||
357 | - @Override | ||
358 | - public void onSuccess(Void msg) { | ||
359 | - SessionMetaData sessionMetaData = transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), UdpDatagramDataHandler.this); | ||
360 | - checkGatewaySession(sessionMetaData); | ||
361 | - pushDeviceMsg(ctx,authEntry.getSuccess()); | ||
362 | - deviceSessionCtx.setConnected(true); | ||
363 | - log.debug("[{}] Client connected!", sessionId); | ||
364 | - | ||
365 | - transportService.process(deviceSessionCtx.getSessionInfo(), TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); | ||
366 | - transportService.getCallbackExecutor().execute(() -> processQueueMessage(ctx)); //this callback will execute in Producer worker thread and hard or blocking work have to be submitted to the separate thread. | ||
367 | - } | ||
368 | - | ||
369 | - @Override | ||
370 | - public void onError(Throwable e) { | ||
371 | - if (e instanceof TbRateLimitsException) { | ||
372 | - log.trace("[{}] Failed to submit session event: {}", sessionId, e.getMessage()); | ||
373 | - } else { | ||
374 | - log.warn("[{}] Failed to submit session event", sessionId, e); | ||
375 | - } | ||
376 | - onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | ||
377 | - } | ||
378 | - }); | ||
379 | - } | 422 | + }); |
380 | } | 423 | } |
424 | + } | ||
381 | 425 | ||
382 | - private void onValidateFailed(ChannelHandlerContext ctx, MqttConnectReturnCode msg) { | ||
383 | - authedCounter.incrementAndGet(); | ||
384 | - if (TkScriptInvokeService.authScripts.size() == authedCounter.intValue()) { | ||
385 | - pushDeviceMsg(ctx,msg.name()); | 426 | + private void onValidateFailed(ChannelHandlerContext ctx, MqttConnectReturnCode msg) { |
427 | + authedCounter.incrementAndGet(); | ||
428 | + if (TkScriptInvokeService.authScripts.size() == authedCounter.intValue()) { | ||
429 | + pushDeviceMsg(ctx, msg.name()); | ||
386 | 430 | ||
387 | -// ctx.close(); | ||
388 | - } | 431 | + // ctx.close(); |
389 | } | 432 | } |
390 | - | ||
391 | - @Override | ||
392 | - public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) { | ||
393 | - | ||
394 | - } | ||
395 | - | ||
396 | - @Override | ||
397 | - public void onAttributeUpdate(UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) { | ||
398 | - | ||
399 | - } | ||
400 | - | ||
401 | - @Override | ||
402 | - public void onRemoteSessionCloseCommand(UUID sessionId, TransportProtos.SessionCloseNotificationProto sessionCloseNotification) { | ||
403 | - log.trace("[{}] Received the remote command to close the session: {}", sessionId, sessionCloseNotification.getMessage()); | ||
404 | -// deviceSessionCtx.getChannel().close(); | ||
405 | - } | ||
406 | - | ||
407 | - @Override | ||
408 | - public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { | ||
409 | - log.debug("【{}】下发RPC命令【{}】给设备【{}】", sessionId, rpcRequest.getParams(), deviceSessionCtx.getDeviceInfo().getDeviceName()); | ||
410 | - TcpTransportAdaptor adaptor = deviceSessionCtx.getPayloadAdaptor(); | ||
411 | - try { | 433 | + } |
434 | + | ||
435 | + @Override | ||
436 | + public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) {} | ||
437 | + | ||
438 | + @Override | ||
439 | + public void onAttributeUpdate( | ||
440 | + UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) {} | ||
441 | + | ||
442 | + @Override | ||
443 | + public void onRemoteSessionCloseCommand( | ||
444 | + UUID sessionId, TransportProtos.SessionCloseNotificationProto sessionCloseNotification) { | ||
445 | + log.trace( | ||
446 | + "[{}] Received the remote command to close the session: {}", | ||
447 | + sessionId, | ||
448 | + sessionCloseNotification.getMessage()); | ||
449 | + // deviceSessionCtx.getChannel().close(); | ||
450 | + } | ||
451 | + | ||
452 | + @Override | ||
453 | + public void onToDeviceRpcRequest( | ||
454 | + UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { | ||
455 | + log.debug( | ||
456 | + "【{}】下发RPC命令【{}】给设备【{}】", | ||
457 | + sessionId, | ||
458 | + rpcRequest.getParams(), | ||
459 | + deviceSessionCtx.getDeviceInfo().getDeviceName()); | ||
460 | + TcpTransportAdaptor adaptor = deviceSessionCtx.getPayloadAdaptor(); | ||
461 | + try { | ||
412 | adaptor | 462 | adaptor |
413 | .convertToPublish(deviceSessionCtx, rpcRequest) | 463 | .convertToPublish(deviceSessionCtx, rpcRequest) |
414 | .ifPresent( | 464 | .ifPresent( |
415 | payload -> { | 465 | payload -> { |
416 | deviceSessionCtx.rpcRequesting(payload.getIdentifier(), rpcRequest); | 466 | deviceSessionCtx.rpcRequesting(payload.getIdentifier(), rpcRequest); |
417 | - Optional.ofNullable(pushDeviceMsg(deviceSessionCtx.getChannel(), payload.getDatas())).ifPresent(cf->{ | ||
418 | - cf.addListener( | ||
419 | - result -> { | 467 | + Optional.ofNullable( |
468 | + pushDeviceMsg(deviceSessionCtx.getChannel(), payload.getDatas())) | ||
469 | + .ifPresent( | ||
470 | + cf -> { | ||
471 | + cf.addListener( | ||
472 | + result -> { | ||
420 | if (result.cause() == null) { | 473 | if (result.cause() == null) { |
421 | - transportService.process( | ||
422 | - deviceSessionCtx.getSessionInfo(), | ||
423 | - rpcRequest, | ||
424 | - RpcStatus.DELIVERED, | ||
425 | - TransportServiceCallback.EMPTY); | 474 | + transportService.process( |
475 | + deviceSessionCtx.getSessionInfo(), | ||
476 | + rpcRequest, | ||
477 | + RpcStatus.DELIVERED, | ||
478 | + TransportServiceCallback.EMPTY); | ||
426 | } else { | 479 | } else { |
427 | - // TODO: send error | 480 | + // TODO: send error |
428 | } | 481 | } |
429 | - }); | ||
430 | - }); | 482 | + }); |
483 | + }); | ||
431 | ; | 484 | ; |
432 | }); | 485 | }); |
433 | - } catch (Exception e) { | ||
434 | - transportService.process(deviceSessionCtx.getSessionInfo(), | ||
435 | - TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
436 | - .setRequestId(rpcRequest.getRequestId()).setError("Failed to convert device RPC command to TCP msg").build(), TransportServiceCallback.EMPTY); | ||
437 | - log.error("[{}] Failed to convert device RPC command to TCP msg", sessionId, e); | ||
438 | - } | 486 | + } catch (Exception e) { |
487 | + transportService.process( | ||
488 | + deviceSessionCtx.getSessionInfo(), | ||
489 | + TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
490 | + .setRequestId(rpcRequest.getRequestId()) | ||
491 | + .setError("Failed to convert device RPC command to TCP msg") | ||
492 | + .build(), | ||
493 | + TransportServiceCallback.EMPTY); | ||
494 | + log.error("[{}] Failed to convert device RPC command to TCP msg", sessionId, e); | ||
439 | } | 495 | } |
440 | - | ||
441 | - | ||
442 | - @Override | ||
443 | - public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg rpcResponse) { | ||
444 | - log.debug("[{}] 服务端响应设备的RPC请求", sessionId); | ||
445 | - } | ||
446 | - | ||
447 | - /** | ||
448 | - * 往设备推送消息 | ||
449 | - * | ||
450 | - * @param message | ||
451 | - * @return | ||
452 | - */ | ||
453 | - private ChannelFuture pushDeviceMsg(ChannelHandlerContext ctx, String message) { | ||
454 | - if(StringUtils.isBlank(message)){ | ||
455 | - return null; | ||
456 | - } | ||
457 | - ByteBuf buff = Unpooled.buffer(); | ||
458 | - if(!message.matches("-?[0-9a-fA-F]+")){ | ||
459 | - //不满足16进制将字符串转为16进制 | ||
460 | - message = ByteUtils.stringEncodeToHex(message); | ||
461 | - } | ||
462 | - buff.writeBytes(ByteUtils.hexToByteArray(message)); | ||
463 | - return ctx.writeAndFlush(buff); | 496 | + } |
497 | + | ||
498 | + @Override | ||
499 | + public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg rpcResponse) { | ||
500 | + log.debug("[{}] 服务端响应设备的RPC请求", sessionId); | ||
501 | + } | ||
502 | + | ||
503 | + /** | ||
504 | + * 往设备推送消息 | ||
505 | + * | ||
506 | + * @param message | ||
507 | + * @return | ||
508 | + */ | ||
509 | + private ChannelFuture pushDeviceMsg(ChannelHandlerContext ctx, String message) { | ||
510 | + if (StringUtils.isBlank(message)) { | ||
511 | + return null; | ||
464 | } | 512 | } |
465 | - | ||
466 | - | ||
467 | - @Override | ||
468 | - public void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) { | ||
469 | - deviceSessionCtx.onDeviceProfileUpdate(sessionInfo, deviceProfile); | ||
470 | - } | ||
471 | - | ||
472 | - @Override | ||
473 | - public void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) { | ||
474 | - deviceSessionCtx.onDeviceUpdate(sessionInfo, device, deviceProfileOpt); | ||
475 | - } | ||
476 | - | ||
477 | - @Override | ||
478 | - public void onDeviceDeleted(DeviceId deviceId) { | ||
479 | - context.onAuthFailure(address); | ||
480 | - ChannelHandlerContext ctx = deviceSessionCtx.getChannel(); | ||
481 | -// ctx.close(); | 513 | + ByteBuf buff = Unpooled.buffer(); |
514 | + if (!message.matches("-?[0-9a-fA-F]+")) { | ||
515 | + // 不满足16进制将字符串转为16进制 | ||
516 | + message = ByteUtils.stringEncodeToHex(message); | ||
482 | } | 517 | } |
518 | + buff.writeBytes(ByteBufUtil.decodeHexDump(message)); | ||
519 | + DatagramPacket packet = new DatagramPacket(buff, address); | ||
520 | + return ctx.writeAndFlush(packet); | ||
521 | + } | ||
522 | + | ||
523 | + @Override | ||
524 | + public void onDeviceProfileUpdate( | ||
525 | + TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) { | ||
526 | + deviceSessionCtx.onDeviceProfileUpdate(sessionInfo, deviceProfile); | ||
527 | + } | ||
528 | + | ||
529 | + @Override | ||
530 | + public void onDeviceUpdate( | ||
531 | + TransportProtos.SessionInfoProto sessionInfo, | ||
532 | + Device device, | ||
533 | + Optional<DeviceProfile> deviceProfileOpt) { | ||
534 | + deviceSessionCtx.onDeviceUpdate(sessionInfo, device, deviceProfileOpt); | ||
535 | + } | ||
536 | + | ||
537 | + @Override | ||
538 | + public void onDeviceDeleted(DeviceId deviceId) { | ||
539 | + context.onAuthFailure(address); | ||
540 | + ChannelHandlerContext ctx = deviceSessionCtx.getChannel(); | ||
541 | + // ctx.close(); | ||
542 | + } | ||
483 | } | 543 | } |
1 | package org.thingsboard.server.dao.yunteng.impl; | 1 | package org.thingsboard.server.dao.yunteng.impl; |
2 | 2 | ||
3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | +import java.util.ArrayList; | ||
5 | +import java.util.List; | ||
6 | +import java.util.Set; | ||
7 | +import java.util.stream.Collectors; | ||
4 | import lombok.RequiredArgsConstructor; | 8 | import lombok.RequiredArgsConstructor; |
5 | import org.springframework.stereotype.Service; | 9 | import org.springframework.stereotype.Service; |
6 | import org.thingsboard.server.common.data.yunteng.dto.DoActionDTO; | 10 | import org.thingsboard.server.common.data.yunteng.dto.DoActionDTO; |
7 | -import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; | ||
8 | import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum; | 11 | import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum; |
9 | import org.thingsboard.server.dao.yunteng.entities.TenantBaseEntity; | 12 | import org.thingsboard.server.dao.yunteng.entities.TenantBaseEntity; |
10 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceEntity; | 13 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceEntity; |
@@ -14,44 +17,46 @@ import org.thingsboard.server.dao.yunteng.mapper.DoActionMapper; | @@ -14,44 +17,46 @@ import org.thingsboard.server.dao.yunteng.mapper.DoActionMapper; | ||
14 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | 17 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; |
15 | import org.thingsboard.server.dao.yunteng.service.DoActionService; | 18 | import org.thingsboard.server.dao.yunteng.service.DoActionService; |
16 | 19 | ||
17 | -import java.util.ArrayList; | ||
18 | -import java.util.List; | ||
19 | -import java.util.Set; | ||
20 | -import java.util.stream.Collectors; | ||
21 | - | ||
22 | -/** @Description @Author cxy @Date 2021/12/6 20:23 */ | 20 | +/** |
21 | + * @Description @Author cxy @Date 2021/12/6 20:23 | ||
22 | + */ | ||
23 | @Service | 23 | @Service |
24 | @RequiredArgsConstructor | 24 | @RequiredArgsConstructor |
25 | public class TkDoActionServiceImpl extends AbstractBaseService<DoActionMapper, TkDoActionEntity> | 25 | public class TkDoActionServiceImpl extends AbstractBaseService<DoActionMapper, TkDoActionEntity> |
26 | implements DoActionService { | 26 | implements DoActionService { |
27 | private final DeviceMapper deviceMapper; | 27 | private final DeviceMapper deviceMapper; |
28 | + | ||
28 | @Override | 29 | @Override |
29 | public List<TkDoActionEntity> getActionsByAll(String sceneId) { | 30 | public List<TkDoActionEntity> getActionsByAll(String sceneId) { |
30 | LambdaQueryWrapper filter = | 31 | LambdaQueryWrapper filter = |
31 | - new LambdaQueryWrapper<TkDoActionEntity>().eq(TkDoActionEntity::getSceneLinkageId, sceneId).eq(TkDoActionEntity::getEntityType, ScopeEnum.ALL); | 32 | + new LambdaQueryWrapper<TkDoActionEntity>() |
33 | + .eq(TkDoActionEntity::getSceneLinkageId, sceneId) | ||
34 | + .eq(TkDoActionEntity::getEntityType, ScopeEnum.ALL); | ||
32 | return baseMapper.selectList(filter); | 35 | return baseMapper.selectList(filter); |
33 | } | 36 | } |
34 | 37 | ||
35 | - | ||
36 | @Override | 38 | @Override |
37 | public List<TkDoActionEntity> getActionsByPart(String sceneId) { | 39 | public List<TkDoActionEntity> getActionsByPart(String sceneId) { |
38 | LambdaQueryWrapper filter = | 40 | LambdaQueryWrapper filter = |
39 | - new LambdaQueryWrapper<TkDoActionEntity>().eq(TkDoActionEntity::getSceneLinkageId, sceneId).eq(TkDoActionEntity::getEntityType, ScopeEnum.PART); | 41 | + new LambdaQueryWrapper<TkDoActionEntity>() |
42 | + .eq(TkDoActionEntity::getSceneLinkageId, sceneId) | ||
43 | + .eq(TkDoActionEntity::getEntityType, ScopeEnum.PART); | ||
40 | List<TkDoActionEntity> source = baseMapper.selectList(filter); | 44 | List<TkDoActionEntity> source = baseMapper.selectList(filter); |
41 | - return source.stream().map(t ->{ | ||
42 | - List<TkDeviceEntity> partDevices = deviceMapper.selectList(new LambdaQueryWrapper<TkDeviceEntity>().in(TkDeviceEntity::getTbDeviceId,t.getDeviceId())); | ||
43 | - List<String> deviceId = new ArrayList<>(); | ||
44 | - for(TkDeviceEntity item : partDevices){ | ||
45 | - if(DeviceTypeEnum.SENSOR.equals(item.getDeviceType())){ | ||
46 | - deviceId.add(item.getGatewayId()); | ||
47 | - }else{ | ||
48 | - deviceId.add(item.getTbDeviceId()); | ||
49 | - } | ||
50 | - } | ||
51 | - t.setDeviceId(deviceId); | ||
52 | - return t; | ||
53 | - }).collect(Collectors.toList()); | ||
54 | - | 45 | + return source.stream() |
46 | + .map( | ||
47 | + t -> { | ||
48 | + List<TkDeviceEntity> partDevices = | ||
49 | + deviceMapper.selectList( | ||
50 | + new LambdaQueryWrapper<TkDeviceEntity>() | ||
51 | + .in(TkDeviceEntity::getTbDeviceId, t.getDeviceId())); | ||
52 | + List<String> deviceId = new ArrayList<>(); | ||
53 | + for (TkDeviceEntity item : partDevices) { | ||
54 | + deviceId.add(item.getTbDeviceId()); | ||
55 | + } | ||
56 | + t.setDeviceId(deviceId); | ||
57 | + return t; | ||
58 | + }) | ||
59 | + .collect(Collectors.toList()); | ||
55 | } | 60 | } |
56 | 61 | ||
57 | @Override | 62 | @Override |