Commit 8b285c8e77f5ff6fb9b88e68c4acc375fa268b5a

Authored by YevhenBondarenko
Committed by Andrew Shvayka
1 parent 5a0336aa

created OtaPackageTransportResource

... ... @@ -16,5 +16,5 @@
16 16 package org.thingsboard.server.common.msg.session;
17 17
18 18 public enum FeatureType {
19   - ATTRIBUTES, TELEMETRY, RPC, CLAIM, PROVISION, FIRMWARE, SOFTWARE
  19 + ATTRIBUTES, TELEMETRY, RPC, CLAIM, PROVISION
20 20 }
... ...
... ... @@ -30,10 +30,7 @@ public enum SessionMsgType {
30 30
31 31 SESSION_OPEN, SESSION_CLOSE,
32 32
33   - CLAIM_REQUEST(),
34   -
35   - GET_FIRMWARE_REQUEST,
36   - GET_SOFTWARE_REQUEST;
  33 + CLAIM_REQUEST();
37 34
38 35 private final boolean requiresRulesProcessing;
39 36
... ...
... ... @@ -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 +}
... ...