Commit bc21db007bff0006a8846c0af47716a39422d4bc
Committed by
GitHub
1 parent
9e2bfa40
Lwm2m add resource fix (#4272)
* lwm2m: add objectKeyId to back and front profile * lwm2m: front^ strategy - select * lwm2m: back fix bag * lwm2m: back fix bag2 * lwm2m: back fix bag3
Showing
6 changed files
with
31 additions
and
138 deletions
@@ -62,7 +62,7 @@ public class ResourceController extends BaseController { | @@ -62,7 +62,7 @@ public class ResourceController extends BaseController { | ||
62 | } | 62 | } |
63 | 63 | ||
64 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 64 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
65 | - @RequestMapping(value = "/resource/page", method = RequestMethod.GET) | 65 | + @RequestMapping(value = "/resource", method = RequestMethod.GET) |
66 | @ResponseBody | 66 | @ResponseBody |
67 | public PageData<Resource> getResources(@RequestParam(required = false) boolean system, | 67 | public PageData<Resource> getResources(@RequestParam(required = false) boolean system, |
68 | @RequestParam int pageSize, | 68 | @RequestParam int pageSize, |
@@ -71,8 +71,6 @@ public class ResourceController extends BaseController { | @@ -71,8 +71,6 @@ public class ResourceController extends BaseController { | ||
71 | @RequestParam(required = false) String sortProperty, | 71 | @RequestParam(required = false) String sortProperty, |
72 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { | 72 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
73 | try { | 73 | try { |
74 | -// int[] objectIds; | ||
75 | -// ResourceType resourceType | ||
76 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | 74 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
77 | return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink)); | 75 | return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink)); |
78 | } catch (Exception e) { | 76 | } catch (Exception e) { |
@@ -101,11 +99,9 @@ public class ResourceController extends BaseController { | @@ -101,11 +99,9 @@ public class ResourceController extends BaseController { | ||
101 | @ResponseBody | 99 | @ResponseBody |
102 | public List<LwM2mObject> getLwm2mListObjects(@RequestParam String sortOrder, | 100 | public List<LwM2mObject> getLwm2mListObjects(@RequestParam String sortOrder, |
103 | @RequestParam String sortProperty, | 101 | @RequestParam String sortProperty, |
104 | - @RequestParam(required = false) String[] objectIds, | ||
105 | - @RequestParam(required = false) String searchText) | ||
106 | - throws ThingsboardException { | 102 | + @RequestParam(required = false) String[] objectIds) throws ThingsboardException { |
107 | try { | 103 | try { |
108 | - return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds, searchText)); | 104 | + return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds)); |
109 | } catch (Exception e) { | 105 | } catch (Exception e) { |
110 | throw handleException(e); | 106 | throw handleException(e); |
111 | } | 107 | } |
@@ -17,10 +17,6 @@ package org.thingsboard.server.service.install; | @@ -17,10 +17,6 @@ package org.thingsboard.server.service.install; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import lombok.extern.slf4j.Slf4j; | 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; | ||
24 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
25 | import org.springframework.beans.factory.annotation.Value; | 21 | import org.springframework.beans.factory.annotation.Value; |
26 | import org.springframework.stereotype.Component; | 22 | import org.springframework.stereotype.Component; |
@@ -34,7 +30,6 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -34,7 +30,6 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
34 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | 30 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; |
35 | import org.thingsboard.server.common.data.rule.RuleChain; | 31 | import org.thingsboard.server.common.data.rule.RuleChain; |
36 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 32 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
37 | -import org.thingsboard.server.common.data.widget.WidgetType; | ||
38 | import org.thingsboard.server.common.data.widget.WidgetTypeDetails; | 33 | import org.thingsboard.server.common.data.widget.WidgetTypeDetails; |
39 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 34 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
40 | import org.thingsboard.server.dao.dashboard.DashboardService; | 35 | import org.thingsboard.server.dao.dashboard.DashboardService; |
@@ -45,8 +40,6 @@ import org.thingsboard.server.dao.rule.RuleChainService; | @@ -45,8 +40,6 @@ import org.thingsboard.server.dao.rule.RuleChainService; | ||
45 | import org.thingsboard.server.dao.widget.WidgetTypeService; | 40 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
46 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 41 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
47 | 42 | ||
48 | -import java.io.ByteArrayInputStream; | ||
49 | -import java.io.File; | ||
50 | import java.io.IOException; | 43 | import java.io.IOException; |
51 | import java.nio.file.DirectoryStream; | 44 | import java.nio.file.DirectoryStream; |
52 | import java.nio.file.Files; | 45 | import java.nio.file.Files; |
@@ -215,8 +208,8 @@ public class InstallScripts { | @@ -215,8 +208,8 @@ public class InstallScripts { | ||
215 | Resource resource = new Resource(); | 208 | Resource resource = new Resource(); |
216 | resource.setTenantId(TenantId.SYS_TENANT_ID); | 209 | resource.setTenantId(TenantId.SYS_TENANT_ID); |
217 | resource.setResourceType(ResourceType.LWM2M_MODEL); | 210 | resource.setResourceType(ResourceType.LWM2M_MODEL); |
218 | - resource.setResourceId(getValueByTeg(source, "ObjectID") + "_" + getValueByTeg(source, "ObjectVersion")); | ||
219 | - resource.setTextSearch(resource.getResourceId() + ":" + getValueByTeg(source, "Name")); | 211 | + resource.setResourceId(getValueByTag(source, "ObjectID") + "_" + getValueByTag(source, "ObjectVersion")); |
212 | + resource.setTextSearch(resource.getResourceId() + ":" + getValueByTag(source, "Name")); | ||
220 | resource.setValue(Base64.getEncoder().encodeToString(fileBytes)); | 213 | resource.setValue(Base64.getEncoder().encodeToString(fileBytes)); |
221 | resourceService.saveResource(resource); | 214 | resourceService.saveResource(resource); |
222 | } catch (Exception e) { | 215 | } catch (Exception e) { |
@@ -238,43 +231,18 @@ public class InstallScripts { | @@ -238,43 +231,18 @@ public class InstallScripts { | ||
238 | resourceService.saveResource(resource); | 231 | resourceService.saveResource(resource); |
239 | } catch (Exception e) { | 232 | } catch (Exception e) { |
240 | log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); | 233 | log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); |
241 | - throw new RuntimeException("Unable to load l2m2m serverKeyStore", e); | 234 | + throw new RuntimeException("Unable to load lwm2m serverKeyStore", e); |
242 | } | 235 | } |
243 | } | 236 | } |
244 | 237 | ||
245 | - private String getValueByTeg(String source, String tagHtml) { | ||
246 | - int lenTag = ("<" + tagHtml + ">").length(); | ||
247 | - int indStart = source.indexOf("<" + tagHtml + ">"); | ||
248 | - int indEnd = source.indexOf("</" + tagHtml + ">"); | 238 | + private String getValueByTag(String source, String tag) { |
239 | + int lenTag = ("<" + tag + ">").length(); | ||
240 | + int indStart = source.indexOf("<" + tag + ">"); | ||
241 | + int indEnd = source.indexOf("</" + tag + ">"); | ||
249 | return (indStart > 0 && indEnd > 0) ? source.substring(indStart + lenTag, indEnd) : null; | 242 | return (indStart > 0 && indEnd > 0) ? source.substring(indStart + lenTag, indEnd) : null; |
250 | 243 | ||
251 | } | 244 | } |
252 | 245 | ||
253 | - private ObjectModel getObjectModelLwm2mValid(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) { | ||
254 | - try { | ||
255 | - DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator); | ||
256 | - return ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0); | ||
257 | - } catch (IOException | InvalidDDFFileException e) { | ||
258 | - log.error("Could not parse the XML file [{}]", streamName, e); | ||
259 | - return null; | ||
260 | - } | ||
261 | - | ||
262 | - } | ||
263 | - | ||
264 | - private void removeFile(Path modelsDir, String nameFile, byte[] fileBytes) { | ||
265 | - String path = "/home/nick/Igor_project/thingsboard_ce_3_2_docker/thingsboard/common/transport/lwm2m/src/main/resources/models/"; | ||
266 | - File file = new File(path + nameFile); | ||
267 | - if (!file.isDirectory()) { | ||
268 | - try { | ||
269 | - Files.write(Paths.get(path + "server/" + nameFile), fileBytes); | ||
270 | - file.delete(); | ||
271 | - } catch (IOException e) { | ||
272 | - e.printStackTrace(); | ||
273 | - } | ||
274 | - | ||
275 | - } | ||
276 | - } | ||
277 | - | ||
278 | public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { | 246 | public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { |
279 | Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR); | 247 | Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR); |
280 | try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) { | 248 | try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) { |
@@ -32,19 +32,18 @@ public interface ResourceService { | @@ -32,19 +32,18 @@ public interface ResourceService { | ||
32 | 32 | ||
33 | PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink); | 33 | PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink); |
34 | 34 | ||
35 | + List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType); | ||
36 | + | ||
35 | List<LwM2mObject> findLwM2mObject(TenantId tenantId, | 37 | List<LwM2mObject> findLwM2mObject(TenantId tenantId, |
36 | String sortOrder, | 38 | String sortOrder, |
37 | String sortProperty, | 39 | String sortProperty, |
38 | - String[] objectIds, | ||
39 | - String searchText); | 40 | + String[] objectIds); |
40 | 41 | ||
41 | List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId, | 42 | List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId, |
42 | String sortProperty, | 43 | String sortProperty, |
43 | String sortOrder, | 44 | String sortOrder, |
44 | PageLink pageLink); | 45 | PageLink pageLink); |
45 | 46 | ||
46 | - List<Resource> findAllByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType); | ||
47 | - | ||
48 | void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); | 47 | void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); |
49 | 48 | ||
50 | void deleteResourcesByTenantId(TenantId tenantId); | 49 | void deleteResourcesByTenantId(TenantId tenantId); |
@@ -17,21 +17,9 @@ package org.thingsboard.server.common.data; | @@ -17,21 +17,9 @@ package org.thingsboard.server.common.data; | ||
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | import lombok.extern.slf4j.Slf4j; | 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; | ||
24 | import org.thingsboard.server.common.data.id.TenantId; | 20 | 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; | ||
28 | 21 | ||
29 | -import java.io.ByteArrayInputStream; | ||
30 | -import java.io.IOException; | ||
31 | import java.io.Serializable; | 22 | import java.io.Serializable; |
32 | -import java.util.ArrayList; | ||
33 | -import java.util.Base64; | ||
34 | -import java.util.List; | ||
35 | 23 | ||
36 | @Slf4j | 24 | @Slf4j |
37 | @Data | 25 | @Data |
@@ -55,38 +43,4 @@ public class Resource implements HasTenantId, Serializable { | @@ -55,38 +43,4 @@ public class Resource implements HasTenantId, Serializable { | ||
55 | res.append('}'); | 43 | res.append('}'); |
56 | return res.toString(); | 44 | return res.toString(); |
57 | } | 45 | } |
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 | - } | ||
91 | - } | ||
92 | } | 46 | } |
@@ -95,22 +95,25 @@ public class BaseResourceService implements ResourceService { | @@ -95,22 +95,25 @@ public class BaseResourceService implements ResourceService { | ||
95 | PageData<Resource> resourcePageData = resourceDao.findResourcesByTenantIdAndResourceType( | 95 | PageData<Resource> resourcePageData = resourceDao.findResourcesByTenantIdAndResourceType( |
96 | tenantId, | 96 | tenantId, |
97 | ResourceType.LWM2M_MODEL, pageLink); | 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; | 98 | + return resourcePageData.getData().stream() |
99 | + .map(this::toLwM2mObject) | ||
100 | + .sorted(getComparator(sortProperty, sortOrder)) | ||
101 | + .collect(Collectors.toList()); | ||
100 | } | 102 | } |
101 | 103 | ||
102 | @Override | 104 | @Override |
103 | public List<LwM2mObject> findLwM2mObject(TenantId tenantId, String sortOrder, | 105 | public List<LwM2mObject> findLwM2mObject(TenantId tenantId, String sortOrder, |
104 | String sortProperty, | 106 | String sortProperty, |
105 | - String[] objectIds, | ||
106 | - String searchText) { | 107 | + String[] objectIds) { |
107 | log.trace("Executing findByTenantId [{}]", tenantId); | 108 | log.trace("Executing findByTenantId [{}]", tenantId); |
108 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 109 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
109 | List<Resource> resources = resourceDao.findResourcesByTenantIdAndResourceType(tenantId, ResourceType.LWM2M_MODEL, | 110 | List<Resource> resources = resourceDao.findResourcesByTenantIdAndResourceType(tenantId, ResourceType.LWM2M_MODEL, |
110 | objectIds, | 111 | 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; | 112 | + null); |
113 | + return resources.stream() | ||
114 | + .map(this::toLwM2mObject) | ||
115 | + .sorted(getComparator(sortProperty, sortOrder)) | ||
116 | + .collect(Collectors.toList()); | ||
114 | } | 117 | } |
115 | 118 | ||
116 | @Override | 119 | @Override |
@@ -128,7 +131,7 @@ public class BaseResourceService implements ResourceService { | @@ -128,7 +131,7 @@ public class BaseResourceService implements ResourceService { | ||
128 | throw new DataValidationException("Resource value should be specified!"); | 131 | throw new DataValidationException("Resource value should be specified!"); |
129 | } | 132 | } |
130 | validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId()); | 133 | validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId()); |
131 | - if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && resource.toLwM2mObject() == null) { | 134 | + if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && this.toLwM2mObject(resource) == null) { |
132 | throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getTextSearch())); | 135 | throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getTextSearch())); |
133 | } | 136 | } |
134 | } | 137 | } |
@@ -177,27 +180,14 @@ public class BaseResourceService implements ResourceService { | @@ -177,27 +180,14 @@ public class BaseResourceService implements ResourceService { | ||
177 | } | 180 | } |
178 | } | 181 | } |
179 | 182 | ||
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 | - } | 183 | + private Comparator<? super LwM2mObject> getComparator(String sortProperty, String sortOrder) { |
184 | + Comparator<LwM2mObject> comparator; | ||
185 | + if ("name".equals(sortProperty)) { | ||
186 | + comparator = Comparator.comparing(LwM2mObject::getName); | ||
187 | + } else { | ||
188 | + comparator = Comparator.comparingLong(LwM2mObject::getId); | ||
199 | } | 189 | } |
200 | - return lwM2mObjects; | 190 | + return "DESC".equals(sortOrder) ? comparator.reversed() : comparator; |
201 | } | 191 | } |
202 | 192 | ||
203 | } | 193 | } |
@@ -179,20 +179,6 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V | @@ -179,20 +179,6 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V | ||
179 | return this.lw2mModels; | 179 | return this.lw2mModels; |
180 | } | 180 | } |
181 | 181 | ||
182 | - private getLwM2mModels(): Observable<Array<ObjectLwM2M>> { | ||
183 | - if (!this.lw2mModels) { | ||
184 | - const sortOrder = { | ||
185 | - property: 'id', | ||
186 | - direction: Direction.ASC | ||
187 | - }; | ||
188 | - this.lw2mModels = this.deviceProfileService.getLwm2mObjects(sortOrder).pipe( | ||
189 | - publishReplay(1), | ||
190 | - refCount() | ||
191 | - ); | ||
192 | - } | ||
193 | - return this.lw2mModels; | ||
194 | - } | ||
195 | - | ||
196 | onFocus = (): void => { | 182 | onFocus = (): void => { |
197 | if (!this.dirty) { | 183 | if (!this.dirty) { |
198 | this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true}); | 184 | this.lwm2mListFormGroup.get('objectLwm2m').updateValueAndValidity({onlySelf: true, emitEvent: true}); |