Commit d190cba27754891dff50aec8f2eae29e2af13964
Committed by
GitHub
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 | 41 | import org.thingsboard.server.common.data.TenantProfile; |
42 | 42 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; |
43 | 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 | 46 | import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; |
45 | 47 | import org.thingsboard.server.common.data.id.CustomerId; |
46 | 48 | import org.thingsboard.server.common.data.id.DeviceId; |
... | ... | @@ -459,7 +461,14 @@ public class DefaultTransportApiService implements TransportApiService { |
459 | 461 | } |
460 | 462 | |
461 | 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 | 472 | .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits()) |
464 | 473 | .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits()) |
465 | 474 | .setCustomerIdMSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getMostSignificantBits()).orElse(0L)) |
... | ... | @@ -470,8 +479,11 @@ public class DefaultTransportApiService implements TransportApiService { |
470 | 479 | .setDeviceType(device.getType()) |
471 | 480 | .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()) |
472 | 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 | 489 | private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() { | ... | ... |
... | ... | @@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; |
20 | 20 | import com.fasterxml.jackson.annotation.JsonIgnore; |
21 | 21 | import lombok.Data; |
22 | 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 | 24 | import java.util.HashMap; |
28 | 25 | import java.util.Map; |
... | ... | @@ -30,6 +27,8 @@ import java.util.Map; |
30 | 27 | @Data |
31 | 28 | public class Lwm2mDeviceTransportConfiguration implements DeviceTransportConfiguration { |
32 | 29 | |
30 | + private PowerMode powerMode; | |
31 | + | |
33 | 32 | @JsonIgnore |
34 | 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 | 16 | package org.thingsboard.server.common.data.device.data.lwm2m; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | +import org.thingsboard.server.common.data.device.data.PowerMode; | |
19 | 20 | |
20 | 21 | @Data |
21 | 22 | public class OtherConfiguration { |
... | ... | @@ -23,7 +24,8 @@ public class OtherConfiguration { |
23 | 24 | private Integer fwUpdateStrategy; |
24 | 25 | private Integer swUpdateStrategy; |
25 | 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 | } | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
... | ... | @@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC |
44 | 44 | import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
45 | 45 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
46 | 46 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
47 | -import org.thingsboard.server.common.data.rpc.RpcStatus; | |
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; |
... | ... | @@ -509,23 +508,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
509 | 508 | closeObserveRelationAndNotify(sessionId, CoAP.ResponseCode.INTERNAL_SERVER_ERROR); |
510 | 509 | successful = false; |
511 | 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 | 512 | if (!successful) { |
530 | 513 | closeAndDeregister(); |
531 | 514 | } | ... | ... |
... | ... | @@ -408,21 +408,7 @@ public class DeviceApiController implements TbTransportService { |
408 | 408 | public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg msg) { |
409 | 409 | log.trace("[{}] Received RPC command to device", sessionId); |
410 | 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 | 414 | @Override | ... | ... |
... | ... | @@ -33,6 +33,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
33 | 33 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
34 | 34 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
35 | 35 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
36 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; | |
36 | 37 | import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer; |
37 | 38 | |
38 | 39 | import java.io.IOException; |
... | ... | @@ -84,7 +85,14 @@ public class LwM2mCredentialsSecurityInfoValidator { |
84 | 85 | } catch (InterruptedException e) { |
85 | 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 | 16 | package org.thingsboard.server.transport.lwm2m.secure; |
17 | 17 | |
18 | 18 | import lombok.RequiredArgsConstructor; |
19 | +import lombok.extern.slf4j.Slf4j; | |
19 | 20 | import org.eclipse.leshan.core.request.Identity; |
20 | 21 | import org.eclipse.leshan.core.request.UplinkRequest; |
21 | 22 | import org.eclipse.leshan.server.registration.Registration; |
... | ... | @@ -24,14 +25,15 @@ import org.eclipse.leshan.server.security.SecurityChecker; |
24 | 25 | import org.eclipse.leshan.server.security.SecurityInfo; |
25 | 26 | import org.springframework.stereotype.Component; |
26 | 27 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
28 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; | |
27 | 29 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
28 | 30 | import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; |
29 | -import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore; | |
30 | 31 | import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; |
31 | 32 | |
32 | 33 | @Component |
33 | 34 | @RequiredArgsConstructor |
34 | 35 | @TbLwM2mTransportComponent |
36 | +@Slf4j | |
35 | 37 | public class TbLwM2MAuthorizer implements Authorizer { |
36 | 38 | |
37 | 39 | private final TbLwM2MDtlsSessionStore sessionStorage; |
... | ... | @@ -57,7 +59,12 @@ public class TbLwM2MAuthorizer implements Authorizer { |
57 | 59 | } |
58 | 60 | SecurityInfo expectedSecurityInfo = null; |
59 | 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 | 69 | if (securityChecker.checkSecurityInfo(registration.getEndpoint(), senderIdentity, expectedSecurityInfo)) { |
63 | 70 | return registration; | ... | ... |
... | ... | @@ -42,6 +42,7 @@ import org.thingsboard.server.common.transport.util.SslUtil; |
42 | 42 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
43 | 43 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
44 | 44 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
45 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; | |
45 | 46 | import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; |
46 | 47 | import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore; |
47 | 48 | |
... | ... | @@ -118,7 +119,12 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer |
118 | 119 | |
119 | 120 | String strCert = SslUtil.getCertificateString(cert); |
120 | 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 | 128 | ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null; |
123 | 129 | if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) { |
124 | 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 | 65 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
66 | 66 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; |
67 | 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 | 70 | @Slf4j |
71 | 71 | @Component |
... | ... | @@ -105,7 +105,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { |
105 | 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 | 109 | this.server.coap().getServer().add(otaCoapResource); |
110 | 110 | this.startLhServer(); |
111 | 111 | this.context.setServer(server); | ... | ... |
... | ... | @@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull; |
23 | 23 | import org.thingsboard.server.common.data.Device; |
24 | 24 | import org.thingsboard.server.common.data.DeviceProfile; |
25 | 25 | import org.thingsboard.server.common.data.ResourceType; |
26 | -import org.thingsboard.server.common.data.rpc.RpcStatus; | |
27 | 26 | import org.thingsboard.server.common.transport.SessionMsgListener; |
28 | 27 | import org.thingsboard.server.common.transport.TransportService; |
29 | 28 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
... | ... | @@ -85,21 +84,7 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s |
85 | 84 | public void onToDeviceRpcRequest(UUID sessionId, ToDeviceRpcRequestMsg toDeviceRequest) { |
86 | 85 | log.trace("[{}] Received RPC command to device", sessionId); |
87 | 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 | 90 | @Override | ... | ... |
... | ... | @@ -31,8 +31,8 @@ import java.util.concurrent.ConcurrentHashMap; |
31 | 31 | import java.util.concurrent.ConcurrentMap; |
32 | 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 | 37 | @Slf4j |
38 | 38 | public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { |
... | ... | @@ -71,8 +71,8 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { |
71 | 71 | protected void processHandleGet(CoapExchange exchange) { |
72 | 72 | log.warn("90) processHandleGet [{}]", exchange); |
73 | 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 | 76 | this.sendOtaData(exchange); |
77 | 77 | } |
78 | 78 | } |
... | ... | @@ -131,7 +131,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { |
131 | 131 | } |
132 | 132 | |
133 | 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 | 136 | UUID currentId = UUID.fromString(idStr); |
137 | 137 | Response response = new Response(CoAP.ResponseCode.CONTENT); |
... | ... | @@ -144,8 +144,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { |
144 | 144 | boolean lastFlag = fwData.length <= chunkSize; |
145 | 145 | response.getOptions().setBlock2(chunkSize, lastFlag, 0); |
146 | 146 | log.warn("92) with blokc2 Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, lastFlag); |
147 | - } | |
148 | - else { | |
147 | + } else { | |
149 | 148 | log.warn("92) with block1 Send currentId: [{}], length: [{}], ", currentId.toString(), fwData.length); |
150 | 149 | } |
151 | 150 | exchange.respond(response); | ... | ... |
... | ... | @@ -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 | 127 | resourcePath) throws CodecException { |
128 | 128 | switch (type) { |
129 | 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 | 32 | import org.eclipse.leshan.server.security.SecurityInfo; |
33 | 33 | import org.thingsboard.server.common.data.Device; |
34 | 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 | 37 | import org.thingsboard.server.common.data.id.TenantId; |
36 | 38 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
37 | 39 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
... | ... | @@ -80,6 +82,9 @@ public class LwM2mClient implements Cloneable { |
80 | 82 | private String deviceProfileName; |
81 | 83 | |
82 | 84 | @Getter |
85 | + private PowerMode powerMode; | |
86 | + | |
87 | + @Getter | |
83 | 88 | private String identity; |
84 | 89 | @Getter |
85 | 90 | private SecurityInfo securityInfo; |
... | ... | @@ -121,6 +126,7 @@ public class LwM2mClient implements Cloneable { |
121 | 126 | this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB()); |
122 | 127 | this.deviceName = session.getDeviceName(); |
123 | 128 | this.deviceProfileName = session.getDeviceType(); |
129 | + this.powerMode = credentials.getDeviceInfo().getPowerMode(); | |
124 | 130 | } |
125 | 131 | |
126 | 132 | public void lock() { |
... | ... | @@ -140,6 +146,7 @@ public class LwM2mClient implements Cloneable { |
140 | 146 | builder.setDeviceName(deviceName); |
141 | 147 | deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder)); |
142 | 148 | this.session = builder.build(); |
149 | + this.powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode(); | |
143 | 150 | } |
144 | 151 | |
145 | 152 | public void onDeviceProfileUpdate(DeviceProfile deviceProfile) { | ... | ... |
... | ... | @@ -87,8 +87,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl |
87 | 87 | public static final String SOFTWARE_TITLE = getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE); |
88 | 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 | 92 | private static final String FW_PACKAGE_5_ID = "/5/0/0"; |
93 | 93 | private static final String FW_URL_ID = "/5/0/1"; |
94 | 94 | private static final String FW_EXECUTE_ID = "/5/0/2"; |
... | ... | @@ -206,7 +206,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl |
206 | 206 | log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy()); |
207 | 207 | LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client); |
208 | 208 | fwInfo.setFwStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy())); |
209 | - fwInfo.setBaseUrl(configuration.getFwUpdateRecourse()); | |
209 | + fwInfo.setBaseUrl(configuration.getFwUpdateResource()); | |
210 | 210 | startFirmwareUpdateIfNeeded(client, fwInfo); |
211 | 211 | } |
212 | 212 | |
... | ... | @@ -215,7 +215,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl |
215 | 215 | log.debug("[{}] Current sw strategy: {}", client.getEndpoint(), configuration.getSwUpdateStrategy()); |
216 | 216 | LwM2MClientOtaInfo swInfo = getOrInitSwInfo(client); |
217 | 217 | swInfo.setSwStrategy(LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(configuration.getSwUpdateStrategy())); |
218 | - swInfo.setBaseUrl(configuration.getSwUpdateRecourse()); | |
218 | + swInfo.setBaseUrl(configuration.getSwUpdateResource()); | |
219 | 219 | startSoftwareUpdateIfNeeded(client, swInfo); |
220 | 220 | } |
221 | 221 | |
... | ... | @@ -339,7 +339,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl |
339 | 339 | downlinkHandler.sendWriteReplaceRequest(client, writeRequest, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId)); |
340 | 340 | break; |
341 | 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 | 343 | break; |
344 | 344 | default: |
345 | 345 | sendStateUpdateToTelemetry(client, fwInfo, OtaPackageUpdateStatus.FAILED, "Unsupported strategy: " + strategy.name()); |
... | ... | @@ -382,7 +382,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl |
382 | 382 | return this.fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> { |
383 | 383 | var profile = clientContext.getProfile(client.getProfileId()); |
384 | 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 | 390 | //TODO: fetch state from the cache or DB. |
391 | 391 | return swStates.computeIfAbsent(client.getEndpoint(), endpoint -> { |
392 | 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 | 37 | import org.springframework.context.annotation.Lazy; |
38 | 38 | import org.springframework.stereotype.Service; |
39 | 39 | import org.thingsboard.common.util.DonAsynchron; |
40 | -import org.thingsboard.server.cache.ota.OtaPackageDataCache; | |
41 | 40 | import org.thingsboard.server.common.data.Device; |
42 | 41 | import org.thingsboard.server.common.data.DeviceProfile; |
43 | 42 | import org.thingsboard.server.common.data.StringUtils; |
43 | +import org.thingsboard.server.common.data.device.data.PowerMode; | |
44 | 44 | import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes; |
45 | 45 | import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration; |
46 | 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 | 83 | import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest; |
84 | 84 | import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; |
85 | 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 | 86 | import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler; |
89 | 87 | import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; |
90 | 88 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
... | ... | @@ -203,30 +201,25 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl |
203 | 201 | executor.submit(() -> { |
204 | 202 | LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint()); |
205 | 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 | 223 | } catch (LwM2MClientStateException stateException) { |
231 | 224 | if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) { |
232 | 225 | log.info("[{}] retry registration due to race condition: [{}].", registration.getEndpoint(), stateException.getState()); |
... | ... | @@ -410,6 +403,26 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl |
410 | 403 | log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); |
411 | 404 | logService.log(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LWM2M_INFO + ": Client is awake!"); |
412 | 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 | 722 | this.updateResourcesValue(client, resource, path + "/" + resId); |
710 | 723 | }); |
711 | 724 | } |
712 | - | |
713 | 725 | } |
714 | 726 | |
715 | 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 | 793 | OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings(); |
782 | 794 | OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings(); |
783 | 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 | 798 | clients.forEach(lwM2MClient -> otaService.onCurrentFirmwareStrategyUpdate(lwM2MClient, newLwM2mSettings)); |
787 | 799 | } |
788 | 800 | |
789 | 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 | 804 | clients.forEach(lwM2MClient -> otaService.onCurrentSoftwareStrategyUpdate(lwM2MClient, newLwM2mSettings)); |
793 | 805 | } |
794 | 806 | } |
... | ... | @@ -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 | 935 | private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) { |
934 | 936 | Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId()); |
935 | 937 | return profile.getObserveAttr().getKeyName(); | ... | ... |
... | ... | @@ -50,7 +50,6 @@ import org.thingsboard.server.common.data.TransportPayloadType; |
50 | 50 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
51 | 51 | import org.thingsboard.server.common.data.id.OtaPackageId; |
52 | 52 | import org.thingsboard.server.common.data.ota.OtaPackageType; |
53 | -import org.thingsboard.server.common.data.rpc.RpcStatus; | |
54 | 53 | import org.thingsboard.server.common.msg.EncryptionUtil; |
55 | 54 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
56 | 55 | import org.thingsboard.server.common.transport.SessionMsgListener; |
... | ... | @@ -820,25 +819,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
820 | 819 | .ifPresent(payload -> { |
821 | 820 | ChannelFuture channelFuture = deviceSessionCtx.getChannel().writeAndFlush(payload); |
822 | 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 | 828 | } catch (Exception e) { | ... | ... |
... | ... | @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.mqtt.session; |
18 | 18 | import io.netty.channel.ChannelFuture; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.thingsboard.server.common.data.DeviceProfile; |
21 | -import org.thingsboard.server.common.data.rpc.RpcStatus; | |
22 | 21 | import org.thingsboard.server.common.transport.SessionMsgListener; |
23 | 22 | import org.thingsboard.server.common.transport.TransportService; |
24 | 23 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
... | ... | @@ -102,25 +101,9 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext imple |
102 | 101 | payload -> { |
103 | 102 | ChannelFuture channelFuture = parent.writeAndFlush(payload); |
104 | 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 | 26 | import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; |
27 | 27 | import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; |
28 | 28 | import org.thingsboard.server.common.data.id.DeviceId; |
29 | -import org.thingsboard.server.common.data.rpc.RpcStatus; | |
30 | 29 | import org.thingsboard.server.common.transport.SessionMsgListener; |
31 | 30 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
32 | 31 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; |
... | ... | @@ -141,23 +140,9 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S |
141 | 140 | |
142 | 141 | @Override |
143 | 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 | 148 | @Override | ... | ... |
... | ... | @@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
46 | 46 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; |
47 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; |
48 | 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 | 50 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; |
51 | 51 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg; |
52 | 52 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
... | ... | @@ -109,7 +109,7 @@ public interface TransportService { |
109 | 109 | |
110 | 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 | 114 | void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback); |
115 | 115 | ... | ... |
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.server.common.transport.auth; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | +import org.thingsboard.server.common.data.device.data.PowerMode; | |
19 | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
20 | 21 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | 22 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
... | ... | @@ -32,6 +33,7 @@ public class TransportDeviceInfo implements Serializable { |
32 | 33 | private DeviceId deviceId; |
33 | 34 | private String deviceName; |
34 | 35 | private String deviceType; |
36 | + private PowerMode powerMode; | |
35 | 37 | private String additionalInfo; |
36 | 38 | |
37 | 39 | } | ... | ... |
... | ... | @@ -34,7 +34,9 @@ import org.thingsboard.server.common.data.DeviceProfile; |
34 | 34 | import org.thingsboard.server.common.data.DeviceTransportType; |
35 | 35 | import org.thingsboard.server.common.data.EntityType; |
36 | 36 | import org.thingsboard.server.common.data.ResourceType; |
37 | +import org.thingsboard.server.common.data.StringUtils; | |
37 | 38 | import org.thingsboard.server.common.data.Tenant; |
39 | +import org.thingsboard.server.common.data.device.data.PowerMode; | |
38 | 40 | import org.thingsboard.server.common.data.id.CustomerId; |
39 | 41 | import org.thingsboard.server.common.data.id.DeviceId; |
40 | 42 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
... | ... | @@ -42,6 +44,7 @@ import org.thingsboard.server.common.data.id.EntityId; |
42 | 44 | import org.thingsboard.server.common.data.id.RuleChainId; |
43 | 45 | import org.thingsboard.server.common.data.id.TenantId; |
44 | 46 | import org.thingsboard.server.common.data.id.TenantProfileId; |
47 | +import org.thingsboard.server.common.data.rpc.RpcStatus; | |
45 | 48 | import org.thingsboard.server.common.msg.TbMsg; |
46 | 49 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
47 | 50 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
... | ... | @@ -439,6 +442,9 @@ public class DefaultTransportService implements TransportService { |
439 | 442 | tdi.setAdditionalInfo(di.getAdditionalInfo()); |
440 | 443 | tdi.setDeviceName(di.getDeviceName()); |
441 | 444 | tdi.setDeviceType(di.getDeviceType()); |
445 | + if (StringUtils.isNotEmpty(di.getPowerMode())) { | |
446 | + tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode())); | |
447 | + } | |
442 | 448 | return tdi; |
443 | 449 | } |
444 | 450 | |
... | ... | @@ -558,11 +564,30 @@ public class DefaultTransportService implements TransportService { |
558 | 564 | } |
559 | 565 | |
560 | 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 | 133 | </mat-select> |
134 | 134 | </mat-form-field> |
135 | 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 | 140 | </mat-error> |
141 | 141 | </mat-form-field> |
142 | 142 | </fieldset> |
... | ... | @@ -150,13 +150,24 @@ |
150 | 150 | </mat-select> |
151 | 151 | </mat-form-field> |
152 | 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 | 157 | </mat-error> |
158 | 158 | </mat-form-field> |
159 | 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 | 171 | <!-- <mat-accordion multi="true">--> |
161 | 172 | <!-- <div *ngIf="false">--> |
162 | 173 | <!-- <mat-expansion-panel>--> | ... | ... |
... | ... | @@ -30,7 +30,8 @@ import { |
30 | 30 | DEFAULT_NOTIF_IF_DESIBLED, |
31 | 31 | DEFAULT_SW_UPDATE_RESOURCE, |
32 | 32 | getDefaultBootstrapServerSecurityConfig, |
33 | - getDefaultBootstrapServersSecurityConfig, getDefaultLwM2MServerSecurityConfig, | |
33 | + getDefaultBootstrapServersSecurityConfig, | |
34 | + getDefaultLwM2MServerSecurityConfig, | |
34 | 35 | getDefaultProfileClientLwM2mSettingsConfig, |
35 | 36 | getDefaultProfileObserveAttrConfig, |
36 | 37 | Instance, |
... | ... | @@ -41,7 +42,10 @@ import { |
41 | 42 | ObjectLwM2M, |
42 | 43 | OBSERVE, |
43 | 44 | OBSERVE_ATTR_TELEMETRY, |
44 | - RESOURCES, ServerSecurityConfig, | |
45 | + PowerMode, | |
46 | + PowerModeTranslationMap, | |
47 | + RESOURCES, | |
48 | + ServerSecurityConfig, | |
45 | 49 | TELEMETRY |
46 | 50 | } from './lwm2m-profile-config.models'; |
47 | 51 | import { DeviceProfileService } from '@core/http/device-profile.service'; |
... | ... | @@ -76,6 +80,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
76 | 80 | sortFunction: (key: string, value: object) => object; |
77 | 81 | isFwUpdateStrategy: boolean; |
78 | 82 | isSwUpdateStrategy: boolean; |
83 | + powerMods = Object.values(PowerMode); | |
84 | + powerModeTranslationMap = PowerModeTranslationMap; | |
79 | 85 | |
80 | 86 | get required(): boolean { |
81 | 87 | return this.requiredValue; |
... | ... | @@ -109,8 +115,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
109 | 115 | clientOnlyObserveAfterConnect: [1, []], |
110 | 116 | fwUpdateStrategy: [1, []], |
111 | 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 | 123 | this.lwm2mDeviceConfigFormGroup = this.fb.group({ |
... | ... | @@ -120,12 +127,12 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
120 | 127 | takeUntil(this.destroy$) |
121 | 128 | ).subscribe((fwStrategy) => { |
122 | 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 | 132 | .patchValue(DEFAULT_FW_UPDATE_RESOURCE, {emitEvent: false}); |
126 | 133 | this.isFwUpdateStrategy = true; |
127 | 134 | } else { |
128 | - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').disable({emitEvent: false}); | |
135 | + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').disable({emitEvent: false}); | |
129 | 136 | this.isFwUpdateStrategy = false; |
130 | 137 | } |
131 | 138 | this.otaUpdateFwStrategyValidate(true); |
... | ... | @@ -134,13 +141,13 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
134 | 141 | takeUntil(this.destroy$) |
135 | 142 | ).subscribe((swStrategy) => { |
136 | 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 | 146 | .patchValue(DEFAULT_SW_UPDATE_RESOURCE, {emitEvent: false}); |
140 | 147 | this.isSwUpdateStrategy = true; |
141 | 148 | } else { |
142 | 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 | 152 | this.otaUpdateSwStrategyValidate(true); |
146 | 153 | }); |
... | ... | @@ -237,10 +244,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
237 | 244 | } |
238 | 245 | |
239 | 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 | 251 | this.lwm2mDeviceProfileFormGroup.patchValue({ |
245 | 252 | objectIds: value, |
246 | 253 | observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value.objectsList), |
... | ... | @@ -249,13 +256,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
249 | 256 | clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect, |
250 | 257 | fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1, |
251 | 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 | 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 | 267 | this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2; |
260 | 268 | this.isSwUpdateStrategy = this.configurationValue.clientLwM2mSettings.swUpdateStrategy === 2; |
261 | 269 | this.otaUpdateSwStrategyValidate(); |
... | ... | @@ -561,20 +569,20 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
561 | 569 | |
562 | 570 | private otaUpdateFwStrategyValidate(updated = false): void { |
563 | 571 | if (this.isFwUpdateStrategy) { |
564 | - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateRecourse').setValidators([Validators.required]); | |
572 | + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').setValidators([Validators.required]); | |
565 | 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 | 579 | private otaUpdateSwStrategyValidate(updated = false): void { |
572 | 580 | if (this.isSwUpdateStrategy) { |
573 | - this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateRecourse').setValidators([Validators.required]); | |
581 | + this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').setValidators([Validators.required]); | |
574 | 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 | 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 | 132 | export interface ModelValue { |
119 | 133 | objectIds: string[]; |
120 | 134 | objectsList: ObjectLwM2M[]; |
... | ... | @@ -160,8 +174,9 @@ export interface ClientLwM2mSettings { |
160 | 174 | clientOnlyObserveAfterConnect: number; |
161 | 175 | fwUpdateStrategy: number; |
162 | 176 | swUpdateStrategy: number; |
163 | - fwUpdateRecourse: string; | |
164 | - swUpdateRecourse: string; | |
177 | + fwUpdateResource: string; | |
178 | + swUpdateResource: string; | |
179 | + powerMode: PowerMode; | |
165 | 180 | } |
166 | 181 | |
167 | 182 | export interface ObservableAttributes { |
... | ... | @@ -216,8 +231,9 @@ export function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSetting |
216 | 231 | clientOnlyObserveAfterConnect: 1, |
217 | 232 | fwUpdateStrategy: 1, |
218 | 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 | 29 | formControlName="configuration"> |
30 | 30 | </tb-mqtt-device-transport-configuration> |
31 | 31 | </ng-template> |
32 | - <!--ng-template [ngSwitchCase]="deviceTransportType.LWM2M"> | |
32 | + <ng-template [ngSwitchCase]="deviceTransportType.LWM2M"> | |
33 | 33 | <tb-lwm2m-device-transport-configuration |
34 | 34 | [required]="required" |
35 | 35 | formControlName="configuration"> |
36 | 36 | </tb-lwm2m-device-transport-configuration> |
37 | - </ng-template--> | |
37 | + </ng-template> | |
38 | 38 | <ng-template [ngSwitchCase]="deviceTransportType.COAP"> |
39 | 39 | <tb-coap-device-transport-configuration |
40 | 40 | [required]="required" | ... | ... |
... | ... | @@ -16,9 +16,13 @@ |
16 | 16 | |
17 | 17 | --> |
18 | 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 | 28 | </form> | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import { |
23 | 23 | DeviceTransportConfiguration, |
24 | 24 | DeviceTransportType, Lwm2mDeviceTransportConfiguration |
25 | 25 | } from '@shared/models/device.models'; |
26 | +import {PowerMode, PowerModeTranslationMap} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models"; | |
26 | 27 | |
27 | 28 | @Component({ |
28 | 29 | selector: 'tb-lwm2m-device-transport-configuration', |
... | ... | @@ -37,6 +38,8 @@ import { |
37 | 38 | export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { |
38 | 39 | |
39 | 40 | lwm2mDeviceTransportConfigurationFormGroup: FormGroup; |
41 | + powerMods = Object.values(PowerMode); | |
42 | + powerModeTranslationMap = PowerModeTranslationMap; | |
40 | 43 | |
41 | 44 | private requiredValue: boolean; |
42 | 45 | get required(): boolean { |
... | ... | @@ -65,7 +68,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA |
65 | 68 | |
66 | 69 | ngOnInit() { |
67 | 70 | this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({ |
68 | - configuration: [null, Validators.required] | |
71 | + powerMode: [null] | |
69 | 72 | }); |
70 | 73 | this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => { |
71 | 74 | this.updateModel(); |
... | ... | @@ -82,13 +85,13 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA |
82 | 85 | } |
83 | 86 | |
84 | 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 | 91 | private updateModel() { |
89 | 92 | let configuration: DeviceTransportConfiguration = null; |
90 | 93 | if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) { |
91 | - configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue().configuration; | |
94 | + configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue(); | |
92 | 95 | // configuration.type = DeviceTransportType.LWM2M; |
93 | 96 | } |
94 | 97 | this.propagateChange(configuration); | ... | ... |
... | ... | @@ -200,7 +200,7 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy |
200 | 200 | DeviceTransportType.LWM2M, |
201 | 201 | { |
202 | 202 | hasProfileConfiguration: true, |
203 | - hasDeviceConfiguration: false, | |
203 | + hasDeviceConfiguration: true, | |
204 | 204 | } |
205 | 205 | ], |
206 | 206 | [ | ... | ... |
... | ... | @@ -1213,6 +1213,13 @@ |
1213 | 1213 | "export-failed-error": "Unable to export device profile: {{error}}", |
1214 | 1214 | "device-profile-file": "Device profile file", |
1215 | 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 | 1223 | "lwm2m": { |
1217 | 1224 | "object-list": "Object list", |
1218 | 1225 | "object-list-empty": "No objects selected.", |
... | ... | @@ -1313,10 +1320,10 @@ |
1313 | 1320 | "sw-update-strategy": "Software update strategy", |
1314 | 1321 | "sw-update-strategy-package": "Push binary file using Object 9 and Resource 2 (Package)", |
1315 | 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 | 1327 | "config-json-tab": "Json Config Profile Device", |
1321 | 1328 | "attributes-name": { |
1322 | 1329 | "min-period": "Minimum period", | ... | ... |