Commit d190cba27754891dff50aec8f2eae29e2af13964

Authored by Andrew Shvayka
Committed by GitHub
2 parents 9bd4bf0e 42898d4a

Merge pull request #4787 from YevhenBondarenko/feature/power-mode

Feature/power mode
Showing 32 changed files with 302 additions and 235 deletions
@@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TbResource; @@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TbResource;
41 import org.thingsboard.server.common.data.TenantProfile; 41 import org.thingsboard.server.common.data.TenantProfile;
42 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; 42 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
43 import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData; 43 import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
  44 +import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
  45 +import org.thingsboard.server.common.data.device.data.PowerMode;
44 import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; 46 import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
45 import org.thingsboard.server.common.data.id.CustomerId; 47 import org.thingsboard.server.common.data.id.CustomerId;
46 import org.thingsboard.server.common.data.id.DeviceId; 48 import org.thingsboard.server.common.data.id.DeviceId;
@@ -459,7 +461,14 @@ public class DefaultTransportApiService implements TransportApiService { @@ -459,7 +461,14 @@ public class DefaultTransportApiService implements TransportApiService {
459 } 461 }
460 462
461 private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException { 463 private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
462 - return DeviceInfoProto.newBuilder() 464 + PowerMode powerMode = null;
  465 + switch (device.getDeviceData().getTransportConfiguration().getType()) {
  466 + case LWM2M:
  467 + powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
  468 + break;
  469 + }
  470 +
  471 + DeviceInfoProto.Builder builder = DeviceInfoProto.newBuilder()
463 .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits()) 472 .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
464 .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits()) 473 .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())
465 .setCustomerIdMSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getMostSignificantBits()).orElse(0L)) 474 .setCustomerIdMSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getMostSignificantBits()).orElse(0L))
@@ -470,8 +479,11 @@ public class DefaultTransportApiService implements TransportApiService { @@ -470,8 +479,11 @@ public class DefaultTransportApiService implements TransportApiService {
470 .setDeviceType(device.getType()) 479 .setDeviceType(device.getType())
471 .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()) 480 .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits())
472 .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits()) 481 .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits())
473 - .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()))  
474 - .build(); 482 + .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()));
  483 + if (powerMode != null) {
  484 + builder.setPowerMode(powerMode.name());
  485 + }
  486 + return builder.build();
475 } 487 }
476 488
477 private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() { 489 private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() {
@@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; @@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
20 import com.fasterxml.jackson.annotation.JsonIgnore; 20 import com.fasterxml.jackson.annotation.JsonIgnore;
21 import lombok.Data; 21 import lombok.Data;
22 import org.thingsboard.server.common.data.DeviceTransportType; 22 import org.thingsboard.server.common.data.DeviceTransportType;
23 -import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfiguration;  
24 -import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;  
25 -import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;  
26 23
27 import java.util.HashMap; 24 import java.util.HashMap;
28 import java.util.Map; 25 import java.util.Map;
@@ -30,6 +27,8 @@ import java.util.Map; @@ -30,6 +27,8 @@ import java.util.Map;
30 @Data 27 @Data
31 public class Lwm2mDeviceTransportConfiguration implements DeviceTransportConfiguration { 28 public class Lwm2mDeviceTransportConfiguration implements DeviceTransportConfiguration {
32 29
  30 + private PowerMode powerMode;
  31 +
33 @JsonIgnore 32 @JsonIgnore
34 private Map<String, Object> properties = new HashMap<>(); 33 private Map<String, Object> properties = new HashMap<>();
35 34
  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.common.data.device.data;
  17 +
  18 +public enum PowerMode {
  19 + PSM, DRX, E_DRX
  20 +}
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.common.data.device.data.lwm2m; 16 package org.thingsboard.server.common.data.device.data.lwm2m;
17 17
18 import lombok.Data; 18 import lombok.Data;
  19 +import org.thingsboard.server.common.data.device.data.PowerMode;
19 20
20 @Data 21 @Data
21 public class OtherConfiguration { 22 public class OtherConfiguration {
@@ -23,7 +24,8 @@ public class OtherConfiguration { @@ -23,7 +24,8 @@ public class OtherConfiguration {
23 private Integer fwUpdateStrategy; 24 private Integer fwUpdateStrategy;
24 private Integer swUpdateStrategy; 25 private Integer swUpdateStrategy;
25 private Integer clientOnlyObserveAfterConnect; 26 private Integer clientOnlyObserveAfterConnect;
26 - private String fwUpdateRecourse;  
27 - private String swUpdateRecourse; 27 + private PowerMode powerMode;
  28 + private String fwUpdateResource;
  29 + private String swUpdateResource;
28 30
29 } 31 }
@@ -115,6 +115,7 @@ message DeviceInfoProto { @@ -115,6 +115,7 @@ message DeviceInfoProto {
115 int64 deviceProfileIdLSB = 9; 115 int64 deviceProfileIdLSB = 9;
116 int64 customerIdMSB = 10; 116 int64 customerIdMSB = 10;
117 int64 customerIdLSB = 11; 117 int64 customerIdLSB = 11;
  118 + string powerMode = 12;
118 } 119 }
119 120
120 /** 121 /**
@@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC @@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC
44 import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; 44 import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
45 import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; 45 import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
46 import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; 46 import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
47 -import org.thingsboard.server.common.data.rpc.RpcStatus;  
48 import org.thingsboard.server.common.data.security.DeviceTokenCredentials; 47 import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
49 import org.thingsboard.server.common.msg.session.FeatureType; 48 import org.thingsboard.server.common.msg.session.FeatureType;
50 import org.thingsboard.server.common.msg.session.SessionMsgType; 49 import org.thingsboard.server.common.msg.session.SessionMsgType;
@@ -509,23 +508,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -509,23 +508,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
509 closeObserveRelationAndNotify(sessionId, CoAP.ResponseCode.INTERNAL_SERVER_ERROR); 508 closeObserveRelationAndNotify(sessionId, CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
510 successful = false; 509 successful = false;
511 } finally { 510 } finally {
512 - if (msg.getPersisted()) {  
513 - RpcStatus status;  
514 - if (!successful) {  
515 - status = RpcStatus.FAILED;  
516 - } else if (msg.getOneway()) {  
517 - status = RpcStatus.SUCCESSFUL;  
518 - } else {  
519 - status = RpcStatus.DELIVERED;  
520 - }  
521 - TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
522 - .setRequestId(msg.getRequestId())  
523 - .setRequestIdLSB(msg.getRequestIdLSB())  
524 - .setRequestIdMSB(msg.getRequestIdMSB())  
525 - .setStatus(status.name())  
526 - .build();  
527 - coapTransportResource.transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);  
528 - } 511 + coapTransportResource.transportService.process(sessionInfo, msg, !successful, TransportServiceCallback.EMPTY);
529 if (!successful) { 512 if (!successful) {
530 closeAndDeregister(); 513 closeAndDeregister();
531 } 514 }
@@ -408,21 +408,7 @@ public class DeviceApiController implements TbTransportService { @@ -408,21 +408,7 @@ public class DeviceApiController implements TbTransportService {
408 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg msg) { 408 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg msg) {
409 log.trace("[{}] Received RPC command to device", sessionId); 409 log.trace("[{}] Received RPC command to device", sessionId);
410 responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg, true).toString(), HttpStatus.OK)); 410 responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg, true).toString(), HttpStatus.OK));
411 - if (msg.getPersisted()) {  
412 - RpcStatus status;  
413 - if (msg.getOneway()) {  
414 - status = RpcStatus.SUCCESSFUL;  
415 - } else {  
416 - status = RpcStatus.DELIVERED;  
417 - }  
418 - TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
419 - .setRequestId(msg.getRequestId())  
420 - .setRequestIdLSB(msg.getRequestIdLSB())  
421 - .setRequestIdMSB(msg.getRequestIdMSB())  
422 - .setStatus(status.name())  
423 - .build();  
424 - transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);  
425 - } 411 + transportService.process(sessionInfo, msg, false, TransportServiceCallback.EMPTY);
426 } 412 }
427 413
428 @Override 414 @Override
@@ -33,6 +33,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; @@ -33,6 +33,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
33 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 33 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
34 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; 34 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
35 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 35 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
  36 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException;
36 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer; 37 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer;
37 38
38 import java.io.IOException; 39 import java.io.IOException;
@@ -84,7 +85,14 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -84,7 +85,14 @@ public class LwM2mCredentialsSecurityInfoValidator {
84 } catch (InterruptedException e) { 85 } catch (InterruptedException e) {
85 log.error("Failed to await credentials!", e); 86 log.error("Failed to await credentials!", e);
86 } 87 }
87 - return resultSecurityStore[0]; 88 +
  89 + TbLwM2MSecurityInfo securityInfo = resultSecurityStore[0];
  90 +
  91 + if (securityInfo.getSecurityMode() == null) {
  92 + throw new LwM2MAuthException();
  93 + }
  94 +
  95 + return securityInfo;
88 } 96 }
89 97
90 /** 98 /**
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.transport.lwm2m.secure; 16 package org.thingsboard.server.transport.lwm2m.secure;
17 17
18 import lombok.RequiredArgsConstructor; 18 import lombok.RequiredArgsConstructor;
  19 +import lombok.extern.slf4j.Slf4j;
19 import org.eclipse.leshan.core.request.Identity; 20 import org.eclipse.leshan.core.request.Identity;
20 import org.eclipse.leshan.core.request.UplinkRequest; 21 import org.eclipse.leshan.core.request.UplinkRequest;
21 import org.eclipse.leshan.server.registration.Registration; 22 import org.eclipse.leshan.server.registration.Registration;
@@ -24,14 +25,15 @@ import org.eclipse.leshan.server.security.SecurityChecker; @@ -24,14 +25,15 @@ import org.eclipse.leshan.server.security.SecurityChecker;
24 import org.eclipse.leshan.server.security.SecurityInfo; 25 import org.eclipse.leshan.server.security.SecurityInfo;
25 import org.springframework.stereotype.Component; 26 import org.springframework.stereotype.Component;
26 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 27 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  28 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException;
27 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 29 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
28 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; 30 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
29 -import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;  
30 import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; 31 import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
31 32
32 @Component 33 @Component
33 @RequiredArgsConstructor 34 @RequiredArgsConstructor
34 @TbLwM2mTransportComponent 35 @TbLwM2mTransportComponent
  36 +@Slf4j
35 public class TbLwM2MAuthorizer implements Authorizer { 37 public class TbLwM2MAuthorizer implements Authorizer {
36 38
37 private final TbLwM2MDtlsSessionStore sessionStorage; 39 private final TbLwM2MDtlsSessionStore sessionStorage;
@@ -57,7 +59,12 @@ public class TbLwM2MAuthorizer implements Authorizer { @@ -57,7 +59,12 @@ public class TbLwM2MAuthorizer implements Authorizer {
57 } 59 }
58 SecurityInfo expectedSecurityInfo = null; 60 SecurityInfo expectedSecurityInfo = null;
59 if (securityStore != null) { 61 if (securityStore != null) {
60 - expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint()); 62 + try {
  63 + expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint());
  64 + } catch (LwM2MAuthException e) {
  65 + log.warn("Registration failed: FORBIDDEN, endpointId: [{}]", registration.getEndpoint());
  66 + return null;
  67 + }
61 } 68 }
62 if (securityChecker.checkSecurityInfo(registration.getEndpoint(), senderIdentity, expectedSecurityInfo)) { 69 if (securityChecker.checkSecurityInfo(registration.getEndpoint(), senderIdentity, expectedSecurityInfo)) {
63 return registration; 70 return registration;
@@ -42,6 +42,7 @@ import org.thingsboard.server.common.transport.util.SslUtil; @@ -42,6 +42,7 @@ import org.thingsboard.server.common.transport.util.SslUtil;
42 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 42 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
43 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 43 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
44 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; 44 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
  45 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException;
45 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; 46 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
46 import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore; 47 import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore;
47 48
@@ -118,7 +119,12 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer @@ -118,7 +119,12 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
118 119
119 String strCert = SslUtil.getCertificateString(cert); 120 String strCert = SslUtil.getCertificateString(cert);
120 String sha3Hash = EncryptionUtil.getSha3Hash(strCert); 121 String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
121 - TbLwM2MSecurityInfo securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, CLIENT); 122 + TbLwM2MSecurityInfo securityInfo;
  123 + try {
  124 + securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, CLIENT);
  125 + } catch (LwM2MAuthException e) {
  126 + securityInfo = null;
  127 + }
122 ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null; 128 ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null;
123 if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) { 129 if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) {
124 LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class); 130 LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class);
@@ -65,7 +65,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE @@ -65,7 +65,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
65 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; 65 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
66 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; 66 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
67 import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig; 67 import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
68 -import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RECOURSE; 68 +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RESOURCE;
69 69
70 @Slf4j 70 @Slf4j
71 @Component 71 @Component
@@ -105,7 +105,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -105,7 +105,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
105 * "coap://host:port/{path}/{token}/{nameFile}" 105 * "coap://host:port/{path}/{token}/{nameFile}"
106 */ 106 */
107 107
108 - LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(otaPackageDataCache, FIRMWARE_UPDATE_COAP_RECOURSE); 108 + LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(otaPackageDataCache, FIRMWARE_UPDATE_COAP_RESOURCE);
109 this.server.coap().getServer().add(otaCoapResource); 109 this.server.coap().getServer().add(otaCoapResource);
110 this.startLhServer(); 110 this.startLhServer();
111 this.context.setServer(server); 111 this.context.setServer(server);
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull; @@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
24 import org.thingsboard.server.common.data.DeviceProfile; 24 import org.thingsboard.server.common.data.DeviceProfile;
25 import org.thingsboard.server.common.data.ResourceType; 25 import org.thingsboard.server.common.data.ResourceType;
26 -import org.thingsboard.server.common.data.rpc.RpcStatus;  
27 import org.thingsboard.server.common.transport.SessionMsgListener; 26 import org.thingsboard.server.common.transport.SessionMsgListener;
28 import org.thingsboard.server.common.transport.TransportService; 27 import org.thingsboard.server.common.transport.TransportService;
29 import org.thingsboard.server.common.transport.TransportServiceCallback; 28 import org.thingsboard.server.common.transport.TransportServiceCallback;
@@ -85,21 +84,7 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s @@ -85,21 +84,7 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
85 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg toDeviceRequest) { 84 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg toDeviceRequest) {
86 log.trace("[{}] Received RPC command to device", sessionId); 85 log.trace("[{}] Received RPC command to device", sessionId);
87 this.rpcHandler.onToDeviceRpcRequest(toDeviceRequest, this.sessionInfo); 86 this.rpcHandler.onToDeviceRpcRequest(toDeviceRequest, this.sessionInfo);
88 - if (toDeviceRequest.getPersisted()) {  
89 - RpcStatus status;  
90 - if (toDeviceRequest.getOneway()) {  
91 - status = RpcStatus.SUCCESSFUL;  
92 - } else {  
93 - status = RpcStatus.DELIVERED;  
94 - }  
95 - TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
96 - .setRequestId(toDeviceRequest.getRequestId())  
97 - .setRequestIdLSB(toDeviceRequest.getRequestIdLSB())  
98 - .setRequestIdMSB(toDeviceRequest.getRequestIdMSB())  
99 - .setStatus(status.name())  
100 - .build();  
101 - transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);  
102 - } 87 + transportService.process(sessionInfo, toDeviceRequest, false, TransportServiceCallback.EMPTY);
103 } 88 }
104 89
105 @Override 90 @Override
@@ -31,8 +31,8 @@ import java.util.concurrent.ConcurrentHashMap; @@ -31,8 +31,8 @@ import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.ConcurrentMap; 31 import java.util.concurrent.ConcurrentMap;
32 import java.util.concurrent.atomic.AtomicInteger; 32 import java.util.concurrent.atomic.AtomicInteger;
33 33
34 -import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RECOURSE;  
35 -import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.SOFTWARE_UPDATE_COAP_RECOURSE; 34 +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RESOURCE;
  35 +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.SOFTWARE_UPDATE_COAP_RESOURCE;
36 36
37 @Slf4j 37 @Slf4j
38 public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { 38 public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
@@ -71,8 +71,8 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { @@ -71,8 +71,8 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
71 protected void processHandleGet(CoapExchange exchange) { 71 protected void processHandleGet(CoapExchange exchange) {
72 log.warn("90) processHandleGet [{}]", exchange); 72 log.warn("90) processHandleGet [{}]", exchange);
73 if (exchange.getRequestOptions().getUriPath().size() >= 2 && 73 if (exchange.getRequestOptions().getUriPath().size() >= 2 &&
74 - (FIRMWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-2)) ||  
75 - SOFTWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-2)))) { 74 + (FIRMWARE_UPDATE_COAP_RESOURCE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size() - 2)) ||
  75 + SOFTWARE_UPDATE_COAP_RESOURCE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size() - 2)))) {
76 this.sendOtaData(exchange); 76 this.sendOtaData(exchange);
77 } 77 }
78 } 78 }
@@ -131,7 +131,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { @@ -131,7 +131,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
131 } 131 }
132 132
133 private void sendOtaData(CoapExchange exchange) { 133 private void sendOtaData(CoapExchange exchange) {
134 - String idStr = exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-1 134 + String idStr = exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size() - 1
135 ); 135 );
136 UUID currentId = UUID.fromString(idStr); 136 UUID currentId = UUID.fromString(idStr);
137 Response response = new Response(CoAP.ResponseCode.CONTENT); 137 Response response = new Response(CoAP.ResponseCode.CONTENT);
@@ -144,8 +144,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { @@ -144,8 +144,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
144 boolean lastFlag = fwData.length <= chunkSize; 144 boolean lastFlag = fwData.length <= chunkSize;
145 response.getOptions().setBlock2(chunkSize, lastFlag, 0); 145 response.getOptions().setBlock2(chunkSize, lastFlag, 0);
146 log.warn("92) with blokc2 Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, lastFlag); 146 log.warn("92) with blokc2 Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, lastFlag);
147 - }  
148 - else { 147 + } else {
149 log.warn("92) with block1 Send currentId: [{}], length: [{}], ", currentId.toString(), fwData.length); 148 log.warn("92) with block1 Send currentId: [{}], length: [{}], ", currentId.toString(), fwData.length);
150 } 149 }
151 exchange.respond(response); 150 exchange.respond(response);
@@ -123,7 +123,7 @@ public class LwM2mTransportUtil { @@ -123,7 +123,7 @@ public class LwM2mTransportUtil {
123 } 123 }
124 } 124 }
125 125
126 - public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath 126 + public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath
127 resourcePath) throws CodecException { 127 resourcePath) throws CodecException {
128 switch (type) { 128 switch (type) {
129 case BOOLEAN: 129 case BOOLEAN:
  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.lwm2m.server.client;
  17 +
  18 +public class LwM2MAuthException extends RuntimeException {
  19 +
  20 + private static final long serialVersionUID = 4202690897971364044L;
  21 +
  22 +}
@@ -32,6 +32,8 @@ import org.eclipse.leshan.server.registration.Registration; @@ -32,6 +32,8 @@ import org.eclipse.leshan.server.registration.Registration;
32 import org.eclipse.leshan.server.security.SecurityInfo; 32 import org.eclipse.leshan.server.security.SecurityInfo;
33 import org.thingsboard.server.common.data.Device; 33 import org.thingsboard.server.common.data.Device;
34 import org.thingsboard.server.common.data.DeviceProfile; 34 import org.thingsboard.server.common.data.DeviceProfile;
  35 +import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
  36 +import org.thingsboard.server.common.data.device.data.PowerMode;
35 import org.thingsboard.server.common.data.id.TenantId; 37 import org.thingsboard.server.common.data.id.TenantId;
36 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 38 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
37 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; 39 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
@@ -80,6 +82,9 @@ public class LwM2mClient implements Cloneable { @@ -80,6 +82,9 @@ public class LwM2mClient implements Cloneable {
80 private String deviceProfileName; 82 private String deviceProfileName;
81 83
82 @Getter 84 @Getter
  85 + private PowerMode powerMode;
  86 +
  87 + @Getter
83 private String identity; 88 private String identity;
84 @Getter 89 @Getter
85 private SecurityInfo securityInfo; 90 private SecurityInfo securityInfo;
@@ -121,6 +126,7 @@ public class LwM2mClient implements Cloneable { @@ -121,6 +126,7 @@ public class LwM2mClient implements Cloneable {
121 this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB()); 126 this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
122 this.deviceName = session.getDeviceName(); 127 this.deviceName = session.getDeviceName();
123 this.deviceProfileName = session.getDeviceType(); 128 this.deviceProfileName = session.getDeviceType();
  129 + this.powerMode = credentials.getDeviceInfo().getPowerMode();
124 } 130 }
125 131
126 public void lock() { 132 public void lock() {
@@ -140,6 +146,7 @@ public class LwM2mClient implements Cloneable { @@ -140,6 +146,7 @@ public class LwM2mClient implements Cloneable {
140 builder.setDeviceName(deviceName); 146 builder.setDeviceName(deviceName);
141 deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder)); 147 deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder));
142 this.session = builder.build(); 148 this.session = builder.build();
  149 + this.powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
143 } 150 }
144 151
145 public void onDeviceProfileUpdate(DeviceProfile deviceProfile) { 152 public void onDeviceProfileUpdate(DeviceProfile deviceProfile) {
@@ -87,8 +87,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -87,8 +87,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
87 public static final String SOFTWARE_TITLE = getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE); 87 public static final String SOFTWARE_TITLE = getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE);
88 public static final String SOFTWARE_URL = getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.URL); 88 public static final String SOFTWARE_URL = getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.URL);
89 89
90 - public static final String FIRMWARE_UPDATE_COAP_RECOURSE = "tbfw";  
91 - public static final String SOFTWARE_UPDATE_COAP_RECOURSE = "tbsw"; 90 + public static final String FIRMWARE_UPDATE_COAP_RESOURCE = "tbfw";
  91 + public static final String SOFTWARE_UPDATE_COAP_RESOURCE = "tbsw";
92 private static final String FW_PACKAGE_5_ID = "/5/0/0"; 92 private static final String FW_PACKAGE_5_ID = "/5/0/0";
93 private static final String FW_URL_ID = "/5/0/1"; 93 private static final String FW_URL_ID = "/5/0/1";
94 private static final String FW_EXECUTE_ID = "/5/0/2"; 94 private static final String FW_EXECUTE_ID = "/5/0/2";
@@ -206,7 +206,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -206,7 +206,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
206 log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy()); 206 log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy());
207 LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client); 207 LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client);
208 fwInfo.setFwStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy())); 208 fwInfo.setFwStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy()));
209 - fwInfo.setBaseUrl(configuration.getFwUpdateRecourse()); 209 + fwInfo.setBaseUrl(configuration.getFwUpdateResource());
210 startFirmwareUpdateIfNeeded(client, fwInfo); 210 startFirmwareUpdateIfNeeded(client, fwInfo);
211 } 211 }
212 212
@@ -215,7 +215,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -215,7 +215,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
215 log.debug("[{}] Current sw strategy: {}", client.getEndpoint(), configuration.getSwUpdateStrategy()); 215 log.debug("[{}] Current sw strategy: {}", client.getEndpoint(), configuration.getSwUpdateStrategy());
216 LwM2MClientOtaInfo swInfo = getOrInitSwInfo(client); 216 LwM2MClientOtaInfo swInfo = getOrInitSwInfo(client);
217 swInfo.setSwStrategy(LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(configuration.getSwUpdateStrategy())); 217 swInfo.setSwStrategy(LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(configuration.getSwUpdateStrategy()));
218 - swInfo.setBaseUrl(configuration.getSwUpdateRecourse()); 218 + swInfo.setBaseUrl(configuration.getSwUpdateResource());
219 startSoftwareUpdateIfNeeded(client, swInfo); 219 startSoftwareUpdateIfNeeded(client, swInfo);
220 } 220 }
221 221
@@ -339,7 +339,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -339,7 +339,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
339 downlinkHandler.sendWriteReplaceRequest(client, writeRequest, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId)); 339 downlinkHandler.sendWriteReplaceRequest(client, writeRequest, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId));
340 break; 340 break;
341 case OBJ_5_TEMP_URL: 341 case OBJ_5_TEMP_URL:
342 - startFirmwareUpdateUsingUrl(client, fwInfo.getBaseUrl() + "/" + FIRMWARE_UPDATE_COAP_RECOURSE + "/" + otaPackageId.toString()); 342 + startFirmwareUpdateUsingUrl(client, fwInfo.getBaseUrl() + "/" + FIRMWARE_UPDATE_COAP_RESOURCE + "/" + otaPackageId.toString());
343 break; 343 break;
344 default: 344 default:
345 sendStateUpdateToTelemetry(client, fwInfo, OtaPackageUpdateStatus.FAILED, "Unsupported strategy: " + strategy.name()); 345 sendStateUpdateToTelemetry(client, fwInfo, OtaPackageUpdateStatus.FAILED, "Unsupported strategy: " + strategy.name());
@@ -382,7 +382,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -382,7 +382,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
382 return this.fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> { 382 return this.fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> {
383 var profile = clientContext.getProfile(client.getProfileId()); 383 var profile = clientContext.getProfile(client.getProfileId());
384 return new LwM2MClientOtaInfo(endpoint, OtaPackageType.FIRMWARE, profile.getClientLwM2mSettings().getFwUpdateStrategy(), 384 return new LwM2MClientOtaInfo(endpoint, OtaPackageType.FIRMWARE, profile.getClientLwM2mSettings().getFwUpdateStrategy(),
385 - profile.getClientLwM2mSettings().getFwUpdateRecourse()); 385 + profile.getClientLwM2mSettings().getFwUpdateResource());
386 }); 386 });
387 } 387 }
388 388
@@ -390,7 +390,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl @@ -390,7 +390,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
390 //TODO: fetch state from the cache or DB. 390 //TODO: fetch state from the cache or DB.
391 return swStates.computeIfAbsent(client.getEndpoint(), endpoint -> { 391 return swStates.computeIfAbsent(client.getEndpoint(), endpoint -> {
392 var profile = clientContext.getProfile(client.getProfileId()); 392 var profile = clientContext.getProfile(client.getProfileId());
393 - return new LwM2MClientOtaInfo(endpoint, OtaPackageType.SOFTWARE, profile.getClientLwM2mSettings().getSwUpdateStrategy(), profile.getClientLwM2mSettings().getSwUpdateRecourse()); 393 + return new LwM2MClientOtaInfo(endpoint, OtaPackageType.SOFTWARE, profile.getClientLwM2mSettings().getSwUpdateStrategy(), profile.getClientLwM2mSettings().getSwUpdateResource());
394 }); 394 });
395 395
396 } 396 }
@@ -37,10 +37,10 @@ import org.eclipse.leshan.server.registration.Registration; @@ -37,10 +37,10 @@ import org.eclipse.leshan.server.registration.Registration;
37 import org.springframework.context.annotation.Lazy; 37 import org.springframework.context.annotation.Lazy;
38 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
39 import org.thingsboard.common.util.DonAsynchron; 39 import org.thingsboard.common.util.DonAsynchron;
40 -import org.thingsboard.server.cache.ota.OtaPackageDataCache;  
41 import org.thingsboard.server.common.data.Device; 40 import org.thingsboard.server.common.data.Device;
42 import org.thingsboard.server.common.data.DeviceProfile; 41 import org.thingsboard.server.common.data.DeviceProfile;
43 import org.thingsboard.server.common.data.StringUtils; 42 import org.thingsboard.server.common.data.StringUtils;
  43 +import org.thingsboard.server.common.data.device.data.PowerMode;
44 import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes; 44 import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
45 import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration; 45 import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
46 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration; 46 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
@@ -83,8 +83,6 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib @@ -83,8 +83,6 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
83 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest; 83 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest;
84 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 84 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
85 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService; 85 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
86 -import org.thingsboard.server.transport.lwm2m.server.ota.firmware.LwM2MFirmwareUpdateStrategy;  
87 -import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareUpdateStrategy;  
88 import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler; 86 import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
89 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; 87 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
90 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; 88 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@@ -203,30 +201,25 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -203,30 +201,25 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
203 executor.submit(() -> { 201 executor.submit(() -> {
204 LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint()); 202 LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
205 try { 203 try {
206 - log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());  
207 - if (lwM2MClient != null) {  
208 - Optional<SessionInfoProto> oldSessionInfo = this.clientContext.register(lwM2MClient, registration);  
209 - if (oldSessionInfo.isPresent()) {  
210 - log.info("[{}] Closing old session: {}", registration.getEndpoint(), new UUID(oldSessionInfo.get().getSessionIdMSB(), oldSessionInfo.get().getSessionIdLSB()));  
211 - closeSession(oldSessionInfo.get());  
212 - }  
213 - logService.log(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());  
214 - SessionInfoProto sessionInfo = lwM2MClient.getSession();  
215 - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));  
216 - log.warn("40) sessionId [{}] Registering rpc subscription after Registration client", new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));  
217 - TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()  
218 - .setSessionInfo(sessionInfo)  
219 - .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))  
220 - .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())  
221 - .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())  
222 - .build();  
223 - transportService.process(msg, null);  
224 - this.initClientTelemetry(lwM2MClient);  
225 - this.initAttributes(lwM2MClient);  
226 - otaService.init(lwM2MClient);  
227 - } else {  
228 - log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), null); 204 + log.debug("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
  205 + Optional<SessionInfoProto> oldSessionInfo = this.clientContext.register(lwM2MClient, registration);
  206 + if (oldSessionInfo.isPresent()) {
  207 + log.info("[{}] Closing old session: {}", registration.getEndpoint(), new UUID(oldSessionInfo.get().getSessionIdMSB(), oldSessionInfo.get().getSessionIdLSB()));
  208 + closeSession(oldSessionInfo.get());
229 } 209 }
  210 + logService.log(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());
  211 + SessionInfoProto sessionInfo = lwM2MClient.getSession();
  212 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));
  213 + TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
  214 + .setSessionInfo(sessionInfo)
  215 + .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
  216 + .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
  217 + .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
  218 + .build();
  219 + transportService.process(msg, null);
  220 + this.initClientTelemetry(lwM2MClient);
  221 + this.initAttributes(lwM2MClient);
  222 + otaService.init(lwM2MClient);
230 } catch (LwM2MClientStateException stateException) { 223 } catch (LwM2MClientStateException stateException) {
231 if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) { 224 if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) {
232 log.info("[{}] retry registration due to race condition: [{}].", registration.getEndpoint(), stateException.getState()); 225 log.info("[{}] retry registration due to race condition: [{}].", registration.getEndpoint(), stateException.getState());
@@ -410,6 +403,26 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -410,6 +403,26 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
410 log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); 403 log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
411 logService.log(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LWM2M_INFO + ": Client is awake!"); 404 logService.log(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LWM2M_INFO + ": Client is awake!");
412 //TODO: associate endpointId with device information. 405 //TODO: associate endpointId with device information.
  406 +
  407 + LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
  408 +
  409 + if (LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
  410 + PowerMode powerMode = lwM2MClient.getPowerMode();
  411 + if (powerMode == null) {
  412 + Lwm2mDeviceProfileTransportConfiguration deviceProfile = clientContext.getProfile(lwM2MClient.getProfileId());
  413 + powerMode = deviceProfile.getClientLwM2mSettings().getPowerMode();
  414 + }
  415 +
  416 + if (PowerMode.PSM.equals(powerMode) || PowerMode.E_DRX.equals(powerMode)) {
  417 + initAttributes(lwM2MClient);
  418 + TransportProtos.TransportToDeviceActorMsg toDeviceActorMsg = TransportProtos.TransportToDeviceActorMsg
  419 + .newBuilder()
  420 + .setSessionInfo(lwM2MClient.getSession())
  421 + .setSendPendingRPC(TransportProtos.SendPendingRPCMsg.newBuilder().build())
  422 + .build();
  423 + transportService.process(toDeviceActorMsg, TransportServiceCallback.EMPTY);
  424 + }
  425 + }
413 } 426 }
414 427
415 /** 428 /**
@@ -709,7 +722,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -709,7 +722,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
709 this.updateResourcesValue(client, resource, path + "/" + resId); 722 this.updateResourcesValue(client, resource, path + "/" + resId);
710 }); 723 });
711 } 724 }
712 -  
713 } 725 }
714 726
715 //TODO: review and optimize the logic to minimize number of the requests to device. 727 //TODO: review and optimize the logic to minimize number of the requests to device.
@@ -781,14 +793,14 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -781,14 +793,14 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
781 OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings(); 793 OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings();
782 OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings(); 794 OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings();
783 if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy()) 795 if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy())
784 - || (StringUtils.isNotEmpty(newLwM2mSettings.getFwUpdateRecourse()) &&  
785 - !newLwM2mSettings.getFwUpdateRecourse().equals(oldLwM2mSettings.getFwUpdateRecourse()))) { 796 + || (StringUtils.isNotEmpty(newLwM2mSettings.getFwUpdateResource()) &&
  797 + !newLwM2mSettings.getFwUpdateResource().equals(oldLwM2mSettings.getFwUpdateResource()))) {
786 clients.forEach(lwM2MClient -> otaService.onCurrentFirmwareStrategyUpdate(lwM2MClient, newLwM2mSettings)); 798 clients.forEach(lwM2MClient -> otaService.onCurrentFirmwareStrategyUpdate(lwM2MClient, newLwM2mSettings));
787 } 799 }
788 800
789 if (!newLwM2mSettings.getSwUpdateStrategy().equals(oldLwM2mSettings.getSwUpdateStrategy()) 801 if (!newLwM2mSettings.getSwUpdateStrategy().equals(oldLwM2mSettings.getSwUpdateStrategy())
790 - || (StringUtils.isNotEmpty(newLwM2mSettings.getSwUpdateRecourse()) &&  
791 - !newLwM2mSettings.getSwUpdateRecourse().equals(oldLwM2mSettings.getSwUpdateRecourse()))) { 802 + || (StringUtils.isNotEmpty(newLwM2mSettings.getSwUpdateResource()) &&
  803 + !newLwM2mSettings.getSwUpdateResource().equals(oldLwM2mSettings.getSwUpdateResource()))) {
792 clients.forEach(lwM2MClient -> otaService.onCurrentSoftwareStrategyUpdate(lwM2MClient, newLwM2mSettings)); 804 clients.forEach(lwM2MClient -> otaService.onCurrentSoftwareStrategyUpdate(lwM2MClient, newLwM2mSettings));
793 } 805 }
794 } 806 }
@@ -920,16 +932,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -920,16 +932,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
920 } 932 }
921 } 933 }
922 934
923 - private TransportProtos.GetOtaPackageRequestMsg createOtaPackageRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) {  
924 - return TransportProtos.GetOtaPackageRequestMsg.newBuilder()  
925 - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())  
926 - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())  
927 - .setTenantIdMSB(sessionInfo.getTenantIdMSB())  
928 - .setTenantIdLSB(sessionInfo.getTenantIdLSB())  
929 - .setType(nameFwSW)  
930 - .build();  
931 - }  
932 -  
933 private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) { 935 private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
934 Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId()); 936 Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId());
935 return profile.getObserveAttr().getKeyName(); 937 return profile.getObserveAttr().getKeyName();
@@ -50,7 +50,6 @@ import org.thingsboard.server.common.data.TransportPayloadType; @@ -50,7 +50,6 @@ import org.thingsboard.server.common.data.TransportPayloadType;
50 import org.thingsboard.server.common.data.device.profile.MqttTopics; 50 import org.thingsboard.server.common.data.device.profile.MqttTopics;
51 import org.thingsboard.server.common.data.id.OtaPackageId; 51 import org.thingsboard.server.common.data.id.OtaPackageId;
52 import org.thingsboard.server.common.data.ota.OtaPackageType; 52 import org.thingsboard.server.common.data.ota.OtaPackageType;
53 -import org.thingsboard.server.common.data.rpc.RpcStatus;  
54 import org.thingsboard.server.common.msg.EncryptionUtil; 53 import org.thingsboard.server.common.msg.EncryptionUtil;
55 import org.thingsboard.server.common.msg.tools.TbRateLimitsException; 54 import org.thingsboard.server.common.msg.tools.TbRateLimitsException;
56 import org.thingsboard.server.common.transport.SessionMsgListener; 55 import org.thingsboard.server.common.transport.SessionMsgListener;
@@ -820,25 +819,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -820,25 +819,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
820 .ifPresent(payload -> { 819 .ifPresent(payload -> {
821 ChannelFuture channelFuture = deviceSessionCtx.getChannel().writeAndFlush(payload); 820 ChannelFuture channelFuture = deviceSessionCtx.getChannel().writeAndFlush(payload);
822 if (rpcRequest.getPersisted()) { 821 if (rpcRequest.getPersisted()) {
823 - channelFuture.addListener(future -> {  
824 - RpcStatus status;  
825 - Throwable t = future.cause();  
826 - if (t != null) {  
827 - log.error("Failed delivering RPC command to device!", t);  
828 - status = RpcStatus.FAILED;  
829 - } else if (rpcRequest.getOneway()) {  
830 - status = RpcStatus.SUCCESSFUL;  
831 - } else {  
832 - status = RpcStatus.DELIVERED;  
833 - }  
834 - TransportProtos.ToDevicePersistedRpcResponseMsg msg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
835 - .setRequestId(rpcRequest.getRequestId())  
836 - .setRequestIdLSB(rpcRequest.getRequestIdLSB())  
837 - .setRequestIdMSB(rpcRequest.getRequestIdMSB())  
838 - .setStatus(status.name())  
839 - .build();  
840 - transportService.process(deviceSessionCtx.getSessionInfo(), msg, TransportServiceCallback.EMPTY);  
841 - }); 822 + channelFuture.addListener(future ->
  823 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest,
  824 + future.cause() != null, TransportServiceCallback.EMPTY)
  825 + );
842 } 826 }
843 }); 827 });
844 } catch (Exception e) { 828 } catch (Exception e) {
@@ -18,7 +18,6 @@ package org.thingsboard.server.transport.mqtt.session; @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.mqtt.session;
18 import io.netty.channel.ChannelFuture; 18 import io.netty.channel.ChannelFuture;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 import org.thingsboard.server.common.data.DeviceProfile; 20 import org.thingsboard.server.common.data.DeviceProfile;
21 -import org.thingsboard.server.common.data.rpc.RpcStatus;  
22 import org.thingsboard.server.common.transport.SessionMsgListener; 21 import org.thingsboard.server.common.transport.SessionMsgListener;
23 import org.thingsboard.server.common.transport.TransportService; 22 import org.thingsboard.server.common.transport.TransportService;
24 import org.thingsboard.server.common.transport.TransportServiceCallback; 23 import org.thingsboard.server.common.transport.TransportServiceCallback;
@@ -102,25 +101,9 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext imple @@ -102,25 +101,9 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext imple
102 payload -> { 101 payload -> {
103 ChannelFuture channelFuture = parent.writeAndFlush(payload); 102 ChannelFuture channelFuture = parent.writeAndFlush(payload);
104 if (request.getPersisted()) { 103 if (request.getPersisted()) {
105 - channelFuture.addListener(future -> {  
106 - RpcStatus status;  
107 - Throwable t = future.cause();  
108 - if (t != null) {  
109 - log.error("Failed delivering RPC command to device!", t);  
110 - status = RpcStatus.FAILED;  
111 - } else if (request.getOneway()) {  
112 - status = RpcStatus.SUCCESSFUL;  
113 - } else {  
114 - status = RpcStatus.DELIVERED;  
115 - }  
116 - TransportProtos.ToDevicePersistedRpcResponseMsg msg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
117 - .setRequestId(request.getRequestId())  
118 - .setRequestIdLSB(request.getRequestIdLSB())  
119 - .setRequestIdMSB(request.getRequestIdMSB())  
120 - .setStatus(status.name())  
121 - .build();  
122 - transportService.process(getSessionInfo(), msg, TransportServiceCallback.EMPTY);  
123 - }); 104 + channelFuture.addListener(future ->
  105 + transportService.process(getSessionInfo(), request, future.cause() != null, TransportServiceCallback.EMPTY)
  106 + );
124 } 107 }
125 } 108 }
126 ); 109 );
@@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.DeviceProfile; @@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.DeviceProfile;
26 import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; 26 import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
27 import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; 27 import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
28 import org.thingsboard.server.common.data.id.DeviceId; 28 import org.thingsboard.server.common.data.id.DeviceId;
29 -import org.thingsboard.server.common.data.rpc.RpcStatus;  
30 import org.thingsboard.server.common.transport.SessionMsgListener; 29 import org.thingsboard.server.common.transport.SessionMsgListener;
31 import org.thingsboard.server.common.transport.TransportServiceCallback; 30 import org.thingsboard.server.common.transport.TransportServiceCallback;
32 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; 31 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
@@ -141,23 +140,9 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -141,23 +140,9 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
141 140
142 @Override 141 @Override
143 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg toDeviceRequest) { 142 public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg toDeviceRequest) {
144 - log.trace("[{}] Received RPC command to device", sessionId);  
145 - snmpTransportContext.getSnmpTransportService().onToDeviceRpcRequest(this, toDeviceRequest);  
146 - if (toDeviceRequest.getPersisted()) {  
147 - RpcStatus status;  
148 - if (toDeviceRequest.getOneway()) {  
149 - status = RpcStatus.SUCCESSFUL;  
150 - } else {  
151 - status = RpcStatus.DELIVERED;  
152 - }  
153 - TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()  
154 - .setRequestId(toDeviceRequest.getRequestId())  
155 - .setRequestIdLSB(toDeviceRequest.getRequestIdLSB())  
156 - .setRequestIdMSB(toDeviceRequest.getRequestIdMSB())  
157 - .setStatus(status.name())  
158 - .build();  
159 - snmpTransportContext.getTransportService().process(getSessionInfo(), responseMsg, TransportServiceCallback.EMPTY);  
160 - } 143 + log.trace("[{}] Received RPC command to device", sessionId);
  144 + snmpTransportContext.getSnmpTransportService().onToDeviceRpcRequest(this, toDeviceRequest);
  145 + snmpTransportContext.getTransportService().process(getSessionInfo(), toDeviceRequest, false, TransportServiceCallback.EMPTY);
161 } 146 }
162 147
163 @Override 148 @Override
@@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; @@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
46 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; 46 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
47 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; 47 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg;
48 import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto; 48 import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto;
49 -import org.thingsboard.server.gen.transport.TransportProtos.ToDevicePersistedRpcResponseMsg; 49 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
50 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; 50 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
51 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg; 51 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
52 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; 52 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
@@ -109,7 +109,7 @@ public interface TransportService { @@ -109,7 +109,7 @@ public interface TransportService {
109 109
110 void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback); 110 void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback);
111 111
112 - void process(SessionInfoProto sessionInfo, ToDevicePersistedRpcResponseMsg msg, TransportServiceCallback<Void> callback); 112 + void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, boolean isFailedRpc, TransportServiceCallback<Void> callback);
113 113
114 void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback); 114 void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback);
115 115
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.common.transport.auth; 16 package org.thingsboard.server.common.transport.auth;
17 17
18 import lombok.Data; 18 import lombok.Data;
  19 +import org.thingsboard.server.common.data.device.data.PowerMode;
19 import org.thingsboard.server.common.data.id.CustomerId; 20 import org.thingsboard.server.common.data.id.CustomerId;
20 import org.thingsboard.server.common.data.id.DeviceId; 21 import org.thingsboard.server.common.data.id.DeviceId;
21 import org.thingsboard.server.common.data.id.DeviceProfileId; 22 import org.thingsboard.server.common.data.id.DeviceProfileId;
@@ -32,6 +33,7 @@ public class TransportDeviceInfo implements Serializable { @@ -32,6 +33,7 @@ public class TransportDeviceInfo implements Serializable {
32 private DeviceId deviceId; 33 private DeviceId deviceId;
33 private String deviceName; 34 private String deviceName;
34 private String deviceType; 35 private String deviceType;
  36 + private PowerMode powerMode;
35 private String additionalInfo; 37 private String additionalInfo;
36 38
37 } 39 }
@@ -34,7 +34,9 @@ import org.thingsboard.server.common.data.DeviceProfile; @@ -34,7 +34,9 @@ import org.thingsboard.server.common.data.DeviceProfile;
34 import org.thingsboard.server.common.data.DeviceTransportType; 34 import org.thingsboard.server.common.data.DeviceTransportType;
35 import org.thingsboard.server.common.data.EntityType; 35 import org.thingsboard.server.common.data.EntityType;
36 import org.thingsboard.server.common.data.ResourceType; 36 import org.thingsboard.server.common.data.ResourceType;
  37 +import org.thingsboard.server.common.data.StringUtils;
37 import org.thingsboard.server.common.data.Tenant; 38 import org.thingsboard.server.common.data.Tenant;
  39 +import org.thingsboard.server.common.data.device.data.PowerMode;
38 import org.thingsboard.server.common.data.id.CustomerId; 40 import org.thingsboard.server.common.data.id.CustomerId;
39 import org.thingsboard.server.common.data.id.DeviceId; 41 import org.thingsboard.server.common.data.id.DeviceId;
40 import org.thingsboard.server.common.data.id.DeviceProfileId; 42 import org.thingsboard.server.common.data.id.DeviceProfileId;
@@ -42,6 +44,7 @@ import org.thingsboard.server.common.data.id.EntityId; @@ -42,6 +44,7 @@ import org.thingsboard.server.common.data.id.EntityId;
42 import org.thingsboard.server.common.data.id.RuleChainId; 44 import org.thingsboard.server.common.data.id.RuleChainId;
43 import org.thingsboard.server.common.data.id.TenantId; 45 import org.thingsboard.server.common.data.id.TenantId;
44 import org.thingsboard.server.common.data.id.TenantProfileId; 46 import org.thingsboard.server.common.data.id.TenantProfileId;
  47 +import org.thingsboard.server.common.data.rpc.RpcStatus;
45 import org.thingsboard.server.common.msg.TbMsg; 48 import org.thingsboard.server.common.msg.TbMsg;
46 import org.thingsboard.server.common.msg.TbMsgMetaData; 49 import org.thingsboard.server.common.msg.TbMsgMetaData;
47 import org.thingsboard.server.common.msg.queue.ServiceQueue; 50 import org.thingsboard.server.common.msg.queue.ServiceQueue;
@@ -439,6 +442,9 @@ public class DefaultTransportService implements TransportService { @@ -439,6 +442,9 @@ public class DefaultTransportService implements TransportService {
439 tdi.setAdditionalInfo(di.getAdditionalInfo()); 442 tdi.setAdditionalInfo(di.getAdditionalInfo());
440 tdi.setDeviceName(di.getDeviceName()); 443 tdi.setDeviceName(di.getDeviceName());
441 tdi.setDeviceType(di.getDeviceType()); 444 tdi.setDeviceType(di.getDeviceType());
  445 + if (StringUtils.isNotEmpty(di.getPowerMode())) {
  446 + tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));
  447 + }
442 return tdi; 448 return tdi;
443 } 449 }
444 450
@@ -558,11 +564,30 @@ public class DefaultTransportService implements TransportService { @@ -558,11 +564,30 @@ public class DefaultTransportService implements TransportService {
558 } 564 }
559 565
560 @Override 566 @Override
561 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDevicePersistedRpcResponseMsg msg, TransportServiceCallback<Void> callback) {  
562 - if (checkLimits(sessionInfo, msg, callback)) {  
563 - reportActivityInternal(sessionInfo);  
564 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPersistedRpcResponseMsg(msg).build(),  
565 - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); 567 + public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, boolean isFailedRpc, TransportServiceCallback<Void> callback) {
  568 + if (msg.getPersisted()) {
  569 + RpcStatus status;
  570 +
  571 + if (isFailedRpc) {
  572 + status = RpcStatus.FAILED;
  573 + } else if (msg.getOneway()) {
  574 + status = RpcStatus.SUCCESSFUL;
  575 + } else {
  576 + status = RpcStatus.DELIVERED;
  577 + }
  578 +
  579 + TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
  580 + .setRequestId(msg.getRequestId())
  581 + .setRequestIdLSB(msg.getRequestIdLSB())
  582 + .setRequestIdMSB(msg.getRequestIdMSB())
  583 + .setStatus(status.name())
  584 + .build();
  585 +
  586 + if (checkLimits(sessionInfo, responseMsg, callback)) {
  587 + reportActivityInternal(sessionInfo);
  588 + sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPersistedRpcResponseMsg(responseMsg).build(),
  589 + new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY));
  590 + }
566 } 591 }
567 } 592 }
568 593
@@ -133,10 +133,10 @@ @@ -133,10 +133,10 @@
133 </mat-select> 133 </mat-select>
134 </mat-form-field> 134 </mat-form-field>
135 <mat-form-field class="mat-block" fxFlex *ngIf="isFwUpdateStrategy"> 135 <mat-form-field class="mat-block" fxFlex *ngIf="isFwUpdateStrategy">
136 - <mat-label>{{ 'device-profile.lwm2m.fw-update-recourse' | translate }}</mat-label>  
137 - <input matInput formControlName="fwUpdateRecourse" required>  
138 - <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').hasError('required')">  
139 - {{ 'device-profile.lwm2m.fw-update-recourse-required' | translate }} 136 + <mat-label>{{ 'device-profile.lwm2m.fw-update-resource' | translate }}</mat-label>
  137 + <input matInput formControlName="fwUpdateResource" required>
  138 + <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').hasError('required')">
  139 + {{ 'device-profile.lwm2m.fw-update-resource-required' | translate }}
140 </mat-error> 140 </mat-error>
141 </mat-form-field> 141 </mat-form-field>
142 </fieldset> 142 </fieldset>
@@ -150,13 +150,24 @@ @@ -150,13 +150,24 @@
150 </mat-select> 150 </mat-select>
151 </mat-form-field> 151 </mat-form-field>
152 <mat-form-field class="mat-block" fxFlex *ngIf="isSwUpdateStrategy"> 152 <mat-form-field class="mat-block" fxFlex *ngIf="isSwUpdateStrategy">
153 - <mat-label>{{ 'device-profile.lwm2m.sw-update-recourse' | translate }}</mat-label>  
154 - <input matInput formControlName="swUpdateRecourse" required>  
155 - <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').hasError('required')">  
156 - {{ 'device-profile.lwm2m.sw-update-recourse-required' | translate }} 153 + <mat-label>{{ 'device-profile.lwm2m.sw-update-resource' | translate }}</mat-label>
  154 + <input matInput formControlName="swUpdateResource" required>
  155 + <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').hasError('required')">
  156 + {{ 'device-profile.lwm2m.sw-update-resource-required' | translate }}
157 </mat-error> 157 </mat-error>
158 </mat-form-field> 158 </mat-form-field>
159 </fieldset> 159 </fieldset>
  160 + <fieldset class="fields-group">
  161 + <legend class="group-title" translate>device-profile.power-saving-mode</legend>
  162 + <mat-form-field class="mat-block" fxFlex>
  163 + <mat-label> </mat-label>
  164 + <mat-select formControlName="powerMode">
  165 + <mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
  166 + {{ powerModeTranslationMap.get(powerMod) | translate}}
  167 + </mat-option>
  168 + </mat-select>
  169 + </mat-form-field>
  170 + </fieldset>
160 <!-- <mat-accordion multi="true">--> 171 <!-- <mat-accordion multi="true">-->
161 <!-- <div *ngIf="false">--> 172 <!-- <div *ngIf="false">-->
162 <!-- <mat-expansion-panel>--> 173 <!-- <mat-expansion-panel>-->
@@ -30,7 +30,8 @@ import { @@ -30,7 +30,8 @@ import {
30 DEFAULT_NOTIF_IF_DESIBLED, 30 DEFAULT_NOTIF_IF_DESIBLED,
31 DEFAULT_SW_UPDATE_RESOURCE, 31 DEFAULT_SW_UPDATE_RESOURCE,
32 getDefaultBootstrapServerSecurityConfig, 32 getDefaultBootstrapServerSecurityConfig,
33 - getDefaultBootstrapServersSecurityConfig, getDefaultLwM2MServerSecurityConfig, 33 + getDefaultBootstrapServersSecurityConfig,
  34 + getDefaultLwM2MServerSecurityConfig,
34 getDefaultProfileClientLwM2mSettingsConfig, 35 getDefaultProfileClientLwM2mSettingsConfig,
35 getDefaultProfileObserveAttrConfig, 36 getDefaultProfileObserveAttrConfig,
36 Instance, 37 Instance,
@@ -41,7 +42,10 @@ import { @@ -41,7 +42,10 @@ import {
41 ObjectLwM2M, 42 ObjectLwM2M,
42 OBSERVE, 43 OBSERVE,
43 OBSERVE_ATTR_TELEMETRY, 44 OBSERVE_ATTR_TELEMETRY,
44 - RESOURCES, ServerSecurityConfig, 45 + PowerMode,
  46 + PowerModeTranslationMap,
  47 + RESOURCES,
  48 + ServerSecurityConfig,
45 TELEMETRY 49 TELEMETRY
46 } from './lwm2m-profile-config.models'; 50 } from './lwm2m-profile-config.models';
47 import { DeviceProfileService } from '@core/http/device-profile.service'; 51 import { DeviceProfileService } from '@core/http/device-profile.service';
@@ -76,6 +80,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -76,6 +80,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
76 sortFunction: (key: string, value: object) => object; 80 sortFunction: (key: string, value: object) => object;
77 isFwUpdateStrategy: boolean; 81 isFwUpdateStrategy: boolean;
78 isSwUpdateStrategy: boolean; 82 isSwUpdateStrategy: boolean;
  83 + powerMods = Object.values(PowerMode);
  84 + powerModeTranslationMap = PowerModeTranslationMap;
79 85
80 get required(): boolean { 86 get required(): boolean {
81 return this.requiredValue; 87 return this.requiredValue;
@@ -109,8 +115,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -109,8 +115,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
109 clientOnlyObserveAfterConnect: [1, []], 115 clientOnlyObserveAfterConnect: [1, []],
110 fwUpdateStrategy: [1, []], 116 fwUpdateStrategy: [1, []],
111 swUpdateStrategy: [1, []], 117 swUpdateStrategy: [1, []],
112 - fwUpdateRecourse: [{value: '', disabled: true}, []],  
113 - swUpdateRecourse: [{value: '', disabled: true}, []] 118 + fwUpdateResource: [{value: '', disabled: true}, []],
  119 + swUpdateResource: [{value: '', disabled: true}, []],
  120 + powerMode: [null, Validators.required]
114 }) 121 })
115 }); 122 });
116 this.lwm2mDeviceConfigFormGroup = this.fb.group({ 123 this.lwm2mDeviceConfigFormGroup = this.fb.group({
@@ -120,12 +127,12 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -120,12 +127,12 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
120 takeUntil(this.destroy$) 127 takeUntil(this.destroy$)
121 ).subscribe((fwStrategy) => { 128 ).subscribe((fwStrategy) => {
122 if (fwStrategy === 2) { 129 if (fwStrategy === 2) {
123 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').enable({emitEvent: false});  
124 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse') 130 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').enable({emitEvent: false});
  131 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource')
125 .patchValue(DEFAULT_FW_UPDATE_RESOURCE, {emitEvent: false}); 132 .patchValue(DEFAULT_FW_UPDATE_RESOURCE, {emitEvent: false});
126 this.isFwUpdateStrategy = true; 133 this.isFwUpdateStrategy = true;
127 } else { 134 } else {
128 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').disable({emitEvent: false}); 135 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').disable({emitEvent: false});
129 this.isFwUpdateStrategy = false; 136 this.isFwUpdateStrategy = false;
130 } 137 }
131 this.otaUpdateFwStrategyValidate(true); 138 this.otaUpdateFwStrategyValidate(true);
@@ -134,13 +141,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -134,13 +141,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
134 takeUntil(this.destroy$) 141 takeUntil(this.destroy$)
135 ).subscribe((swStrategy) => { 142 ).subscribe((swStrategy) => {
136 if (swStrategy === 2) { 143 if (swStrategy === 2) {
137 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').enable({emitEvent: false});  
138 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse') 144 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').enable({emitEvent: false});
  145 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource')
139 .patchValue(DEFAULT_SW_UPDATE_RESOURCE, {emitEvent: false}); 146 .patchValue(DEFAULT_SW_UPDATE_RESOURCE, {emitEvent: false});
140 this.isSwUpdateStrategy = true; 147 this.isSwUpdateStrategy = true;
141 } else { 148 } else {
142 this.isSwUpdateStrategy = false; 149 this.isSwUpdateStrategy = false;
143 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').disable({emitEvent: false}); 150 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').disable({emitEvent: false});
144 } 151 }
145 this.otaUpdateSwStrategyValidate(true); 152 this.otaUpdateSwStrategyValidate(true);
146 }); 153 });
@@ -237,10 +244,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -237,10 +244,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
237 } 244 }
238 245
239 private updateWriteValue = (value: ModelValue): void => { 246 private updateWriteValue = (value: ModelValue): void => {
240 - const fwResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateRecourse) ?  
241 - this.configurationValue.clientLwM2mSettings.fwUpdateRecourse : '';  
242 - const swResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateRecourse) ?  
243 - this.configurationValue.clientLwM2mSettings.swUpdateRecourse : ''; 247 + const fwResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateResource) ?
  248 + this.configurationValue.clientLwM2mSettings.fwUpdateResource : '';
  249 + const swResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.swUpdateResource) ?
  250 + this.configurationValue.clientLwM2mSettings.swUpdateResource : '';
244 this.lwm2mDeviceProfileFormGroup.patchValue({ 251 this.lwm2mDeviceProfileFormGroup.patchValue({
245 objectIds: value, 252 objectIds: value,
246 observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value.objectsList), 253 observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value.objectsList),
@@ -249,13 +256,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -249,13 +256,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
249 clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect, 256 clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
250 fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1, 257 fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1,
251 swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy || 1, 258 swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy || 1,
252 - fwUpdateRecourse: fwResource,  
253 - swUpdateRecourse: swResource 259 + fwUpdateResource: fwResource,
  260 + swUpdateResource: swResource,
  261 + powerMode: this.configurationValue.clientLwM2mSettings.powerMode
254 } 262 }
255 }, 263 },
256 {emitEvent: false}); 264 {emitEvent: false});
257 - this.configurationValue.clientLwM2mSettings.fwUpdateRecourse = fwResource;  
258 - this.configurationValue.clientLwM2mSettings.swUpdateRecourse = swResource; 265 + this.configurationValue.clientLwM2mSettings.fwUpdateResource = fwResource;
  266 + this.configurationValue.clientLwM2mSettings.swUpdateResource = swResource;
259 this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2; 267 this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2;
260 this.isSwUpdateStrategy = this.configurationValue.clientLwM2mSettings.swUpdateStrategy === 2; 268 this.isSwUpdateStrategy = this.configurationValue.clientLwM2mSettings.swUpdateStrategy === 2;
261 this.otaUpdateSwStrategyValidate(); 269 this.otaUpdateSwStrategyValidate();
@@ -561,20 +569,20 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -561,20 +569,20 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
561 569
562 private otaUpdateFwStrategyValidate(updated = false): void { 570 private otaUpdateFwStrategyValidate(updated = false): void {
563 if (this.isFwUpdateStrategy) { 571 if (this.isFwUpdateStrategy) {
564 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').setValidators([Validators.required]); 572 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').setValidators([Validators.required]);
565 } else { 573 } else {
566 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').clearValidators(); 574 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').clearValidators();
567 } 575 }
568 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').updateValueAndValidity({emitEvent: updated}); 576 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').updateValueAndValidity({emitEvent: updated});
569 } 577 }
570 578
571 private otaUpdateSwStrategyValidate(updated = false): void { 579 private otaUpdateSwStrategyValidate(updated = false): void {
572 if (this.isSwUpdateStrategy) { 580 if (this.isSwUpdateStrategy) {
573 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').setValidators([Validators.required]); 581 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').setValidators([Validators.required]);
574 } else { 582 } else {
575 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').clearValidators(); 583 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').clearValidators();
576 } 584 }
577 - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').updateValueAndValidity({emitEvent: updated}); 585 + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').updateValueAndValidity({emitEvent: updated});
578 } 586 }
579 587
580 } 588 }
@@ -115,6 +115,20 @@ export const securityConfigModeNames = new Map<securityConfigMode, string>( @@ -115,6 +115,20 @@ export const securityConfigModeNames = new Map<securityConfigMode, string>(
115 ] 115 ]
116 ); 116 );
117 117
  118 +export enum PowerMode {
  119 + PSM = 'PSM',
  120 + DRX = 'DRX',
  121 + E_DRX = 'E_DRX'
  122 +}
  123 +
  124 +export const PowerModeTranslationMap = new Map<PowerMode, string>(
  125 + [
  126 + [PowerMode.PSM, 'device-profile.power-saving-mode-type.psm'],
  127 + [PowerMode.DRX, 'device-profile.power-saving-mode-type.drx'],
  128 + [PowerMode.E_DRX, 'device-profile.power-saving-mode-type.edrx']
  129 + ]
  130 +);
  131 +
118 export interface ModelValue { 132 export interface ModelValue {
119 objectIds: string[]; 133 objectIds: string[];
120 objectsList: ObjectLwM2M[]; 134 objectsList: ObjectLwM2M[];
@@ -160,8 +174,9 @@ export interface ClientLwM2mSettings { @@ -160,8 +174,9 @@ export interface ClientLwM2mSettings {
160 clientOnlyObserveAfterConnect: number; 174 clientOnlyObserveAfterConnect: number;
161 fwUpdateStrategy: number; 175 fwUpdateStrategy: number;
162 swUpdateStrategy: number; 176 swUpdateStrategy: number;
163 - fwUpdateRecourse: string;  
164 - swUpdateRecourse: string; 177 + fwUpdateResource: string;
  178 + swUpdateResource: string;
  179 + powerMode: PowerMode;
165 } 180 }
166 181
167 export interface ObservableAttributes { 182 export interface ObservableAttributes {
@@ -216,8 +231,9 @@ export function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSetting @@ -216,8 +231,9 @@ export function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSetting
216 clientOnlyObserveAfterConnect: 1, 231 clientOnlyObserveAfterConnect: 1,
217 fwUpdateStrategy: 1, 232 fwUpdateStrategy: 1,
218 swUpdateStrategy: 1, 233 swUpdateStrategy: 1,
219 - fwUpdateRecourse: DEFAULT_FW_UPDATE_RESOURCE,  
220 - swUpdateRecourse: DEFAULT_SW_UPDATE_RESOURCE 234 + fwUpdateResource: DEFAULT_FW_UPDATE_RESOURCE,
  235 + swUpdateResource: DEFAULT_SW_UPDATE_RESOURCE,
  236 + powerMode: PowerMode.DRX
221 }; 237 };
222 } 238 }
223 239
@@ -29,12 +29,12 @@ @@ -29,12 +29,12 @@
29 formControlName="configuration"> 29 formControlName="configuration">
30 </tb-mqtt-device-transport-configuration> 30 </tb-mqtt-device-transport-configuration>
31 </ng-template> 31 </ng-template>
32 - <!--ng-template [ngSwitchCase]="deviceTransportType.LWM2M"> 32 + <ng-template [ngSwitchCase]="deviceTransportType.LWM2M">
33 <tb-lwm2m-device-transport-configuration 33 <tb-lwm2m-device-transport-configuration
34 [required]="required" 34 [required]="required"
35 formControlName="configuration"> 35 formControlName="configuration">
36 </tb-lwm2m-device-transport-configuration> 36 </tb-lwm2m-device-transport-configuration>
37 - </ng-template--> 37 + </ng-template>
38 <ng-template [ngSwitchCase]="deviceTransportType.COAP"> 38 <ng-template [ngSwitchCase]="deviceTransportType.COAP">
39 <tb-coap-device-transport-configuration 39 <tb-coap-device-transport-configuration
40 [required]="required" 40 [required]="required"
@@ -16,9 +16,13 @@ @@ -16,9 +16,13 @@
16 16
17 --> 17 -->
18 <form [formGroup]="lwm2mDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;"> 18 <form [formGroup]="lwm2mDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;">
19 - <!--tb-json-object-edit  
20 - [required]="required"  
21 - label="{{ 'device-profile.transport-type-lwm2m' | translate }}"  
22 - formControlName="configuration">  
23 - </tb-json-object-edit--> 19 + <mat-form-field class="mat-block" fxFlex>
  20 + <mat-label translate>device-profile.power-saving-mode</mat-label>
  21 + <mat-select formControlName="powerMode">
  22 + <mat-option [value]="null">{{ "device-profile.power-saving-mode-type.default" | translate }}</mat-option>
  23 + <mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
  24 + {{ powerModeTranslationMap.get(powerMod) | translate }}
  25 + </mat-option>
  26 + </mat-select>
  27 + </mat-form-field>
24 </form> 28 </form>
@@ -23,6 +23,7 @@ import { @@ -23,6 +23,7 @@ import {
23 DeviceTransportConfiguration, 23 DeviceTransportConfiguration,
24 DeviceTransportType, Lwm2mDeviceTransportConfiguration 24 DeviceTransportType, Lwm2mDeviceTransportConfiguration
25 } from '@shared/models/device.models'; 25 } from '@shared/models/device.models';
  26 +import {PowerMode, PowerModeTranslationMap} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models";
26 27
27 @Component({ 28 @Component({
28 selector: 'tb-lwm2m-device-transport-configuration', 29 selector: 'tb-lwm2m-device-transport-configuration',
@@ -37,6 +38,8 @@ import { @@ -37,6 +38,8 @@ import {
37 export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { 38 export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit {
38 39
39 lwm2mDeviceTransportConfigurationFormGroup: FormGroup; 40 lwm2mDeviceTransportConfigurationFormGroup: FormGroup;
  41 + powerMods = Object.values(PowerMode);
  42 + powerModeTranslationMap = PowerModeTranslationMap;
40 43
41 private requiredValue: boolean; 44 private requiredValue: boolean;
42 get required(): boolean { 45 get required(): boolean {
@@ -65,7 +68,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA @@ -65,7 +68,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
65 68
66 ngOnInit() { 69 ngOnInit() {
67 this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({ 70 this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
68 - configuration: [null, Validators.required] 71 + powerMode: [null]
69 }); 72 });
70 this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => { 73 this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => {
71 this.updateModel(); 74 this.updateModel();
@@ -82,13 +85,13 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA @@ -82,13 +85,13 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
82 } 85 }
83 86
84 writeValue(value: Lwm2mDeviceTransportConfiguration | null): void { 87 writeValue(value: Lwm2mDeviceTransportConfiguration | null): void {
85 - this.lwm2mDeviceTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); 88 + this.lwm2mDeviceTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
86 } 89 }
87 90
88 private updateModel() { 91 private updateModel() {
89 let configuration: DeviceTransportConfiguration = null; 92 let configuration: DeviceTransportConfiguration = null;
90 if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) { 93 if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) {
91 - configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue().configuration; 94 + configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue();
92 // configuration.type = DeviceTransportType.LWM2M; 95 // configuration.type = DeviceTransportType.LWM2M;
93 } 96 }
94 this.propagateChange(configuration); 97 this.propagateChange(configuration);
@@ -200,7 +200,7 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy @@ -200,7 +200,7 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy
200 DeviceTransportType.LWM2M, 200 DeviceTransportType.LWM2M,
201 { 201 {
202 hasProfileConfiguration: true, 202 hasProfileConfiguration: true,
203 - hasDeviceConfiguration: false, 203 + hasDeviceConfiguration: true,
204 } 204 }
205 ], 205 ],
206 [ 206 [
@@ -1213,6 +1213,13 @@ @@ -1213,6 +1213,13 @@
1213 "export-failed-error": "Unable to export device profile: {{error}}", 1213 "export-failed-error": "Unable to export device profile: {{error}}",
1214 "device-profile-file": "Device profile file", 1214 "device-profile-file": "Device profile file",
1215 "invalid-device-profile-file-error": "Unable to import device profile: Invalid device profile data structure.", 1215 "invalid-device-profile-file-error": "Unable to import device profile: Invalid device profile data structure.",
  1216 + "power-saving-mode": "Power Saving Mode",
  1217 + "power-saving-mode-type": {
  1218 + "default": "Use device profile power saving mode",
  1219 + "psm": "Power Saving Mode (PSM)",
  1220 + "drx": "Discontinuous Reception (DRX)",
  1221 + "edrx": "Extended Discontinuous Reception (eDRX)"
  1222 + },
1216 "lwm2m": { 1223 "lwm2m": {
1217 "object-list": "Object list", 1224 "object-list": "Object list",
1218 "object-list-empty": "No objects selected.", 1225 "object-list-empty": "No objects selected.",
@@ -1313,10 +1320,10 @@ @@ -1313,10 +1320,10 @@
1313 "sw-update-strategy": "Software update strategy", 1320 "sw-update-strategy": "Software update strategy",
1314 "sw-update-strategy-package": "Push binary file using Object 9 and Resource 2 (Package)", 1321 "sw-update-strategy-package": "Push binary file using Object 9 and Resource 2 (Package)",
1315 "sw-update-strategy-package-uri": "Auto-generate unique CoAP URL to download the package and push software update using Object 9 and Resource 3 (Package URI)", 1322 "sw-update-strategy-package-uri": "Auto-generate unique CoAP URL to download the package and push software update using Object 9 and Resource 3 (Package URI)",
1316 - "fw-update-recourse": "Firmware update CoAP recourse",  
1317 - "fw-update-recourse-required": "Firmware update CoAP recourse is required.",  
1318 - "sw-update-recourse": "Software update CoAP recourse",  
1319 - "sw-update-recourse-required": "Software update CoAP recourse is required.", 1323 + "fw-update-resource": "Firmware update CoAP resource",
  1324 + "fw-update-resource-required": "Firmware update CoAP resource is required.",
  1325 + "sw-update-resource": "Software update CoAP resource",
  1326 + "sw-update-resource-required": "Software update CoAP resource is required.",
1320 "config-json-tab": "Json Config Profile Device", 1327 "config-json-tab": "Json Config Profile Device",
1321 "attributes-name": { 1328 "attributes-name": {
1322 "min-period": "Minimum period", 1329 "min-period": "Minimum period",