Commit 8b285c8e77f5ff6fb9b88e68c4acc375fa268b5a
Committed by
Andrew Shvayka
1 parent
5a0336aa
created OtaPackageTransportResource
Showing
5 changed files
with
149 additions
and
77 deletions
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
... | ... | @@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC |
44 | 44 | import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
45 | 45 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
46 | 46 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
47 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | |
48 | 47 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
49 | 48 | import org.thingsboard.server.common.msg.session.FeatureType; |
50 | 49 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
... | ... | @@ -139,10 +138,6 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
139 | 138 | processExchangeGetRequest(exchange, featureType.get()); |
140 | 139 | } else if (featureType.get() == FeatureType.ATTRIBUTES) { |
141 | 140 | processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST); |
142 | - } else if (featureType.get() == FeatureType.FIRMWARE) { | |
143 | - processRequest(exchange, SessionMsgType.GET_FIRMWARE_REQUEST); | |
144 | - } else if (featureType.get() == FeatureType.SOFTWARE) { | |
145 | - processRequest(exchange, SessionMsgType.GET_SOFTWARE_REQUEST); | |
146 | 141 | } else { |
147 | 142 | log.trace("Invalid feature type parameter"); |
148 | 143 | exchange.respond(CoAP.ResponseCode.BAD_REQUEST); |
... | ... | @@ -349,12 +344,6 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
349 | 344 | coapTransportAdaptor.convertToGetAttributes(sessionId, request), |
350 | 345 | new CoapNoOpCallback(exchange)); |
351 | 346 | break; |
352 | - case GET_FIRMWARE_REQUEST: | |
353 | - getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.FIRMWARE); | |
354 | - break; | |
355 | - case GET_SOFTWARE_REQUEST: | |
356 | - getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.SOFTWARE); | |
357 | - break; | |
358 | 347 | } |
359 | 348 | } catch (AdaptorException e) { |
360 | 349 | log.trace("[{}] Failed to decode message: ", sessionId, e); |
... | ... | @@ -366,16 +355,6 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
366 | 355 | return new UUID(sessionInfoProto.getSessionIdMSB(), sessionInfoProto.getSessionIdLSB()); |
367 | 356 | } |
368 | 357 | |
369 | - private void getOtaPackageCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, OtaPackageType firmwareType) { | |
370 | - TransportProtos.GetOtaPackageRequestMsg requestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder() | |
371 | - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | |
372 | - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | |
373 | - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | |
374 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | |
375 | - .setType(firmwareType.name()).build(); | |
376 | - transportContext.getTransportService().process(sessionInfo, requestMsg, new OtaPackageCallback(exchange)); | |
377 | - } | |
378 | - | |
379 | 358 | private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) { |
380 | 359 | tokenToObserveNotificationSeqMap.remove(token); |
381 | 360 | return tokenToSessionInfoMap.remove(token); |
... | ... | @@ -470,57 +449,6 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
470 | 449 | } |
471 | 450 | } |
472 | 451 | |
473 | - private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> { | |
474 | - private final CoapExchange exchange; | |
475 | - | |
476 | - OtaPackageCallback(CoapExchange exchange) { | |
477 | - this.exchange = exchange; | |
478 | - } | |
479 | - | |
480 | - @Override | |
481 | - public void onSuccess(TransportProtos.GetOtaPackageResponseMsg msg) { | |
482 | - String title = exchange.getQueryParameter("title"); | |
483 | - String version = exchange.getQueryParameter("version"); | |
484 | - if (msg.getResponseStatus().equals(TransportProtos.ResponseStatus.SUCCESS)) { | |
485 | - String firmwareId = new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()).toString(); | |
486 | - if (msg.getTitle().equals(title) && msg.getVersion().equals(version)) { | |
487 | - String strChunkSize = exchange.getQueryParameter("size"); | |
488 | - String strChunk = exchange.getQueryParameter("chunk"); | |
489 | - int chunkSize = StringUtils.isEmpty(strChunkSize) ? 0 : Integer.parseInt(strChunkSize); | |
490 | - int chunk = StringUtils.isEmpty(strChunk) ? 0 : Integer.parseInt(strChunk); | |
491 | - exchange.respond(CoAP.ResponseCode.CONTENT, transportContext.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk)); | |
492 | - } | |
493 | - else if (firmwareId != null) { | |
494 | - sendOtaData(exchange, firmwareId); | |
495 | - } else { | |
496 | - exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
497 | - } | |
498 | - } else { | |
499 | - exchange.respond(CoAP.ResponseCode.NOT_FOUND); | |
500 | - } | |
501 | - } | |
502 | - | |
503 | - @Override | |
504 | - public void onError(Throwable e) { | |
505 | - log.warn("Failed to process request", e); | |
506 | - exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
507 | - } | |
508 | - } | |
509 | - | |
510 | - private void sendOtaData(CoapExchange exchange, String firmwareId) { | |
511 | - Response response = new Response(CoAP.ResponseCode.CONTENT); | |
512 | - byte[] fwData = transportContext.getOtaPackageDataCache().get(firmwareId); | |
513 | - if (fwData != null && fwData.length > 0) { | |
514 | - response.setPayload(fwData); | |
515 | - if (exchange.getRequestOptions().getBlock2() != null) { | |
516 | - int chunkSize = exchange.getRequestOptions().getBlock2().getSzx(); | |
517 | - boolean moreFlag = fwData.length > chunkSize; | |
518 | - response.getOptions().setBlock2(chunkSize, moreFlag, 0); | |
519 | - } | |
520 | - exchange.respond(response); | |
521 | - } | |
522 | - } | |
523 | - | |
524 | 452 | private static class CoapSessionListener implements SessionMsgListener { |
525 | 453 | |
526 | 454 | private final CoapTransportResource coapTransportResource; | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import org.springframework.stereotype.Service; |
23 | 23 | import org.thingsboard.server.common.data.TbTransportService; |
24 | 24 | import org.thingsboard.server.coapserver.CoapServerService; |
25 | 25 | import org.thingsboard.server.coapserver.TbCoapServerComponent; |
26 | +import org.thingsboard.server.common.data.ota.OtaPackageType; | |
26 | 27 | import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; |
27 | 28 | |
28 | 29 | import javax.annotation.PostConstruct; |
... | ... | @@ -59,6 +60,8 @@ public class CoapTransportService implements TbTransportService { |
59 | 60 | efento.add(efentoMeasurementsTransportResource); |
60 | 61 | coapServer.add(api); |
61 | 62 | coapServer.add(efento); |
63 | + coapServer.add(new OtaPackageTransportResource(coapTransportContext, OtaPackageType.FIRMWARE)); | |
64 | + coapServer.add(new OtaPackageTransportResource(coapTransportContext, OtaPackageType.SOFTWARE)); | |
62 | 65 | log.info("CoAP transport started!"); |
63 | 66 | } |
64 | 67 | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.transport.coap; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.californium.core.coap.CoAP; | |
20 | +import org.eclipse.californium.core.coap.Request; | |
21 | +import org.eclipse.californium.core.coap.Response; | |
22 | +import org.eclipse.californium.core.network.Exchange; | |
23 | +import org.eclipse.californium.core.server.resources.CoapExchange; | |
24 | +import org.eclipse.californium.core.server.resources.Resource; | |
25 | +import org.thingsboard.server.common.data.DeviceTransportType; | |
26 | +import org.thingsboard.server.common.data.StringUtils; | |
27 | +import org.thingsboard.server.common.data.ota.OtaPackageType; | |
28 | +import org.thingsboard.server.common.data.security.DeviceTokenCredentials; | |
29 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | |
30 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
31 | + | |
32 | +import java.util.List; | |
33 | +import java.util.Optional; | |
34 | +import java.util.UUID; | |
35 | + | |
36 | +@Slf4j | |
37 | +public class OtaPackageTransportResource extends AbstractCoapTransportResource { | |
38 | + private static final int ACCESS_TOKEN_POSITION = 2; | |
39 | + | |
40 | + private final OtaPackageType otaPackageType; | |
41 | + | |
42 | + public OtaPackageTransportResource(CoapTransportContext ctx, OtaPackageType otaPackageType) { | |
43 | + super(ctx, otaPackageType.getKeyPrefix()); | |
44 | + this.otaPackageType = otaPackageType; | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + protected void processHandleGet(CoapExchange exchange) { | |
49 | + log.trace("Processing {}", exchange.advanced().getRequest()); | |
50 | + exchange.accept(); | |
51 | + Exchange advanced = exchange.advanced(); | |
52 | + Request request = advanced.getRequest(); | |
53 | + processAccessTokenRequest(exchange, request); | |
54 | + } | |
55 | + | |
56 | + @Override | |
57 | + protected void processHandlePost(CoapExchange exchange) { | |
58 | + exchange.respond(CoAP.ResponseCode.METHOD_NOT_ALLOWED); | |
59 | + } | |
60 | + | |
61 | + private void processAccessTokenRequest(CoapExchange exchange, Request request) { | |
62 | + Optional<DeviceTokenCredentials> credentials = decodeCredentials(request); | |
63 | + if (credentials.isEmpty()) { | |
64 | + exchange.respond(CoAP.ResponseCode.UNAUTHORIZED); | |
65 | + return; | |
66 | + } | |
67 | + transportService.process(DeviceTransportType.COAP, TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder().setToken(credentials.get().getCredentialsId()).build(), | |
68 | + new CoapDeviceAuthCallback(transportContext, exchange, (sessionInfo, deviceProfile) -> { | |
69 | + getOtaPackageCallback(sessionInfo, exchange, otaPackageType); | |
70 | + })); | |
71 | + } | |
72 | + | |
73 | + private void getOtaPackageCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, OtaPackageType firmwareType) { | |
74 | + TransportProtos.GetOtaPackageRequestMsg requestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder() | |
75 | + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | |
76 | + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | |
77 | + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | |
78 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | |
79 | + .setType(firmwareType.name()).build(); | |
80 | + transportContext.getTransportService().process(sessionInfo, requestMsg, new OtaPackageCallback(exchange)); | |
81 | + } | |
82 | + | |
83 | + private Optional<DeviceTokenCredentials> decodeCredentials(Request request) { | |
84 | + List<String> uriPath = request.getOptions().getUriPath(); | |
85 | + if (uriPath.size() == ACCESS_TOKEN_POSITION) { | |
86 | + return Optional.of(new DeviceTokenCredentials(uriPath.get(ACCESS_TOKEN_POSITION - 1))); | |
87 | + } else { | |
88 | + return Optional.empty(); | |
89 | + } | |
90 | + } | |
91 | + | |
92 | + @Override | |
93 | + public Resource getChild(String name) { | |
94 | + return this; | |
95 | + } | |
96 | + | |
97 | + private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> { | |
98 | + private final CoapExchange exchange; | |
99 | + | |
100 | + OtaPackageCallback(CoapExchange exchange) { | |
101 | + this.exchange = exchange; | |
102 | + } | |
103 | + | |
104 | + @Override | |
105 | + public void onSuccess(TransportProtos.GetOtaPackageResponseMsg msg) { | |
106 | + String title = exchange.getQueryParameter("title"); | |
107 | + String version = exchange.getQueryParameter("version"); | |
108 | + if (msg.getResponseStatus().equals(TransportProtos.ResponseStatus.SUCCESS)) { | |
109 | + String firmwareId = new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()).toString(); | |
110 | + if ((title == null || msg.getTitle().equals(title)) && (version == null || msg.getVersion().equals(version))) { | |
111 | + String strChunkSize = exchange.getQueryParameter("size"); | |
112 | + String strChunk = exchange.getQueryParameter("chunk"); | |
113 | + int chunkSize = StringUtils.isEmpty(strChunkSize) ? 0 : Integer.parseInt(strChunkSize); | |
114 | + int chunk = StringUtils.isEmpty(strChunk) ? 0 : Integer.parseInt(strChunk); | |
115 | + respondOtaPackage(exchange, transportContext.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk)); | |
116 | + } else { | |
117 | + exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | |
118 | + } | |
119 | + } else { | |
120 | + exchange.respond(CoAP.ResponseCode.NOT_FOUND); | |
121 | + } | |
122 | + } | |
123 | + | |
124 | + @Override | |
125 | + public void onError(Throwable e) { | |
126 | + log.warn("Failed to process request", e); | |
127 | + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | |
128 | + } | |
129 | + } | |
130 | + | |
131 | + private void respondOtaPackage(CoapExchange exchange, byte[] data) { | |
132 | + Response response = new Response(CoAP.ResponseCode.CONTENT); | |
133 | + if (data != null && data.length > 0) { | |
134 | + response.setPayload(data); | |
135 | + if (exchange.getRequestOptions().getBlock2() != null) { | |
136 | + int chunkSize = exchange.getRequestOptions().getBlock2().getSzx(); | |
137 | + boolean moreFlag = data.length > chunkSize; | |
138 | + response.getOptions().setBlock2(chunkSize, moreFlag, 0); | |
139 | + } | |
140 | + exchange.respond(response); | |
141 | + } | |
142 | + } | |
143 | + | |
144 | +} | ... | ... |