Commit 201476f912e317ce7d7c466c0bffec72189611bb

Authored by nickAS21
Committed by Andrew Shvayka
1 parent 3420eeb9

lwm2m: add objectKeyId to back and front profile

Showing 26 changed files with 458 additions and 140 deletions
@@ -27,11 +27,14 @@ import org.thingsboard.server.common.data.Resource; @@ -27,11 +27,14 @@ import org.thingsboard.server.common.data.Resource;
27 import org.thingsboard.server.common.data.ResourceType; 27 import org.thingsboard.server.common.data.ResourceType;
28 import org.thingsboard.server.common.data.exception.ThingsboardException; 28 import org.thingsboard.server.common.data.exception.ThingsboardException;
29 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
  30 +import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
30 import org.thingsboard.server.common.data.page.PageData; 31 import org.thingsboard.server.common.data.page.PageData;
31 import org.thingsboard.server.common.data.page.PageLink; 32 import org.thingsboard.server.common.data.page.PageLink;
32 import org.thingsboard.server.dao.resource.ResourceService; 33 import org.thingsboard.server.dao.resource.ResourceService;
33 import org.thingsboard.server.queue.util.TbCoreComponent; 34 import org.thingsboard.server.queue.util.TbCoreComponent;
34 35
  36 +import java.util.List;
  37 +
35 @Slf4j 38 @Slf4j
36 @RestController 39 @RestController
37 @TbCoreComponent 40 @TbCoreComponent
@@ -59,21 +62,55 @@ public class ResourceController extends BaseController { @@ -59,21 +62,55 @@ public class ResourceController extends BaseController {
59 } 62 }
60 63
61 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 64 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
62 - @RequestMapping(value = "/resource", method = RequestMethod.GET) 65 + @RequestMapping(value = "/resource/page", method = RequestMethod.GET)
63 @ResponseBody 66 @ResponseBody
64 public PageData<Resource> getResources(@RequestParam(required = false) boolean system, 67 public PageData<Resource> getResources(@RequestParam(required = false) boolean system,
65 @RequestParam int pageSize, 68 @RequestParam int pageSize,
66 @RequestParam int page, 69 @RequestParam int page,
  70 + @RequestParam(required = false) String textSearch,
67 @RequestParam(required = false) String sortProperty, 71 @RequestParam(required = false) String sortProperty,
68 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 72 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
69 try { 73 try {
70 - PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder); 74 +// int[] objectIds;
  75 +// ResourceType resourceType
  76 + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
71 return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink)); 77 return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink));
72 } catch (Exception e) { 78 } catch (Exception e) {
73 throw handleException(e); 79 throw handleException(e);
74 } 80 }
75 } 81 }
76 82
  83 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
  84 + @RequestMapping(value = "/resource/lwm2m/page", method = RequestMethod.GET)
  85 + @ResponseBody
  86 + public List<LwM2mObject> getLwm2mListObjectsPage(@RequestParam int pageSize,
  87 + @RequestParam int page,
  88 + @RequestParam(required = false) String textSearch,
  89 + @RequestParam(required = false) String sortProperty,
  90 + @RequestParam(required = false) String sortOrder) throws ThingsboardException {
  91 + try {
  92 + PageLink pageLink = new PageLink(pageSize, page, textSearch);
  93 + return checkNotNull(resourceService.findLwM2mObjectPage(getTenantId(), sortProperty, sortOrder, pageLink));
  94 + } catch (Exception e) {
  95 + throw handleException(e);
  96 + }
  97 + }
  98 +
  99 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
  100 + @RequestMapping(value = "/resource/lwm2m", method = RequestMethod.GET)
  101 + @ResponseBody
  102 + public List<LwM2mObject> getLwm2mListObjects(@RequestParam String sortOrder,
  103 + @RequestParam String sortProperty,
  104 + @RequestParam(required = false) String[] objectIds,
  105 + @RequestParam(required = false) String searchText)
  106 + throws ThingsboardException {
  107 + try {
  108 + return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds, searchText));
  109 + } catch (Exception e) {
  110 + throw handleException(e);
  111 + }
  112 + }
  113 +
77 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 114 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
78 @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE) 115 @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE)
79 @ResponseBody 116 @ResponseBody
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData;
37 import org.thingsboard.server.common.data.widget.WidgetType; 37 import org.thingsboard.server.common.data.widget.WidgetType;
38 import org.thingsboard.server.common.data.widget.WidgetsBundle; 38 import org.thingsboard.server.common.data.widget.WidgetsBundle;
39 import org.thingsboard.server.dao.dashboard.DashboardService; 39 import org.thingsboard.server.dao.dashboard.DashboardService;
  40 +import org.thingsboard.server.dao.exception.DataValidationException;
40 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; 41 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
41 import org.thingsboard.server.dao.resource.ResourceService; 42 import org.thingsboard.server.dao.resource.ResourceService;
42 import org.thingsboard.server.dao.rule.RuleChainService; 43 import org.thingsboard.server.dao.rule.RuleChainService;
@@ -202,7 +203,6 @@ public class InstallScripts { @@ -202,7 +203,6 @@ public class InstallScripts {
202 } 203 }
203 204
204 public void loadSystemLwm2mResources() throws Exception { 205 public void loadSystemLwm2mResources() throws Exception {
205 -// Path modelsDir = Paths.get("/home/nick/Igor_project/thingsboard_ce_3_2_docker/thingsboard/common/transport/lwm2m/src/main/resources/models/");  
206 Path modelsDir = Paths.get(getDataDir(), MODELS_DIR); 206 Path modelsDir = Paths.get(getDataDir(), MODELS_DIR);
207 if (Files.isDirectory(modelsDir)) { 207 if (Files.isDirectory(modelsDir)) {
208 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) { 208 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) {
@@ -210,18 +210,16 @@ public class InstallScripts { @@ -210,18 +210,16 @@ public class InstallScripts {
210 path -> { 210 path -> {
211 try { 211 try {
212 byte[] fileBytes = Files.readAllBytes(path); 212 byte[] fileBytes = Files.readAllBytes(path);
213 - String key = getObjectModelLwm2mValid(fileBytes, path.getFileName().toString(), new DefaultDDFFileValidator());  
214 - if (key != null) {  
215 - Resource resource = new Resource();  
216 - resource.setTenantId(TenantId.SYS_TENANT_ID);  
217 - resource.setResourceType(ResourceType.LWM2M_MODEL);  
218 - resource.setResourceId(key);  
219 - resource.setValue(Base64.getEncoder().encodeToString(fileBytes));  
220 - resourceService.saveResource(resource);  
221 - } 213 + String source = new String(fileBytes);
  214 + Resource resource = new Resource();
  215 + resource.setTenantId(TenantId.SYS_TENANT_ID);
  216 + resource.setResourceType(ResourceType.LWM2M_MODEL);
  217 + resource.setResourceId(getValueByTeg(source, "ObjectID") + "_" + getValueByTeg(source, "ObjectVersion"));
  218 + resource.setTextSearch(resource.getResourceId() + ":" + getValueByTeg(source, "Name"));
  219 + resource.setValue(Base64.getEncoder().encodeToString(fileBytes));
  220 + resourceService.saveResource(resource);
222 } catch (Exception e) { 221 } catch (Exception e) {
223 - log.error("Unable to load lwm2m model [{}]", path.toString());  
224 - throw new RuntimeException("Unable to load lwm2m model", e); 222 + throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", path.toString()));
225 } 223 }
226 } 224 }
227 ); 225 );
@@ -234,6 +232,7 @@ public class InstallScripts { @@ -234,6 +232,7 @@ public class InstallScripts {
234 resource.setTenantId(TenantId.SYS_TENANT_ID); 232 resource.setTenantId(TenantId.SYS_TENANT_ID);
235 resource.setResourceType(ResourceType.JKS); 233 resource.setResourceType(ResourceType.JKS);
236 resource.setResourceId(jksPath.getFileName().toString()); 234 resource.setResourceId(jksPath.getFileName().toString());
  235 + resource.setTextSearch(jksPath.getFileName().toString());
237 resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); 236 resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath)));
238 resourceService.saveResource(resource); 237 resourceService.saveResource(resource);
239 } catch (Exception e) { 238 } catch (Exception e) {
@@ -242,11 +241,18 @@ public class InstallScripts { @@ -242,11 +241,18 @@ public class InstallScripts {
242 } 241 }
243 } 242 }
244 243
245 - private String getObjectModelLwm2mValid(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) { 244 + private String getValueByTeg(String source, String tagHtml) {
  245 + int lenTag = ("<" + tagHtml + ">").length();
  246 + int indStart = source.indexOf("<" + tagHtml + ">");
  247 + int indEnd = source.indexOf("</" + tagHtml + ">");
  248 + return (indStart > 0 && indEnd > 0) ? source.substring(indStart + lenTag, indEnd) : null;
  249 +
  250 + }
  251 +
  252 + private ObjectModel getObjectModelLwm2mValid(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) {
246 try { 253 try {
247 DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator); 254 DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator);
248 - ObjectModel objectModel = ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0);  
249 - return objectModel.id + "##" + objectModel.getVersion(); 255 + return ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0);
250 } catch (IOException | InvalidDDFFileException e) { 256 } catch (IOException | InvalidDDFFileException e) {
251 log.error("Could not parse the XML file [{}]", streamName, e); 257 log.error("Could not parse the XML file [{}]", streamName, e);
252 return null; 258 return null;
@@ -442,6 +442,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService @@ -442,6 +442,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
442 " tenant_id uuid NOT NULL," + 442 " tenant_id uuid NOT NULL," +
443 " resource_type varchar(32) NOT NULL," + 443 " resource_type varchar(32) NOT NULL," +
444 " resource_id varchar(255) NOT NULL," + 444 " resource_id varchar(255) NOT NULL," +
  445 + " text_search varchar(255)," +
445 " resource_value varchar," + 446 " resource_value varchar," +
446 " CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)" + 447 " CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)" +
447 " );"); 448 " );");
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.resource; @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.resource;
18 import org.thingsboard.server.common.data.Resource; 18 import org.thingsboard.server.common.data.Resource;
19 import org.thingsboard.server.common.data.ResourceType; 19 import org.thingsboard.server.common.data.ResourceType;
20 import org.thingsboard.server.common.data.id.TenantId; 20 import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
21 import org.thingsboard.server.common.data.page.PageData; 22 import org.thingsboard.server.common.data.page.PageData;
22 import org.thingsboard.server.common.data.page.PageLink; 23 import org.thingsboard.server.common.data.page.PageLink;
23 24
@@ -31,7 +32,18 @@ public interface ResourceService { @@ -31,7 +32,18 @@ public interface ResourceService {
31 32
32 PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink); 33 PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink);
33 34
34 - List<Resource> findResourcesByTenantIdResourceType(TenantId tenantId, ResourceType resourceType); 35 + List<LwM2mObject> findLwM2mObject(TenantId tenantId,
  36 + String sortOrder,
  37 + String sortProperty,
  38 + String[] objectIds,
  39 + String searchText);
  40 +
  41 + List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId,
  42 + String sortProperty,
  43 + String sortOrder,
  44 + PageLink pageLink);
  45 +
  46 + List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType);
35 47
36 void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); 48 void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId);
37 49
@@ -79,6 +79,10 @@ @@ -79,6 +79,10 @@
79 <groupId>org.thingsboard</groupId> 79 <groupId>org.thingsboard</groupId>
80 <artifactId>protobuf-dynamic</artifactId> 80 <artifactId>protobuf-dynamic</artifactId>
81 </dependency> 81 </dependency>
  82 + <dependency>
  83 + <groupId>org.eclipse.leshan</groupId>
  84 + <artifactId>leshan-core</artifactId>
  85 + </dependency>
82 </dependencies> 86 </dependencies>
83 87
84 <build> 88 <build>
@@ -16,10 +16,24 @@ @@ -16,10 +16,24 @@
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
18 import lombok.Data; 18 import lombok.Data;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.eclipse.leshan.core.model.DDFFileParser;
  21 +import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
  22 +import org.eclipse.leshan.core.model.InvalidDDFFileException;
  23 +import org.eclipse.leshan.core.model.ObjectModel;
19 import org.thingsboard.server.common.data.id.TenantId; 24 import org.thingsboard.server.common.data.id.TenantId;
  25 +import org.thingsboard.server.common.data.lwm2m.LwM2mInstance;
  26 +import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
  27 +import org.thingsboard.server.common.data.lwm2m.LwM2mResource;
20 28
  29 +import java.io.ByteArrayInputStream;
  30 +import java.io.IOException;
21 import java.io.Serializable; 31 import java.io.Serializable;
  32 +import java.util.ArrayList;
  33 +import java.util.Base64;
  34 +import java.util.List;
22 35
  36 +@Slf4j
23 @Data 37 @Data
24 public class Resource implements HasTenantId, Serializable { 38 public class Resource implements HasTenantId, Serializable {
25 39
@@ -28,14 +42,51 @@ public class Resource implements HasTenantId, Serializable { @@ -28,14 +42,51 @@ public class Resource implements HasTenantId, Serializable {
28 private TenantId tenantId; 42 private TenantId tenantId;
29 private ResourceType resourceType; 43 private ResourceType resourceType;
30 private String resourceId; 44 private String resourceId;
  45 + private String textSearch;
31 private String value; 46 private String value;
32 47
33 @Override 48 @Override
34 public String toString() { 49 public String toString() {
35 - return "Resource{" +  
36 - "tenantId=" + tenantId +  
37 - ", resourceType=" + resourceType +  
38 - ", resourceId='" + resourceId + '\'' +  
39 - '}'; 50 + final StringBuilder res = new StringBuilder("Resource{");
  51 + res.append("tenantId=").append(tenantId);
  52 + res.append(", resourceType='").append(resourceType).append('\'');
  53 + res.append(", resourceId='").append(resourceId).append('\'');
  54 + res.append(", textSearch='").append(textSearch).append('\'');
  55 + res.append('}');
  56 + return res.toString();
  57 + }
  58 +
  59 + public LwM2mObject toLwM2mObject () {
  60 + try {
  61 + DDFFileParser ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator());
  62 + List<ObjectModel> objectModels = ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(this.value)), this.textSearch);
  63 + if (objectModels.size() == 0) {
  64 + return null;
  65 + }
  66 + else {
  67 + ObjectModel obj = objectModels.get(0);
  68 + LwM2mObject lwM2mObject = new LwM2mObject();
  69 + lwM2mObject.setId(obj.id);
  70 + lwM2mObject.setKeyId(this.resourceId);
  71 + lwM2mObject.setName(obj.name);
  72 + lwM2mObject.setMultiple(obj.multiple);
  73 + lwM2mObject.setMandatory(obj.mandatory);
  74 + LwM2mInstance instance = new LwM2mInstance();
  75 + instance.setId(0);
  76 + List<LwM2mResource> resources = new ArrayList<>();
  77 + obj.resources.forEach((k, v) -> {
  78 + if (!v.operations.isExecutable()) {
  79 + LwM2mResource resource = new LwM2mResource(k, v.name, false, false, false);
  80 + resources.add(resource);
  81 + }
  82 + });
  83 + instance.setResources(resources.stream().toArray(LwM2mResource[]::new));
  84 + lwM2mObject.setInstances(new LwM2mInstance[]{instance});
  85 + return lwM2mObject;
  86 + }
  87 + } catch (IOException | InvalidDDFFileException e) {
  88 + log.error("Could not parse the XML of objectModel with name [{}]", this.textSearch, e);
  89 + return null;
  90 + }
40 } 91 }
41 } 92 }
@@ -20,6 +20,7 @@ import lombok.Data; @@ -20,6 +20,7 @@ import lombok.Data;
20 @Data 20 @Data
21 public class LwM2mObject { 21 public class LwM2mObject {
22 int id; 22 int id;
  23 + String keyId;
23 String name; 24 String name;
24 boolean multiple; 25 boolean multiple;
25 boolean mandatory; 26 boolean mandatory;
@@ -214,6 +214,10 @@ @@ -214,6 +214,10 @@
214 <groupId>org.elasticsearch.client</groupId> 214 <groupId>org.elasticsearch.client</groupId>
215 <artifactId>rest</artifactId> 215 <artifactId>rest</artifactId>
216 </dependency> 216 </dependency>
  217 + <dependency>
  218 + <groupId>org.eclipse.leshan</groupId>
  219 + <artifactId>leshan-core</artifactId>
  220 + </dependency>
217 </dependencies> 221 </dependencies>
218 <build> 222 <build>
219 <plugins> 223 <plugins>
@@ -460,8 +460,10 @@ public class ModelConstants { @@ -460,8 +460,10 @@ public class ModelConstants {
460 public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN; 460 public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
461 public static final String RESOURCE_TYPE_COLUMN = "resource_type"; 461 public static final String RESOURCE_TYPE_COLUMN = "resource_type";
462 public static final String RESOURCE_ID_COLUMN = "resource_id"; 462 public static final String RESOURCE_ID_COLUMN = "resource_id";
  463 + public static final String TEXT_SEARCH_COLUMN = "text_search";
463 public static final String RESOURCE_VALUE_COLUMN = "resource_value"; 464 public static final String RESOURCE_VALUE_COLUMN = "resource_value";
464 465
  466 +
465 /** 467 /**
466 * Cassandra attributes and timeseries constants. 468 * Cassandra attributes and timeseries constants.
467 */ 469 */
@@ -33,6 +33,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAM @@ -33,6 +33,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAM
33 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN; 33 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN;
34 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TYPE_COLUMN; 34 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TYPE_COLUMN;
35 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_VALUE_COLUMN; 35 import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_VALUE_COLUMN;
  36 +import static org.thingsboard.server.dao.model.ModelConstants.TEXT_SEARCH_COLUMN;
36 37
37 @Data 38 @Data
38 @Entity 39 @Entity
@@ -52,6 +53,9 @@ public class ResourceEntity implements ToData<Resource> { @@ -52,6 +53,9 @@ public class ResourceEntity implements ToData<Resource> {
52 @Column(name = RESOURCE_ID_COLUMN) 53 @Column(name = RESOURCE_ID_COLUMN)
53 private String resourceId; 54 private String resourceId;
54 55
  56 + @Column(name = TEXT_SEARCH_COLUMN)
  57 + private String textSearch;
  58 +
55 @Column(name = RESOURCE_VALUE_COLUMN) 59 @Column(name = RESOURCE_VALUE_COLUMN)
56 private String value; 60 private String value;
57 61
@@ -62,6 +66,7 @@ public class ResourceEntity implements ToData<Resource> { @@ -62,6 +66,7 @@ public class ResourceEntity implements ToData<Resource> {
62 this.tenantId = resource.getTenantId().getId(); 66 this.tenantId = resource.getTenantId().getId();
63 this.resourceType = resource.getResourceType().name(); 67 this.resourceType = resource.getResourceType().name();
64 this.resourceId = resource.getResourceId(); 68 this.resourceId = resource.getResourceId();
  69 + this.textSearch = resource.getTextSearch();
65 this.value = resource.getValue(); 70 this.value = resource.getValue();
66 } 71 }
67 72
@@ -71,6 +76,7 @@ public class ResourceEntity implements ToData<Resource> { @@ -71,6 +76,7 @@ public class ResourceEntity implements ToData<Resource> {
71 resource.setTenantId(new TenantId(tenantId)); 76 resource.setTenantId(new TenantId(tenantId));
72 resource.setResourceType(ResourceType.valueOf(resourceType)); 77 resource.setResourceType(ResourceType.valueOf(resourceType));
73 resource.setResourceId(resourceId); 78 resource.setResourceId(resourceId);
  79 + resource.setTextSearch(textSearch);
74 resource.setValue(value); 80 resource.setValue(value);
75 return resource; 81 return resource;
76 } 82 }
@@ -16,15 +16,28 @@ @@ -16,15 +16,28 @@
16 package org.thingsboard.server.dao.resource; 16 package org.thingsboard.server.dao.resource;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.leshan.core.model.DDFFileParser;
  20 +import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
  21 +import org.eclipse.leshan.core.model.InvalidDDFFileException;
  22 +import org.eclipse.leshan.core.model.ObjectModel;
19 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
20 import org.thingsboard.server.common.data.Resource; 24 import org.thingsboard.server.common.data.Resource;
21 import org.thingsboard.server.common.data.ResourceType; 25 import org.thingsboard.server.common.data.ResourceType;
22 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.data.lwm2m.LwM2mInstance;
  28 +import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
  29 +import org.thingsboard.server.common.data.lwm2m.LwM2mResource;
23 import org.thingsboard.server.common.data.page.PageData; 30 import org.thingsboard.server.common.data.page.PageData;
24 import org.thingsboard.server.common.data.page.PageLink; 31 import org.thingsboard.server.common.data.page.PageLink;
25 import org.thingsboard.server.dao.exception.DataValidationException; 32 import org.thingsboard.server.dao.exception.DataValidationException;
26 33
  34 +import java.io.ByteArrayInputStream;
  35 +import java.io.IOException;
  36 +import java.util.ArrayList;
  37 +import java.util.Base64;
  38 +import java.util.Comparator;
27 import java.util.List; 39 import java.util.List;
  40 +import java.util.stream.Collectors;
28 41
29 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; 42 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID;
30 import static org.thingsboard.server.dao.service.Validator.validateId; 43 import static org.thingsboard.server.dao.service.Validator.validateId;
@@ -69,10 +82,35 @@ public class BaseResourceService implements ResourceService { @@ -69,10 +82,35 @@ public class BaseResourceService implements ResourceService {
69 82
70 83
71 @Override 84 @Override
72 - public List<Resource> findResourcesByTenantIdResourceType(TenantId tenantId, ResourceType resourceType) { 85 + public List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType) {
73 log.trace("Executing findByTenantId [{}]", tenantId); 86 log.trace("Executing findByTenantId [{}]", tenantId);
74 validateId(tenantId, INCORRECT_TENANT_ID + tenantId); 87 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
75 - return resourceDao.findAllByTenantIdResourceType(tenantId, resourceType); 88 + return resourceDao.findAllByTenantIdAndResourceType(tenantId, resourceType);
  89 + }
  90 +
  91 + @Override
  92 + public List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId, String sortProperty, String sortOrder, PageLink pageLink) {
  93 + log.trace("Executing findByTenantId [{}]", tenantId);
  94 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  95 + PageData<Resource> resourcePageData = resourceDao.findResourcesByTenantIdAndResourceType(
  96 + tenantId,
  97 + ResourceType.LWM2M_MODEL, pageLink);
  98 + List<LwM2mObject> lwM2mObjects = resourcePageData.getData().stream().map(this::toLwM2mObject).collect(Collectors.toList());
  99 + return lwM2mObjects.size() > 1 ? this.sortList (lwM2mObjects, sortProperty, sortOrder) : lwM2mObjects;
  100 + }
  101 +
  102 + @Override
  103 + public List<LwM2mObject> findLwM2mObject(TenantId tenantId, String sortOrder,
  104 + String sortProperty,
  105 + String[] objectIds,
  106 + String searchText) {
  107 + log.trace("Executing findByTenantId [{}]", tenantId);
  108 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  109 + List<Resource> resources = resourceDao.findResourcesByTenantIdAndResourceType(tenantId, ResourceType.LWM2M_MODEL,
  110 + objectIds,
  111 + searchText);
  112 + List<LwM2mObject> lwM2mObjects = resources.stream().map(this::toLwM2mObject).collect(Collectors.toList());
  113 + return lwM2mObjects.size() > 1 ? this.sortList (lwM2mObjects, sortProperty, sortOrder) : lwM2mObjects;
76 } 114 }
77 115
78 @Override 116 @Override
@@ -86,11 +124,13 @@ public class BaseResourceService implements ResourceService { @@ -86,11 +124,13 @@ public class BaseResourceService implements ResourceService {
86 if (resource == null) { 124 if (resource == null) {
87 throw new DataValidationException("Resource should be specified!"); 125 throw new DataValidationException("Resource should be specified!");
88 } 126 }
89 -  
90 if (resource.getValue() == null) { 127 if (resource.getValue() == null) {
91 throw new DataValidationException("Resource value should be specified!"); 128 throw new DataValidationException("Resource value should be specified!");
92 } 129 }
93 validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId()); 130 validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId());
  131 + if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && resource.toLwM2mObject() == null) {
  132 + throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getTextSearch()));
  133 + }
94 } 134 }
95 135
96 protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) { 136 protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) {
@@ -103,4 +143,61 @@ public class BaseResourceService implements ResourceService { @@ -103,4 +143,61 @@ public class BaseResourceService implements ResourceService {
103 validateId(tenantId, "Incorrect tenantId "); 143 validateId(tenantId, "Incorrect tenantId ");
104 } 144 }
105 145
  146 + private LwM2mObject toLwM2mObject(Resource resource) {
  147 + try {
  148 + DDFFileParser ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator());
  149 + List<ObjectModel> objectModels =
  150 + ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getValue())), resource.getTextSearch());
  151 + if (objectModels.size() == 0) {
  152 + return null;
  153 + } else {
  154 + ObjectModel obj = objectModels.get(0);
  155 + LwM2mObject lwM2mObject = new LwM2mObject();
  156 + lwM2mObject.setId(obj.id);
  157 + lwM2mObject.setKeyId(resource.getResourceId());
  158 + lwM2mObject.setName(obj.name);
  159 + lwM2mObject.setMultiple(obj.multiple);
  160 + lwM2mObject.setMandatory(obj.mandatory);
  161 + LwM2mInstance instance = new LwM2mInstance();
  162 + instance.setId(0);
  163 + List<LwM2mResource> resources = new ArrayList<>();
  164 + obj.resources.forEach((k, v) -> {
  165 + if (!v.operations.isExecutable()) {
  166 + LwM2mResource lwM2mResource = new LwM2mResource(k, v.name, false, false, false);
  167 + resources.add(lwM2mResource);
  168 + }
  169 + });
  170 + instance.setResources(resources.stream().toArray(LwM2mResource[]::new));
  171 + lwM2mObject.setInstances(new LwM2mInstance[]{instance});
  172 + return lwM2mObject;
  173 + }
  174 + } catch (IOException | InvalidDDFFileException e) {
  175 + log.error("Could not parse the XML of objectModel with name [{}]", resource.getTextSearch(), e);
  176 + return null;
  177 + }
  178 + }
  179 +
  180 + private List<LwM2mObject> sortList (List<LwM2mObject> lwM2mObjects, String sortProperty, String sortOrder) {
  181 + switch (sortProperty) {
  182 + case "name":
  183 + switch (sortOrder) {
  184 + case "ASC":
  185 + lwM2mObjects.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
  186 + break;
  187 + case "DESC":
  188 + lwM2mObjects.stream().sorted(Comparator.comparing(LwM2mObject::getName).reversed());
  189 + break;
  190 + }
  191 + case "id":
  192 + switch (sortOrder) {
  193 + case "ASC":
  194 + lwM2mObjects.sort((o1, o2) -> Long.compare(o1.getId(), o2.getId()));
  195 + break;
  196 + case "DESC":
  197 + lwM2mObjects.sort((o1, o2) -> Long.compare(o2.getId(), o1.getId()));
  198 + }
  199 + }
  200 + return lwM2mObjects;
  201 + }
  202 +
106 } 203 }
@@ -33,8 +33,15 @@ public interface ResourceDao { @@ -33,8 +33,15 @@ public interface ResourceDao {
33 33
34 PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink); 34 PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink);
35 35
  36 + PageData<Resource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
  37 + ResourceType resourceType,
  38 + PageLink pageLink);
36 39
37 - List<Resource> findAllByTenantIdResourceType(TenantId tenantId, ResourceType resourceType); 40 + List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType);
38 41
  42 + List<Resource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
  43 + ResourceType resourceType,
  44 + String[] objectIds,
  45 + String searchText);
39 void removeAllByTenantId(TenantId tenantId); 46 void removeAllByTenantId(TenantId tenantId);
40 } 47 }
@@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.ResourceEntity; @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.ResourceEntity;
29 import org.thingsboard.server.dao.resource.ResourceDao; 29 import org.thingsboard.server.dao.resource.ResourceDao;
30 30
31 import java.util.List; 31 import java.util.List;
  32 +import java.util.Objects;
32 33
33 @Slf4j 34 @Slf4j
34 @Component 35 @Component
@@ -73,11 +74,40 @@ public class ResourceDaoImpl implements ResourceDao { @@ -73,11 +74,40 @@ public class ResourceDaoImpl implements ResourceDao {
73 } 74 }
74 75
75 @Override 76 @Override
76 - public List<Resource> findAllByTenantIdResourceType(TenantId tenantId, ResourceType resourceType) { 77 + public List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType) {
77 return DaoUtil.convertDataList(resourceRepository.findAllByTenantIdAndResourceType(tenantId.getId(), resourceType.name())); 78 return DaoUtil.convertDataList(resourceRepository.findAllByTenantIdAndResourceType(tenantId.getId(), resourceType.name()));
78 } 79 }
79 80
80 @Override 81 @Override
  82 + public PageData<Resource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
  83 + ResourceType resourceType,
  84 + PageLink pageLink) {
  85 + return DaoUtil.toPageData(resourceRepository.findResourcesPage(
  86 + tenantId.getId(),
  87 + TenantId.SYS_TENANT_ID.getId(),
  88 + resourceType.name(),
  89 + Objects.toString(pageLink.getTextSearch(), ""),
  90 + DaoUtil.toPageable(pageLink)
  91 + ));
  92 + }
  93 +
  94 + @Override
  95 + public List<Resource> findResourcesByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType,
  96 + String[] objectIds,
  97 + String searchText) {
  98 + return objectIds == null ?
  99 + DaoUtil.convertDataList(resourceRepository.findResources(
  100 + tenantId.getId(),
  101 + TenantId.SYS_TENANT_ID.getId(),
  102 + resourceType.name(),
  103 + Objects.toString(searchText, ""))) :
  104 + DaoUtil.convertDataList(resourceRepository.findResourcesByIds(
  105 + tenantId.getId(),
  106 + TenantId.SYS_TENANT_ID.getId(),
  107 + resourceType.name(), objectIds));
  108 + }
  109 +
  110 + @Override
81 public void removeAllByTenantId(TenantId tenantId) { 111 public void removeAllByTenantId(TenantId tenantId) {
82 resourceRepository.removeAllByTenantId(tenantId.getId()); 112 resourceRepository.removeAllByTenantId(tenantId.getId());
83 } 113 }
@@ -17,7 +17,9 @@ package org.thingsboard.server.dao.sql.resource; @@ -17,7 +17,9 @@ package org.thingsboard.server.dao.sql.resource;
17 17
18 import org.springframework.data.domain.Page; 18 import org.springframework.data.domain.Page;
19 import org.springframework.data.domain.Pageable; 19 import org.springframework.data.domain.Pageable;
  20 +import org.springframework.data.jpa.repository.Query;
20 import org.springframework.data.repository.CrudRepository; 21 import org.springframework.data.repository.CrudRepository;
  22 +import org.springframework.data.repository.query.Param;
21 import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; 23 import org.thingsboard.server.dao.model.sql.ResourceCompositeKey;
22 import org.thingsboard.server.dao.model.sql.ResourceEntity; 24 import org.thingsboard.server.dao.model.sql.ResourceEntity;
23 25
@@ -26,10 +28,57 @@ import java.util.UUID; @@ -26,10 +28,57 @@ import java.util.UUID;
26 28
27 public interface ResourceRepository extends CrudRepository<ResourceEntity, ResourceCompositeKey> { 29 public interface ResourceRepository extends CrudRepository<ResourceEntity, ResourceCompositeKey> {
28 30
  31 +
29 Page<ResourceEntity> findAllByTenantId(UUID tenantId, Pageable pageable); 32 Page<ResourceEntity> findAllByTenantId(UUID tenantId, Pageable pageable);
30 33
  34 + @Query("SELECT tr FROM ResourceEntity tr " +
  35 + "WHERE tr.resourceType = :resourceType " +
  36 + "AND LOWER(tr.textSearch) LIKE LOWER(CONCAT('%', :searchText, '%')) " +
  37 + "AND (tr.tenantId = :tenantId " +
  38 + "OR (tr.tenantId = :systemAdminId " +
  39 + "AND NOT EXISTS " +
  40 + "(SELECT sr FROM ResourceEntity sr " +
  41 + "WHERE sr.tenantId = :tenantId " +
  42 + "AND sr.resourceType = :resourceType " +
  43 + "AND tr.resourceId = sr.resourceId)))")
  44 + Page<ResourceEntity> findResourcesPage(
  45 + @Param("tenantId") UUID tenantId,
  46 + @Param("systemAdminId") UUID sysAdminId,
  47 + @Param("resourceType") String resourceType,
  48 + @Param("searchText") String search,
  49 + Pageable pageable);
31 50
32 List<ResourceEntity> findAllByTenantIdAndResourceType(UUID tenantId, String resourceType); 51 List<ResourceEntity> findAllByTenantIdAndResourceType(UUID tenantId, String resourceType);
33 52
34 void removeAllByTenantId(UUID tenantId); 53 void removeAllByTenantId(UUID tenantId);
  54 +
  55 + @Query("SELECT tr FROM ResourceEntity tr " +
  56 + "WHERE tr.resourceType = :resourceType " +
  57 + "AND LOWER(tr.textSearch) LIKE LOWER(CONCAT('%', :searchText, '%')) " +
  58 + "AND (tr.tenantId = :tenantId " +
  59 + "OR (tr.tenantId = :systemAdminId " +
  60 + "AND NOT EXISTS " +
  61 + "(SELECT sr FROM ResourceEntity sr " +
  62 + "WHERE sr.tenantId = :tenantId " +
  63 + "AND sr.resourceType = :resourceType " +
  64 + "AND tr.resourceId = sr.resourceId)))")
  65 + List<ResourceEntity> findResources(@Param("tenantId") UUID tenantId,
  66 + @Param("systemAdminId") UUID sysAdminId,
  67 + @Param("resourceType") String resourceType,
  68 + @Param("searchText") String search);
  69 +
  70 + @Query("SELECT tr FROM ResourceEntity tr " +
  71 + "WHERE tr.resourceType = :resourceType " +
  72 + "AND tr.resourceId in (:resourceIds) " +
  73 + "AND (tr.tenantId = :tenantId " +
  74 + "OR (tr.tenantId = :systemAdminId " +
  75 + "AND NOT EXISTS " +
  76 + "(SELECT sr FROM ResourceEntity sr " +
  77 + "WHERE sr.tenantId = :tenantId " +
  78 + "AND sr.resourceType = :resourceType " +
  79 + "AND tr.resourceId = sr.resourceId)))")
  80 + List<ResourceEntity> findResourcesByIds(@Param("tenantId") UUID tenantId,
  81 + @Param("systemAdminId") UUID sysAdminId,
  82 + @Param("resourceType") String resourceType,
  83 + @Param("resourceIds") String[] objectIds);
35 } 84 }
@@ -425,6 +425,7 @@ CREATE TABLE IF NOT EXISTS resource ( @@ -425,6 +425,7 @@ CREATE TABLE IF NOT EXISTS resource (
425 tenant_id uuid NOT NULL, 425 tenant_id uuid NOT NULL,
426 resource_type varchar(32) NOT NULL, 426 resource_type varchar(32) NOT NULL,
427 resource_id varchar(255) NOT NULL, 427 resource_id varchar(255) NOT NULL,
  428 + text_search varchar(255),
428 resource_value varchar, 429 resource_value varchar,
429 CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) 430 CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)
430 ); 431 );
@@ -451,6 +451,7 @@ CREATE TABLE IF NOT EXISTS resource ( @@ -451,6 +451,7 @@ CREATE TABLE IF NOT EXISTS resource (
451 tenant_id uuid NOT NULL, 451 tenant_id uuid NOT NULL,
452 resource_type varchar(32) NOT NULL, 452 resource_type varchar(32) NOT NULL,
453 resource_id varchar(255) NOT NULL, 453 resource_id varchar(255) NOT NULL,
  454 + text_search varchar(255),
454 resource_value varchar, 455 resource_value varchar,
455 CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) 456 CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)
456 ); 457 );
@@ -14,16 +14,16 @@ @@ -14,16 +14,16 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { Injectable } from '@angular/core';  
18 -import { HttpClient } from '@angular/common/http';  
19 -import { PageLink } from '@shared/models/page/page-link';  
20 -import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';  
21 -import { Observable } from 'rxjs';  
22 -import { PageData } from '@shared/models/page/page-data';  
23 -import { DeviceProfile, DeviceProfileInfo, DeviceTransportType } from '@shared/models/device.models';  
24 -import { isDefinedAndNotNull, isEmptyStr } from '@core/utils';  
25 -import { ObjectLwM2M, ServerSecurityConfig } from '@home/components/profile/device/lwm2m/profile-config.models';  
26 -import { SortOrder } from '@shared/models/page/sort-order'; 17 +import {Injectable} from '@angular/core';
  18 +import {HttpClient} from '@angular/common/http';
  19 +import {PageLink} from '@shared/models/page/page-link';
  20 +import {defaultHttpOptionsFromConfig, RequestConfig} from './http-utils';
  21 +import {Observable} from 'rxjs';
  22 +import {PageData} from '@shared/models/page/page-data';
  23 +import {DeviceProfile, DeviceProfileInfo, DeviceTransportType} from '@shared/models/device.models';
  24 +import {isDefinedAndNotNull, isEmptyStr} from '@core/utils';
  25 +import {ObjectLwM2M, ServerSecurityConfig} from '@home/components/profile/device/lwm2m/profile-config.models';
  26 +import {SortOrder} from '@shared/models/page/sort-order';
27 27
28 @Injectable({ 28 @Injectable({
29 providedIn: 'root' 29 providedIn: 'root'
@@ -43,9 +43,9 @@ export class DeviceProfileService { @@ -43,9 +43,9 @@ export class DeviceProfileService {
43 return this.http.get<DeviceProfile>(`/api/deviceProfile/${deviceProfileId}`, defaultHttpOptionsFromConfig(config)); 43 return this.http.get<DeviceProfile>(`/api/deviceProfile/${deviceProfileId}`, defaultHttpOptionsFromConfig(config));
44 } 44 }
45 45
46 - public getLwm2mObjects(sortOrder: SortOrder, objectIds?: number[], searchText?: string, config?: RequestConfig): 46 + public getLwm2mObjects(sortOrder: SortOrder, objectIds?: string[], searchText?: string, config?: RequestConfig):
47 Observable<Array<ObjectLwM2M>> { 47 Observable<Array<ObjectLwM2M>> {
48 - let url = `/api/lwm2m/deviceProfile/?sortProperty=${sortOrder.property}&sortOrder=${sortOrder.direction}`; 48 + let url = `/api/resource/lwm2m/?sortProperty=${sortOrder.property}&sortOrder=${sortOrder.direction}`;
49 if (isDefinedAndNotNull(objectIds) && objectIds.length > 0) { 49 if (isDefinedAndNotNull(objectIds) && objectIds.length > 0) {
50 url += `&objectIds=${objectIds}`; 50 url += `&objectIds=${objectIds}`;
51 } 51 }
@@ -63,9 +63,9 @@ export class DeviceProfileService { @@ -63,9 +63,9 @@ export class DeviceProfileService {
63 ); 63 );
64 } 64 }
65 65
66 - public getLwm2mObjectsPage(pageLink: PageLink, config?: RequestConfig): Observable<PageData<ObjectLwM2M>> {  
67 - return this.http.get<PageData<ObjectLwM2M>>(  
68 - `/api/lwm2m/deviceProfile/objects${pageLink.toQuery()}`, 66 + public getLwm2mObjectsPage(pageLink: PageLink, config?: RequestConfig): Observable<Array<ObjectLwM2M>> {
  67 + return this.http.get<Array<ObjectLwM2M>>(
  68 + `/api/resource/lwm2m/page${pageLink.toQuery()}`,
69 defaultHttpOptionsFromConfig(config) 69 defaultHttpOptionsFromConfig(config)
70 ); 70 );
71 } 71 }
@@ -172,7 +172,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -172,7 +172,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
172 172
173 private updateObserveAttrTelemetryObjectFormGroup = (objectsList: ObjectLwM2M[]): void => { 173 private updateObserveAttrTelemetryObjectFormGroup = (objectsList: ObjectLwM2M[]): void => {
174 this.lwm2mDeviceProfileFormGroup.patchValue({ 174 this.lwm2mDeviceProfileFormGroup.patchValue({
175 - observeAttrTelemetry: this.getObserveAttrTelemetryObjects(objectsList) 175 + observeAttrTelemetry: deepClone(this.getObserveAttrTelemetryObjects(objectsList))
176 }, 176 },
177 {emitEvent: false}); 177 {emitEvent: false});
178 } 178 }
@@ -195,32 +195,32 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -195,32 +195,32 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
195 } 195 }
196 } 196 }
197 197
198 - private getObserveAttrTelemetryObjects = (listObject: ObjectLwM2M[]): object => {  
199 - const clientObserveAttrTelemetry = listObject;  
200 - if (this.configurationValue.observeAttr) { 198 + private getObserveAttrTelemetryObjects = (objectList: ObjectLwM2M[]): object => {
  199 + const objectLwM2MS = deepClone(objectList);
  200 + if (this.configurationValue.observeAttr && objectLwM2MS.length > 0) {
201 const observeArray = this.configurationValue.observeAttr.observe; 201 const observeArray = this.configurationValue.observeAttr.observe;
202 const attributeArray = this.configurationValue.observeAttr.attribute; 202 const attributeArray = this.configurationValue.observeAttr.attribute;
203 const telemetryArray = this.configurationValue.observeAttr.telemetry; 203 const telemetryArray = this.configurationValue.observeAttr.telemetry;
204 let keyNameJson = this.configurationValue.observeAttr.keyName; 204 let keyNameJson = this.configurationValue.observeAttr.keyName;
205 if (this.includesNotZeroInstance(attributeArray, telemetryArray)) { 205 if (this.includesNotZeroInstance(attributeArray, telemetryArray)) {
206 - this.addInstances(attributeArray, telemetryArray, clientObserveAttrTelemetry); 206 + this.addInstances(attributeArray, telemetryArray, objectLwM2MS);
207 } 207 }
208 if (isDefinedAndNotNull(observeArray)) { 208 if (isDefinedAndNotNull(observeArray)) {
209 - this.updateObserveAttrTelemetryObjects(observeArray, clientObserveAttrTelemetry, OBSERVE); 209 + this.updateObserveAttrTelemetryObjects(observeArray, objectLwM2MS, OBSERVE);
210 } 210 }
211 if (isDefinedAndNotNull(attributeArray)) { 211 if (isDefinedAndNotNull(attributeArray)) {
212 - this.updateObserveAttrTelemetryObjects(attributeArray, clientObserveAttrTelemetry, ATTRIBUTE); 212 + this.updateObserveAttrTelemetryObjects(attributeArray, objectLwM2MS, ATTRIBUTE);
213 } 213 }
214 if (isDefinedAndNotNull(telemetryArray)) { 214 if (isDefinedAndNotNull(telemetryArray)) {
215 - this.updateObserveAttrTelemetryObjects(telemetryArray, clientObserveAttrTelemetry, TELEMETRY); 215 + this.updateObserveAttrTelemetryObjects(telemetryArray, objectLwM2MS, TELEMETRY);
216 } 216 }
217 if (isDefinedAndNotNull(keyNameJson)) { 217 if (isDefinedAndNotNull(keyNameJson)) {
218 this.configurationValue.observeAttr.keyName = this.validateKeyNameObjects(keyNameJson, attributeArray, telemetryArray); 218 this.configurationValue.observeAttr.keyName = this.validateKeyNameObjects(keyNameJson, attributeArray, telemetryArray);
219 this.upDateJsonAllConfig(); 219 this.upDateJsonAllConfig();
220 - this.updateKeyNameObjects(clientObserveAttrTelemetry); 220 + this.updateKeyNameObjects(objectLwM2MS);
221 } 221 }
222 } 222 }
223 - return {clientLwM2M: clientObserveAttrTelemetry}; 223 + return {clientLwM2M: objectLwM2MS};
224 } 224 }
225 225
226 private includesNotZeroInstance = (attribute: string[], telemetry: string[]): boolean => { 226 private includesNotZeroInstance = (attribute: string[], telemetry: string[]): boolean => {
@@ -235,35 +235,39 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -235,35 +235,39 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
235 .sort(this.sortPath); 235 .sort(this.sortPath);
236 236
237 new Set(instancesPath).forEach(path => { 237 new Set(instancesPath).forEach(path => {
238 - const pathParameter = Array.from(path.split('/'), Number);  
239 - const objectLwM2M = clientObserveAttrTelemetry.find(x => x.id === pathParameter[0]); 238 + const pathParameter = Array.from(path.split('/'), String);
  239 + const objectLwM2M = clientObserveAttrTelemetry.find(x => x.keyId === pathParameter[0]);
240 if (objectLwM2M) { 240 if (objectLwM2M) {
241 const instance = deepClone(objectLwM2M.instances[0]); 241 const instance = deepClone(objectLwM2M.instances[0]);
242 - instance.id = pathParameter[1]; 242 + instance.id = +pathParameter[1];
243 objectLwM2M.instances.push(instance); 243 objectLwM2M.instances.push(instance);
244 } 244 }
245 }); 245 });
246 } 246 }
247 247
248 - private updateObserveAttrTelemetryObjects = (parameters: string[], clientObserveAttrTelemetry: ObjectLwM2M[], 248 + private updateObserveAttrTelemetryObjects = (parameters: string[], objectLwM2MS: ObjectLwM2M[],
249 nameParameter: string): void => { 249 nameParameter: string): void => {
250 parameters.forEach(parameter => { 250 parameters.forEach(parameter => {
251 - const [objectId, instanceId, resourceId] = Array.from(parameter.substring(1).split('/'), Number);  
252 - clientObserveAttrTelemetry.find(objectLwm2m => objectLwm2m.id === objectId)  
253 - .instances.find(itrInstance => itrInstance.id === instanceId)  
254 - .resources.find(resource => resource.id === resourceId)  
255 - [nameParameter] = true; 251 + const [objectKeyId, instanceId, resourceId] = Array.from(parameter.substring(1).split('/'), String);
  252 + const objectLwM2M = objectLwM2MS.find(objectLwm2m => objectLwm2m.keyId === objectKeyId);
  253 + if (objectLwM2M) {
  254 + objectLwM2M.instances.find(itrInstance => itrInstance.id === +instanceId)
  255 + .resources.find(resource => resource.id === +resourceId)
  256 + [nameParameter] = true;
  257 + }
256 }); 258 });
  259 +
257 } 260 }
258 261
259 private updateKeyNameObjects = (clientObserveAttrTelemetry: ObjectLwM2M[]): void => { 262 private updateKeyNameObjects = (clientObserveAttrTelemetry: ObjectLwM2M[]): void => {
260 Object.keys(this.configurationValue.observeAttr.keyName).forEach(key => { 263 Object.keys(this.configurationValue.observeAttr.keyName).forEach(key => {
261 - const [objectId, instanceId, resourceId] = Array.from(key.substring(1).split('/'), Number);  
262 - clientObserveAttrTelemetry.find(objectLwm2m => objectLwm2m.id === objectId)  
263 - .instances.find(instance => instance.id === instanceId)  
264 - .resources.find(resource => resource.id === resourceId) 264 + const [objectKeyId, instanceId, resourceId] = Array.from(key.substring(1).split('/'), String);
  265 + const objectLwM2M = clientObserveAttrTelemetry.find(objectLwm2m => objectLwm2m.keyId === objectKeyId)
  266 + if (objectLwM2M) {
  267 + objectLwM2M.instances.find(instance => instance.id === +instanceId)
  268 + .resources.find(resource => resource.id === +resourceId)
265 .keyName = this.configurationValue.observeAttr.keyName[key]; 269 .keyName = this.configurationValue.observeAttr.keyName[key];
266 - }); 270 + }});
267 } 271 }
268 272
269 private validateKeyNameObjects = (nameJson: JsonObject, attributeArray: JsonArray, telemetryArray: JsonArray): {} => { 273 private validateKeyNameObjects = (nameJson: JsonObject, attributeArray: JsonArray, telemetryArray: JsonArray): {} => {
@@ -290,7 +294,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -290,7 +294,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
290 if (instance.hasOwnProperty(RESOURCES) && Array.isArray(instance.resources)) { 294 if (instance.hasOwnProperty(RESOURCES) && Array.isArray(instance.resources)) {
291 instance.resources.forEach(resource => { 295 instance.resources.forEach(resource => {
292 if (resource.attribute || resource.telemetry) { 296 if (resource.attribute || resource.telemetry) {
293 - let pathRes = `/${obj.id}/${instance.id}/${resource.id}`; 297 + let pathRes = `/${obj.keyId}/${instance.id}/${resource.id}`;
294 if (resource.observe) { 298 if (resource.observe) {
295 observeArray.push(pathRes); 299 observeArray.push(pathRes);
296 } 300 }
@@ -345,22 +349,22 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -345,22 +349,22 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
345 }); 349 });
346 } 350 }
347 351
348 - private getObjectsFromJsonAllConfig = (): number[] => {  
349 - const objectsIds = new Set<number>(); 352 + private getObjectsFromJsonAllConfig = (): string[] => {
  353 + const objectsIds = new Set<string>();
350 if (this.configurationValue.observeAttr) { 354 if (this.configurationValue.observeAttr) {
351 if (this.configurationValue.observeAttr.observe) { 355 if (this.configurationValue.observeAttr.observe) {
352 this.configurationValue.observeAttr.observe.forEach(obj => { 356 this.configurationValue.observeAttr.observe.forEach(obj => {
353 - objectsIds.add(Array.from(obj.substring(1).split('/'), Number)[0]); 357 + objectsIds.add(Array.from(obj.substring(1).split('/'), String)[0]);
354 }); 358 });
355 } 359 }
356 if (this.configurationValue.observeAttr.attribute) { 360 if (this.configurationValue.observeAttr.attribute) {
357 this.configurationValue.observeAttr.attribute.forEach(obj => { 361 this.configurationValue.observeAttr.attribute.forEach(obj => {
358 - objectsIds.add(Array.from(obj.substring(1).split('/'), Number)[0]); 362 + objectsIds.add(Array.from(obj.substring(1).split('/'), String)[0]);
359 }); 363 });
360 } 364 }
361 if (this.configurationValue.observeAttr.telemetry) { 365 if (this.configurationValue.observeAttr.telemetry) {
362 this.configurationValue.observeAttr.telemetry.forEach(obj => { 366 this.configurationValue.observeAttr.telemetry.forEach(obj => {
363 - objectsIds.add(Array.from(obj.substring(1).split('/'), Number)[0]); 367 + objectsIds.add(Array.from(obj.substring(1).split('/'), String)[0]);
364 }); 368 });
365 } 369 }
366 } 370 }
@@ -379,21 +383,21 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -379,21 +383,21 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
379 383
380 removeObjectsList = (value: ObjectLwM2M): void => { 384 removeObjectsList = (value: ObjectLwM2M): void => {
381 const objectsOld = this.lwm2mDeviceProfileFormGroup.get(OBSERVE_ATTR_TELEMETRY).value.clientLwM2M; 385 const objectsOld = this.lwm2mDeviceProfileFormGroup.get(OBSERVE_ATTR_TELEMETRY).value.clientLwM2M;
382 - const isIdIndex = (element) => element.id === value.id; 386 + const isIdIndex = (element) => element.keyId === value.keyId;
383 const index = objectsOld.findIndex(isIdIndex); 387 const index = objectsOld.findIndex(isIdIndex);
384 if (index >= 0) { 388 if (index >= 0) {
385 objectsOld.splice(index, 1); 389 objectsOld.splice(index, 1);
386 } 390 }
387 - this.removeObserveAttrTelemetryFromJson(OBSERVE, value.id);  
388 - this.removeObserveAttrTelemetryFromJson(TELEMETRY, value.id);  
389 - this.removeObserveAttrTelemetryFromJson(ATTRIBUTE, value.id);  
390 - this.removeKeyNameFromJson(value.id); 391 + this.removeObserveAttrTelemetryFromJson(OBSERVE, value.keyId);
  392 + this.removeObserveAttrTelemetryFromJson(TELEMETRY, value.keyId);
  393 + this.removeObserveAttrTelemetryFromJson(ATTRIBUTE, value.keyId);
  394 + this.removeKeyNameFromJson(value.keyId);
391 this.updateObserveAttrTelemetryObjectFormGroup(objectsOld); 395 this.updateObserveAttrTelemetryObjectFormGroup(objectsOld);
392 this.upDateJsonAllConfig(); 396 this.upDateJsonAllConfig();
393 } 397 }
394 398
395 - private removeObserveAttrTelemetryFromJson = (observeAttrTel: string, id: number): void => {  
396 - const isIdIndex = (element) => element.startsWith(`/${id}`); 399 + private removeObserveAttrTelemetryFromJson = (observeAttrTel: string, keyId: string): void => {
  400 + const isIdIndex = (element) => element.startsWith(`/${keyId}`);
397 let index = this.configurationValue.observeAttr[observeAttrTel].findIndex(isIdIndex); 401 let index = this.configurationValue.observeAttr[observeAttrTel].findIndex(isIdIndex);
398 while (index >= 0) { 402 while (index >= 0) {
399 this.configurationValue.observeAttr[observeAttrTel].splice(index, 1); 403 this.configurationValue.observeAttr[observeAttrTel].splice(index, 1);
@@ -401,10 +405,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro @@ -401,10 +405,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
401 } 405 }
402 } 406 }
403 407
404 - private removeKeyNameFromJson = (id: number): void => { 408 + private removeKeyNameFromJson = (keyId: string): void => {
405 const keyNameJson = this.configurationValue.observeAttr.keyName; 409 const keyNameJson = this.configurationValue.observeAttr.keyName;
406 Object.keys(keyNameJson).forEach(key => { 410 Object.keys(keyNameJson).forEach(key => {
407 - if (key.startsWith(`/${id}`)) { 411 + if (key.startsWith(`/${keyId}`)) {
408 delete keyNameJson[key]; 412 delete keyNameJson[key];
409 } 413 }
410 }); 414 });
@@ -14,12 +14,11 @@ @@ -14,12 +14,11 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { Component, forwardRef, } from '@angular/core';  
18 -import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';  
19 -import { Store } from '@ngrx/store';  
20 -import { AppState } from '@core/core.state';  
21 -import { INSTANCES_ID_VALUE_MAX, INSTANCES_ID_VALUE_MIN, KEY_REGEXP_NUMBER } from './profile-config.models';  
22 -import { DeviceProfileService } from '@core/http/device-profile.service'; 17 +import {Component, forwardRef,} from '@angular/core';
  18 +import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators} from '@angular/forms';
  19 +import {Store} from '@ngrx/store';
  20 +import {AppState} from '@core/core.state';
  21 +import {INSTANCES_ID_VALUE_MAX, INSTANCES_ID_VALUE_MIN, KEY_REGEXP_NUMBER} from './profile-config.models';
23 22
24 @Component({ 23 @Component({
25 selector: 'tb-profile-lwm2m-object-add-instances-list', 24 selector: 'tb-profile-lwm2m-object-add-instances-list',
@@ -43,7 +42,6 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso @@ -43,7 +42,6 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso
43 private propagateChange = (v: any) => { }; 42 private propagateChange = (v: any) => { };
44 43
45 constructor(private store: Store<AppState>, 44 constructor(private store: Store<AppState>,
46 - private deviceProfileService: DeviceProfileService,  
47 private fb: FormBuilder) { 45 private fb: FormBuilder) {
48 this.instancesListFormGroup = this.fb.group({ 46 this.instancesListFormGroup = this.fb.group({
49 instanceIdInput: [null, [ 47 instanceIdInput: [null, [
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 --> 17 -->
18 <form [formGroup]="instancesFormGroup" (ngSubmit)="add()" style="min-width: 400px;"> 18 <form [formGroup]="instancesFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
19 <mat-toolbar fxLayout="row" color="primary"> 19 <mat-toolbar fxLayout="row" color="primary">
20 - <b><i>{{data.objectName}}</i></b> &nbsp;&nbsp; (object&nbsp;[<b>{{data.objectId}}</b>]) 20 + <b><i>{{data.objectName}}</i></b> &nbsp;&nbsp; (object&nbsp;[<b>{{data.objectKeyId}}</b>])
21 <span fxFlex></span> 21 <span fxFlex></span>
22 <button mat-button mat-icon-button 22 <button mat-button mat-icon-button
23 (click)="cancel()" 23 (click)="cancel()"
@@ -14,18 +14,18 @@ @@ -14,18 +14,18 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { Component, Inject, OnInit } from '@angular/core';  
18 -import { DialogComponent } from '@shared/components/dialog.component';  
19 -import { FormBuilder, FormGroup } from '@angular/forms';  
20 -import { Store } from '@ngrx/store';  
21 -import { AppState } from '@core/core.state';  
22 -import { Router } from '@angular/router';  
23 -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; 17 +import {Component, Inject, OnInit} from '@angular/core';
  18 +import {DialogComponent} from '@shared/components/dialog.component';
  19 +import {FormBuilder, FormGroup} from '@angular/forms';
  20 +import {Store} from '@ngrx/store';
  21 +import {AppState} from '@core/core.state';
  22 +import {Router} from '@angular/router';
  23 +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
24 24
25 export interface Lwm2mObjectAddInstancesData { 25 export interface Lwm2mObjectAddInstancesData {
26 instancesIds: Set<number>; 26 instancesIds: Set<number>;
27 objectName?: string; 27 objectName?: string;
28 - objectId?: number; 28 + objectKeyId?: string;
29 } 29 }
30 30
31 @Component({ 31 @Component({
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 class="tb-autocomplete" 40 class="tb-autocomplete"
41 [displayWith]="displayObjectLwm2mFn"> 41 [displayWith]="displayObjectLwm2mFn">
42 <mat-option *ngFor="let objectLwm2m of filteredObjectsList | async" [value]="objectLwm2m"> 42 <mat-option *ngFor="let objectLwm2m of filteredObjectsList | async" [value]="objectLwm2m">
43 - <span [innerHTML]="objectLwm2m.id + ': ' + objectLwm2m.name | highlight:searchText"></span> 43 + <span [innerHTML]="objectLwm2m.keyId + ': ' + objectLwm2m.name | highlight:searchText"></span>
44 </mat-option> 44 </mat-option>
45 <mat-option *ngIf="!(filteredObjectsList | async)?.length" [value]="null"> 45 <mat-option *ngIf="!(filteredObjectsList | async)?.length" [value]="null">
46 <span> 46 <span>
@@ -14,17 +14,18 @@ @@ -14,17 +14,18 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core';  
18 -import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';  
19 -import { coerceBooleanProperty } from '@angular/cdk/coercion';  
20 -import { Store } from '@ngrx/store';  
21 -import { AppState } from '@core/core.state';  
22 -import { Observable } from 'rxjs';  
23 -import { filter, map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators';  
24 -import { ModelValue, ObjectLwM2M } from './profile-config.models';  
25 -import { DeviceProfileService } from '@core/http/device-profile.service';  
26 -import { Direction } from '@shared/models/page/sort-order';  
27 -import { isDefined, isDefinedAndNotNull, isEmptyStr, isString } from '@core/utils'; 17 +import {Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild} from '@angular/core';
  18 +import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators} from '@angular/forms';
  19 +import {coerceBooleanProperty} from '@angular/cdk/coercion';
  20 +import {Store} from '@ngrx/store';
  21 +import {AppState} from '@core/core.state';
  22 +import {Observable} from 'rxjs';
  23 +import {filter, map, mergeMap, publishReplay, refCount, tap} from 'rxjs/operators';
  24 +import {ModelValue, ObjectLwM2M, PAGE_SIZE_LIMIT} from './profile-config.models';
  25 +import {DeviceProfileService} from '@core/http/device-profile.service';
  26 +import {Direction} from '@shared/models/page/sort-order';
  27 +import {isDefined, isDefinedAndNotNull, isString} from '@core/utils';
  28 +import {PageLink} from "@shared/models/page/page-link";
28 29
29 @Component({ 30 @Component({
30 selector: 'tb-profile-lwm2m-object-list', 31 selector: 'tb-profile-lwm2m-object-list',
@@ -41,7 +42,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -41,7 +42,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
41 private requiredValue: boolean; 42 private requiredValue: boolean;
42 private dirty = false; 43 private dirty = false;
43 private lw2mModels: Observable<Array<ObjectLwM2M>>; 44 private lw2mModels: Observable<Array<ObjectLwM2M>>;
44 - private modelValue: Array<number> = []; 45 + private modelValue: Array<string> = [];
45 46
46 lwm2mListFormGroup: FormGroup; 47 lwm2mListFormGroup: FormGroup;
47 objectsList: Array<ObjectLwM2M> = []; 48 objectsList: Array<ObjectLwM2M> = [];
@@ -134,8 +135,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -134,8 +135,8 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
134 } 135 }
135 136
136 private add(object: ObjectLwM2M): void { 137 private add(object: ObjectLwM2M): void {
137 - if (isDefinedAndNotNull(this.modelValue) && this.modelValue.indexOf(object.id) === -1) {  
138 - this.modelValue.push(object.id); 138 + if (isDefinedAndNotNull(this.modelValue) && this.modelValue.indexOf(object.keyId) === -1) {
  139 + this.modelValue.push(object.keyId);
139 this.objectsList.push(object); 140 this.objectsList.push(object);
140 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList); 141 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
141 this.addList.next(this.objectsList); 142 this.addList.next(this.objectsList);
@@ -148,7 +149,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -148,7 +149,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
148 if (index >= 0) { 149 if (index >= 0) {
149 this.objectsList.splice(index, 1); 150 this.objectsList.splice(index, 1);
150 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList); 151 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
151 - index = this.modelValue.indexOf(object.id); 152 + index = this.modelValue.indexOf(object.keyId);
152 this.modelValue.splice(index, 1); 153 this.modelValue.splice(index, 1);
153 this.removeList.next(object); 154 this.removeList.next(object);
154 this.clear(); 155 this.clear();
@@ -159,25 +160,29 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V @@ -159,25 +160,29 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
159 return object ? object.name : undefined; 160 return object ? object.name : undefined;
160 } 161 }
161 162
162 - private fetchListObjects = (searchText?: string): Observable<Array<ObjectLwM2M>> => { 163 + private fetchListObjects = (searchText?: string): Observable<Array<ObjectLwM2M>> => {
163 this.searchText = searchText; 164 this.searchText = searchText;
164 - const filters = {names: [], ids: []};  
165 - if (isDefinedAndNotNull(searchText) && !isEmptyStr(searchText)) {  
166 - const ids = searchText.match(/\d+/g);  
167 - filters.ids = ids !== null ? ids.map(Number) : filters.ids;  
168 - filters.names = searchText.trim().toUpperCase().split(' ');  
169 - }  
170 - const predicate = objectLwM2M => filters.names.find(word => objectLwM2M.name.toUpperCase().includes(word))  
171 - || filters.ids.includes(objectLwM2M.id);  
172 - return this.getLwM2mModels().pipe(  
173 - map(objectLwM2Ms => searchText ? objectLwM2Ms.filter(predicate) : objectLwM2Ms)  
174 - ); 165 + return this.getLwM2mModelsPage().pipe(
  166 + map(objectLwM2Ms => objectLwM2Ms)
  167 + );
  168 + }
  169 +
  170 + private getLwM2mModelsPage(): Observable<Array<ObjectLwM2M>> {
  171 + const pageLink = new PageLink(PAGE_SIZE_LIMIT, 0, this.searchText, {
  172 + property: 'id',
  173 + direction: Direction.ASC
  174 + });
  175 + this.lw2mModels = this.deviceProfileService.getLwm2mObjectsPage(pageLink).pipe(
  176 + publishReplay(1),
  177 + refCount()
  178 + );
  179 + return this.lw2mModels;
175 } 180 }
176 181
177 private getLwM2mModels(): Observable<Array<ObjectLwM2M>> { 182 private getLwM2mModels(): Observable<Array<ObjectLwM2M>> {
178 if (!this.lw2mModels) { 183 if (!this.lw2mModels) {
179 const sortOrder = { 184 const sortOrder = {
180 - property: 'name', 185 + property: 'id',
181 direction: Direction.ASC 186 direction: Direction.ASC
182 }; 187 };
183 this.lw2mModels = this.deviceProfileService.getLwm2mObjects(sortOrder).pipe( 188 this.lw2mModels = this.deviceProfileService.getLwm2mObjects(sortOrder).pipe(
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 [formGroupName]="i"> 22 [formGroupName]="i">
23 <mat-expansion-panel-header> 23 <mat-expansion-panel-header>
24 <mat-panel-title fxLayoutAlign="start center"> 24 <mat-panel-title fxLayoutAlign="start center">
25 - <b><i>{{ objectLwM2M.get('name').value}}</i></b>&nbsp;&lt;id: {{ objectLwM2M.get('id').value}}> 25 + <b><i>{{ objectLwM2M.get('name').value}}</i></b>&nbsp;&lt;id: {{ objectLwM2M.get('keyId').value}}>
26 </mat-panel-title> 26 </mat-panel-title>
27 <mat-panel-description fxLayoutAlign="end center" *ngIf="!disabled"> 27 <mat-panel-description fxLayoutAlign="end center" *ngIf="!disabled">
28 <button type="button" 28 <button type="button"
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 /// 15 ///
16 16
17 17
18 -import { Component, forwardRef, Input } from '@angular/core'; 18 +import {Component, forwardRef, Input} from '@angular/core';
19 import { 19 import {
20 AbstractControl, 20 AbstractControl,
21 ControlValueAccessor, 21 ControlValueAccessor,
@@ -25,13 +25,13 @@ import { @@ -25,13 +25,13 @@ import {
25 NG_VALUE_ACCESSOR, 25 NG_VALUE_ACCESSOR,
26 Validators 26 Validators
27 } from '@angular/forms'; 27 } from '@angular/forms';
28 -import { Store } from '@ngrx/store';  
29 -import { AppState } from '@core/core.state';  
30 -import { coerceBooleanProperty } from '@angular/cdk/coercion';  
31 -import { CLIENT_LWM2M, Instance, INSTANCES, ObjectLwM2M, ResourceLwM2M, RESOURCES } from './profile-config.models';  
32 -import { deepClone, isDefinedAndNotNull, isEqual, isUndefined } from '@core/utils';  
33 -import { MatDialog } from '@angular/material/dialog';  
34 -import { TranslateService } from '@ngx-translate/core'; 28 +import {Store} from '@ngrx/store';
  29 +import {AppState} from '@core/core.state';
  30 +import {coerceBooleanProperty} from '@angular/cdk/coercion';
  31 +import {CLIENT_LWM2M, Instance, INSTANCES, ObjectLwM2M, ResourceLwM2M, RESOURCES} from './profile-config.models';
  32 +import {deepClone, isDefinedAndNotNull, isEqual, isUndefined} from '@core/utils';
  33 +import {MatDialog} from '@angular/material/dialog';
  34 +import {TranslateService} from '@ngx-translate/core';
35 import { 35 import {
36 Lwm2mObjectAddInstancesComponent, 36 Lwm2mObjectAddInstancesComponent,
37 Lwm2mObjectAddInstancesData 37 Lwm2mObjectAddInstancesData
@@ -139,7 +139,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -139,7 +139,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
139 private createObjectsLwM2M = (objectsLwM2M: ObjectLwM2M[]): FormArray => { 139 private createObjectsLwM2M = (objectsLwM2M: ObjectLwM2M[]): FormArray => {
140 return this.fb.array(objectsLwM2M.map((objectLwM2M) => { 140 return this.fb.array(objectsLwM2M.map((objectLwM2M) => {
141 return this.fb.group({ 141 return this.fb.group({
142 - id: objectLwM2M.id, 142 + keyId: objectLwM2M.keyId,
143 name: objectLwM2M.name, 143 name: objectLwM2M.name,
144 multiple: objectLwM2M.multiple, 144 multiple: objectLwM2M.multiple,
145 mandatory: objectLwM2M.mandatory, 145 mandatory: objectLwM2M.mandatory,
@@ -228,7 +228,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -228,7 +228,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
228 data: { 228 data: {
229 instancesIds: this.instancesToSetId(object.instances), 229 instancesIds: this.instancesToSetId(object.instances),
230 objectName: object.name, 230 objectName: object.name,
231 - objectId: object.id 231 + objectKeyId: object.keyId
232 } 232 }
233 }).afterClosed().subscribe( 233 }).afterClosed().subscribe(
234 (res: Lwm2mObjectAddInstancesData | undefined) => { 234 (res: Lwm2mObjectAddInstancesData | undefined) => {
@@ -241,7 +241,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -241,7 +241,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
241 241
242 private updateInstancesIds = (data: Lwm2mObjectAddInstancesData): void => { 242 private updateInstancesIds = (data: Lwm2mObjectAddInstancesData): void => {
243 const objectLwM2MFormGroup = (this.observeAttrTelemetryFormGroup.get(CLIENT_LWM2M) as FormArray).controls 243 const objectLwM2MFormGroup = (this.observeAttrTelemetryFormGroup.get(CLIENT_LWM2M) as FormArray).controls
244 - .find(e => e.value.id === data.objectId) as FormGroup; 244 + .find(e => e.value.keyId === data.objectKeyId) as FormGroup;
245 const instancesArray = objectLwM2MFormGroup.value.instances as Instance []; 245 const instancesArray = objectLwM2MFormGroup.value.instances as Instance [];
246 const instancesFormArray = objectLwM2MFormGroup.get(INSTANCES) as FormArray; 246 const instancesFormArray = objectLwM2MFormGroup.get(INSTANCES) as FormArray;
247 const instance0 = deepClone(instancesFormArray.at(0).value as Instance); 247 const instance0 = deepClone(instancesFormArray.at(0).value as Instance);
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
  17 +export const PAGE_SIZE_LIMIT = 50;
17 export const INSTANCES = 'instances'; 18 export const INSTANCES = 'instances';
18 export const RESOURCES = 'resources'; 19 export const RESOURCES = 'resources';
19 export const CLIENT_LWM2M = 'clientLwM2M'; 20 export const CLIENT_LWM2M = 'clientLwM2M';
@@ -58,7 +59,7 @@ export const SECURITY_CONFIG_MODE_NAMES = new Map<SECURITY_CONFIG_MODE, string>( @@ -58,7 +59,7 @@ export const SECURITY_CONFIG_MODE_NAMES = new Map<SECURITY_CONFIG_MODE, string>(
58 ); 59 );
59 60
60 export interface ModelValue { 61 export interface ModelValue {
61 - objectIds: number[] | null, 62 + objectIds: string[] | null,
62 objectsList: ObjectLwM2M[] 63 objectsList: ObjectLwM2M[]
63 } 64 }
64 65
@@ -190,6 +191,7 @@ export interface Instance { @@ -190,6 +191,7 @@ export interface Instance {
190 */ 191 */
191 export interface ObjectLwM2M { 192 export interface ObjectLwM2M {
192 id: number; 193 id: number;
  194 + keyId: string;
193 name: string; 195 name: string;
194 multiple?: boolean; 196 multiple?: boolean;
195 mandatory?: boolean; 197 mandatory?: boolean;