lwm2m: notification in transport, add, update, del models (#4309)

* lwm2m: notification in transport, add, update, del models

* lwm2m: notification in transport, add, update, del models2
This commit is contained in:
nickAS21 2021-03-26 17:32:26 +02:00 committed by GitHub
parent 8369429faa
commit ba4d2ff480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 191 additions and 98 deletions

View File

@ -20,6 +20,6 @@ import lombok.Data;
@Data
public class LwM2mInstance {
int id;
LwM2mResource [] resources;
LwM2mResourceObserve[] resources;
}

View File

@ -22,7 +22,7 @@ import java.util.stream.Stream;
@Data
@AllArgsConstructor
public class LwM2mResource {
public class LwM2mResourceObserve {
int id;
String name;
boolean observe;
@ -30,7 +30,7 @@ public class LwM2mResource {
boolean telemetry;
String keyName;
public LwM2mResource(int id, String name, boolean observe, boolean attribute, boolean telemetry) {
public LwM2mResourceObserve(int id, String name, boolean observe, boolean attribute, boolean telemetry) {
this.id = id;
this.name = name;
this.observe = observe;

View File

@ -20,10 +20,11 @@ import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.transport.SessionMsgListener;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
@ -85,4 +86,16 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
public void operationComplete(Future<? super Void> future) throws Exception {
log.info("[{}] operationComplete", future);
}
public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) {
this.service.onResourceUpdate(resourceUpdateMsgOpt);
}
}
public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) {
this.service.onResourceDelete(resourceDeleteMsgOpt);
}
}
}

View File

@ -83,7 +83,7 @@ public class LwM2mTransportRequest {
private LwM2mValueConverterImpl converter;
private final LwM2mTransportContextServer context;
private final LwM2mTransportContextServer lwM2mTransportContextServer;
private final LwM2mClientContext lwM2mClientContext;
@ -91,8 +91,8 @@ public class LwM2mTransportRequest {
private final LwM2mTransportServiceImpl serviceImpl;
public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) {
this.context = context;
public LwM2mTransportRequest(LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) {
this.lwM2mTransportContextServer = lwM2mTransportContextServer;
this.lwM2mClientContext = lwM2mClientContext;
this.leshanServer = leshanServer;
this.serviceImpl = serviceImpl;
@ -101,7 +101,7 @@ public class LwM2mTransportRequest {
@PostConstruct
public void init() {
this.converter = LwM2mValueConverterImpl.getInstance();
executorResponse = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRequestPoolSize(),
executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getRequestPoolSize(),
new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
}
@ -120,7 +120,8 @@ public class LwM2mTransportRequest {
if (registration != null && resultIds.getObjectId() >= 0) {
DownlinkRequest request = null;
ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;
ResourceModel resource = serviceImpl.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, resultIds);
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
ResourceModel resource = lwM2MClient.getResourceModel(target);
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
switch (typeOper) {
case GET_TYPE_OPER_READ:
@ -217,7 +218,10 @@ public class LwM2mTransportRequest {
}
if (request != null) {
this.sendRequest(registration, request, timeoutInMs);
this.sendRequest(registration, lwM2MClient, request, timeoutInMs);
}
else {
log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, target);
}
}
}
@ -230,8 +234,7 @@ public class LwM2mTransportRequest {
*/
@SuppressWarnings("unchecked")
private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs) {
leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
if (!lwM2MClient.isInit()) {
lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration));

View File

@ -47,6 +47,10 @@ public interface LwM2mTransportService {
void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
void onResourceUpdate (Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt);
void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt);
void doTrigger(Registration registration, String path);
void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);

View File

@ -52,7 +52,6 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@ -73,9 +72,6 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject;
@ -107,8 +103,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
private ExecutorService executorUpdateRegistered;
private ExecutorService executorUnRegistered;
private LwM2mValueConverterImpl converter;
protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
protected final Lock writeLock = readWriteLock.writeLock();
private final TransportService transportService;
@ -162,7 +156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
if (lwM2MClient != null) {
SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
if (sessionInfo != null) {
this.initLwM2mClient (lwM2MClient, sessionInfo);
this.initLwM2mClient(lwM2MClient, sessionInfo);
transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
@ -223,7 +217,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
});
}
private void initLwM2mClient (LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) {
private void initLwM2mClient(LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) {
lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
lwM2MClient.setDeviceName(sessionInfo.getDeviceName());
@ -309,7 +303,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) {
ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer)));
ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer);
if (resourceModel != null && resourceModel.operations.isWritable()) {
lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE,
ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout());
@ -360,6 +354,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt));
}
/**
*
* @param resourceUpdateMsgOpt -
*/
@Override
public void onResourceUpdate (Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
String idVer = resourceUpdateMsgOpt.get().getResourceKey(); // 19_1.0
lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider()));
}
/**
*
* @param resourceDeleteMsgOpt -
*/
@Override
public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey(); // 19_1.0
lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider()));
}
/**
* Trigger Server path = "/1/0/8"
* <p>
@ -519,10 +533,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
lwM2MClient.updateResourceValue(path, lwM2mResource);
Set<String> paths = new HashSet<>();
paths.add(path);
this.updateAttrTelemetry(registration, paths);
if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())) {
Set<String> paths = new HashSet<>();
paths.add(path);
this.updateAttrTelemetry(registration, paths);
}
else {
log.error("Fail update Resource [{}]", lwM2mResource);
}
}
/**
@ -538,12 +556,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
JsonObject attributes = new JsonObject();
JsonObject telemetries = new JsonObject();
try {
writeLock.lock();
this.getParametersFromProfile(attributes, telemetries, registration, paths);
} catch (Exception e) {
log.error("UpdateAttrTelemetry", e);
} finally {
writeLock.unlock();
}
if (attributes.getAsJsonObject().entrySet().size() > 0)
this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration);
@ -558,8 +573,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) {
try {
List<String> attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(), new TypeToken<List<String>>() {
}.getType());
List<String> attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(),
new TypeToken<List<String>>() {}.getType());
return attributesSet.stream().anyMatch(p -> p.equals(path));
} catch (Exception e) {
log.error("Fail Validate Path [{}] ClientProfile.Attribute", path, e);
@ -717,9 +732,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
private String getResourceValueToString(LwM2mClient lwM2MClient, String path) {
LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(path));
ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path);
LwM2mResource resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path);
return resourceValue == null ? null :
this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString();
this.converter.convertValue(resourceValue.isMultiInstances() ? resourceValue.getValues() : resourceValue.getValue(), resourceValue.getType(), ResourceModel.Type.STRING, pathIds).toString();
}
/**
@ -727,10 +742,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
* @param path -
* @return - return value of Resource by idPath
*/
private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {
ResourceValue resourceValue = null;
private LwM2mResource returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {
LwM2mResource resourceValue = null;
if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) {
resourceValue = lwM2MClient.getResources().get(path);
resourceValue = lwM2MClient.getResources().get(path).getLwM2mResource();
}
return resourceValue;
}
@ -967,9 +982,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
*/
private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
Registration registration = lwM2mClientContext.getLwM2MClient(sessionInfo).getRegistration();
LwM2mClient lwM2mClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
.filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(registration, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
.filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
.orElse("");
}
@ -1118,7 +1133,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()
.stream()
.filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient.getRegistration(), e.getKey(), true)))
.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();
@ -1126,13 +1141,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
return new ArrayList<>(namesIsWritable);
}
private boolean validateResourceInModel(Registration registration, String pathKey, boolean isWritable) {
ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration,
new LwM2mPath(convertToObjectIdFromIdVer(pathKey)));
private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathKey, boolean isWritable) {
ResourceModel resourceModel = lwM2mClient.getResourceModel(pathKey);
Integer objectId = validateObjectIdFromKey(pathKey);
String objectVer = validateObjectVerFromKey(pathKey);
return resourceModel != null && (isWritable ?
objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)) && resourceModel.operations.isWritable() :
objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)));
objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() :
objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)));
}
}

View File

@ -85,7 +85,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
if (objectModel != null)
return objectModel.resources.get(resourceId);
else
log.warn("TbResources (Object model) with id [{}/{}] not found on the server", objectId, resourceId);
log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId);
return null;
} catch (Exception e) {
log.error("", e);

View File

@ -17,9 +17,10 @@ package org.thingsboard.server.transport.lwm2m.server.client;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -28,9 +29,14 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer;
@Slf4j
@Data
@ -67,21 +73,79 @@ public class LwM2mClient implements Cloneable {
this.init = false;
}
public void updateResourceValue(String pathRez, LwM2mResource rez) {
if (rez instanceof LwM2mMultipleResource) {
this.resources.put(pathRez, new ResourceValue(rez.getValues(), null, true));
} else if (rez instanceof LwM2mSingleResource) {
this.resources.put(pathRez, new ResourceValue(null, rez.getValue(), false));
public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) {
this.resources.get(pathRez).setLwM2mResource(rez);
return true;
} else {
LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
if (resourceModel != null) {
this.resources.put(pathRez, new ResourceValue(rez, resourceModel));
return true;
} else {
return false;
}
}
}
public void initValue(LwM2mTransportServiceImpl lwM2MTransportService, String path) {
public ResourceModel getResourceModel(String pathRez) {
if (this.getResources().get(pathRez) != null) {
return this.getResources().get(pathRez).getResourceModel();
} else {
return null;
}
}
/**
*
* @param pathIdVer == "3_1.0"
* @param modelProvider -
*/
public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) {
Set key = getKeysEqualsIdVer(pathIdVer);
key.forEach(pathRez -> {
LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez.toString()));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
if (resourceModel != null) {
this.resources.get(pathRez).setResourceModel(resourceModel);
}
else {
this.resources.remove(pathRez);
}
});
}
/**
*
* @param idVer -
* @param modelProvider -
*/
public void updateResourceModel(String idVer, LwM2mModelProvider modelProvider) {
Set key = getKeysEqualsIdVer(idVer);
key.forEach(k -> this.saveResourceModel(k.toString(), modelProvider));
}
private void saveResourceModel(String pathRez, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
this.resources.get(pathRez).setResourceModel(resourceModel);
}
private Set getKeysEqualsIdVer(String idVer) {
return this.resources.keySet()
.stream()
.filter(e -> idVer.equals(e.split(LWM2M_SEPARATOR_PATH)[1]))
.collect(Collectors.toSet());
}
public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) {
if (path != null) {
this.pendingRequests.remove(path);
}
if (this.pendingRequests.size() == 0) {
this.init = true;
lwM2MTransportService.putDelayedUpdateResourcesThingsboard(this);
serviceImpl.putDelayedUpdateResourcesThingsboard(this);
}
}

View File

@ -34,25 +34,25 @@ public class LwM2mClientProfile {
/**
* {"keyName": {
* "/3/0/1": "modelNumber",
* "/3/0/0": "manufacturer",
* "/3/0/2": "serialNumber"
* "/3_1.0/0/1": "modelNumber",
* "/3_1.0/0/0": "manufacturer",
* "/3_1.0/0/2": "serialNumber"
* }
**/
private JsonObject postKeyNameProfile;
/**
* [ "/2/0/0", "/2/0/1"]
* [ "/3_1.0/0/0", "/3_1.0/0/1"]
*/
private JsonArray postAttributeProfile;
/**
* [ "/2/0/0", "/2/0/1"]
* [ "/3_1.0/0/0", "/3_1.0/0/2"]
*/
private JsonArray postTelemetryProfile;
/**
* [ "/2/0/0", "/2/0/1"]
* [ "/3_1.0/0", "/3_1.0/0/1, "/3_1.0/0/2"]
*/
private JsonArray postObserveProfile;

View File

@ -16,23 +16,16 @@
package org.thingsboard.server.transport.lwm2m.server.client;
import lombok.Data;
import java.util.Map;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mResource;
@Data
public class ResourceValue {
Map<Integer, ?> values;
Object value;
boolean multiInstances;
private LwM2mResource lwM2mResource;
private ResourceModel resourceModel;
public ResourceValue(Map<Integer, ?> values, Object value, boolean multiInstances) {
this.values = values;
this.value = value;
this.multiInstances = multiInstances;
public ResourceValue(LwM2mResource lwM2mResource, ResourceModel resourceModel) {
this.lwM2mResource = lwM2mResource;
this.resourceModel = resourceModel;
}
public Object getResourceValue() {
return this.multiInstances ? this.values : this.value;
}
}

View File

@ -18,11 +18,11 @@ package org.thingsboard.server.common.transport;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;
import java.util.Optional;
@ -44,9 +44,12 @@ public interface SessionMsgListener {
default void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto toTransportUpdateCredentials){}
default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) {
}
default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) {}
default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {
}
default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device,
Optional<DeviceProfile> deviceProfileOpt) {}
default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {}
default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {}
}

View File

@ -18,10 +18,7 @@ package org.thingsboard.server.common.transport.lwm2m;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.registration.Registration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
@ -219,13 +216,4 @@ public class LwM2MTransportConfigServer {
}
return FULL_FILE_PATH.toUri().getPath();
}
public ResourceModel getResourceModel(Registration registration, LwM2mPath pathIds) {
return this.modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
}
public ResourceModel.Type getResourceModelType(Registration registration, LwM2mPath pathIds) {
ResourceModel resource = this.getResourceModel(registration, pathIds);
return (resource == null) ? null : resource.type;
}
}

View File

@ -288,7 +288,7 @@ public class DefaultTransportService implements TransportService {
}
@Override
public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback<TransportProtos.ValidateDeviceCredentialsResponseMsg> callback) {
public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback<TransportProtos.ValidateDeviceCredentialsResponseMsg> callback) {
log.trace("Processing msg: {}", msg);
TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(msg).build());
AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg),
@ -710,12 +710,21 @@ public class DefaultTransportService implements TransportService {
ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
String resourceId = msg.getResourceKey();
transportResourceCache.update(tenantId, resourceType, resourceId);
sessions.forEach((id, mdRez) -> {
log.warn("ResourceUpdate - [{}] [{}]", id, mdRez);
transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(Optional.ofNullable(msg)));
});
} else if (toSessionMsg.hasResourceDeleteMsg()) {
TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg();
TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
String resourceId = msg.getResourceKey();
transportResourceCache.evict(tenantId, resourceType, resourceId);
sessions.forEach((id, mdRez) -> {
log.warn("ResourceDelete - [{}] [{}]", id, mdRez);
transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(Optional.ofNullable(msg)));
});
} else {
//TODO: should we notify the device actor about missed session?
log.debug("[{}] Missing session.", sessionId);
@ -827,7 +836,7 @@ public class DefaultTransportService implements TransportService {
}
private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json,
TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) {
TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) {
DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId);
RuleChainId ruleChainId;

View File

@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.lwm2m.LwM2mInstance;
import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
import org.thingsboard.server.common.data.lwm2m.LwM2mResource;
import org.thingsboard.server.common.data.lwm2m.LwM2mResourceObserve;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.exception.DataValidationException;
@ -87,7 +87,9 @@ public class BaseTbResourceService implements TbResourceService {
String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion();
String name = objectModel.name;
resource.setResourceKey(resourceKey);
resource.setTitle(name + " id=" +objectModel.id + " v" + objectModel.getVersion());
if (resource.getId() == null) {
resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion());
}
resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);
} else {
throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));
@ -205,14 +207,14 @@ public class BaseTbResourceService implements TbResourceService {
lwM2mObject.setMandatory(obj.mandatory);
LwM2mInstance instance = new LwM2mInstance();
instance.setId(0);
List<LwM2mResource> resources = new ArrayList<>();
List<LwM2mResourceObserve> resources = new ArrayList<>();
obj.resources.forEach((k, v) -> {
if (!v.operations.isExecutable()) {
LwM2mResource lwM2mResource = new LwM2mResource(k, v.name, false, false, false);
resources.add(lwM2mResource);
LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
resources.add(lwM2MResourceObserve);
}
});
instance.setResources(resources.toArray(LwM2mResource[]::new));
instance.setResources(resources.toArray(LwM2mResourceObserve[]::new));
lwM2mObject.setInstances(new LwM2mInstance[]{instance});
return lwM2mObject;
}