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:
parent
8369429faa
commit
ba4d2ff480
@ -20,6 +20,6 @@ import lombok.Data;
|
||||
@Data
|
||||
public class LwM2mInstance {
|
||||
int id;
|
||||
LwM2mResource [] resources;
|
||||
LwM2mResourceObserve[] resources;
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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) {}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user