diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java index d107318ad0..7199c3c31c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java @@ -58,7 +58,7 @@ public class LwM2MTransportContextServer extends TransportContext { private LwM2MTransportConfigServer ctxServer; @Autowired - LwM2MTransportConfigServer lwM2MTransportConfigServer; + protected LwM2MTransportConfigServer lwM2MTransportConfigServer; @Autowired private TransportService transportService; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java index f29649de7d..1e84af7d48 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java @@ -27,7 +27,9 @@ import org.eclipse.leshan.core.node.LwM2mMultipleResource; import org.eclipse.leshan.core.node.LwM2mNode; import org.eclipse.leshan.core.node.LwM2mObject; import org.eclipse.leshan.core.node.LwM2mObjectInstance; +import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mSingleResource; +import org.eclipse.leshan.core.node.codec.CodecException; import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.californium.LeshanServerBuilder; @@ -53,7 +55,7 @@ import java.util.Optional; @Slf4j @Component("LwM2MTransportHandler") @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") -public class LwM2MTransportHandler{ +public class LwM2MTransportHandler { // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to // send a Confirmable message to the time when an acknowledgement is no longer expected. @@ -132,8 +134,7 @@ public class LwM2MTransportHandler{ this.lhServerNoSecPskRpk.getRegistrationService().addListener(lwM2mServerListener.registrationListener); this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener); this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener); - } - catch (java.lang.NullPointerException e) { + } catch (java.lang.NullPointerException e) { log.error("init [{}]", e.toString()); } } @@ -151,31 +152,49 @@ public class LwM2MTransportHandler{ return coapConfig; } - public static String getValueTypeToString (Object value, ResourceModel.Type type, int val) { - try{ +// public static String getValueTypeToString (Object value, ResourceModel.Type type, int val) { +// try{ +// switch (type) { +// case STRING: // String +// case OBJLNK: // ObjectLink +// return value.toString(); +// case INTEGER: // Long +// return Long.toString((long) value); +// case BOOLEAN: // Boolean +// return Boolean.toString((Boolean) value); +// case FLOAT: // Double +// return Double.toString((Double) value); +// case TIME: // Date +// return Long.toString(((Date) value).getTime()); +//// String DATE_FORMAT = "MMM d, yyyy HH:mm a"; +//// DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); +//// return formatter.format(new Date(Integer.toUnsignedLong((Integer) value))); +// case OPAQUE: // byte[] value, base64 +// return Hex.encodeHexString((byte[])value); +// default: +// return null; +// } +// } catch (Exception e) { +// log.error(e.getStackTrace().toString()); +// return null; +// } +// } + + public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { switch (type) { - case STRING: // String - case OBJLNK: // ObjectLink - return value.toString(); - case INTEGER: // Long - return Long.toString((long) value); - case BOOLEAN: // Boolean - return Boolean.toString((Boolean) value); - case FLOAT: // Double - return Double.toString((Double) value); - case TIME: // Date - return Long.toString(((Date) value).getTime()); -// String DATE_FORMAT = "MMM d, yyyy HH:mm a"; -// DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); -// return formatter.format(new Date(Integer.toUnsignedLong((Integer) value))); - case OPAQUE: // byte[] value, base64 - return Hex.encodeHexString((byte[])value); + case BOOLEAN: + case INTEGER: + case FLOAT: + return String.valueOf(valueOld).equals(String.valueOf(valueNew)); + case TIME: + return ((Date) valueOld).getTime() == ((Date) valueNew).getTime(); + case STRING: + case OBJLNK: + return valueOld.equals(valueNew); + case OPAQUE: + return Hex.decodeHex(((String) valueOld).toCharArray()).equals(Hex.decodeHex(((String) valueNew).toCharArray())); default: - return null; - } - } catch (Exception e) { - log.error(e.getStackTrace().toString()); - return null; + throw new CodecException("Invalid value type for resource %s, type %s", resourcePath, type); } } @@ -198,19 +217,18 @@ public class LwM2MTransportHandler{ attrTelemetryObserveValue.setPostAttributeProfile(profilesConfigData.get(ATTRIBUTE).getAsJsonArray()); attrTelemetryObserveValue.setPostTelemetryProfile(profilesConfigData.get(TELEMETRY).getAsJsonArray()); attrTelemetryObserveValue.setPostObserveProfile(profilesConfigData.get(OBSERVE).getAsJsonArray()); - return attrTelemetryObserveValue; + return attrTelemetryObserveValue; } /** - * @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard * Example: with pathResource (use only pathResource) * property: "observeAttr" * {"keyName": { - * "/3/0/1": "modelNumber", - * "/3/0/0": "manufacturer", - * "/3/0/2": "serialNumber" - * }, + * "/3/0/1": "modelNumber", + * "/3/0/0": "manufacturer", + * "/3/0/2": "serialNumber" + * }, * "attribute":["/2/0/1","/3/0/9"], * "telemetry":["/1/0/1","/2/0/1","/6/0/1"], * "observe":["/2/0","/2/0/0","/4/0/2"]} @@ -312,12 +330,12 @@ public class LwM2MTransportHandler{ } } - public static String splitCamelCaseString(String s){ + public static String splitCamelCaseString(String s) { LinkedList linkedListOut = new LinkedList<>(); LinkedList linkedList = new LinkedList((Arrays.asList(s.split(" ")))); - linkedList.forEach(str-> { + linkedList.forEach(str -> { String strOut = str.replaceAll("\\W", "").replaceAll("_", "").toUpperCase(); - if (strOut.length()>1) linkedListOut.add(strOut.charAt(0) + strOut.substring(1).toLowerCase()); + if (strOut.length() > 1) linkedListOut.add(strOut.charAt(0) + strOut.substring(1).toLowerCase()); else linkedListOut.add(strOut); }); linkedListOut.set(0, (linkedListOut.get(0).substring(0, 1).toLowerCase() + linkedListOut.get(0).substring(1))); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java index 2c7721089c..f0b96d0225 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java @@ -123,10 +123,7 @@ public class LwM2MTransportRequest { if (registration != null && resultIds.getObjectId() >= 0) { DownlinkRequest request = null; ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; - ResourceModel resource = (resultIds.getResourceId() !=null && lwM2MClient != null) ? - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()) : null; - ResourceModel.Type resType = (resource == null) ? null : resource.type; - boolean resMultiple = (resource == null) ? false : resource.multiple; + ResourceModel resource = service.context.getCtxServer().getResourceModel(resultIds); timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; switch (typeOper) { case GET_TYPE_OPER_READ: @@ -148,21 +145,23 @@ public class LwM2MTransportRequest { request = new CancelObservationRequest(observation); break; case POST_TYPE_OPER_EXECUTE: - if (params != null && !resMultiple) { + if (params != null && resource != null && !resource.multiple) { // request = new ExecuteRequest(target, LwM2MTransportHandler.getValueTypeToString(params, resType)); - request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resType, ResourceModel.Type.STRING, resultIds)); + request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resource.type, ResourceModel.Type.STRING, resultIds)); } else { request = new ExecuteRequest(target); } break; case POST_TYPE_OPER_WRITE_REPLACE: // Request to write a String Single-Instance Resource using the TLV content format. - if (contentFormat.equals(ContentFormat.TLV) && !resMultiple) { - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resType, registration); - } - // Mode.REPLACE && Request to write a String Single-Instance Resource using the given content format (TEXT, TLV, JSON) - else if (!contentFormat.equals(ContentFormat.TLV) && !resMultiple) { - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resType, registration); + if (resource != null) { + if (contentFormat.equals(ContentFormat.TLV) && !resource.multiple) { + request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resource.type, registration); + } + // Mode.REPLACE && Request to write a String Single-Instance Resource using the given content format (TEXT, TLV, JSON) + else if (!contentFormat.equals(ContentFormat.TLV) && !resource.multiple) { + request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resource.type, registration); + } } break; case PUT_TYPE_OPER_WRITE_UPDATE: @@ -217,10 +216,10 @@ public class LwM2MTransportRequest { break; default: } + if (request != null) { this.sendRequest(lwServer, registration, request, lwM2MClient, timeoutInMs, isDelayedUpdate); - } - else if (request == null && isDelayedUpdate) { + } else if (request == null && isDelayedUpdate) { String msg = String.format(LOG_LW2M_ERROR + ": sendRequest: Resource path - %s msg No SendRequest to Client", target); service.sentLogsToThingsboard(msg, registration.getId()); log.error("[{}] - [{}] No SendRequest", target); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java index 59768d1d32..5e4d4198f0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java @@ -19,8 +19,8 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mMultipleResource; import org.eclipse.leshan.core.node.LwM2mObject; @@ -55,12 +55,12 @@ import org.thingsboard.server.transport.lwm2m.server.client.ModelObject; import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore; +import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -103,6 +103,8 @@ public class LwM2MTransportService { private ExecutorService executorRegistered; private ExecutorService executorUpdateRegistered; private ExecutorService executorUnRegistered; + private LwM2mValueConverterImpl converter; + @Autowired private TransportService transportService; @@ -118,13 +120,14 @@ public class LwM2MTransportService { @PostConstruct public void init() { - context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getCtxServer().getSessionReportTimeout()), context.getCtxServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS); - executorRegistered = Executors.newCachedThreadPool( + this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getCtxServer().getSessionReportTimeout()), context.getCtxServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS); + this.executorRegistered = Executors.newCachedThreadPool( new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL))); - executorUpdateRegistered = Executors.newCachedThreadPool( + this.executorUpdateRegistered = Executors.newCachedThreadPool( new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL))); - executorUnRegistered = Executors.newCachedThreadPool( + this.executorUnRegistered = Executors.newCachedThreadPool( new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL))); + this.converter = new LwM2mValueConverterImpl(); } /** @@ -148,7 +151,6 @@ public class LwM2MTransportService { log.info("[{}] Client: onRegistered name ", registration.getEndpoint()); LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.updateInSessionsLwM2MClient(lwServer, registration); if (lwM2MClient != null) { - lwM2MClient.setLwM2MTransportService(this); lwM2MClient.setLwM2MTransportService(this); lwM2MClient.setSessionUuid(UUID.randomUUID()); this.setLwM2MClient(lwServer, registration, lwM2MClient); @@ -183,6 +185,8 @@ public class LwM2MTransportService { try { SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration.getId()); if (sessionInfo != null) { +// transportService.reportActivity(sessionInfo); +// transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo)); log.info("Client: [{}] updatedReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType()); } else { log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); @@ -199,7 +203,7 @@ public class LwM2MTransportService { * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect */ public void unReg(Registration registration, Collection observations) { - executorUpdateRegistered.submit(() -> { + executorUnRegistered.submit(() -> { try { this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); this.closeClientSession(registration); @@ -262,6 +266,7 @@ public class LwM2MTransportService { } /** + * #0 Add new ObjectModel to context * Create new LwM2MClient for current session -> setModelClient... * #1 Add all ObjectLinks (instance) to control the process of executing requests to the client * to get the client model with current values @@ -272,6 +277,8 @@ public class LwM2MTransportService { * @param lwM2MClient - object with All parameters off client */ private void setLwM2MClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) { + // #0 + this.setNewObjectModels(lwServer, registration); // #1 Arrays.stream(registration.getObjectLinks()).forEach(url -> { LwM2mPath pathIds = new LwM2mPath(url.getUrl()); @@ -289,6 +296,16 @@ public class LwM2MTransportService { }); } + private void setNewObjectModels(LeshanServer lwServer, Registration registration) { + Arrays.stream(registration.getObjectLinks()).forEach(url -> { + LwM2mPath pathIds = new LwM2mPath(url.getUrl()); + if (pathIds.isObjectInstance() && !pathIds.isResource() && !context.getCtxServer().getObjectModels().containsKey(pathIds.getObjectId())) { + ObjectModel model = lwServer.getModelProvider().getObjectModel(registration).getObjectModels().stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0); + context.getCtxServer().getObjectModels().put(pathIds.getObjectId(), model); + } + }); + } + /** * @param registrationId - Id of Registration LwM2M Client * @return - sessionInfo after access connect client @@ -396,8 +413,8 @@ public class LwM2MTransportService { lwM2MClient.getDelayedRequests().forEach((k, v) -> { List listV = new ArrayList(); listV.add(v.getKv()); - this.putDelayedUpdateResourcesClient(lwM2MClient, lwM2MClient.getResourceValue(k), getJsonObject(listV).get(v.getKv().getKey()), k); - System.out.printf(" k: %s, v: %s%n, v1: %s%n", k, v.getKv().getStringV(), lwM2MClient.getResourceValue(k)); + this.putDelayedUpdateResourcesClient(lwM2MClient, this.getResourceValueToString(lwM2MClient, k), getJsonObject(listV).get(v.getKv().getKey()), k); + System.out.printf(" k: %s, v: %s%n, v1: %s%n", k, v.getKv().getStringV(), this.getResourceValueToString(lwM2MClient, k)); }); lwM2MClient.getDelayedRequestsId().remove(attributesResponse.getRequestId()); if (lwM2MClient.getDelayedRequests().size() == 0) { @@ -427,10 +444,11 @@ public class LwM2MTransportService { ConcurrentMap keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), ConcurrentHashMap.class); ConcurrentMap keyNamesIsWritable = keyNamesMap.entrySet() .stream() - .filter(e -> (attrSet.contains(e.getKey()) && lwM2MClient.getOperation(e.getKey()).isWritable())) + .filter(e -> (attrSet.contains(e.getKey()) && context.getCtxServer().getResourceModel(new LwM2mPath(e.getKey())) != null && + context.getCtxServer().getResourceModel(new LwM2mPath(e.getKey())).operations.isWritable())) .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); namesIsIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values())); - keyNamesIsWritable.keySet().forEach(p -> namesIsIsWritable.add(lwM2MClient.getResourceName(p))); + keyNamesIsWritable.keySet().forEach(p -> namesIsIsWritable.add(this.getResourceName(p))); return new ArrayList<>(namesIsIsWritable); } @@ -501,7 +519,7 @@ public class LwM2MTransportService { LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); if (pathIds.isResource()) { if (path == null || path.contains(p.getAsString())) { - this.addParameters(p.getAsString().toString(), attributes, registration, "attributes"); + this.addParameters(p.getAsString().toString(), attributes, registration); } } }); @@ -510,7 +528,7 @@ public class LwM2MTransportService { LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); if (pathIds.isResource()) { if (path == null || path.contains(p.getAsString())) { - this.addParameters(p.getAsString().toString(), telemetry, registration, "telemetry"); + this.addParameters(p.getAsString().toString(), telemetry, registration); } } }); @@ -520,13 +538,15 @@ public class LwM2MTransportService { * @param parameters - JsonObject attributes/telemetry * @param registration - Registration LwM2M Client */ - private void addParameters(String path, JsonObject parameters, Registration registration, String nameParam) { - JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()).getPostKeyNameProfile(); + private void addParameters(String path, JsonObject parameters, Registration registration) { + LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()); + JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2MClient.getProfileUuid()).getPostKeyNameProfile(); String resName = String.valueOf(names.get(path)); if (resName != null && !resName.isEmpty()) { String resValue = null; try { - resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path); +// resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValueString(path); + resValue = this.getResourceValueToString(lwM2MClient, path); if (resValue != null) { // log.info("addParameters Path: [{}] ResValue : [{}] nameParam [{}]", path, lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path), nameParam); parameters.addProperty(resName, resValue); @@ -577,7 +597,7 @@ public class LwM2MTransportService { p.getAsString().toString() : null; if (target != null) { // #2 - if (lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(target) != null) { + if (this.getResourceValueToString(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()), target) != null) { lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, GET_TYPE_OPER_OBSERVE, null, null, null, null, this.context.getCtxServer().getTimeout(), false); @@ -635,7 +655,7 @@ public class LwM2MTransportService { * @param path - observe * @param response - observe */ - @SneakyThrows + public void onObservationResponse(Registration registration, String path, ReadResponse response) { if (response.getContent() != null) { if (response.getContent() instanceof LwM2mObject) { @@ -655,13 +675,8 @@ public class LwM2MTransportService { /** * Sending observe value of resources to thingsboard - * #1 Return old Resource from ModelObject - * #2 Create new Resource with value from observation - * #3 Create new Resources from old Resources - * #4 Update new Resources (replace old Resource on new Resource) - * #5 Remove old Instance from modelClient - * #6 Create new Instance with new Resources values - * #7 Update modelClient.getModelObjects(idObject) (replace old Instance on new Instance) + * #1 Return old Value Resource from LwM2MClient + * #2 Update new Resources (replace old Resource Value on new Resource Value) * * @param registration - Registration LwM2M Client * @param value - LwM2mSingleResource response.getContent() @@ -669,72 +684,38 @@ public class LwM2MTransportService { * @param path - resource */ private void onObservationSetResourcesValue(Registration registration, Object value, Map values, String path) { + CountDownLatch respLatch = new CountDownLatch(1); + boolean isChange = false; try { - CountDownLatch respLatch = new CountDownLatch(1); - try { - // #1 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); - LwM2mPath resultIds = new LwM2mPath(path); - log.warn("#0 nameDevice: [{}] resultIds: [{}] value: [{}], values: [{}] ", lwM2MClient.getDeviceName(), resultIds, value, values); - ResourceModel.Type resType = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).type; - Map instancesModelObject = (lwM2MClient.getModelObjects().get(resultIds.getObjectId()) != null) ? lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances() : null; - Map resourcesOld = null; - try { - CountDownLatch respResLatch = new CountDownLatch(1); - try { - resourcesOld = (instancesModelObject != null && - instancesModelObject.get(resultIds.getObjectInstanceId()) != null && - instancesModelObject.get(resultIds.getObjectInstanceId()).getResources() != null) ? instancesModelObject.get(resultIds.getObjectInstanceId()).getResources() : null; - - } finally { - respResLatch.countDown(); - } - try { - respResLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - ex.printStackTrace(); - log.error("#1_2 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); - } - } catch (Exception e) { - e.printStackTrace(); - log.error("#1_2_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); - } - LwM2mResource resourceOld = (resourcesOld != null && resourcesOld.get(resultIds.getResourceId()) != null) ? resourcesOld.get(resultIds.getResourceId()) : null; - // #2 - LwM2mResource resourceNew = null; - if ((resourceOld != null && resourceOld.isMultiInstances() && !resourceOld.getValues().equals(values)) || - (resourceOld == null && value == null)) { - resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resType); - } else if ((resourceOld != null && !resourceOld.isMultiInstances() && !resourceOld.getValue().equals(values)) || - (resourceOld == null && value != null)) { - resourceNew = LwM2mSingleResource.newResource(resultIds.getResourceId(), value, resType); - } - if (resourceNew != null) { - //#3 - Map resourcesNew = (resourcesOld == null) ? new HashMap<>() : new HashMap<>(resourcesOld); - // #4 - if ((resourceOld != null)) resourcesNew.remove(resourceOld); - // #5 - resourcesNew.put(resultIds.getResourceId(), resourceNew); - // #6 - LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.getObjectInstanceId(), resourcesNew.values()); - // #7 - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.getObjectInstanceId()); - instancesModelObject.put(resultIds.getObjectInstanceId(), instanceNew); - Set paths = new HashSet<>(); - paths.add(path); - this.updateAttrTelemetry(registration, false, paths); - } - } finally { - respLatch.countDown(); - } - try { - respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - ex.printStackTrace(); - log.error("#1_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); + // #1 + LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); + LwM2mPath pathIds = new LwM2mPath(path); + log.warn("#0 nameDevice: [{}] resultIds: [{}] value: [{}], values: [{}] ", lwM2MClient.getDeviceName(), pathIds, value, values); + ResourceModel.Type resModelType = context.getCtxServer().getResourceModelType(pathIds); + ResourceValue resValueOld = lwM2MClient.getResources().get(path); + // #2 + if (resValueOld.isMultiInstances() && !values.toString().equals(resValueOld.getResourceValue().toString())) { + ResourceValue resourceValue = new ResourceValue ( values, null, true); + lwM2MClient.getResources().put(path, resourceValue); + isChange = true; + } else if (!LwM2MTransportHandler.equalsResourceValue(resValueOld.getValue(), value, resModelType, pathIds)) { + ResourceValue resourceValue = new ResourceValue ( null, value, false); + lwM2MClient.getResources().put(path, resourceValue); + isChange = true; } - } catch (Exception ignored) { + } finally { + respLatch.countDown(); + } + try { + respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + ex.printStackTrace(); + log.error("#1_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); + } + if (isChange) { + Set paths = new HashSet<>(); + paths.add(path); + this.updateAttrTelemetry(registration, false, paths); } } @@ -762,19 +743,19 @@ public class LwM2MTransportService { String value = de.getValue().getAsString(); LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue(); AttrTelemetryObserveValue profile = lwM2mInMemorySecurityStore.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); + ResourceModel resourceModel = context.getCtxServer().getResourceModel(new LwM2mPath(path)); if (path != null && (this.validatePathInAttrProfile(profile, path) || this.validatePathInTelemetryProfile(profile, path))) { - if (lwM2MClient.getOperation(path).isWritable()) { + if (resourceModel != null && resourceModel.operations.isWritable()) { lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, ContentFormat.TLV.getName(), lwM2MClient, null, value, this.context.getCtxServer().getTimeout(), false); -// log.info("[{}] path onAttributeUpdate", path); } else { - log.error(LOG_LW2M_ERROR + ": Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); + log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); String logMsg = String.format(LOG_LW2M_ERROR + ": attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", path, value); this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); } } else { - log.error(LOG_LW2M_ERROR + ": Attribute name - [{}] value - [{}] is not present as attribute in profile and cannot be updated", de.getKey(), value); + log.error("Attribute name - [{}] value - [{}] is not present as attribute in profile and cannot be updated", de.getKey(), value); String logMsg = String.format(LOG_LW2M_ERROR + ": attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", de.getKey(), value); this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); } @@ -845,7 +826,8 @@ public class LwM2MTransportService { Predicate> predicateObj = (obj -> { return obj.getValue().getObjectModel().resources.entrySet().stream().filter(predicateRes).findFirst().isPresent(); }); - Map.Entry object = lwM2MClient.getModelObjects().entrySet().stream().filter(predicateObj).findFirst().get(); +// Map.Entry object = lwM2MClient.getModelObjects().entrySet().stream().filter(predicateObj).findFirst().get(); + Map.Entry object = null; ModelObject modelObject = object.getValue(); LwM2mObjectInstance instance = modelObject.getInstances().entrySet().stream().findFirst().get().getValue(); ResourceModel resource = modelObject.getObjectModel().resources.entrySet().stream().filter(predicateRes).findFirst().get().getValue(); @@ -867,7 +849,8 @@ public class LwM2MTransportService { // ResultIds resultIds = new ResultIds(path); LwM2mPath resultIds = new LwM2mPath(path); LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); - LwM2mResource resource = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances().get(resultIds.getObjectInstanceId()).getResource(resultIds.getResourceId()); +// LwM2mResource resource = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances().get(resultIds.getObjectInstanceId()).getResource(resultIds.getResourceId()); + LwM2mResource resource = null; if (resource.isMultiInstances()) { this.onObservationSetResourcesValue(registration, null, ((LwM2mSingleResource) request.getNode()).getValues(), path); } else { @@ -1080,8 +1063,9 @@ public class LwM2MTransportService { targets.forEach(target -> { // ResultIds pathIds = new ResultIds(target); LwM2mPath pathIds = new LwM2mPath(target); - if (pathIds.isResource() && lwM2MClient.getModelObjects().get(pathIds.getObjectId()) - .getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) { +// if (pathIds.isResource() && lwM2MClient.getModelObjects().get(pathIds.getObjectId()) +// .getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) { + if (pathIds.isResource()) { if (GET_TYPE_OPER_READ.equals(typeOper)) { lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout(), @@ -1098,32 +1082,17 @@ public class LwM2MTransportService { private void cancelObserveIsValue(LeshanServer lwServer, Registration registration, Set paramAnallyzer) { LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); paramAnallyzer.forEach(p -> { - if (this.getResourceValue(lwM2MClient, p) != null) { + if (this.getResourceValue(lwM2MClient, new LwM2mPath(p)) != null) { this.setCancelObservationRecourse(lwServer, registration, p); } } ); } - private ResourceValue getResourceValue(LwM2MClient lwM2MClient, String path) { + private ResourceValue getResourceValue(LwM2MClient lwM2MClient, LwM2mPath pathIds) { ResourceValue resourceValue = null; -// ResultIds pathIds = new ResultIds(path); - LwM2mPath pathIds = new LwM2mPath(path); if (pathIds.isResource()) { - LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()); - if (resource.isMultiInstances()) { - if (resource.getValues().size() > 0) { - resourceValue = new ResourceValue(); - resourceValue.setMultiInstances(resource.isMultiInstances()); - resourceValue.setValues(resource.getValues()); - } - } else { - if (resource.getValue() != null) { - resourceValue = new ResourceValue(); - resourceValue.setMultiInstances(resource.isMultiInstances()); - resourceValue.setValue(resource.getValue()); - } - } + resourceValue = lwM2MClient.getResources().get(pathIds.toString()); } return resourceValue; } @@ -1174,4 +1143,20 @@ public class LwM2MTransportService { } } + private String getResourceName(String path) { + LwM2mPath resultIds = new LwM2mPath(path); + return (context.getCtxServer().getObjectModels().get(resultIds.getObjectId()) != null) ? + context.getCtxServer().getObjectModels().get(resultIds.getObjectId()).resources.get(resultIds.getResourceId()).name : ""; + } + + /** + * @param path - path resource + * @return - value of Resource or null + */ + public String getResourceValueToString(LwM2MClient lwM2MClient, String path) { + LwM2mPath pathIds = new LwM2mPath(path); + ResourceValue resourceValue = this.getResourceValue(lwM2MClient, pathIds); + return (String) this.converter.convertValue(resourceValue.getResourceValue(), this.context.getCtxServer().getResourceModelType(pathIds), ResourceModel.Type.STRING, pathIds); + } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java index 4c0f314bc1..89ef741da9 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java @@ -18,12 +18,10 @@ package org.thingsboard.server.transport.lwm2m.server.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.model.ObjectModel; -import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mObjectInstance; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.response.LwM2mResponse; import org.eclipse.leshan.core.response.ReadResponse; -import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.SecurityInfo; @@ -38,8 +36,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; - @Slf4j @Data public class LwM2MClient implements Cloneable { @@ -56,7 +52,7 @@ public class LwM2MClient implements Cloneable { private Registration registration; private ValidateDeviceCredentialsResponseMsg credentialsResponse; private Map attributes; - private Map modelObjects; + private Map resources; private Set pendingRequests; private Map delayedRequests; private Set delayedRequestsId; @@ -67,15 +63,15 @@ public class LwM2MClient implements Cloneable { return super.clone(); } - public LwM2MClient(String endPoint, String identity, SecurityInfo info, ValidateDeviceCredentialsResponseMsg credentialsResponse, Map attributes, Map modelObjects, UUID profileUuid) { + public LwM2MClient(String endPoint, String identity, SecurityInfo info, ValidateDeviceCredentialsResponseMsg credentialsResponse, Map attributes, UUID profileUuid) { this.endPoint = endPoint; this.identity = identity; this.info = info; this.credentialsResponse = credentialsResponse; this.attributes = (attributes != null && attributes.size() > 0) ? attributes : new ConcurrentHashMap(); - this.modelObjects = (modelObjects != null && modelObjects.size() > 0) ? modelObjects : new ConcurrentHashMap(); this.pendingRequests = ConcurrentHashMap.newKeySet(); this.delayedRequests = new ConcurrentHashMap<>(); + this.resources = new ConcurrentHashMap<>(); this.delayedRequestsId = ConcurrentHashMap.newKeySet(); this.profileUuid = profileUuid; /** @@ -102,21 +98,29 @@ public class LwM2MClient implements Cloneable { private void initValue() { this.responses.forEach((key, resp) -> { - LwM2mPath pathIds = new LwM2mPath(key); + LwM2mPath pathIds = new LwM2mPath(key); if (pathIds.isObject() || pathIds.isObjectInstance() || pathIds.isResource()) { ObjectModel objectModel = this.lwServer.getModelProvider().getObjectModel(registration).getObjectModels().stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0); - if (this.modelObjects.get(pathIds.getObjectId()) != null) { - this.modelObjects.get(pathIds.getObjectId()).getInstances().put(((ReadResponse) resp).getContent().getId(), (LwM2mObjectInstance) ((ReadResponse) resp).getContent()); - } else { - Map instances = new ConcurrentHashMap<>(); - instances.put(((ReadResponse) resp).getContent().getId(), (LwM2mObjectInstance) ((ReadResponse) resp).getContent()); - ModelObject modelObject = new ModelObject(objectModel, instances); - this.modelObjects.put(pathIds.getObjectId(), modelObject); + if (objectModel != null) { + ((LwM2mObjectInstance)((ReadResponse)resp).getContent()).getResources().forEach((k, v) -> { + String rez = pathIds.toString() + "/" + k; + boolean ismulti = objectModel.resources.get(k).multiple; + if (objectModel.resources.get(k).multiple){ + this.resources.put(rez, new ResourceValue(v.getValues(), null, true)); + } + else { + this.resources.put(rez, new ResourceValue(null, v.getValue(), false)); + } + }); } } }); } + /** + * if path != null + * @param path + */ public void onSuccessOrErrorDelayedRequests(String path) { if (path != null) this.delayedRequests.remove(path); if (this.delayedRequests.size() == 0 && this.getDelayedRequestsId().size() == 0) { @@ -124,43 +128,5 @@ public class LwM2MClient implements Cloneable { } } - public ResourceModel.Operations getOperation(String path) { - LwM2mPath resultIds = new LwM2mPath(path); - return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? - this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).operations : - ResourceModel.Operations.NONE; - } - - public String getResourceName(String path) { - LwM2mPath resultIds = new LwM2mPath(path); - return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).name : ""; - } - - /** - * @param path - path resource - * @return - value of Resource or null - */ - public String getResourceValue(String path) { - String resValue = null; - LwM2mPath pathIds = new LwM2mPath(path); - ModelObject modelObject = this.getModelObjects().get(pathIds.getObjectId()); - - if (modelObject != null && modelObject.getInstances().get(pathIds.getObjectInstanceId()) != null) { - LwM2mObjectInstance instance = modelObject.getInstances().get(pathIds.getObjectInstanceId()); - if (instance.getResource(pathIds.getResourceId()) != null) { - try { - resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ? - Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() : - (instance.getResource(pathIds.getResourceId()).isMultiInstances()) ? - instance.getResource(pathIds.getResourceId()).getValues().toString() : -// getValueTypeToString(instance.getResource(pathIds.getResourceId()).getValue(), instance.getResource(pathIds.getResourceId()).getType()); - (String) converter.convertValue(instance.getResource(pathIds.getResourceId()).getValue(), instance.getResource(pathIds.getResourceId()).getType(), ResourceModel.Type.STRING, pathIds); - } catch (Exception e) { - log.warn("getResourceValue [{}]", e.getStackTrace().toString()); - } - } - } - return resValue; - } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java index 312973b9d0..d58890dfba 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java @@ -23,4 +23,14 @@ public class ResourceValue { Map values; Object value; boolean multiInstances; + + public ResourceValue ( Map values, Object value, boolean multiInstances) { + this.values = values; + this.value = value; + this.multiInstances = multiInstances; + } + public Object getResourceValue() { + return this.multiInstances ? this.values : this.value; + } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java index 07294bccfe..216136be8b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java @@ -179,11 +179,13 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { if (store.getSecurityInfo() != null) { if (store.getSecurityMode() < DEFAULT_MODE.code) { String endpoint = store.getSecurityInfo().getEndpoint(); - sessions.put(endpoint, new LwM2MClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), null, null, profileUuid)); +// sessions.put(endpoint, new LwM2MClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), null, null, profileUuid)); + sessions.put(endpoint, new LwM2MClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), null, profileUuid)); } } else { if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) - sessions.put(identity, new LwM2MClient(identity, null, null, store.getMsg(), null, null, profileUuid)); +// sessions.put(identity, new LwM2MClient(identity, null, null, store.getMsg(), null, null, profileUuid)); + sessions.put(identity, new LwM2MClient(identity, null, null, store.getMsg(), null, profileUuid)); else { log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity); /** diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index d7cae734a2..44fcfad9b6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -26,6 +26,8 @@ import org.eclipse.leshan.core.util.StringUtils; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Date; @Slf4j @@ -120,6 +122,12 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { case INTEGER: case FLOAT: return String.valueOf(value); + case TIME: +// return Long.toString(((Date) value).getTime()); + String DATE_FORMAT = "MMM d, yyyy HH:mm a"; + Long timeValue = ((Date) value).getTime(); + DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); + return formatter.format(new Date(timeValue)); default: break; } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java index d8f305a049..89c1600bf5 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java @@ -20,6 +20,8 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.model.ObjectLoader; import org.eclipse.leshan.core.model.ObjectModel; +import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.core.node.LwM2mPath; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; @@ -33,6 +35,8 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component @@ -173,6 +177,10 @@ public class LwM2MTransportConfigServer { @Value("${transport.lwm2m.secure.redis_url:}") private String redisUrl; + @Getter + @Setter + private Map objectModels; + @PostConstruct public void init() { modelsValue = ObjectLoader.loadDefault(); @@ -188,6 +196,7 @@ public class LwM2MTransportConfigServer { log.error(" [{}] Read Models", path.getAbsoluteFile()); } getInKeyStore(); + this.objectModels = new ConcurrentHashMap(); } private File getPathModels() { @@ -238,4 +247,22 @@ public class LwM2MTransportConfigServer { } return FULL_FILE_PATH.toUri().getPath(); } + + public ResourceModel getResourceModel(LwM2mPath pathIds) { + return (this.objectModels.size()>0 && + this.objectModels.containsKey(pathIds.getObjectId()) && + this.objectModels.get(pathIds.getObjectId()).resources.containsKey(pathIds.getResourceId())) ? + this.objectModels.get(pathIds.getObjectId()).resources.get(pathIds.getResourceId()) : null; + } + + public ResourceModel.Type getResourceModelType(LwM2mPath pathIds) { + ResourceModel resource = this.getResourceModel(pathIds); + return (resource == null) ? null : resource.type; + } + + public ResourceModel.Operations getOperation(LwM2mPath pathIds) { + ResourceModel resource = this.getResourceModel(pathIds); + return (resource == null) ? ResourceModel.Operations.NONE : resource.operations; + } + }