Browse Source

Lwm2m: firmwareUpdate (#4516)

* Lwm2m: firmwareUpdate

* Lwm2m: firmwareUpdate with merge master

* Lwm2m: firmwareUpdate cleaned

* Lwm2m: delete Californium.properties

* Lwm2m: merge with master
pull/4525/head
nickAS21 5 years ago
committed by GitHub
parent
commit
e33420d3a8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java
  2. 4
      common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
  3. 3
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java
  4. 100
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java
  5. 14
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
  6. 33
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java
  7. 123
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
  8. 8
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java
  9. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java
  10. 255
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java
  11. 21
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java
  12. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java
  13. 18
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  14. 10
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  15. 27
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java
  16. 15
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts
  17. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

2
application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java

@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService {
instance.setId(0);
List<LwM2mResourceObserve> resources = new ArrayList<>();
obj.resources.forEach((k, v) -> {
if (!v.operations.isExecutable()) {
if (v.operations.isReadable()) {
LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
resources.add(lwM2MResourceObserve);
}

4
common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java

@ -95,8 +95,8 @@ public class DataConstants {
//firmware
//telemetry
public static final String CURRENT_FIRMWARE_TITLE = "cur_fw_title";
public static final String CURRENT_FIRMWARE_VERSION = "cur_fw_version";
public static final String CURRENT_FIRMWARE_TITLE = "current_fw_title";
public static final String CURRENT_FIRMWARE_VERSION = "current_fw_version";
public static final String TARGET_FIRMWARE_TITLE = "target_fw_title";
public static final String TARGET_FIRMWARE_VERSION = "target_fw_version";
public static final String TARGET_FIRMWARE_TS = "target_fw_ts";

3
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java

@ -55,7 +55,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
@Slf4j
@Component
@ -93,7 +93,6 @@ public class LwM2MTransportBootstrapServerConfiguration {
builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort));
/** Define model provider (Create Models )*/
// builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon()));
/** Create credentials */
this.setServerWithCredentials(builder);

100
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java

@ -0,0 +1,100 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server;
import org.eclipse.californium.core.network.config.NetworkConfig;
public class LwM2mNetworkConfig {
public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
NetworkConfig coapConfig = new NetworkConfig();
coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec);
coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort);
/**
* Example:Property for large packet:
* #NetworkConfig config = new NetworkConfig();
* #config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32);
* #config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32);
* #config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048);
* #config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3);
* #config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000);
*/
/**
* Property to indicate if the response should always include the Block2 option \
* when client request early blockwise negociation but the response can be sent on one packet.
* - value of false indicate that the server will respond without block2 option if no further blocks are required.
* - value of true indicate that the server will response with block2 option event if no further blocks are required.
* CoAP client will try to use block mode
* or adapt the block size when receiving a 4.13 Entity too large response code
*/
coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true);
/***
* Property to indicate if the response should always include the Block2 option \
* when client request early blockwise negociation but the response can be sent on one packet.
* - value of false indicate that the server will respond without block2 option if no further blocks are required.
* - value of true indicate that the server will response with block2 option event if no further blocks are required.
*/
coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000);
/**
* !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
* The maximum size of a resource body (in bytes) that will be accepted
* as the payload of a POST/PUT or the response to a GET request in a
* transparent> blockwise transfer.
* This option serves as a safeguard against excessive memory
* consumption when many resources contain large bodies that cannot be
* transferred in a single CoAP message. This option has no impact on
* *manually* managed blockwise transfers in which the blocks are handled individually.
* Note that this option does not prevent local clients or resource
* implementations from sending large bodies as part of a request or response to a peer.
* The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192
* A value of {@code 0} turns off transparent handling of blockwise transfers altogether.
*/
// coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 8192);
coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 16384);
/**
* The default DTLS response matcher.
* Supported values are STRICT, RELAXED, or PRINCIPAL.
* The default value is STRICT.
* Create new instance of udp endpoint context matcher.
* Params:
* checkAddress
* true with address check, (STRICT, UDP)
* - false, without
*/
coapConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "STRICT");
/**
* https://tools.ietf.org/html/rfc7959#section-2.9.3
* The block size (number of bytes) to use when doing a blockwise transfer. \
* This value serves as the upper limit for block size in blockwise transfers
*/
coapConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 512);
/**
* The maximum payload size (in bytes) that can be transferred in a
* single message, i.e. without requiring a blockwise transfer.
* NB: this value MUST be adapted to the maximum message size supported by the transport layer.
* In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol
* DEFAULT_VALUE = 1024
*/
coapConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 512);
coapConfig.setInt(NetworkConfig.Keys.MAX_RETRANSMIT, 4);
return coapConfig;
}
}

14
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java

@ -26,6 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate;
import java.util.Collection;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer;
@Slf4j
@ -85,17 +86,19 @@ public class LwM2mServerListener {
@Override
public void cancelled(Observation observation) {
log.info("Received notification cancelled from [{}] ", observation.getPath());
String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath());
service.sendLogsToThingsboard(msg, observation.getRegistrationId());
log.trace(msg);
}
@Override
public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
if (registration != null) {
try {
service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
registration), response, null);
} catch (Exception e) {
log.error("[{}] onResponse", e.toString());
log.error("Observation/Read onResponse", e);
}
}
@ -108,7 +111,10 @@ public class LwM2mServerListener {
@Override
public void newObservation(Observation observation, Registration registration) {
log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint());
String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO,
observation.getPath());
service.sendLogsToThingsboard(msg, registration.getId());
log.trace(msg);
}
};

33
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java

@ -25,7 +25,6 @@ import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.leshan.core.attributes.Attribute;
import org.eclipse.leshan.core.attributes.AttributeSet;
import org.eclipse.leshan.core.model.ObjectModel;
@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException;
import org.eclipse.leshan.core.request.DownlinkRequest;
import org.eclipse.leshan.core.request.WriteAttributesRequest;
import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.server.californium.LeshanServerBuilder;
import org.eclipse.leshan.server.registration.Registration;
import org.nustaq.serialization.FSTConfiguration;
import org.thingsboard.server.common.data.DeviceProfile;
@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@ -72,7 +69,6 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA
@Slf4j
public class LwM2mTransportHandler {
// public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me";
public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0";
public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings";
public static final String BOOTSTRAP = "bootstrap";
@ -85,19 +81,12 @@ public class LwM2mTransportHandler {
public static final String KEY_NAME = "keyName";
public static final String OBSERVE_LWM2M = "observe";
public static final String ATTRIBUTE_LWM2M = "attributeLwm2m";
// public static final String RESOURCE_VALUE = "resValue";
// public static final String RESOURCE_TYPE = "resType";
private static final String REQUEST = "/request";
// private static final String RESPONSE = "/response";
private static final String ATTRIBUTES = "/" + ATTRIBUTE;
public static final String TELEMETRIES = "/" + TELEMETRY;
// public static final String ATTRIBUTES_RESPONSE = ATTRIBUTES + RESPONSE;
public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST;
// public static final String DEVICE_ATTRIBUTES_RESPONSE = ATTRIBUTES_RESPONSE + "/";
public static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/";
// public static final String DEVICE_ATTRIBUTES_TOPIC = BASE_DEVICE_API_TOPIC + ATTRIBUTES;
// public static final String DEVICE_TELEMETRY_TOPIC = BASE_DEVICE_API_TOPIC + TELEMETRIES;
public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms
@ -112,6 +101,11 @@ public class LwM2mTransportHandler {
public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
public static final Integer FR_OBJECT_ID = 5;
public static final Integer FR_RESOURCE_VER_ID = 7;
public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH
+ "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID;
public enum LwM2mTypeServer {
BOOTSTRAP(0, "bootstrap"),
CLIENT(1, "client");
@ -168,6 +162,8 @@ public class LwM2mTransportHandler {
WRITE_ATTRIBUTES(8, "WriteAttributes"),
DELETE(9, "Delete");
// READ_INFO_FW(10, "ReadInfoFirmware");
public int code;
public String type;
@ -190,21 +186,6 @@ public class LwM2mTransportHandler {
public static final String SERVICE_CHANNEL = "SERVICE";
public static final String RESPONSE_CHANNEL = "RESP";
public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
NetworkConfig coapConfig;
File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME);
if (configFile.isFile()) {
coapConfig = new NetworkConfig();
coapConfig.load(configFile);
} else {
coapConfig = LeshanServerBuilder.createDefaultNetworkConfig();
coapConfig.store(configFile);
}
coapConfig.setString("COAP_PORT", Integer.toString(serverPortNoSec));
coapConfig.setString("COAP_SECURE_PORT", Integer.toString(serverSecurePort));
return coapConfig;
}
public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException {
switch (type) {
case BOOLEAN:

123
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

@ -67,6 +67,7 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.FR_PATH_RESOURCE_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE;
@ -125,7 +126,6 @@ public class LwM2mTransportRequest {
public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper,
String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
try {
String target = convertPathFromIdVerToObjectId(targetIdVer);
DownlinkRequest request = null;
ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
@ -145,11 +145,11 @@ public class LwM2mTransportRequest {
break;
case OBSERVE:
if (resultIds.isResource()) {
request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
} else if (resultIds.isObjectInstance()) {
request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId());
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
} else if (resultIds.getObjectId() >= 0) {
request = new ObserveRequest(resultIds.getObjectId());
request = new ObserveRequest(contentFormat, resultIds.getObjectId());
}
break;
case OBSERVE_CANCEL:
@ -171,8 +171,6 @@ public class LwM2mTransportRequest {
break;
case WRITE_REPLACE:
// Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
// resource = lwM2MClient.getResourceModel(targetIdVer);
// if (contentFormat.equals(ContentFormat.TLV) && !resource.multiple) {
resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
.getModelProvider());
if (contentFormat.equals(ContentFormat.TLV)) {
@ -181,7 +179,6 @@ public class LwM2mTransportRequest {
registration, rpcRequest);
}
// Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON)
// else if (!contentFormat.equals(ContentFormat.TLV) && !resource.multiple) {
else if (!contentFormat.equals(ContentFormat.TLV)) {
request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type,
@ -215,13 +212,16 @@ public class LwM2mTransportRequest {
long finalTimeoutInMs = timeoutInMs;
lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest));
} catch (Exception e) {
log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper, e);
log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
}
} else if (OBSERVE_CANCEL == typeOper) {
log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
if (rpcRequest != null) {
rpcRequest.setInfoMsg(null);
serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null);
}
} else if (OBSERVE_CANCEL == typeOper && rpcRequest != null) {
rpcRequest.setInfoMsg(null);
serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null);
} else {
log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, targetIdVer);
log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
if (rpcRequest != null) {
String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
@ -236,8 +236,8 @@ public class LwM2mTransportRequest {
Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO,
OBSERVE_READ_ALL.type, observationPaths);
serviceImpl.sendLogsToThingsboard(msg, registration);
log.info("[{}], [{}]", registration.getEndpoint(), msg);
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg);
if (rpcRequest != null) {
String valueMsg = String.format("Observation paths - %s", observationPaths);
serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
@ -246,7 +246,7 @@ public class LwM2mTransportRequest {
} catch (Exception e) {
String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
typeOper.name(), e.getMessage());
serviceImpl.sendLogsToThingsboard(msg, registration);
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
throw new Exception(e);
}
}
@ -261,45 +261,53 @@ public class LwM2mTransportRequest {
private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
if (!lwM2MClient.isInit()) {
lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
}
if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) {
this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest);
if (request instanceof WriteRequest && ((WriteRequest) request).isReplaceRequest()) {
LwM2mNode node = ((WriteRequest) request).getNode();
Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(),
((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath());
String msg = String.format("%s: sendRequest Replace: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s SendRequest to Client",
LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(),
response.getCode().getName(), request.getPath().toString(), value);
serviceImpl.sendLogsToThingsboard(msg, registration);
log.info("[{}] [{}] - [{}] [{}] Update SendRequest[{}]", registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(),
request.getPath().toString(), value);
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO);
}
} else {
String msg = String.format("%s: sendRequest: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s SendRequest to Client", LOG_LW2M_ERROR,
String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(),
((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString());
serviceImpl.sendLogsToThingsboard(msg, registration);
log.error("[{}], [{}] - [{}] [{}] error SendRequest", registration.getEndpoint(), ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());
if (!lwM2MClient.isInit()) {
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
}
if (rpcRequest != null) {
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
}
/** Not Found
* set setClient_fw_version = empty
**/
if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
lwM2MClient.setUpdateFw(false);
lwM2MClient.getFrUpdate().setClientFwVersion("");
log.warn("updateFirmwareClient1");
serviceImpl.updateFirmwareClient(lwM2MClient);
}
}
}, e -> {
/** version == null
* set setClient_fw_version = empty
**/
if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
lwM2MClient.setUpdateFw(false);
lwM2MClient.getFrUpdate().setClientFwVersion("");
log.warn("updateFirmwareClient2");
serviceImpl.updateFirmwareClient(lwM2MClient);
}
if (!lwM2MClient.isInit()) {
lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
}
String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client",
LOG_LW2M_ERROR, request.getPath().toString(), e.getMessage());
serviceImpl.sendLogsToThingsboard(msg, registration);
log.error("[{}] - [{}] error SendRequest", request.getPath().toString(), e.toString());
String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s",
LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage());
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString());
if (rpcRequest != null) {
serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
}
});
}
private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId,
@ -323,7 +331,9 @@ public class LwM2mTransportRequest {
Date date = new Date(Long.decode(value.toString()));
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date);
case OPAQUE: // byte[] value, base64
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray()));
byte[] valueRequest = value instanceof byte[] ? (byte[]) value : Hex.decodeHex(value.toString().toCharArray());
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, valueRequest) :
new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueRequest);
default:
}
}
@ -337,7 +347,7 @@ public class LwM2mTransportRequest {
String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
patn, type, value, e.toString());
serviceImpl.sendLogsToThingsboard(msg, registration);
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
if (rpcRequest != null) {
String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
@ -369,7 +379,7 @@ public class LwM2mTransportRequest {
DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
if (response instanceof ReadResponse) {
serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
} else if (response instanceof CancelObservationResponse) {
log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response);
@ -389,14 +399,33 @@ public class LwM2mTransportRequest {
} else if (response instanceof WriteAttributesResponse) {
log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
} else if (response instanceof WriteResponse) {
log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", pathIdVer, response);
log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
this.infoWriteResponse(registration, response, request);
serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
}
if (rpcRequest != null && (response instanceof ExecuteResponse
|| response instanceof WriteAttributesResponse
|| response instanceof DeleteResponse)) {
rpcRequest.setInfoMsg(null);
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null);
if (rpcRequest != null) {
if (response instanceof ExecuteResponse
|| response instanceof WriteAttributesResponse
|| response instanceof DeleteResponse) {
rpcRequest.setInfoMsg(null);
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null);
} else if (response instanceof WriteResponse) {
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO);
}
}
}
private void infoWriteResponse(Registration registration, LwM2mResponse response,
DownlinkRequest request) {
LwM2mNode node = ((WriteRequest) request).getNode();
Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(),
((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath());
String msg = String.format("%s: Update finished successfully: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s",
LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(),
response.getCode().getName(), request.getPath().toString(), value);
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName().toString(), registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(),
request.getPath().toString(), value);
}
}

8
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java

@ -16,6 +16,8 @@
package org.thingsboard.server.transport.lwm2m.server;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.core.network.stack.BlockwiseLayer;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
@ -57,7 +59,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
@Slf4j
@Component
@ -92,7 +94,10 @@ public class LwM2mTransportServerConfiguration {
/** Use a magic converter to support bad type send by the UI. */
builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
/** Create CoAP Config */
NetworkConfig networkConfig = getCoapConfig(serverPortNoSec, serverSecurePort);
BlockwiseLayer blockwiseLayer = new BlockwiseLayer(networkConfig);
builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort));
/** Define model provider (Create Models )*/
@ -110,6 +115,7 @@ public class LwM2mTransportServerConfiguration {
/** Create DTLS Config */
DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
dtlsConfig.setServerOnly(true);
dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups());
dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers());
if (this.pskMode) {

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java

@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService {
void setCancelObservations(Registration registration);
void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo);
@ -60,6 +60,4 @@ public interface LwM2mTransportService extends TbTransportService {
void doTrigger(Registration registration, String path);
void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
}

255
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java

@ -38,10 +38,12 @@ import org.eclipse.leshan.server.registration.Registration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.firmware.FirmwareDataCache;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.common.transport.service.DefaultTransportService;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -77,9 +79,12 @@ import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.FR_PATH_RESOURCE_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE;
@ -110,6 +115,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
private ExecutorService executorUpdateRegistered;
private ExecutorService executorUnRegistered;
private LwM2mValueConverterImpl converter;
private FirmwareDataCache firmwareDataCache;
private final TransportService transportService;
@ -121,12 +128,15 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
private final LwM2mTransportRequest lwM2mTransportRequest;
public LwM2mTransportServiceImpl(TransportService transportService, LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, @Lazy LwM2mTransportRequest lwM2mTransportRequest) {
public LwM2mTransportServiceImpl(TransportService transportService, LwM2mTransportContextServer lwM2mTransportContextServer,
LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer,
@Lazy LwM2mTransportRequest lwM2mTransportRequest, FirmwareDataCache firmwareDataCache) {
this.transportService = transportService;
this.lwM2mTransportContextServer = lwM2mTransportContextServer;
this.lwM2mClientContext = lwM2mClientContext;
this.leshanServer = leshanServer;
this.lwM2mTransportRequest = lwM2mTransportRequest;
this.firmwareDataCache = firmwareDataCache;
}
@PostConstruct
@ -168,8 +178,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
this.getInfoFirmwareUpdate(lwM2MClient);
this.initLwM2mFromClientValue(registration, lwM2MClient);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
} else {
log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
}
@ -224,7 +235,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
executorUnRegistered.submit(() -> {
try {
this.setCancelObservations(registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
this.closeClientSession(registration);
} catch (Throwable t) {
log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t);
@ -257,7 +268,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
@Override
public void onSleepingDev(Registration registration) {
log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint());
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration.getId());
//TODO: associate endpointId with device information.
}
@ -280,7 +291,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
* @param response - observe
*/
@Override
public void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
if (response.getContent() != null) {
if (response.getContent() instanceof LwM2mObject) {
LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
@ -304,20 +315,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
/**
* Update - send request in change value resources in Client
* Path to resources from profile equal keyName or from ModelObject equal name
* Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)
* Delete - nothing *
* 1. FirmwareUpdate:
* - If msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
* 2. Shared Other AttributeUpdate
* -- Path to resources from profile equal keyName or from ModelObject equal name
* -- Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)
* 3. Delete - nothing
*
* @param msg -
*/
@Override
public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
if (msg.getSharedUpdatedCount() > 0) {
msg.getSharedUpdatedList().forEach(tsKvProto -> {
String pathName = tsKvProto.getKv().getKey();
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv());
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
this.getInfoFirmwareUpdate(lwM2MClient);
}
if (pathIdVer != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
.getModelProvider());
@ -327,19 +344,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew);
String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
LOG_LW2M_ERROR, pathIdVer, valueNew);
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration());
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
}
} else {
log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew);
String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated",
LOG_LW2M_ERROR, pathName, valueNew);
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration());
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
}
});
} else if (msg.getSharedDeletedCount() > 0) {
msg.getSharedUpdatedList().forEach(tsKvProto -> {
String pathName = tsKvProto.getKv().getKey();
Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv());
if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew);
}
});
log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
}
}
/**
@ -455,23 +479,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
}
if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) {
lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey)
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType()));
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType()));
}
lwm2mClientRpcRequest.setSessionInfo(sessionInfo);
if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) {
lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " +
lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
}
else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper()
} else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper()
|| WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper())
&& lwm2mClientRpcRequest.getTargetIdVer() !=null
&& lwm2mClientRpcRequest.getTargetIdVer() != null
&& !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource()
|| new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) {
lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey
lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey
+ ". Only Resource or ResourceInstance can be this operation");
}
else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()){
} else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) {
lwm2mClientRpcRequest.setErrorMsg("Procedures In Development...");
}
} else {
@ -483,23 +505,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
return lwm2mClientRpcRequest;
}
public void sentRpcRequest (Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
rpcRequest.setResponseCode(requestCode);
if (LOG_LW2M_ERROR.equals(typeMsg)) {
rpcRequest.setInfoMsg(null);
rpcRequest.setValueMsg(null);
if (rpcRequest.getErrorMsg() == null) {
msg = msg.isEmpty() ? null : msg;
rpcRequest.setErrorMsg(msg);
}
} else if (LOG_LW2M_INFO.equals(typeMsg)) {
if (rpcRequest.getInfoMsg() == null) {
rpcRequest.setInfoMsg(msg);
}
} else if (LOG_LW2M_VALUE.equals(typeMsg)) {
if (rpcRequest.getValueMsg() == null) {
rpcRequest.setValueMsg(msg);
}
if (LOG_LW2M_ERROR.equals(typeMsg)) {
rpcRequest.setInfoMsg(null);
rpcRequest.setValueMsg(null);
if (rpcRequest.getErrorMsg() == null) {
msg = msg.isEmpty() ? null : msg;
rpcRequest.setErrorMsg(msg);
}
} else if (LOG_LW2M_INFO.equals(typeMsg)) {
if (rpcRequest.getInfoMsg() == null) {
rpcRequest.setInfoMsg(msg);
}
} else if (LOG_LW2M_VALUE.equals(typeMsg)) {
if (rpcRequest.getValueMsg() == null) {
rpcRequest.setValueMsg(msg);
}
}
this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo());
}
@ -556,7 +578,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
protected void onAwakeDev(Registration registration) {
log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId());
//TODO: associate endpointId with device information.
}
@ -583,10 +605,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
/**
* @param logMsg - text msg
* @param registration - Id of Registration LwM2M Client
* @param registrationId - Id of Registration LwM2M Client
*/
public void sendLogsToThingsboard(String logMsg, Registration registration) {
SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
public void sendLogsToThingsboard(String logMsg, String registrationId) {
SessionInfoProto sessionInfo = this.getValidateSessionInfo(registrationId);
if (logMsg != null && sessionInfo != null) {
this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(this.lwM2mTransportContextServer.getKvLogyToThingsboard(logMsg), sessionInfo);
}
@ -610,7 +632,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
if (clientObjects != null && clientObjects.size() > 0) {
if (LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
// #2
lwM2MClient.getPendingRequests().addAll(clientObjects);
lwM2MClient.getPendingReadRequests().addAll(clientObjects);
clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(),
null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null));
}
@ -652,6 +674,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
* Sending observe value of resources to thingsboard
* #1 Return old Value Resource from LwM2MClient
* #2 Update new Resources (replace old Resource Value on new Resource Value)
* #3 If fr_update -> UpdateFirmware
* #4 updateAttrTelemetry
*
* @param registration - Registration LwM2M Client
* @param lwM2mResource - LwM2mSingleResource response.getContent()
@ -661,6 +685,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
.getModelProvider())) {
if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) &&
lwM2MClient.getFrUpdate().getCurrentFwVersion() != null
&& !lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())
&& lwM2MClient.isUpdateFw()) {
/** version != null
* set setClient_fw_version = value
**/
lwM2MClient.setUpdateFw(false);
lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString());
log.warn("updateFirmwareClient3");
this.updateFirmwareClient(lwM2MClient);
}
Set<String> paths = new HashSet<>();
paths.add(path);
this.updateAttrTelemetry(registration, paths);
@ -669,6 +706,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
}
}
/**
* send Attribute and Telemetry to Thingsboard
* #1 - get AttrName/TelemetryName with value from LwM2MClient:
@ -723,22 +761,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile());
result = params.keySet();
}
if (!result.isEmpty()) {
if (result != null && !result.isEmpty()) {
// #1
Set<String> pathSend = result.stream().filter(target -> {
return target.split(LWM2M_SEPARATOR_PATH).length < 3 ?
clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) :
clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]);
}
)
.collect(Collectors.toUnmodifiableSet());
).collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) {
lwM2MClient.getPendingRequests().addAll(pathSend);
lwM2MClient.getPendingReadRequests().addAll(pathSend);
ConcurrentHashMap<String, Object> finalParams = params;
pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),
finalParams != null ? finalParams.get(target) : null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null));
pathSend.forEach(target -> {
lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),
finalParams != null ? finalParams.get(target) : null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
});
if (OBSERVE.equals(typeOper)) {
lwM2MClient.initValue(this, null);
lwM2MClient.initReadValue(this, null);
}
}
}
@ -969,7 +1008,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
// update value in Resources
registrationIds.forEach(registrationId -> {
Registration registration = lwM2mClientContext.getRegistration(registrationId);
this.readResourceValueObserve(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
// send attr/telemetry to tingsboard for new path
this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
});
@ -998,12 +1037,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
registrationIds.forEach(registrationId -> {
Registration registration = lwM2mClientContext.getRegistration(registrationId);
if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) {
this.readResourceValueObserve(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
}
// 5.3 del
// send Request cancel observe to Client
if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) {
this.cancelObserveIsValue(registration, postObserveAnalyzer.getPathPostParametersDel());
this.cancelObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersDel());
}
});
}
@ -1043,7 +1082,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
* @param registration - Registration LwM2M Client
* @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
*/
private void readResourceValueObserve(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) {
private void readObserveFromProfile(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) {
targets.forEach(target -> {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target));
if (pathIds.isResource()) {
@ -1133,7 +1172,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
}
private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) {
private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
paramAnallyzer.forEach(pathIdVer -> {
if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) {
@ -1153,7 +1192,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
log.error("Failed update resource [{}] [{}]", path, valueNew);
String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad",
LOG_LW2M_ERROR, path, valueNew);
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration());
this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
log.info("Failed update resource [{}] [{}]", path, valueNew);
}
}
@ -1182,8 +1221,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
}
/**
* Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values
* #1 Get path resource by result attributesResponse
* 1. FirmwareUpdate:
* - msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
* 2. Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values
* - Get path resource by result attributesResponse
*
* @param attributesResponse -
* @param sessionInfo -
@ -1191,6 +1232,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) {
try {
List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList();
this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo);
} catch (Exception e) {
log.error(String.valueOf(e));
@ -1274,7 +1316,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
private SessionInfoProto getValidateSessionInfo(String registrationId) {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId);
return getNewSessionInfoProto(lwM2MClient);
return lwM2MClient != null ? this.getNewSessionInfoProto(lwM2MClient) : null;
}
/**
@ -1293,28 +1335,88 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
}
/**
* !!! sharedAttr === profileAttr !!!
* If there is a difference in values between the current resource values and the shared attribute values
* when the client connects to the server
* #1 get attributes name from profile include name resources in ModelObject if resource isWritable
* #2.1 #1 size > 0 => send Request getAttributes to thingsboard
* #1. !!! sharedAttr === profileAttr !!!
* - If there is a difference in values between the current resource values and the shared attribute values
* - when the client connects to the server
* #1.1 get attributes name from profile include name resources in ModelObject if resource isWritable
* #1.2 #1 size > 0 => send Request getAttributes to thingsboard
* #2. FirmwareAttribute subscribe:
*
* @param lwM2MClient - LwM2M Client
*/
public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
if (sessionInfo != null) {
//#1.1 + #1.2
List<String> attrSharedNames = this.getNamesAttrFromProfileIsWritable(lwM2MClient);
if (attrSharedNames.size() > 0) {
//#2.1
//#1.1
ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
if (keyNamesMap.values().size() > 0) {
try {
TransportProtos.GetAttributeRequestMsg getAttributeMsg = lwM2mTransportContextServer.getAdaptor().convertToGetAttributes(null, attrSharedNames);
//#1.2
TransportProtos.GetAttributeRequestMsg getAttributeMsg = lwM2mTransportContextServer.getAdaptor().convertToGetAttributes(null, keyNamesMap.values());
transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST));
} catch (AdaptorException e) {
log.warn("Failed to decode get attributes request", e);
}
}
}
}
public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
if (sessionInfo != null) {
TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
.build();
transportService.process(sessionInfo, getFirmwareRequestMsg,
new TransportServiceCallback<>() {
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) {
lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion());
lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
lwM2MClient.setUpdateFw(true);
readRequestToClientFirmwareVer(lwM2MClient.getRegistration());
} else {
log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
}
}
@Override
public void onError(Throwable e) {
log.trace("Failed to process credentials ", e);
}
});
}
}
/**
* @param registration
*/
public void readRequestToClientFirmwareVer(Registration registration) {
String pathIdVer = convertPathFromObjectIdToIdVer(FR_PATH_RESOURCE_VER_ID, registration);
lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, READ, ContentFormat.TLV.getName(),
null, lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
}
/**
*
* @param lwM2MClient -
*/
public void updateFirmwareClient(LwM2mClient lwM2MClient) {
if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) {
int chunkSize = 0;
int chunk = 0;
byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk);
Integer objectId = 5;
String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(objectId);
String targetIdVer = LWM2M_SEPARATOR_PATH + objectId + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0;
lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.TLV.getName(),
firmwareChunk, lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion());
}
}
@ -1326,23 +1428,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
* @param lwM2MClient -
* @return ArrayList keyNames from profile profileAttr && IsWritable
*/
private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) {
private ConcurrentMap<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId());
Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(),
new TypeToken<HashSet<String>>() {
}.getType());
ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
return new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
new TypeToken<ConcurrentHashMap<String, String>>() {
}.getType());
ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()
.stream()
.filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient, e.getKey(), true)))
.collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue));
Set<String> namesIsWritable = ConcurrentHashMap.newKeySet();
namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values()));
return new ArrayList<>(namesIsWritable);
}
private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {

21
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java

@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
import org.thingsboard.server.gen.transport.TransportProtos;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Collection;
import java.util.Random;
import java.util.Set;
@Slf4j
@Component("LwM2MJsonAdaptor")
@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor {
}
@Override
public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException {
return processGetAttributeRequestMsg(clientKeys, sharedKeys);
}
protected TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException {
public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException {
try {
TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder();
Random random = new Random();
@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor {
throw new AdaptorException(e);
}
}
private Set<String> toStringSet(JsonElement requestBody, String name) {
JsonElement element = requestBody.getAsJsonObject().get(name);
if (element != null) {
return new HashSet<>(Arrays.asList(element.getAsString().split(",")));
} else {
return null;
}
}
}

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java

@ -19,7 +19,7 @@ import com.google.gson.JsonElement;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.gen.transport.TransportProtos;
import java.util.List;
import java.util.Collection;
public interface LwM2MTransportAdaptor {
@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor {
TransportProtos.PostAttributeMsg convertToPostAttributes(JsonElement jsonElement) throws AdaptorException;
TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException;
TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException;
}

18
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java

@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable {
private UUID deviceId;
private UUID sessionId;
private UUID profileId;
private volatile LwM2mFirmwareUpdate frUpdate;
private Registration registration;
private ValidateDeviceCredentialsResponseMsg credentialsResponse;
private final Map<String, ResourceValue> resources;
private final Map<String, TransportProtos.TsKvProto> delayedRequests;
private final List<String> pendingRequests;
private final List<String> pendingReadRequests;
private final Queue<LwM2mQueuedRequest> queuedRequests;
private boolean init;
private volatile boolean updateFw;
public Object clone() throws CloneNotSupportedException {
return super.clone();
@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable {
this.securityInfo = securityInfo;
this.credentialsResponse = credentialsResponse;
this.delayedRequests = new ConcurrentHashMap<>();
this.pendingRequests = new CopyOnWriteArrayList<>();
this.pendingReadRequests = new CopyOnWriteArrayList<>();
this.resources = new ConcurrentHashMap<>();
this.profileId = profileId;
this.sessionId = sessionId;
this.init = false;
this.updateFw = false;
this.queuedRequests = new ConcurrentLinkedQueue<>();
this.frUpdate = new LwM2mFirmwareUpdate();
}
public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez));
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
String verRez = getVerFromPathIdVerOrId(pathRez);
return (verRez == null || verSupportedObject.equals(verRez)) ? modelProvider.getObjectModel(registration)
return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration)
.getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null;
}
public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider,
LwM2mValueConverterImpl converter) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
String verRez = getVerFromPathIdVerOrId(pathRezIdVer);
Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources;
@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable {
.collect(Collectors.toSet());
}
public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) {
public void initReadValue(LwM2mTransportServiceImpl serviceImpl, String path) {
if (path != null) {
this.pendingRequests.remove(path);
this.pendingReadRequests.remove(path);
}
if (this.pendingRequests.size() == 0) {
if (this.pendingReadRequests.size() == 0) {
this.init = true;
serviceImpl.putDelayedUpdateResourcesThingsboard(this);
}

10
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java

@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override
public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) {
LwM2mClient client = registrationId != null ?
LwM2mClient client = registrationId != null && this.lwM2mClients.containsKey(registrationId) ?
this.lwM2mClients.get(registrationId) :
this.lwM2mClients.containsKey(registration.getId()) ?
this.lwM2mClients.get(registration.getId()) :
this.lwM2mClients.get(registration.getEndpoint());
return client != null ? client : updateInSessionsLwM2MClient(registration);
registration !=null && this.lwM2mClients.containsKey(registration.getId()) ?
this.lwM2mClients.get(registration.getId()) : registration !=null && this.lwM2mClients.containsKey(registration) ?
this.lwM2mClients.get(registration.getEndpoint()) : null;
return client != null ? client : registration!= null ? updateInSessionsLwM2MClient(registration) : null;
}
@Override

27
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.client;
import lombok.Data;
import java.util.UUID;
@Data
public class LwM2mFirmwareUpdate {
private volatile String clientFwVersion;
private volatile String currentFwVersion;
private volatile UUID currentFwId;
}

15
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts

@ -24,6 +24,8 @@ import {
NG_VALUE_ACCESSOR,
Validators
} from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import {
ATTRIBUTE,
@ -38,6 +40,7 @@ import {
} from './lwm2m-profile-config.models';
import { deepClone, isDefinedAndNotNull, isEqual, isUndefined } from '@core/utils';
import { MatDialog } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import {
Lwm2mObjectAddInstancesData,
Lwm2mObjectAddInstancesDialogComponent
@ -80,8 +83,10 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
@Input()
disabled: boolean;
constructor(private fb: FormBuilder,
private dialog: MatDialog) {
constructor(private store: Store<AppState>,
private fb: FormBuilder,
private dialog: MatDialog,
public translate: TranslateService) {
this.observeAttrTelemetryFormGroup = this.fb.group({
[CLIENT_LWM2M]: this.fb.array([])
});
@ -93,7 +98,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
}
private propagateChange = (v: any) => {
}
};
registerOnChange(fn: any): void {
this.propagateChange = fn;
@ -184,7 +189,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
this.observeAttrTelemetryFormGroup.get(CLIENT_LWM2M).updateValueAndValidity();
}
trackByParams = (index: number): number => {
trackByParams = (index: number, element: any): number => {
return index;
}
@ -312,7 +317,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
return objectName + ' <' + idVerObj + '>';
}
getNameInstanceLwm2m = (instance: Instance, idVerObj: string): string => {
return ` instance <${idVerObj}/${instance.id}>`;
return ' instance <' + idVerObj + '/' + instance.id +'>';
}
updateAttributeLwm2mObject = (event: Event, objectKeyId: number): void => {

2
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1205,7 +1205,7 @@
"telemetry-label": "Telemetry",
"key-name-label": "Key Name",
"attribute-lwm2m-label": "AttrLwm2m",
"resource-tip": "ID & Original Name of the Resource",
"resource-tip": "ID & Original Name of the Resource (only Operations isReadable)",
"is-observe-tip": "Is Observe",
"not-observe-tip": "To observe select telemetry or attributes first",
"is-attr-tip": "Is Attribute",

Loading…
Cancel
Save