Commit 24ccd2a2b54f5a6cf0de824c862178eb2cba9d63

Authored by Andrew Shvayka
1 parent df6151f5

Revert "[3.2.1] Develop/lwm2m (#3547)"

This reverts commit df6151f5.
Showing 49 changed files with 58 additions and 4439 deletions

Too many changes to show.

To preserve performance only 49 of 575 files are displayed.

@@ -86,10 +86,6 @@ @@ -86,10 +86,6 @@
86 <artifactId>coap</artifactId> 86 <artifactId>coap</artifactId>
87 </dependency> 87 </dependency>
88 <dependency> 88 <dependency>
89 - <groupId>org.thingsboard.common.transport</groupId>  
90 - <artifactId>lwm2m</artifactId>  
91 - </dependency>  
92 - <dependency>  
93 <groupId>org.thingsboard</groupId> 89 <groupId>org.thingsboard</groupId>
94 <artifactId>dao</artifactId> 90 <artifactId>dao</artifactId>
95 </dependency> 91 </dependency>
@@ -62,7 +62,7 @@ public class DeviceActor extends ContextAwareActor { @@ -62,7 +62,7 @@ public class DeviceActor extends ContextAwareActor {
62 processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg); 62 processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg);
63 break; 63 break;
64 case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: 64 case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG:
65 - processor.processCredentialsUpdate(msg); 65 + processor.processCredentialsUpdate();
66 break; 66 break;
67 case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: 67 case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
68 processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); 68 processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg);
@@ -24,7 +24,6 @@ import lombok.extern.slf4j.Slf4j; @@ -24,7 +24,6 @@ import lombok.extern.slf4j.Slf4j;
24 import org.apache.commons.collections.CollectionUtils; 24 import org.apache.commons.collections.CollectionUtils;
25 import org.thingsboard.rule.engine.api.RpcError; 25 import org.thingsboard.rule.engine.api.RpcError;
26 import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; 26 import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
27 -import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg;  
28 import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; 27 import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg;
29 import org.thingsboard.server.actors.ActorSystemContext; 28 import org.thingsboard.server.actors.ActorSystemContext;
30 import org.thingsboard.server.actors.TbActorCtx; 29 import org.thingsboard.server.actors.TbActorCtx;
@@ -37,9 +36,6 @@ import org.thingsboard.server.common.data.kv.AttributeKey; @@ -37,9 +36,6 @@ import org.thingsboard.server.common.data.kv.AttributeKey;
37 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 36 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
38 import org.thingsboard.server.common.data.kv.KvEntry; 37 import org.thingsboard.server.common.data.kv.KvEntry;
39 import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; 38 import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
40 -import org.thingsboard.server.common.data.security.DeviceCredentials;  
41 -import org.thingsboard.server.common.data.security.DeviceCredentialsType;  
42 -import org.thingsboard.server.common.msg.TbActorMsg;  
43 import org.thingsboard.server.common.msg.TbMsgMetaData; 39 import org.thingsboard.server.common.msg.TbMsgMetaData;
44 import org.thingsboard.server.common.msg.queue.TbCallback; 40 import org.thingsboard.server.common.msg.queue.TbCallback;
45 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; 41 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
@@ -65,7 +61,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseM @@ -65,7 +61,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseM
65 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; 61 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
66 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; 62 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
67 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; 63 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
68 -import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;  
69 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; 64 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
70 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; 65 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
71 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; 66 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg;
@@ -455,19 +450,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { @@ -455,19 +450,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
455 dumpSessions(); 450 dumpSessions();
456 } 451 }
457 452
458 - void processCredentialsUpdate(TbActorMsg msg) {  
459 - if (((DeviceCredentialsUpdateNotificationMsg) msg).getDeviceCredentials().getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) {  
460 - log.info("1) LwM2Mtype: ");  
461 - sessions.forEach((k, v) -> {  
462 - notifyTransportAboutProfileUpdate(k, v, ((DeviceCredentialsUpdateNotificationMsg) msg).getDeviceCredentials());  
463 - });  
464 - } else {  
465 - sessions.forEach(this::notifyTransportAboutClosedSession);  
466 - attributeSubscriptions.clear();  
467 - rpcSubscriptions.clear();  
468 - dumpSessions();  
469 -  
470 - } 453 + void processCredentialsUpdate() {
  454 + sessions.forEach(this::notifyTransportAboutClosedSession);
  455 + attributeSubscriptions.clear();
  456 + rpcSubscriptions.clear();
  457 + dumpSessions();
471 } 458 }
472 459
473 private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) { 460 private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) {
@@ -478,18 +465,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { @@ -478,18 +465,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
478 systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg); 465 systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg);
479 } 466 }
480 467
481 - void notifyTransportAboutProfileUpdate(UUID sessionId, SessionInfoMetaData sessionMd, DeviceCredentials deviceCredentials) {  
482 - log.info("2) LwM2Mtype: ");  
483 - TransportProtos.ToTransportUpdateCredentialsProto.Builder notification = TransportProtos.ToTransportUpdateCredentialsProto.newBuilder();  
484 - notification.addCredentialsId(deviceCredentials.getCredentialsId());  
485 - notification.addCredentialsValue(deviceCredentials.getCredentialsValue());  
486 - ToTransportMsg msg = ToTransportMsg.newBuilder()  
487 - .setSessionIdMSB(sessionId.getMostSignificantBits())  
488 - .setSessionIdLSB(sessionId.getLeastSignificantBits())  
489 - .setToTransportUpdateCredentialsNotification(notification).build();  
490 - systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg);  
491 - }  
492 -  
493 void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { 468 void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) {
494 this.deviceName = msg.getDeviceName(); 469 this.deviceName = msg.getDeviceName();
495 this.deviceType = msg.getDeviceType(); 470 this.deviceType = msg.getDeviceType();
@@ -92,7 +92,6 @@ import org.thingsboard.server.queue.discovery.PartitionService; @@ -92,7 +92,6 @@ import org.thingsboard.server.queue.discovery.PartitionService;
92 import org.thingsboard.server.queue.provider.TbQueueProducerProvider; 92 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
93 import org.thingsboard.server.queue.util.TbCoreComponent; 93 import org.thingsboard.server.queue.util.TbCoreComponent;
94 import org.thingsboard.server.service.component.ComponentDiscoveryService; 94 import org.thingsboard.server.service.component.ComponentDiscoveryService;
95 -import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository;  
96 import org.thingsboard.server.service.profile.TbDeviceProfileCache; 95 import org.thingsboard.server.service.profile.TbDeviceProfileCache;
97 import org.thingsboard.server.dao.tenant.TbTenantProfileCache; 96 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
98 import org.thingsboard.server.service.queue.TbClusterService; 97 import org.thingsboard.server.service.queue.TbClusterService;
@@ -212,9 +211,6 @@ public abstract class BaseController { @@ -212,9 +211,6 @@ public abstract class BaseController {
212 @Autowired 211 @Autowired
213 protected TbDeviceProfileCache deviceProfileCache; 212 protected TbDeviceProfileCache deviceProfileCache;
214 213
215 - @Autowired  
216 - protected LwM2MModelsRepository lwM2MModelsRepository;  
217 -  
218 @Value("${server.log_controller_error_stack_trace}") 214 @Value("${server.log_controller_error_stack_trace}")
219 @Getter 215 @Getter
220 private boolean logControllerErrorStackTrace; 216 private boolean logControllerErrorStackTrace;
@@ -278,8 +278,9 @@ public class DeviceController extends BaseController { @@ -278,8 +278,9 @@ public class DeviceController extends BaseController {
278 try { 278 try {
279 Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); 279 Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS);
280 DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); 280 DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials));
281 - //log.info("0 LwM2M CredentialsUpdate start)  
282 - tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null); 281 +
  282 + tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null);
  283 +
283 logEntityAction(device.getId(), device, 284 logEntityAction(device.getId(), device,
284 device.getCustomerId(), 285 device.getCustomerId(),
285 ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); 286 ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.controller;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.springframework.security.access.prepost.PreAuthorize;  
20 -import org.springframework.web.bind.annotation.*;  
21 -import org.thingsboard.server.common.data.exception.ThingsboardException;  
22 -import org.thingsboard.server.common.data.lwm2m.LwM2mObject;  
23 -import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig;  
24 -import org.thingsboard.server.common.data.page.PageData;  
25 -import org.thingsboard.server.common.data.page.PageLink;  
26 -import org.thingsboard.server.queue.util.TbCoreComponent;  
27 -  
28 -import java.util.List;  
29 -  
30 -@Slf4j  
31 -@RestController  
32 -@TbCoreComponent  
33 -@RequestMapping("/api")  
34 -public class DeviceLwm2mController extends BaseController {  
35 -  
36 -  
37 - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")  
38 - @RequestMapping(value = "/lwm2m/deviceProfile/{objectIds}", method = RequestMethod.GET)  
39 - @ResponseBody  
40 - public List<LwM2mObject> getLwm2mListObjects(@PathVariable("objectIds") int[] objectIds) throws ThingsboardException {  
41 - try {  
42 - return lwM2MModelsRepository.getLwm2mObjects(objectIds, null);  
43 - } catch (Exception e) {  
44 - throw handleException(e);  
45 - }  
46 - }  
47 -  
48 - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")  
49 - @RequestMapping(value = "/lwm2m/deviceProfile/objects", params = {"pageSize", "page"}, method = RequestMethod.GET)  
50 - @ResponseBody  
51 - public PageData<LwM2mObject> getLwm2mListObjects(@RequestParam int pageSize,  
52 - @RequestParam int page,  
53 - @RequestParam(required = false) String textSearch,  
54 - @RequestParam(required = false) String sortProperty,  
55 - @RequestParam(required = false) String sortOrder) throws ThingsboardException {  
56 - try {  
57 - PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);  
58 - return checkNotNull(lwM2MModelsRepository.findDeviceLwm2mObjects(getTenantId(), pageLink));  
59 - } catch (Exception e) {  
60 - throw handleException(e);  
61 - }  
62 - }  
63 -  
64 - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")  
65 - @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{securityMode}/{bootstrapServerIs}", method = RequestMethod.GET)  
66 - @ResponseBody  
67 - public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String securityMode,  
68 - @PathVariable("bootstrapServerIs") boolean bootstrapServerIs) throws ThingsboardException {  
69 - try {  
70 - return lwM2MModelsRepository.getBootstrapSecurityInfo(securityMode, bootstrapServerIs);  
71 - } catch (Exception e) {  
72 - throw handleException(e);  
73 - }  
74 - }  
75 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.service.lwm2m;  
17 -  
18 -  
19 -import lombok.extern.slf4j.Slf4j;  
20 -import org.eclipse.leshan.core.model.ObjectModel;  
21 -import org.eclipse.leshan.core.util.Hex;  
22 -import org.springframework.beans.factory.annotation.Autowired;  
23 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
24 -import org.springframework.data.domain.PageImpl;  
25 -import org.springframework.stereotype.Service;  
26 -import org.thingsboard.server.common.data.lwm2m.*;  
27 -import org.thingsboard.server.common.data.id.TenantId;  
28 -import org.thingsboard.server.common.data.page.PageData;  
29 -import org.thingsboard.server.common.data.page.PageLink;  
30 -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap;  
31 -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer;  
32 -import org.thingsboard.server.dao.service.Validator;  
33 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
34 -  
35 -import java.math.BigInteger;  
36 -import java.security.*;  
37 -import java.security.cert.CertificateEncodingException;  
38 -import java.security.cert.X509Certificate;  
39 -import java.security.spec.ECGenParameterSpec;  
40 -import java.security.spec.ECParameterSpec;  
41 -import java.security.spec.ECPublicKeySpec;  
42 -import java.security.spec.ECPoint;  
43 -import java.security.spec.KeySpec;  
44 -import java.util.List;  
45 -import java.util.ArrayList;  
46 -import java.util.function.Predicate;  
47 -import java.util.stream.Collectors;  
48 -import java.util.stream.IntStream;  
49 -  
50 -import static org.thingsboard.server.dao.service.Validator.validateId;  
51 -  
52 -@Slf4j  
53 -@Service  
54 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'")  
55 -public class LwM2MModelsRepository {  
56 -  
57 - private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";  
58 -  
59 - @Autowired  
60 - LwM2MTransportConfigServer contextServer;  
61 -  
62 -  
63 - @Autowired  
64 - LwM2MTransportConfigBootstrap contextBootStrap;  
65 -  
66 - /**  
67 - * @param objectIds  
68 - * @param textSearch  
69 - * @return list of LwM2mObject  
70 - * Filter by Predicate (uses objectIds, if objectIds is null then it uses textSearch,  
71 - * if textSearch is null then it uses AllList from List<ObjectModel>)  
72 - */  
73 - public List<LwM2mObject> getLwm2mObjects(int[] objectIds, String textSearch) {  
74 - return getLwm2mObjects((objectIds != null && objectIds.length > 0) ?  
75 - (ObjectModel element) -> IntStream.of(objectIds).anyMatch(x -> x == element.id) :  
76 - (textSearch != null && !textSearch.isEmpty()) ? (ObjectModel element) -> element.name.contains(textSearch) : null);  
77 - }  
78 -  
79 - /**  
80 - * @param predicate  
81 - * @return list of LwM2mObject  
82 - */  
83 - private List<LwM2mObject> getLwm2mObjects(Predicate<? super ObjectModel> predicate) {  
84 - List<LwM2mObject> lwM2mObjects = new ArrayList<>();  
85 - List<ObjectModel> listObjects = (predicate == null) ? this.contextServer.getModelsValue() :  
86 - contextServer.getModelsValue().stream()  
87 - .filter(predicate)  
88 - .collect(Collectors.toList());  
89 - listObjects.forEach(obj -> {  
90 - LwM2mObject lwM2mObject = new LwM2mObject();  
91 - lwM2mObject.setId(obj.id);  
92 - lwM2mObject.setName(obj.name);  
93 - lwM2mObject.setMultiple(obj.multiple);  
94 - lwM2mObject.setMandatory(obj.mandatory);  
95 - LwM2mInstance instance = new LwM2mInstance();  
96 - instance.setId(0);  
97 - List<LwM2mResource> resources = new ArrayList<>();  
98 - obj.resources.forEach((k, v) -> {  
99 - if (!v.operations.isExecutable()) {  
100 - LwM2mResource resource = new LwM2mResource(k, v.name, false, false, false);  
101 - resources.add(resource);  
102 - }  
103 - });  
104 - instance.setResources(resources.stream().toArray(LwM2mResource[]::new));  
105 - lwM2mObject.setInstances(new LwM2mInstance[]{instance});  
106 - lwM2mObjects.add(lwM2mObject);  
107 - });  
108 - return lwM2mObjects;  
109 - }  
110 -  
111 - /**  
112 - * @param tenantId  
113 - * @param pageLink  
114 - * @return List of LwM2mObject in PageData format  
115 - */  
116 - public PageData<LwM2mObject> findDeviceLwm2mObjects(TenantId tenantId, PageLink pageLink) {  
117 - log.trace("Executing findDeviceProfileInfos tenantId [{}], pageLink [{}]", tenantId, pageLink);  
118 - validateId(tenantId, INCORRECT_TENANT_ID + tenantId);  
119 - Validator.validatePageLink(pageLink);  
120 - return this.findLwm2mListObjects(pageLink);  
121 - }  
122 -  
123 - /**  
124 - * @param pageLink  
125 - * @return List of LwM2mObject in PageData format, filter == TextSearch  
126 - * PageNumber = 1, PageSize = List<LwM2mObject>.size()  
127 - */  
128 - public PageData<LwM2mObject> findLwm2mListObjects(PageLink pageLink) {  
129 - PageImpl page = new PageImpl(getLwm2mObjects(null, pageLink.getTextSearch()));  
130 - PageData pageData = new PageData(page.getContent(), page.getTotalPages(), page.getTotalElements(), page.hasNext());  
131 - return pageData;  
132 - }  
133 -  
134 - /**  
135 - *  
136 - * @param securityMode  
137 - * @param bootstrapServerIs  
138 - * @return ServerSecurityConfig more value is default: Important - port, host, publicKey  
139 - */  
140 - public ServerSecurityConfig getBootstrapSecurityInfo(String securityMode, boolean bootstrapServerIs) {  
141 - LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(securityMode.toLowerCase());  
142 - return getBootstrapServer(bootstrapServerIs, lwM2MSecurityMode);  
143 - }  
144 -  
145 - /**  
146 - *  
147 - * @param bootstrapServerIs  
148 - * @param mode  
149 - * @return ServerSecurityConfig more value is default: Important - port, host, publicKey  
150 - */  
151 - private ServerSecurityConfig getBootstrapServer(boolean bootstrapServerIs, LwM2MSecurityMode mode) {  
152 - ServerSecurityConfig bsServ = new ServerSecurityConfig();  
153 - if (bootstrapServerIs) {  
154 - switch (mode) {  
155 - case NO_SEC:  
156 - bsServ.setHost(contextBootStrap.getBootstrapHost());  
157 - bsServ.setPort(contextBootStrap.getBootstrapPort());  
158 - bsServ.setServerPublicKey("");  
159 - break;  
160 - case PSK:  
161 - bsServ.setHost(contextBootStrap.getBootstrapSecureHost());  
162 - bsServ.setPort(contextBootStrap.getBootstrapSecurePort());  
163 - bsServ.setServerPublicKey("");  
164 - break;  
165 - case RPK:  
166 - bsServ.setHost(contextBootStrap.getBootstrapSecureHost());  
167 - bsServ.setPort(contextBootStrap.getBootstrapSecurePort());  
168 - bsServ.setServerPublicKey(getRPKPublicKey(this.contextBootStrap.getBootstrapPublicX(), this.contextBootStrap.getBootstrapPublicY()));  
169 - break;  
170 - case X509:  
171 - bsServ.setHost(contextBootStrap.getBootstrapSecureHost());  
172 - bsServ.setPort(contextBootStrap.getBootstrapSecurePortCert());  
173 - bsServ.setServerPublicKey(getServerPublicKeyX509(contextBootStrap.getBootstrapAlias()));  
174 - break;  
175 - default:  
176 - break;  
177 - }  
178 - } else {  
179 - bsServ.setBootstrapServerIs(bootstrapServerIs);  
180 - bsServ.setServerId(123);  
181 - switch (mode) {  
182 - case NO_SEC:  
183 - bsServ.setHost(contextServer.getServerHost());  
184 - bsServ.setPort(contextServer.getServerPort());  
185 - bsServ.setServerPublicKey("");  
186 - break;  
187 - case PSK:  
188 - bsServ.setHost(contextServer.getServerSecureHost());  
189 - bsServ.setPort(contextServer.getServerSecurePort());  
190 - bsServ.setServerPublicKey("");  
191 - break;  
192 - case RPK:  
193 - bsServ.setHost(contextServer.getServerSecureHost());  
194 - bsServ.setPort(contextServer.getServerSecurePort());  
195 - bsServ.setServerPublicKey(getRPKPublicKey(this.contextServer.getServerPublicX(), this.contextServer.getServerPublicY()));  
196 - break;  
197 - case X509:  
198 - bsServ.setHost(contextServer.getServerSecureHost());  
199 - bsServ.setPort(contextServer.getServerSecurePortCert());  
200 - bsServ.setServerPublicKey(getServerPublicKeyX509(contextServer.getServerAlias()));  
201 - break;  
202 - default:  
203 - break;  
204 - }  
205 - }  
206 - return bsServ;  
207 - }  
208 -  
209 - /**  
210 - *  
211 - * @param alias  
212 - * @return PublicKey format HexString or null  
213 - */  
214 - private String getServerPublicKeyX509 (String alias) {  
215 - try {  
216 - X509Certificate serverCertificate = (X509Certificate) contextServer.getKeyStoreValue().getCertificate(alias);  
217 - return Hex.encodeHexString(serverCertificate.getEncoded());  
218 - } catch (CertificateEncodingException | KeyStoreException e) {  
219 - e.printStackTrace();  
220 - }  
221 - return null;  
222 - }  
223 -  
224 - /**  
225 - *  
226 - * @param publicServerX  
227 - * @param publicServerY  
228 - * @return PublicKey format HexString or null  
229 - */  
230 - private String getRPKPublicKey(String publicServerX, String publicServerY) {  
231 - try {  
232 - /** Get Elliptic Curve Parameter spec for secp256r1 */  
233 - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");  
234 - algoParameters.init(new ECGenParameterSpec("secp256r1"));  
235 - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);  
236 - if (publicServerX != null && !publicServerX.isEmpty() && publicServerY != null && !publicServerY.isEmpty()) {  
237 - /** Get point values */  
238 - byte[] publicX = Hex.decodeHex(publicServerX.toCharArray());  
239 - byte[] publicY = Hex.decodeHex(publicServerY.toCharArray());  
240 - /** Create key specs */  
241 - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),  
242 - parameterSpec);  
243 - /** Get keys */  
244 - PublicKey publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);  
245 - if (publicKey != null && publicKey.getEncoded().length > 0 ) {  
246 - return Hex.encodeHexString(publicKey.getEncoded());  
247 - }  
248 - }  
249 - } catch (GeneralSecurityException | IllegalArgumentException e) {  
250 - log.error("[{}] Failed generate Server RPK for profile", e.getMessage());  
251 - throw new RuntimeException(e);  
252 - }  
253 - return null;  
254 - }  
255 -}  
256 -  
@@ -53,8 +53,6 @@ public class DefaultDeviceAuthService implements DeviceAuthService { @@ -53,8 +53,6 @@ public class DefaultDeviceAuthService implements DeviceAuthService {
53 return DeviceAuthResult.of(credentials.getDeviceId()); 53 return DeviceAuthResult.of(credentials.getDeviceId());
54 case X509_CERTIFICATE: 54 case X509_CERTIFICATE:
55 return DeviceAuthResult.of(credentials.getDeviceId()); 55 return DeviceAuthResult.of(credentials.getDeviceId());
56 - case LWM2M_CREDENTIALS:  
57 - return DeviceAuthResult.of(credentials.getDeviceId());  
58 default: 56 default:
59 return DeviceAuthResult.of("Credentials Type is not supported yet!"); 57 return DeviceAuthResult.of("Credentials Type is not supported yet!");
60 } 58 }
@@ -67,4 +65,4 @@ public class DefaultDeviceAuthService implements DeviceAuthService { @@ -67,4 +65,4 @@ public class DefaultDeviceAuthService implements DeviceAuthService {
67 } 65 }
68 } 66 }
69 67
70 -} 68 +}
@@ -201,7 +201,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer @@ -201,7 +201,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
201 } 201 }
202 202
203 @Override 203 @Override
204 -  
205 public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) { 204 public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) {
206 saveAndNotify(tenantId, entityId, scope, attributes, true, callback); 205 saveAndNotify(tenantId, entityId, scope, attributes, true, callback);
207 } 206 }
@@ -69,7 +69,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponse @@ -69,7 +69,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponse
69 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; 69 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
70 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; 70 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
71 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; 71 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
72 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;  
73 import org.thingsboard.server.queue.common.TbProtoQueueMsg; 72 import org.thingsboard.server.queue.common.TbProtoQueueMsg;
74 import org.thingsboard.server.queue.util.TbCoreComponent; 73 import org.thingsboard.server.queue.util.TbCoreComponent;
75 import org.thingsboard.server.dao.device.provision.ProvisionFailedException; 74 import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
@@ -150,13 +149,6 @@ public class DefaultTransportApiService implements TransportApiService { @@ -150,13 +149,6 @@ public class DefaultTransportApiService implements TransportApiService {
150 } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { 149 } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
151 return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()), 150 return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()),
152 value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); 151 value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());
153 - } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) {  
154 - return Futures.transform(handle(transportApiRequestMsg.getLwM2MRequestMsg()),  
155 - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());  
156 - } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) {  
157 - ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg();  
158 - return Futures.transform(validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS),  
159 - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());  
160 } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { 152 } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) {
161 return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), 153 return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()),
162 value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); 154 value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());
@@ -404,40 +396,4 @@ public class DefaultTransportApiService implements TransportApiService { @@ -404,40 +396,4 @@ public class DefaultTransportApiService implements TransportApiService {
404 return TransportApiResponseMsg.newBuilder() 396 return TransportApiResponseMsg.newBuilder()
405 .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build(); 397 .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build();
406 } 398 }
407 -  
408 - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.LwM2MRequestMsg requestMsg) {  
409 - if (requestMsg.hasRegistrationMsg()) {  
410 - return handleRegistration(requestMsg.getRegistrationMsg());  
411 - } else {  
412 - return Futures.immediateFailedFuture(new RuntimeException("Not supported!"));  
413 - }  
414 - }  
415 -  
416 - private ListenableFuture<TransportApiResponseMsg> handleRegistration(TransportProtos.LwM2MRegistrationRequestMsg msg) {  
417 - TenantId tenantId = new TenantId(UUID.fromString(msg.getTenantId()));  
418 - String deviceName = msg.getEndpoint();  
419 - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock());  
420 - deviceCreationLock.lock();  
421 - try {  
422 - Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);  
423 - if (device == null) {  
424 - device = new Device();  
425 - device.setTenantId(tenantId);  
426 - device.setName(deviceName);  
427 - device.setType("LwM2M");  
428 - device = deviceService.saveDevice(device);  
429 - deviceStateService.onDeviceAdded(device);  
430 - }  
431 - TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg =  
432 - TransportProtos.LwM2MRegistrationResponseMsg.newBuilder()  
433 - .setDeviceInfo(getDeviceInfoProto(device)).build();  
434 - TransportProtos.LwM2MResponseMsg responseMsg = TransportProtos.LwM2MResponseMsg.newBuilder().setRegistrationMsg(registrationResponseMsg).build();  
435 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build());  
436 - } catch (JsonProcessingException e) {  
437 - log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e);  
438 - throw new RuntimeException(e);  
439 - } finally {  
440 - deviceCreationLock.unlock();  
441 - }  
442 - }  
443 } 399 }
1 - ______ __ _ __ __  
2 - /_ __/ / /_ (_) ____ ____ _ _____ / /_ ____ ____ _ _____ ____/ /  
3 - / / / __ \ / / / __ \ / __ `/ / ___/ / __ \ / __ \ / __ `/ / ___/ / __ /  
4 - / / / / / / / / / / / / / /_/ / (__ ) / /_/ // /_/ // /_/ / / / / /_/ /  
5 -/_/ /_/ /_/ /_/ /_/ /_/ \__, / /____/ /_.___/ \____/ \__,_/ /_/ \__,_/  
6 - /____/  
7 -  
8 =================================================== 1 ===================================================
9 :: ${application.title} :: ${application.formatted-version} 2 :: ${application.title} :: ${application.formatted-version}
10 =================================================== 3 ===================================================
@@ -433,7 +433,7 @@ spring: @@ -433,7 +433,7 @@ spring:
433 database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}" 433 database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}"
434 datasource: 434 datasource:
435 driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}" 435 driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}"
436 - url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_ce_3_2_2}" 436 + url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard}"
437 username: "${SPRING_DATASOURCE_USERNAME:postgres}" 437 username: "${SPRING_DATASOURCE_USERNAME:postgres}"
438 password: "${SPRING_DATASOURCE_PASSWORD:postgres}" 438 password: "${SPRING_DATASOURCE_PASSWORD:postgres}"
439 hikari: 439 hikari:
@@ -488,7 +488,7 @@ js: @@ -488,7 +488,7 @@ js:
488 # Built-in JVM JavaScript environment properties 488 # Built-in JVM JavaScript environment properties
489 local: 489 local:
490 # Use Sandboxed (secured) JVM JavaScript environment 490 # Use Sandboxed (secured) JVM JavaScript environment
491 - use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:false}" 491 + use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:true}"
492 # Specify thread pool size for JavaScript sandbox resource monitor 492 # Specify thread pool size for JavaScript sandbox resource monitor
493 monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" 493 monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}"
494 # Maximum CPU time in milliseconds allowed for script execution 494 # Maximum CPU time in milliseconds allowed for script execution
@@ -565,74 +565,6 @@ transport: @@ -565,74 +565,6 @@ transport:
565 bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" 565 bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}"
566 bind_port: "${COAP_BIND_PORT:5683}" 566 bind_port: "${COAP_BIND_PORT:5683}"
567 timeout: "${COAP_TIMEOUT:10000}" 567 timeout: "${COAP_TIMEOUT:10000}"
568 - # Local LwM2M transport parameters  
569 - lwm2m:  
570 - # Enable/disable lvm2m transport protocol.  
571 - enabled: "${LWM2M_ENABLED:true}"  
572 - # We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to  
573 - # send a Confirmable message to the time when an acknowledgement is no longer expected.  
574 - # DEFAULT_TIMEOUT = 2 * 60 * 1000l; 2 min in ms  
575 - timeout: "${LWM2M_TIMEOUT:120000}"  
576 -# model_path_file: "${LWM2M_MODEL_PATH_FILE:./common/transport/lwm2m/src/main/resources/models/}"  
577 - model_path_file: "${LWM2M_MODEL_PATH_FILE:}"  
578 - support_deprecated_ciphers_enable: "${LWM2M_SUPPORT_DEPRECATED_CIPHERS_ENABLED:true}"  
579 - secure:  
580 - # Only Certificate_x509:  
581 - # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format  
582 - # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh  
583 - key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}"  
584 - # key_store_type: "${LWM2M_KEYSTORE_TYPE:PKCS12}"  
585 -# key_store_path_file: "${KEY_STORE_PATH_FILE:/usr/share/thingsboard/conf/credentials/serverKeyStore.jks}"  
586 - key_store_path_file: "${KEY_STORE_PATH_FILE:}"  
587 - key_store_password: "${LWM2M_KEYSTORE_PASSWORD_SERVER:server_ks_password}"  
588 - root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}"  
589 - enable_gen_psk_rpk: "${ENABLE_GEN_PSK_RPK:true}"  
590 - server:  
591 - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}"  
592 - bind_port: "${LWM2M_BIND_PORT:5685}"  
593 - bind_port_cert: "${LWM2M_BIND_PORT_CERT:5687}"  
594 - secure:  
595 - start_all: "${START_SERVER_ALL:true}"  
596 - #leshan.core (V1_1)  
597 - #DTLS security modes:  
598 - #0: Pre-Shared Key mode  
599 - #1: Raw Public Key mode  
600 - #2: Certificate mode X509  
601 - #3: NoSec mode *  
602 - #OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A (add)  
603 - #4: Certificate mode X509 with EST  
604 - # If only startAll == false  
605 - dtls_mode: "${LWM2M_SECURITY_MODE:1}"  
606 - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}"  
607 - bind_port: "${LWM2M_BIND_PORT_SEC:5686}"  
608 - bind_port_cert: "${LWM2M_BIND_PORT_SEC_CERT:5688}"  
609 - # Only RPK: Public & Private Key  
610 -# create_rpk: "${CREATE_RPK:}"  
611 - public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}"  
612 - public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}"  
613 - private_s: "${LWM2M_SERVER_PRIVATE_S:274671fe40ce937b8a6352cf0a418e8a39e4bf0bb9bf74c910db953c20c73802}"  
614 - # Only Certificate_x509:  
615 - alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"  
616 - bootstrap:  
617 - enable: "${BOOTSTRAP:true}"  
618 - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"  
619 - bind_port: "${LWM2M_BIND_PORT_BS:5689}"  
620 - bind_port_cert: "${LWM2M_BIND_PORT_SER_BS:5691}"  
621 - secure:  
622 - start_all: "${START_BOOTSTRAP_ALL:true}"  
623 - # If only startAll == false  
624 - dtls_mode: "${LWM2M_SECURITY_MODE_BS:1}"  
625 - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"  
626 - bind_port: "${LWM2M_BIND_PORT_SEC_BS:5690}"  
627 - bind_port_cert: "${LWM2M_BIND_PORT_SEC_CERT_BS:5692}"  
628 - # Only RPK: Public & Private Key  
629 - public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}"  
630 - public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}"  
631 - private_s: "${LWM2M_SERVER_PRIVATE_S_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}"  
632 - # Only Certificate_x509:  
633 - alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}"  
634 - # Redis  
635 - redis_url: "${LWM2M_REDIS_URL:''}"  
636 568
637 swagger: 569 swagger:
638 api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}" 570 api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}"
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.common.data.lwm2m;  
17 -  
18 -import lombok.Data;  
19 -  
20 -@Data  
21 -public class LwM2mInstance {  
22 - int id;  
23 - LwM2mResource [] resources;  
24 -  
25 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.common.data.lwm2m;  
17 -  
18 -import lombok.Data;  
19 -  
20 -@Data  
21 -public class LwM2mObject {  
22 - int id;  
23 - String name;  
24 - boolean multiple;  
25 - boolean mandatory;  
26 - LwM2mInstance [] instances;  
27 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.common.data.lwm2m;  
17 -  
18 -import lombok.AllArgsConstructor;  
19 -import lombok.Data;  
20 -  
21 -import java.util.stream.Stream;  
22 -  
23 -@Data  
24 -@AllArgsConstructor  
25 -public class LwM2mResource {  
26 - int id;  
27 - String name;  
28 - boolean observe;  
29 - boolean attribute;  
30 - boolean telemetry;  
31 - String keyName;  
32 -  
33 - public LwM2mResource(int id, String name, boolean observe, boolean attribute, boolean telemetry) {  
34 - this.id = id;  
35 - this.name = name;  
36 - this.observe = observe;  
37 - this.attribute = attribute;  
38 - this.telemetry = telemetry;  
39 - this.keyName = getCamelCase (this.name);  
40 - }  
41 -  
42 - private String getCamelCase (String name) {  
43 - name = name.replaceAll("-", " ");  
44 - name = name.replaceAll("_", " ");  
45 - String [] nameCamel1 = name.split(" ");  
46 - String [] nameCamel2 = new String[nameCamel1.length];  
47 - int[] idx = { 0 };  
48 - Stream.of(nameCamel1).forEach((s -> {  
49 - nameCamel2[idx[0]] = toProperCase(idx[0]++, s);  
50 - }));  
51 - return String.join("", nameCamel2);  
52 - }  
53 -  
54 - private String toProperCase(int idx, String s) {  
55 - if (!s.isEmpty() && s.length()> 0) {  
56 - String s1 = (idx == 0) ? s.substring(0, 1).toLowerCase() : s.substring(0, 1).toUpperCase();  
57 - String s2 = "";  
58 - if (s.length()> 1) s2 = s.substring(1).toLowerCase();  
59 - s = s1 + s2;  
60 - }  
61 - return s;  
62 - }  
63 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.common.data.lwm2m;  
17 -  
18 -import lombok.Builder;  
19 -import lombok.Data;  
20 -  
21 -@Data  
22 -public class ServerSecurityConfig {  
23 - String host;  
24 - Integer port;  
25 - String serverPublicKey;  
26 - @Builder.Default  
27 - boolean bootstrapServerIs = true;  
28 - @Builder.Default  
29 - Integer clientHoldOffTime = 1;  
30 - @Builder.Default  
31 - Integer serverId = 111;  
32 - @Builder.Default  
33 - Integer bootstrapServerAccountTimeout = 0;  
34 -}  
@@ -19,8 +19,6 @@ public enum DeviceCredentialsType { @@ -19,8 +19,6 @@ public enum DeviceCredentialsType {
19 19
20 ACCESS_TOKEN, 20 ACCESS_TOKEN,
21 X509_CERTIFICATE, 21 X509_CERTIFICATE,
22 - MQTT_BASIC,  
23 - LWM2M_CREDENTIALS  
24 - 22 + MQTT_BASIC
25 23
26 } 24 }
@@ -183,47 +183,6 @@ message GetEntityProfileRequestMsg { @@ -183,47 +183,6 @@ message GetEntityProfileRequestMsg {
183 int64 entityIdLSB = 3; 183 int64 entityIdLSB = 3;
184 } 184 }
185 185
186 -message LwM2MRegistrationRequestMsg {  
187 - string tenantId = 1;  
188 - string endpoint = 2;  
189 -}  
190 -  
191 -message LwM2MRegistrationResponseMsg {  
192 - DeviceInfoProto deviceInfo = 1;  
193 -}  
194 -  
195 -message LwM2MRequestMsg {  
196 - LwM2MRegistrationRequestMsg registrationMsg = 1;  
197 -}  
198 -  
199 -message LwM2MResponseMsg {  
200 - LwM2MRegistrationResponseMsg registrationMsg = 1;  
201 -}  
202 -  
203 -message ValidateDeviceLwM2MCredentialsRequestMsg {  
204 - string credentialsId = 1;  
205 -}  
206 -  
207 -message ToTransportUpdateCredentialsProto {  
208 - repeated string credentialsId = 1;  
209 - repeated string credentialsValue = 2;  
210 -}  
211 -  
212 -message GetTenantRoutingInfoRequestMsg {  
213 - int64 tenantIdMSB = 1;  
214 - int64 tenantIdLSB = 2;  
215 -}  
216 -  
217 -message GetTenantRoutingInfoResponseMsg {  
218 - bool isolatedTbCore = 1;  
219 - bool isolatedTbRuleEngine = 2;  
220 -}  
221 -  
222 -message GetDeviceProfileRequestMsg {  
223 - int64 profileIdMSB = 1;  
224 - int64 profileIdLSB = 2;  
225 -}  
226 -  
227 message GetEntityProfileResponseMsg { 186 message GetEntityProfileResponseMsg {
228 string entityType = 1; 187 string entityType = 1;
229 bytes data = 2; 188 bytes data = 2;
@@ -520,10 +479,8 @@ message TransportApiRequestMsg { @@ -520,10 +479,8 @@ message TransportApiRequestMsg {
520 ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2; 479 ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2;
521 GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3; 480 GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3;
522 GetEntityProfileRequestMsg entityProfileRequestMsg = 4; 481 GetEntityProfileRequestMsg entityProfileRequestMsg = 4;
523 - LwM2MRequestMsg lwM2MRequestMsg = 5;  
524 ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; 482 ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6;
525 ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; 483 ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7;
526 - ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8;  
527 } 484 }
528 485
529 /* Response from ThingsBoard Core Service to Transport Service */ 486 /* Response from ThingsBoard Core Service to Transport Service */
@@ -532,7 +489,6 @@ message TransportApiResponseMsg { @@ -532,7 +489,6 @@ message TransportApiResponseMsg {
532 GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; 489 GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2;
533 GetEntityProfileResponseMsg entityProfileResponseMsg = 3; 490 GetEntityProfileResponseMsg entityProfileResponseMsg = 3;
534 ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; 491 ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4;
535 - LwM2MResponseMsg lwM2MResponseMsg = 6;  
536 } 492 }
537 493
538 /* Messages that are handled by ThingsBoard Core Service */ 494 /* Messages that are handled by ThingsBoard Core Service */
@@ -573,10 +529,10 @@ message ToTransportMsg { @@ -573,10 +529,10 @@ message ToTransportMsg {
573 AttributeUpdateNotificationMsg attributeUpdateNotification = 5; 529 AttributeUpdateNotificationMsg attributeUpdateNotification = 5;
574 ToDeviceRpcRequestMsg toDeviceRequest = 6; 530 ToDeviceRpcRequestMsg toDeviceRequest = 6;
575 ToServerRpcResponseMsg toServerResponse = 7; 531 ToServerRpcResponseMsg toServerResponse = 7;
  532 + /* For Tenant, TenantProfile and DeviceProfile */
576 EntityUpdateMsg entityUpdateMsg = 8; 533 EntityUpdateMsg entityUpdateMsg = 8;
577 EntityDeleteMsg entityDeleteMsg = 9; 534 EntityDeleteMsg entityDeleteMsg = 9;
578 ProvisionDeviceResponseMsg provisionResponse = 10; 535 ProvisionDeviceResponseMsg provisionResponse = 10;
579 - ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11;  
580 } 536 }
581 537
582 message UsageStatsKVProto{ 538 message UsageStatsKVProto{
@@ -24,7 +24,6 @@ import org.springframework.stereotype.Component; @@ -24,7 +24,6 @@ import org.springframework.stereotype.Component;
24 import org.thingsboard.server.common.transport.TransportContext; 24 import org.thingsboard.server.common.transport.TransportContext;
25 import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; 25 import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor;
26 26
27 -  
28 /** 27 /**
29 * Created by ashvayka on 18.10.18. 28 * Created by ashvayka on 18.10.18.
30 */ 29 */
@@ -16,15 +16,14 @@ @@ -16,15 +16,14 @@
16 package org.thingsboard.server.transport.coap; 16 package org.thingsboard.server.transport.coap;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 -import org.eclipse.californium.core.CoapObserveRelation;  
20 import org.eclipse.californium.core.CoapResource; 19 import org.eclipse.californium.core.CoapResource;
21 -import org.eclipse.californium.core.coap.CoAP;  
22 import org.eclipse.californium.core.coap.CoAP.ResponseCode; 20 import org.eclipse.californium.core.coap.CoAP.ResponseCode;
23 import org.eclipse.californium.core.coap.Request; 21 import org.eclipse.californium.core.coap.Request;
24 -import org.eclipse.californium.core.network.Endpoint;  
25 import org.eclipse.californium.core.network.Exchange; 22 import org.eclipse.californium.core.network.Exchange;
  23 +import org.eclipse.californium.core.network.ExchangeObserver;
26 import org.eclipse.californium.core.server.resources.CoapExchange; 24 import org.eclipse.californium.core.server.resources.CoapExchange;
27 import org.eclipse.californium.core.server.resources.Resource; 25 import org.eclipse.californium.core.server.resources.Resource;
  26 +import org.springframework.util.ReflectionUtils;
28 import org.thingsboard.server.common.data.DataConstants; 27 import org.thingsboard.server.common.data.DataConstants;
29 import org.thingsboard.server.common.data.DeviceTransportType; 28 import org.thingsboard.server.common.data.DeviceTransportType;
30 import org.thingsboard.server.common.data.security.DeviceTokenCredentials; 29 import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
@@ -41,26 +40,26 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes @@ -41,26 +40,26 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes
41 import org.thingsboard.server.gen.transport.TransportProtos; 40 import org.thingsboard.server.gen.transport.TransportProtos;
42 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; 41 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
43 42
  43 +import java.lang.reflect.Field;
44 import java.util.List; 44 import java.util.List;
45 import java.util.Optional; 45 import java.util.Optional;
46 import java.util.Set; 46 import java.util.Set;
47 import java.util.UUID; 47 import java.util.UUID;
48 -import java.util.Timer;  
49 -import java.util.TimerTask;  
50 import java.util.concurrent.ConcurrentHashMap; 48 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.concurrent.ConcurrentMap; 49 import java.util.concurrent.ConcurrentMap;
52 -import java.util.concurrent.ScheduledThreadPoolExecutor;  
53 import java.util.concurrent.atomic.AtomicInteger; 50 import java.util.concurrent.atomic.AtomicInteger;
54 import java.util.function.Consumer; 51 import java.util.function.Consumer;
55 52
56 @Slf4j 53 @Slf4j
57 public class CoapTransportResource extends CoapResource { 54 public class CoapTransportResource extends CoapResource {
  55 + // coap://localhost:port/api/v1/DEVICE_TOKEN/[attributes|telemetry|rpc[/requestId]]
58 private static final int ACCESS_TOKEN_POSITION = 3; 56 private static final int ACCESS_TOKEN_POSITION = 3;
59 private static final int FEATURE_TYPE_POSITION = 4; 57 private static final int FEATURE_TYPE_POSITION = 4;
60 private static final int REQUEST_ID_POSITION = 5; 58 private static final int REQUEST_ID_POSITION = 5;
61 59
62 private final CoapTransportContext transportContext; 60 private final CoapTransportContext transportContext;
63 private final TransportService transportService; 61 private final TransportService transportService;
  62 + private final Field observerField;
64 private final long timeout; 63 private final long timeout;
65 private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>(); 64 private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>();
66 private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet(); 65 private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet();
@@ -74,20 +73,9 @@ public class CoapTransportResource extends CoapResource { @@ -74,20 +73,9 @@ public class CoapTransportResource extends CoapResource {
74 // This is important to turn off existing observable logic in 73 // This is important to turn off existing observable logic in
75 // CoapResource. We will have our own observe monitoring due to 1:1 74 // CoapResource. We will have our own observe monitoring due to 1:1
76 // observe relationship. 75 // observe relationship.
77 - this.setObservable(true); // enable observing  
78 - this.setObserveType(CoAP.Type.CON); // configure the notification type to CONs  
79 - this.getAttributes().setObservable(); // mark observable in the Link-Format  
80 - // schedule a periodic update task, otherwise let events call changed()  
81 - Timer timer = new Timer();  
82 - timer.schedule(new UpdateTask(), 0, 5000);  
83 - }  
84 -  
85 - private class UpdateTask extends TimerTask {  
86 - @Override  
87 - public void run() {  
88 - // .. periodic update of the resource  
89 - changed(); // notify all observers  
90 - } 76 + this.setObservable(false);
  77 + observerField = ReflectionUtils.findField(Exchange.class, "observer");
  78 + observerField.setAccessible(true);
91 } 79 }
92 80
93 @Override 81 @Override
@@ -199,7 +187,9 @@ public class CoapTransportResource extends CoapResource { @@ -199,7 +187,9 @@ public class CoapTransportResource extends CoapResource {
199 new CoapOkCallback(exchange)); 187 new CoapOkCallback(exchange));
200 break; 188 break;
201 case SUBSCRIBE_ATTRIBUTES_REQUEST: 189 case SUBSCRIBE_ATTRIBUTES_REQUEST:
202 - transportService.registerSyncSession(sessionInfo, new CoapSessionListener(sessionId, exchange), transportContext.getTimeout()); 190 + attributeSubscriptions.add(sessionId);
  191 + advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced),
  192 + registerAsyncCoapSession(exchange, request, sessionInfo, sessionId)));
203 transportService.process(sessionInfo, 193 transportService.process(sessionInfo,
204 TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), 194 TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(),
205 new CoapNoOpCallback(exchange)); 195 new CoapNoOpCallback(exchange));
@@ -216,6 +206,8 @@ public class CoapTransportResource extends CoapResource { @@ -216,6 +206,8 @@ public class CoapTransportResource extends CoapResource {
216 break; 206 break;
217 case SUBSCRIBE_RPC_COMMANDS_REQUEST: 207 case SUBSCRIBE_RPC_COMMANDS_REQUEST:
218 rpcSubscriptions.add(sessionId); 208 rpcSubscriptions.add(sessionId);
  209 + advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced),
  210 + registerAsyncCoapSession(exchange, request, sessionInfo, sessionId)));
219 transportService.process(sessionInfo, 211 transportService.process(sessionInfo,
220 TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), 212 TransportProtos.SubscribeToRPCMsg.getDefaultInstance(),
221 new CoapNoOpCallback(exchange)); 213 new CoapNoOpCallback(exchange));
@@ -251,6 +243,9 @@ public class CoapTransportResource extends CoapResource { @@ -251,6 +243,9 @@ public class CoapTransportResource extends CoapResource {
251 } catch (AdaptorException e) { 243 } catch (AdaptorException e) {
252 log.trace("[{}] Failed to decode message: ", sessionId, e); 244 log.trace("[{}] Failed to decode message: ", sessionId, e);
253 exchange.respond(ResponseCode.BAD_REQUEST); 245 exchange.respond(ResponseCode.BAD_REQUEST);
  246 + } catch (IllegalAccessException e) {
  247 + log.trace("[{}] Failed to process message: ", sessionId, e);
  248 + exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR);
254 } 249 }
255 })); 250 }));
256 } 251 }
@@ -464,17 +459,24 @@ public class CoapTransportResource extends CoapResource { @@ -464,17 +459,24 @@ public class CoapTransportResource extends CoapResource {
464 } 459 }
465 } 460 }
466 461
467 - public class CoapExchangeObserverProxy extends CoapObserveRelation {  
468 -  
469 - /**  
470 - * Constructs a new CoapObserveRelation with the specified request.  
471 - *  
472 - * @param request the request  
473 - * @param endpoint the endpoint  
474 - * @param executor  
475 - */  
476 - protected CoapExchangeObserverProxy(Request request, Endpoint endpoint, ScheduledThreadPoolExecutor executor) {  
477 - super(request, endpoint, executor); 462 + public class CoapExchangeObserverProxy implements ExchangeObserver {
  463 +
  464 + private final ExchangeObserver proxy;
  465 + private final String token;
  466 +
  467 + CoapExchangeObserverProxy(ExchangeObserver proxy, String token) {
  468 + super();
  469 + this.proxy = proxy;
  470 + this.token = token;
  471 + }
  472 +
  473 + @Override
  474 + public void completed(Exchange exchange) {
  475 + proxy.completed(exchange);
  476 + TransportProtos.SessionInfoProto session = tokenToSessionIdMap.remove(token);
  477 + if (session != null) {
  478 + closeAndDeregister(session);
  479 + }
478 } 480 }
479 } 481 }
480 482
@@ -18,9 +18,8 @@ package org.thingsboard.server.transport.coap; @@ -18,9 +18,8 @@ package org.thingsboard.server.transport.coap;
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.eclipse.californium.core.CoapResource; 19 import org.eclipse.californium.core.CoapResource;
20 import org.eclipse.californium.core.CoapServer; 20 import org.eclipse.californium.core.CoapServer;
21 -  
22 import org.eclipse.californium.core.network.CoapEndpoint; 21 import org.eclipse.californium.core.network.CoapEndpoint;
23 -import org.eclipse.californium.core.network.CoapEndpoint.Builder; 22 +import org.eclipse.californium.core.network.config.NetworkConfig;
24 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 24 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
26 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
@@ -48,15 +47,11 @@ public class CoapTransportService { @@ -48,15 +47,11 @@ public class CoapTransportService {
48 public void init() throws UnknownHostException { 47 public void init() throws UnknownHostException {
49 log.info("Starting CoAP transport..."); 48 log.info("Starting CoAP transport...");
50 log.info("Starting CoAP transport server"); 49 log.info("Starting CoAP transport server");
51 - this.server = new CoapServer(); 50 + this.server = new CoapServer(NetworkConfig.createStandardWithoutFile());
52 createResources(); 51 createResources();
53 InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); 52 InetAddress addr = InetAddress.getByName(coapTransportContext.getHost());
54 InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort()); 53 InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort());
55 - Builder builder = new Builder();  
56 - builder.setInetSocketAddress(sockAddr);  
57 - CoapEndpoint coapEndpoint = builder.build();  
58 -  
59 - server.addEndpoint(coapEndpoint); 54 + server.addEndpoint(new CoapEndpoint(sockAddr));
60 server.start(); 55 server.start();
61 log.info("CoAP transport started!"); 56 log.info("CoAP transport started!");
62 } 57 }
@@ -31,7 +31,6 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; @@ -31,7 +31,6 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter;
31 import org.thingsboard.server.gen.transport.TransportProtos; 31 import org.thingsboard.server.gen.transport.TransportProtos;
32 import org.thingsboard.server.transport.coap.CoapTransportResource; 32 import org.thingsboard.server.transport.coap.CoapTransportResource;
33 33
34 -  
35 import java.util.Arrays; 34 import java.util.Arrays;
36 import java.util.HashSet; 35 import java.util.HashSet;
37 import java.util.List; 36 import java.util.List;
@@ -28,7 +28,6 @@ import org.eclipse.californium.core.CoapClient; @@ -28,7 +28,6 @@ import org.eclipse.californium.core.CoapClient;
28 import org.eclipse.californium.core.CoapHandler; 28 import org.eclipse.californium.core.CoapHandler;
29 import org.eclipse.californium.core.CoapResponse; 29 import org.eclipse.californium.core.CoapResponse;
30 import org.eclipse.californium.core.coap.MediaTypeRegistry; 30 import org.eclipse.californium.core.coap.MediaTypeRegistry;
31 -import org.eclipse.californium.elements.exception.ConnectorException;  
32 import org.thingsboard.server.common.msg.session.FeatureType; 31 import org.thingsboard.server.common.msg.session.FeatureType;
33 import org.slf4j.Logger; 32 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory; 33 import org.slf4j.LoggerFactory;
@@ -62,7 +61,7 @@ public class DeviceEmulator { @@ -62,7 +61,7 @@ public class DeviceEmulator {
62 this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES)); 61 this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES));
63 this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY)); 62 this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY));
64 this.rpcClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC)); 63 this.rpcClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC));
65 - this.keys = (keys != null && !keys.isEmpty()) ? keys.split(",") : null; 64 + this.keys = keys.split(",");
66 } 65 }
67 66
68 public void start() { 67 public void start() {
@@ -73,8 +72,11 @@ public class DeviceEmulator { @@ -73,8 +72,11 @@ public class DeviceEmulator {
73 try { 72 try {
74 sendObserveRequest(rpcClient); 73 sendObserveRequest(rpcClient);
75 while (!Thread.interrupted()) { 74 while (!Thread.interrupted()) {
  75 +
  76 +
76 sendRequest(attributesClient, createAttributesRequest()); 77 sendRequest(attributesClient, createAttributesRequest());
77 sendRequest(telemetryClient, createTelemetryRequest()); 78 sendRequest(telemetryClient, createTelemetryRequest());
  79 +
78 Thread.sleep(1000); 80 Thread.sleep(1000);
79 } 81 }
80 } catch (Exception e) { 82 } catch (Exception e) {
@@ -82,8 +84,8 @@ public class DeviceEmulator { @@ -82,8 +84,8 @@ public class DeviceEmulator {
82 } 84 }
83 } 85 }
84 86
85 - private void sendRequest(CoapClient client, JsonNode request) throws IOException, ConnectorException {  
86 - CoapResponse telemetryResponse = client.setTimeout((long) 60000).post(mapper.writeValueAsString(request), 87 + private void sendRequest(CoapClient client, JsonNode request) throws JsonProcessingException {
  88 + CoapResponse telemetryResponse = client.setTimeout(60000).post(mapper.writeValueAsString(request),
87 MediaTypeRegistry.APPLICATION_JSON); 89 MediaTypeRegistry.APPLICATION_JSON);
88 log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText()); 90 log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText());
89 } 91 }
@@ -111,7 +113,6 @@ public class DeviceEmulator { @@ -111,7 +113,6 @@ public class DeviceEmulator {
111 113
112 @Override 114 @Override
113 public void onError() { 115 public void onError() {
114 - log.info("Command Response Ack Error, No connect");  
115 //Do nothing 116 //Do nothing
116 } 117 }
117 }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); 118 }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON);
@@ -156,15 +157,6 @@ public class DeviceEmulator { @@ -156,15 +157,6 @@ public class DeviceEmulator {
156 if (args.length != 4) { 157 if (args.length != 4) {
157 System.out.println("Usage: java -jar " + DeviceEmulator.class.getSimpleName() + ".jar host port device_token keys"); 158 System.out.println("Usage: java -jar " + DeviceEmulator.class.getSimpleName() + ".jar host port device_token keys");
158 } 159 }
159 - /**  
160 - * DeviceEmulator(String host, int port, String token, String keys)  
161 - * args[]:  
162 - * host = "localhost",  
163 - * port = 0,  
164 - * token = "{Tokrn device from thingboard}"), kSzbDRGwaZqZ6Y25gTLF  
165 - * keys = "{Telemetry}"  
166 - *  
167 - */  
168 final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]); 160 final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]);
169 emulator.start(); 161 emulator.start();
170 Runtime.getRuntime().addShutdownHook(new Thread() { 162 Runtime.getRuntime().addShutdownHook(new Thread() {
@@ -175,6 +167,7 @@ public class DeviceEmulator { @@ -175,6 +167,7 @@ public class DeviceEmulator {
175 }); 167 });
176 } 168 }
177 169
  170 +
178 private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) { 171 private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) {
179 return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase(); 172 return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase();
180 } 173 }
@@ -327,7 +327,6 @@ public class DeviceApiController { @@ -327,7 +327,6 @@ public class DeviceApiController {
327 public void onToServerRpcResponse(ToServerRpcResponseMsg msg) { 327 public void onToServerRpcResponse(ToServerRpcResponseMsg msg) {
328 responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); 328 responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK));
329 } 329 }
330 -  
331 } 330 }
332 331
333 private void reportActivity(SessionInfoProto sessionInfo) { 332 private void reportActivity(SessionInfoProto sessionInfo) {
1 -  
2 -<!--  
3 -  
4 - Copyright © 2016-2020 The Thingsboard Authors  
5 -  
6 - Licensed under the Apache License, Version 2.0 (the "License");  
7 - you may not use this file except in compliance with the License.  
8 - You may obtain a copy of the License at  
9 -  
10 - http://www.apache.org/licenses/LICENSE-2.0  
11 -  
12 - Unless required by applicable law or agreed to in writing, software  
13 - distributed under the License is distributed on an "AS IS" BASIS,  
14 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
15 - See the License for the specific language governing permissions and  
16 - limitations under the License.  
17 -  
18 --->  
19 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
20 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
21 - <modelVersion>4.0.0</modelVersion>  
22 - <parent>  
23 - <groupId>org.thingsboard.common</groupId>  
24 - <version>3.2.0-SNAPSHOT</version>  
25 - <artifactId>transport</artifactId>  
26 - </parent>  
27 - <groupId>org.thingsboard.common.transport</groupId>  
28 - <artifactId>lwm2m</artifactId>  
29 - <packaging>jar</packaging>  
30 -  
31 - <name>Thingsboard LwM2M Transport Common</name>  
32 - <url>https://thingsboard.io</url>  
33 -  
34 - <properties>  
35 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
36 - <main.dir>${basedir}/../../..</main.dir>  
37 - </properties>  
38 -  
39 - <dependencies>  
40 - <dependency>  
41 - <groupId>org.thingsboard.common.transport</groupId>  
42 - <artifactId>transport-api</artifactId>  
43 - </dependency>  
44 - <dependency>  
45 - <groupId>org.springframework</groupId>  
46 - <artifactId>spring-context-support</artifactId>  
47 - </dependency>  
48 - <dependency>  
49 - <groupId>org.springframework</groupId>  
50 - <artifactId>spring-context</artifactId>  
51 - </dependency>  
52 - <dependency>  
53 - <groupId>org.slf4j</groupId>  
54 - <artifactId>slf4j-api</artifactId>  
55 - </dependency>  
56 - <dependency>  
57 - <groupId>org.slf4j</groupId>  
58 - <artifactId>log4j-over-slf4j</artifactId>  
59 - </dependency>  
60 - <dependency>  
61 - <groupId>ch.qos.logback</groupId>  
62 - <artifactId>logback-core</artifactId>  
63 - </dependency>  
64 - <dependency>  
65 - <groupId>ch.qos.logback</groupId>  
66 - <artifactId>logback-classic</artifactId>  
67 - </dependency>  
68 - <!-- lechan start -->  
69 - <dependency>  
70 - <groupId>org.eclipse.leshan</groupId>  
71 - <artifactId>leshan-server-cf</artifactId>  
72 - </dependency>  
73 -<!-- <dependency>-->  
74 -<!-- <groupId>org.eclipse.leshan</groupId>-->  
75 -<!-- <artifactId>leshan-server-cf</artifactId>-->  
76 -<!-- </dependency> -->  
77 - <dependency>  
78 - <groupId>org.eclipse.leshan</groupId>  
79 - <artifactId>leshan-client-cf</artifactId>  
80 - </dependency>  
81 -  
82 - <dependency>  
83 - <groupId>org.eclipse.leshan</groupId>  
84 - <artifactId>leshan-server-redis</artifactId>  
85 - </dependency>  
86 -<!-- <dependency>-->  
87 -<!-- <groupId>org.eclipse.californium</groupId>-->  
88 -<!-- <artifactId>californium-core</artifactId>-->  
89 -<!-- </dependency>-->  
90 - <!-- leshan finish -->  
91 -  
92 - <dependency>  
93 - <groupId>org.springframework.boot</groupId>  
94 - <artifactId>spring-boot-starter-test</artifactId>  
95 - <scope>test</scope>  
96 - </dependency>  
97 - <dependency>  
98 - <groupId>junit</groupId>  
99 - <artifactId>junit</artifactId>  
100 - <scope>test</scope>  
101 - </dependency>  
102 - <dependency>  
103 - <groupId>org.mockito</groupId>  
104 - <artifactId>mockito-all</artifactId>  
105 - <scope>test</scope>  
106 - </dependency>  
107 - <dependency>  
108 - <groupId>org.eclipse.californium</groupId>  
109 - <artifactId>californium-core</artifactId>  
110 - <version>${californium.version}</version>  
111 - <type>test-jar</type>  
112 - <scope>test</scope>  
113 - </dependency>  
114 - <dependency>  
115 - <groupId>org.eclipse.californium</groupId>  
116 - <artifactId>element-connector</artifactId>  
117 - <version>${californium.version}</version>  
118 - <type>test-jar</type>  
119 - <scope>test</scope>  
120 - </dependency>  
121 - </dependencies>  
122 -  
123 -</project>  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.californium.scandium.config.DtlsConnectorConfig;  
20 -import org.eclipse.leshan.core.model.StaticModel;  
21 -import org.eclipse.leshan.server.bootstrap.BootstrapSessionManager;  
22 -import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;  
23 -import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder;  
24 -import org.springframework.beans.factory.annotation.Autowired;  
25 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
26 -import org.springframework.context.annotation.Bean;  
27 -import org.springframework.context.annotation.Primary;  
28 -import org.springframework.stereotype.Component;  
29 -import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore;  
30 -import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore;  
31 -import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MSetSecurityStoreBootstrap;  
32 -import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager;  
33 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
34 -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;  
35 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509;  
36 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RPK;  
37 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig;  
38 -  
39 -@Slf4j  
40 -@Component  
41 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true'&& '${transport.lwm2m.bootstrap.enable:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true'&& '${transport.lwm2m.bootstrap.enable}'=='true')")  
42 -public class LwM2MTransportBootstrapServerConfiguration {  
43 -  
44 - @Autowired  
45 - private LwM2MTransportContextBootstrap contextBs;  
46 -  
47 - @Autowired  
48 - private LwM2MTransportContextServer contextS;  
49 -  
50 - @Autowired  
51 - private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore;  
52 -  
53 - @Autowired  
54 - private LwM2MInMemoryBootstrapConfigStore lwM2MInMemoryBootstrapConfigStore;  
55 -  
56 -  
57 - @Primary  
58 - @Bean(name = "leshanBootstrapCert")  
59 - public LeshanBootstrapServer getLeshanBootstrapServerCert() {  
60 - log.info("Prepare and start BootstrapServerCert... PostConstruct");  
61 - return getLeshanBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortCert(), this.contextBs.getCtxBootStrap().getBootstrapSecurePortCert(), X509);  
62 - }  
63 -  
64 - @Bean(name = "leshanBootstrapRPK")  
65 - public LeshanBootstrapServer getLeshanBootstrapServerRPK() {  
66 - log.info("Prepare and start BootstrapServerRPK... PostConstruct");  
67 - return getLeshanBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPort(), this.contextBs.getCtxBootStrap().getBootstrapSecurePort(), RPK);  
68 - }  
69 -  
70 - public LeshanBootstrapServer getLeshanBootstrapServer(Integer bootstrapPort, Integer bootstrapSecurePort, LwM2MSecurityMode dtlsMode) {  
71 - LeshanBootstrapServerBuilder builder = new LeshanBootstrapServerBuilder();  
72 - builder.setLocalAddress(this.contextBs.getCtxBootStrap().getBootstrapHost(), bootstrapPort);  
73 - builder.setLocalSecureAddress(this.contextBs.getCtxBootStrap().getBootstrapSecureHost(), bootstrapSecurePort);  
74 -  
75 - /** Create CoAP Config */  
76 - builder.setCoapConfig(getCoapConfig ());  
77 -  
78 - /** ConfigStore */  
79 - builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore);  
80 -  
81 - /** SecurityStore */  
82 - builder.setSecurityStore(lwM2MBootstrapSecurityStore);  
83 -  
84 - /** Define model provider (Create Models )*/  
85 - builder.setModel(new StaticModel(contextS.getCtxServer().getModelsValue()));  
86 -  
87 - /** Create and Set DTLS Config */  
88 - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();  
89 - dtlsConfig.setRecommendedCipherSuitesOnly(contextS.getCtxServer().isSupportDeprecatedCiphersEnable());  
90 - builder.setDtlsConfig(dtlsConfig);  
91 -  
92 - /** Create credentials */  
93 - new LwM2MSetSecurityStoreBootstrap(builder, contextBs, contextS, dtlsMode);  
94 -  
95 - BootstrapSessionManager sessionManager = new LwM2mDefaultBootstrapSessionManager(lwM2MBootstrapSecurityStore);  
96 - builder.setSessionManager(sessionManager);  
97 -  
98 - /** Create BootstrapServer */  
99 - return builder.build();  
100 - }  
101 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap;  
17 -import lombok.extern.slf4j.Slf4j;  
18 -import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;  
19 -import org.springframework.beans.factory.annotation.Autowired;  
20 -import org.springframework.beans.factory.annotation.Qualifier;  
21 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
22 -import org.springframework.stereotype.Service;  
23 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
24 -  
25 -import javax.annotation.PostConstruct;  
26 -import javax.annotation.PreDestroy;  
27 -  
28 -@Slf4j  
29 -@Service  
30 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled}'=='true'&& '${transport.lwm2m.bootstrap.enable}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true'&& '${transport.lwm2m.bootstrap.enable}'=='true')")  
31 -public class LwM2MTransportBootstrapServerInitializer {  
32 -  
33 - @Autowired  
34 - @Qualifier("leshanBootstrapCert")  
35 - private LeshanBootstrapServer lhBServerCert;  
36 -  
37 - @Autowired  
38 - @Qualifier("leshanBootstrapRPK")  
39 - private LeshanBootstrapServer lhBServerRPK;  
40 -  
41 - @Autowired  
42 - private LwM2MTransportContextBootstrap contextBS;  
43 -  
44 - @PostConstruct  
45 - public void init() {  
46 - if (this.contextBS.getCtxBootStrap().isBootstrapStartAll()) {  
47 - this.lhBServerCert.start();  
48 - this.lhBServerRPK.start();  
49 - }  
50 - else {  
51 - if (this.contextBS.getCtxBootStrap().getBootStrapDtlsMode() == LwM2MSecurityMode.X509.code) {  
52 - this.lhBServerCert.start();  
53 - }  
54 - else {  
55 - this.lhBServerRPK.start();  
56 - }  
57 - }  
58 - }  
59 -  
60 - @PreDestroy  
61 - public void shutdown() throws InterruptedException {  
62 - log.info("Stopping LwM2M transport Bootstrap Server!");  
63 - try {  
64 - lhBServerCert.destroy();  
65 - lhBServerRPK.destroy();  
66 - } finally {  
67 - }  
68 - log.info("LwM2M transport Bootstrap Server stopped!");  
69 - }  
70 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap;  
17 -/**  
18 - * Copyright © 2016-2020 The Thingsboard Authors  
19 - *  
20 - * Licensed under the Apache License, Version 2.0 (the "License");  
21 - * you may not use this file except in compliance with the License.  
22 - * You may obtain a copy of the License at  
23 - *  
24 - * http://www.apache.org/licenses/LICENSE-2.0  
25 - *  
26 - * Unless required by applicable law or agreed to in writing, software  
27 - * distributed under the License is distributed on an "AS IS" BASIS,  
28 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
29 - * See the License for the specific language governing permissions and  
30 - * limitations under the License.  
31 - */  
32 -  
33 -import lombok.extern.slf4j.Slf4j;  
34 -import org.springframework.beans.factory.annotation.Autowired;  
35 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
36 -import org.springframework.stereotype.Component;  
37 -import org.thingsboard.server.common.transport.TransportContext;  
38 -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap;  
39 -  
40 -import javax.annotation.PostConstruct;  
41 -  
42 -  
43 -@Slf4j  
44 -@Component  
45 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'")  
46 -public class LwM2MTransportContextBootstrap extends TransportContext {  
47 -  
48 - private LwM2MTransportConfigBootstrap ctxBootStrap;  
49 - @Autowired  
50 - LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstarp;  
51 -  
52 - @PostConstruct  
53 - public void init() {  
54 - this.ctxBootStrap = lwM2MTransportConfigBootstarp;  
55 - }  
56 -  
57 - public LwM2MTransportConfigBootstrap getCtxBootStrap() {  
58 - return this.ctxBootStrap;  
59 - }  
60 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.Builder;  
19 -import lombok.Data;  
20 -import org.eclipse.leshan.core.SecurityMode;  
21 -import org.eclipse.leshan.core.request.BindingMode;  
22 -import org.eclipse.leshan.core.util.Hex;  
23 -import org.eclipse.leshan.server.bootstrap.BootstrapConfig;  
24 -  
25 -import java.nio.charset.StandardCharsets;  
26 -  
27 -@Data  
28 -public class LwM2MBootstrapConfig {  
29 - /**  
30 - * interface BootstrapSecurityConfig  
31 - * servers: BootstrapServersSecurityConfig,  
32 - * bootstrapServer: ServerSecurityConfig,  
33 - * lwm2mServer: ServerSecurityConfig  
34 - * }  
35 - */  
36 - /** -servers  
37 - * shortId: number,  
38 - * lifetime: number,  
39 - * defaultMinPeriod: number,  
40 - * notifIfDisabled: boolean,  
41 - * binding: string  
42 - * */  
43 - @Builder.Default  
44 - LwM2MBootstrapServers servers;  
45 -  
46 - /** -bootstrapServer, lwm2mServer  
47 - * interface ServerSecurityConfig  
48 - * host?: string,  
49 - * port?: number,  
50 - * isBootstrapServer?: boolean,  
51 - * securityMode: string,  
52 - * clientPublicKeyOrId?: string,  
53 - * clientSecretKey?: string,  
54 - * serverPublicKey?: string;  
55 - * clientHoldOffTime?: number,  
56 - * serverId?: number,  
57 - * bootstrapServerAccountTimeout: number  
58 - * */  
59 - LwM2MServerBootstrap bootstrapServer;  
60 -  
61 - LwM2MServerBootstrap lwm2mServer;  
62 -  
63 - public BootstrapConfig getLwM2MBootstrapConfig() {  
64 - BootstrapConfig configBs = new BootstrapConfig();  
65 - /** Delete old security objects */  
66 - configBs.toDelete.add("/0");  
67 - configBs.toDelete.add("/1");  
68 - /** Server Configuration (object 1) as defined in LWM2M 1.0.x TS. */  
69 - BootstrapConfig.ServerConfig server0 = new BootstrapConfig.ServerConfig();  
70 - server0.shortId = servers.getShortId();  
71 - server0.lifetime = servers.getLifetime();  
72 - server0.defaultMinPeriod = servers.getDefaultMinPeriod();  
73 - server0.notifIfDisabled = servers.isNotifIfDisabled();  
74 - server0.binding = BindingMode.valueOf(servers.getBinding());  
75 - configBs.servers.put(0, server0);  
76 - /** Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Bootstrap instance = 0 */  
77 - this.bootstrapServer.setBootstrapServerIs(true);  
78 - configBs.security.put(0, setServerSecuruty(this.bootstrapServer.getHost(), this.bootstrapServer.getPort(), this.bootstrapServer.isBootstrapServerIs(), this.bootstrapServer.getSecurityMode(), this.bootstrapServer.getClientPublicKeyOrId(), this.bootstrapServer.getServerPublicKey(), this.bootstrapServer.getClientSecretKey(), this.bootstrapServer.getServerId()));  
79 - /** Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Server instance = 1 */  
80 - configBs.security.put(1, setServerSecuruty(this.lwm2mServer.getHost(), this.lwm2mServer.getPort(), this.lwm2mServer.isBootstrapServerIs(), this.lwm2mServer.getSecurityMode(), this.lwm2mServer.getClientPublicKeyOrId(), this.lwm2mServer.getServerPublicKey(), this.lwm2mServer.getClientSecretKey(), this.lwm2mServer.getServerId()));  
81 - return configBs;  
82 - }  
83 -  
84 - private BootstrapConfig.ServerSecurity setServerSecuruty(String host, Integer port, boolean bootstrapServer, String securityMode, String clientPublicKey, String serverPublicKey, String secretKey, int serverId) {  
85 - BootstrapConfig.ServerSecurity serverSecurity = new BootstrapConfig.ServerSecurity();  
86 - serverSecurity.uri = "coaps://" + host + ":" + Integer.toString(port);  
87 - serverSecurity.bootstrapServer = bootstrapServer;  
88 - serverSecurity.securityMode = SecurityMode.valueOf(securityMode);  
89 - serverSecurity.publicKeyOrId = setPublicKeyOrId(clientPublicKey, securityMode);  
90 - serverSecurity.serverPublicKey = (serverPublicKey != null && !serverPublicKey.isEmpty()) ? Hex.decodeHex(serverPublicKey.toCharArray()) : new byte[]{};  
91 - serverSecurity.secretKey = (secretKey != null && !secretKey.isEmpty()) ? Hex.decodeHex(secretKey.toCharArray()) : new byte[]{};  
92 - serverSecurity.serverId = serverId;  
93 - return serverSecurity;  
94 - }  
95 -  
96 - private byte[] setPublicKeyOrId(String publicKeyOrIdStr, String securityMode) {  
97 - byte[] publicKey = (publicKeyOrIdStr == null || publicKeyOrIdStr.isEmpty()) ? new byte[]{} :  
98 - SecurityMode.valueOf(securityMode).equals(SecurityMode.PSK) ? publicKeyOrIdStr.getBytes(StandardCharsets.UTF_8) :  
99 - Hex.decodeHex(publicKeyOrIdStr.toCharArray());  
100 - return publicKey;  
101 - }  
102 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import com.fasterxml.jackson.core.JsonProcessingException;  
19 -import com.fasterxml.jackson.databind.ObjectMapper;  
20 -import com.google.gson.JsonObject;  
21 -import lombok.extern.slf4j.Slf4j;  
22 -import org.eclipse.leshan.core.SecurityMode;  
23 -import org.eclipse.leshan.core.util.Hex;  
24 -import org.eclipse.leshan.core.util.SecurityUtil;  
25 -import org.eclipse.leshan.server.bootstrap.BootstrapConfig;  
26 -import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore;  
27 -import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException;  
28 -import org.eclipse.leshan.server.security.BootstrapSecurityStore;  
29 -import org.eclipse.leshan.server.security.SecurityInfo;  
30 -import org.springframework.beans.factory.annotation.Autowired;  
31 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
32 -import org.springframework.stereotype.Component;  
33 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MGetSecurityInfo;  
34 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
35 -import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;  
36 -import org.thingsboard.server.transport.lwm2m.utils.TypeServer;  
37 -  
38 -import java.io.IOException;  
39 -import java.security.GeneralSecurityException;  
40 -import java.util.Arrays;  
41 -import java.util.List;  
42 -  
43 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.*;  
44 -  
45 -@Slf4j  
46 -@Component("LwM2MBootstrapSecurityStore")  
47 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' && '${transport.lwm2m.bootstrap.enable:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true' && '${transport.lwm2m.bootstrap.enable}'=='true')")  
48 -public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {  
49 -  
50 - private final EditableBootstrapConfigStore bootstrapConfigStore;  
51 -  
52 - @Autowired  
53 - LwM2MGetSecurityInfo lwM2MGetSecurityInfo;  
54 -  
55 - public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore) {  
56 - this.bootstrapConfigStore = bootstrapConfigStore;  
57 - }  
58 -  
59 - @Override  
60 - public List<SecurityInfo> getAllByEndpoint(String endPoint) {  
61 - String endPointKey = endPoint;  
62 - ReadResultSecurityStore store = lwM2MGetSecurityInfo.getSecurityInfo(endPointKey, TypeServer.BOOTSTRAP);  
63 - if (store.getBootstrapJsonCredential() != null) {  
64 - /** add value to store from BootstrapJson */  
65 - this.setBootstrapConfigScurityInfo(store);  
66 - BootstrapConfig bsConfigNew = store.getBootstrapConfig();  
67 - if (bsConfigNew != null) {  
68 - try {  
69 - for (String config : bootstrapConfigStore.getAll().keySet()) {  
70 - if (config.equals(endPoint)) {  
71 - bootstrapConfigStore.remove(config);  
72 - }  
73 - }  
74 - bootstrapConfigStore.add(endPoint, bsConfigNew);  
75 - } catch (InvalidConfigurationException e) {  
76 - e.printStackTrace();  
77 - }  
78 - return store.getSecurityInfo() == null ? null : Arrays.asList(store.getSecurityInfo());  
79 - }  
80 - }  
81 - return null;  
82 - }  
83 -  
84 - @Override  
85 - public SecurityInfo getByIdentity(String identity) {  
86 - ReadResultSecurityStore store = lwM2MGetSecurityInfo.getSecurityInfo(identity, TypeServer.BOOTSTRAP);  
87 - /** add value to store from BootstrapJson */  
88 - this.setBootstrapConfigScurityInfo(store);  
89 -  
90 - if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {  
91 - BootstrapConfig bsConfig = store.getBootstrapConfig();  
92 - if (bsConfig.security != null) {  
93 - try {  
94 - bootstrapConfigStore.add(store.getEndPoint(), bsConfig);  
95 - } catch (InvalidConfigurationException e) {  
96 - e.printStackTrace();  
97 - }  
98 - return store.getSecurityInfo();  
99 - }  
100 - }  
101 - return null;  
102 - }  
103 -  
104 - private void setBootstrapConfigScurityInfo(ReadResultSecurityStore store) {  
105 - /** BootstrapConfig */  
106 - LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store);  
107 - if (lwM2MBootstrapConfig != null) {  
108 - /** Security info */  
109 - switch (SecurityMode.valueOf(lwM2MBootstrapConfig.getBootstrapServer().getSecurityMode())) {  
110 - /** Use RPK only */  
111 - case PSK:  
112 - store.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(store.getEndPoint(),  
113 - lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId(),  
114 - Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientSecretKey().toCharArray())));  
115 - store.setSecurityMode(SecurityMode.PSK.code);  
116 - break;  
117 - case RPK:  
118 - try {  
119 - store.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(store.getEndPoint(),  
120 - SecurityUtil.publicKey.decode(Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId().toCharArray()))));  
121 - store.setSecurityMode(SecurityMode.RPK.code);  
122 - break;  
123 - } catch (IOException | GeneralSecurityException e) {  
124 - log.error("Unable to decode Client public key for [{}] [{}]", store.getEndPoint(), e.getMessage());  
125 - }  
126 - case X509:  
127 - store.setSecurityInfo(SecurityInfo.newX509CertInfo(store.getEndPoint()));  
128 - store.setSecurityMode(SecurityMode.X509.code);  
129 - break;  
130 - case NO_SEC:  
131 - store.setSecurityMode(SecurityMode.NO_SEC.code);  
132 - store.setSecurityInfo(null);  
133 - break;  
134 - default:  
135 - }  
136 - BootstrapConfig bootstrapConfig = lwM2MBootstrapConfig.getLwM2MBootstrapConfig();  
137 - store.setBootstrapConfig(bootstrapConfig);  
138 - }  
139 - }  
140 -  
141 - private LwM2MBootstrapConfig getParametersBootstrap(ReadResultSecurityStore store) {  
142 - try {  
143 - JsonObject bootstrapJsonCredential = store.getBootstrapJsonCredential();  
144 - ObjectMapper mapper = new ObjectMapper();  
145 - LwM2MBootstrapConfig lwM2MBootstrapConfig = mapper.readValue(bootstrapJsonCredential.toString(), LwM2MBootstrapConfig.class);  
146 - JsonObject bootstrapObject = getBootstrapParametersFromThingsboard(store.getDeviceProfile());  
147 - lwM2MBootstrapConfig.servers = mapper.readValue(bootstrapObject.get(SERVERS).toString(), LwM2MBootstrapServers.class);  
148 - LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class);  
149 - LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class);  
150 - if (getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) {  
151 - lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);  
152 - lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);  
153 - return lwM2MBootstrapConfig;  
154 - }  
155 - else {  
156 - log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint());  
157 - log.error(LOG_LW2M_ERROR + " getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", store.getEndPoint());  
158 - String logMsg = String.format(LOG_LW2M_ERROR + " getParametersBootstrap: %s Different values SecurityMode between of client and profile.", store.getEndPoint());  
159 -// sentLogsToThingsboard(logMsg, store.getEndPoint());  
160 - return null;  
161 - }  
162 - } catch (JsonProcessingException e) {  
163 - log.error("Unable to decode Json or Certificate for [{}] [{}]", store.getEndPoint(), e.getMessage());  
164 - return null;  
165 - }  
166 - }  
167 -  
168 - /**  
169 - * Bootstrap security have to sync between (bootstrapServer in credential and bootstrapServer in profile)  
170 - * and (lwm2mServer in credential and lwm2mServer in profile  
171 - * @param bootstrapFromCredential - Bootstrap -> Security of bootstrapServer in credential  
172 - * @param profileServerBootstrap - Bootstrap -> Security of bootstrapServer in profile  
173 - * @param lwm2mFromCredential - Bootstrap -> Security of lwm2mServer in credential  
174 - * @param profileLwm2mServer - Bootstrap -> Security of lwm2mServer in profile  
175 - * @return false if not sync between SecurityMode of Bootstrap credential and profile  
176 - */  
177 - private boolean getValidatedSecurityMode(LwM2MServerBootstrap bootstrapFromCredential, LwM2MServerBootstrap profileServerBootstrap, LwM2MServerBootstrap lwm2mFromCredential, LwM2MServerBootstrap profileLwm2mServer) {  
178 - return (bootstrapFromCredential.getSecurityMode().equals(profileServerBootstrap.getSecurityMode()) &&  
179 - lwm2mFromCredential.getSecurityMode().equals(profileLwm2mServer.getSecurityMode()));  
180 - }  
181 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.Builder;  
19 -import lombok.Data;  
20 -  
21 -@Data  
22 -public class LwM2MBootstrapServers {  
23 - @Builder.Default  
24 - private Integer shortId = 123;  
25 - @Builder.Default  
26 - private Integer lifetime = 300;  
27 - @Builder.Default  
28 - private Integer defaultMinPeriod = 1;  
29 - @Builder.Default  
30 - private boolean notifIfDisabled = true;  
31 - @Builder.Default  
32 - private String binding = "U";  
33 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.server.bootstrap.BootstrapConfig;  
20 -import org.eclipse.leshan.server.bootstrap.InMemoryBootstrapConfigStore;  
21 -import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException;  
22 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
23 -import org.springframework.stereotype.Component;  
24 -import java.util.Map;  
25 -import java.util.concurrent.locks.Lock;  
26 -import java.util.concurrent.locks.ReadWriteLock;  
27 -import java.util.concurrent.locks.ReentrantReadWriteLock;  
28 -  
29 -@Slf4j  
30 -@Component("LwM2MInMemoryBootstrapConfigStore")  
31 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' && '${transport.lwm2m.bootstrap.enable:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true'&& '${transport.lwm2m.bootstrap.enable}'=='true')")  
32 -public class LwM2MInMemoryBootstrapConfigStore extends InMemoryBootstrapConfigStore {  
33 - private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
34 - private final Lock readLock = readWriteLock.readLock();  
35 - private final Lock writeLock = readWriteLock.writeLock();  
36 -  
37 - @Override  
38 - public Map<String, BootstrapConfig> getAll() {  
39 - readLock.lock();  
40 - try {  
41 - return super.getAll();  
42 - } finally {  
43 - readLock.unlock();  
44 - }  
45 - }  
46 -  
47 - @Override  
48 - public void add(String endpoint, BootstrapConfig config) throws InvalidConfigurationException {  
49 - writeLock.lock();  
50 - try {  
51 - addToStore(endpoint, config);  
52 - } finally {  
53 - writeLock.unlock();  
54 - }  
55 - }  
56 -  
57 - @Override  
58 - public BootstrapConfig remove(String enpoint) {  
59 - writeLock.lock();  
60 - try {  
61 - BootstrapConfig res = super.remove(enpoint);  
62 - return res;  
63 - } finally {  
64 - writeLock.unlock();  
65 - }  
66 - }  
67 -  
68 - public void addToStore(String endpoint, BootstrapConfig config) throws InvalidConfigurationException {  
69 - super.add(endpoint, config);  
70 - }  
71 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.Builder;  
19 -import lombok.Data;  
20 -import lombok.extern.slf4j.Slf4j;  
21 -import org.eclipse.leshan.core.SecurityMode;  
22 -  
23 -@Slf4j  
24 -@Data  
25 -public class LwM2MServerBootstrap {  
26 -  
27 - @Builder.Default  
28 - String clientPublicKeyOrId = "";  
29 - @Builder.Default  
30 - String clientSecretKey = "";  
31 - @Builder.Default  
32 - String serverPublicKey = "";  
33 - @Builder.Default  
34 - Integer clientHoldOffTime = 1;  
35 - @Builder.Default  
36 - Integer bootstrapServerAccountTimeout = 0;  
37 -  
38 - @Builder.Default  
39 - String host = "0.0.0.0";  
40 - @Builder.Default  
41 - Integer port = 0;  
42 -  
43 - @Builder.Default  
44 - String securityMode = SecurityMode.NO_SEC.name();  
45 -  
46 - @Builder.Default  
47 - Integer serverId = 123;  
48 - @Builder.Default  
49 - boolean bootstrapServerIs = false;  
50 -  
51 - public LwM2MServerBootstrap(){};  
52 -  
53 - public LwM2MServerBootstrap(LwM2MServerBootstrap bootstrapFromCredential, LwM2MServerBootstrap profileServerBootstrap) {  
54 - this.clientPublicKeyOrId = bootstrapFromCredential.getClientPublicKeyOrId();  
55 - this.clientSecretKey = bootstrapFromCredential.getClientSecretKey();  
56 - this.serverPublicKey = profileServerBootstrap.getServerPublicKey();  
57 - this.clientHoldOffTime = profileServerBootstrap.getClientHoldOffTime();  
58 - this.bootstrapServerAccountTimeout = profileServerBootstrap.getBootstrapServerAccountTimeout();  
59 - this.host = (profileServerBootstrap.getHost().equals("0.0.0.0")) ? "localhost" : profileServerBootstrap.getHost();  
60 - this.port = profileServerBootstrap.getPort();  
61 - this.securityMode = profileServerBootstrap.getSecurityMode();  
62 - this.serverId = profileServerBootstrap.getServerId();  
63 - this.bootstrapServerIs = profileServerBootstrap.bootstrapServerIs;  
64 - }  
65 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.Data;  
19 -import lombok.extern.slf4j.Slf4j;  
20 -import org.eclipse.leshan.core.util.Hex;  
21 -import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder;  
22 -import org.eclipse.leshan.server.security.EditableSecurityStore;  
23 -import org.thingsboard.server.transport.lwm2m.bootstrap.LwM2MTransportContextBootstrap;  
24 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
25 -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;  
26 -  
27 -import java.math.BigInteger;  
28 -import java.security.AlgorithmParameters;  
29 -import java.security.KeyStore;  
30 -import java.security.PublicKey;  
31 -import java.security.PrivateKey;  
32 -import java.security.KeyFactory;  
33 -import java.security.GeneralSecurityException;  
34 -import java.security.KeyStoreException;  
35 -import java.security.cert.X509Certificate;  
36 -import java.security.interfaces.ECPublicKey;  
37 -import java.security.spec.ECGenParameterSpec;  
38 -import java.security.spec.ECParameterSpec;  
39 -import java.security.spec.ECPublicKeySpec;  
40 -import java.security.spec.ECPoint;  
41 -import java.security.spec.KeySpec;  
42 -import java.security.spec.ECPrivateKeySpec;  
43 -import java.util.Arrays;  
44 -  
45 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC;  
46 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509;  
47 -  
48 -@Slf4j  
49 -@Data  
50 -public class LwM2MSetSecurityStoreBootstrap {  
51 -  
52 - private KeyStore keyStore;  
53 - private PublicKey publicKey;  
54 - private PrivateKey privateKey;  
55 - private LwM2MTransportContextBootstrap contextBs;  
56 - private LwM2MTransportContextServer contextS;  
57 - private LeshanBootstrapServerBuilder builder;  
58 - EditableSecurityStore securityStore;  
59 -  
60 - public LwM2MSetSecurityStoreBootstrap(LeshanBootstrapServerBuilder builder, LwM2MTransportContextBootstrap contextBs, LwM2MTransportContextServer contextS, LwM2MSecurityMode dtlsMode) {  
61 - this.builder = builder;  
62 - this.contextBs = contextBs;  
63 - this.contextS = contextS;  
64 - /** Set securityStore with new registrationStore */  
65 -  
66 - switch (dtlsMode) {  
67 - /** Use No_Sec only */  
68 - case NO_SEC:  
69 - setServerWithX509Cert(NO_SEC.code);  
70 - break;  
71 - /** Use PSK/RPK */  
72 - case PSK:  
73 - case RPK:  
74 - setRPK();  
75 - break;  
76 - case X509:  
77 - setServerWithX509Cert(X509.code);  
78 - break;  
79 - /** Use X509_EST only */  
80 - case X509_EST:  
81 - // TODO support sentinel pool and make pool configurable  
82 - break;  
83 - /** Use ather X509, PSK, No_Sec ?? */  
84 - default:  
85 - break;  
86 - }  
87 - }  
88 -  
89 - private void setRPK() {  
90 - try {  
91 - /** Get Elliptic Curve Parameter spec for secp256r1 */  
92 - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");  
93 - algoParameters.init(new ECGenParameterSpec("secp256r1"));  
94 - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);  
95 - if (this.contextBs.getCtxBootStrap().getBootstrapPublicX() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicX().isEmpty() && this.contextBs.getCtxBootStrap().getBootstrapPublicY() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicY().isEmpty()) {  
96 - /** Get point values */  
97 - byte[] publicX = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicX().toCharArray());  
98 - byte[] publicY = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicY().toCharArray());  
99 - /** Create key specs */  
100 - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),  
101 - parameterSpec);  
102 - /** Get keys */  
103 - this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);  
104 - }  
105 - if (this.contextBs.getCtxBootStrap().getBootstrapPrivateS() != null && !this.contextBs.getCtxBootStrap().getBootstrapPrivateS().isEmpty()) {  
106 - /** Get point values */  
107 - byte[] privateS = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPrivateS().toCharArray());  
108 - /** Create key specs */  
109 - KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec);  
110 - /** Get keys */  
111 - this.privateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec);  
112 - }  
113 - if (this.publicKey != null && this.publicKey.getEncoded().length > 0 &&  
114 - this.privateKey != null && this.privateKey.getEncoded().length > 0) {  
115 - this.builder.setPublicKey(this.publicKey);  
116 - this.builder.setPrivateKey(this.privateKey);  
117 - this.contextBs.getCtxBootStrap().setBootstrapPublicKey(this.publicKey);  
118 - getParamsRPK();  
119 - }  
120 - } catch (GeneralSecurityException | IllegalArgumentException e) {  
121 - log.error("[{}] Failed generate Server PSK/RPK", e.getMessage());  
122 - throw new RuntimeException(e);  
123 - }  
124 - }  
125 -  
126 - private void setServerWithX509Cert(int securityModeCode) {  
127 - try {  
128 - if (this.contextS.getCtxServer().getKeyStoreValue() != null) {  
129 - KeyStore keyStoreServer = this.contextS.getCtxServer().getKeyStoreValue();  
130 - setBuilderX509();  
131 - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getCtxServer().getRootAlias());  
132 - if (rootCAX509Cert != null && securityModeCode == X509.code) {  
133 - X509Certificate[] trustedCertificates = new X509Certificate[1];  
134 - trustedCertificates[0] = rootCAX509Cert;  
135 - this.builder.setTrustedCertificates(trustedCertificates);  
136 - } else {  
137 - /** by default trust all */  
138 - this.builder.setTrustedCertificates(new X509Certificate[0]);  
139 - }  
140 - }  
141 - else {  
142 - /** by default trust all */  
143 - this.builder.setTrustedCertificates(new X509Certificate[0]);  
144 - log.error("Unable to load X509 files for BootStrapServer");  
145 - }  
146 - } catch (KeyStoreException ex) {  
147 - log.error("[{}] Unable to load X509 files server", ex.getMessage());  
148 - }  
149 -  
150 - }  
151 -  
152 - private void setBuilderX509() {  
153 - /**  
154 - * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE  
155 - * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks  
156 - */  
157 - try {  
158 - X509Certificate serverCertificate = (X509Certificate) this.contextS.getCtxServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias());  
159 - this.privateKey = (PrivateKey) this.contextS.getCtxServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getCtxServer().getKeyStorePasswordServer() == null ? null : this.contextS.getCtxServer().getKeyStorePasswordServer().toCharArray());  
160 - if (this.privateKey != null && this.privateKey.getEncoded().length > 0) {  
161 - this.builder.setPrivateKey(this.privateKey);  
162 - }  
163 - if (serverCertificate != null) {  
164 - this.builder.setCertificateChain(new X509Certificate[]{serverCertificate});  
165 - this.contextBs.getCtxBootStrap().setBootstrapCertificate(serverCertificate);  
166 - }  
167 - } catch (Exception ex) {  
168 - log.error("[{}] Unable to load KeyStore files server", ex.getMessage());  
169 - }  
170 - }  
171 -  
172 - private void getParamsRPK() {  
173 - if (this.publicKey instanceof ECPublicKey) {  
174 - /** Get x coordinate */  
175 - byte[] x = ((ECPublicKey) this.publicKey).getW().getAffineX().toByteArray();  
176 - if (x[0] == 0)  
177 - x = Arrays.copyOfRange(x, 1, x.length);  
178 -  
179 - /** Get Y coordinate */  
180 - byte[] y = ((ECPublicKey) this.publicKey).getW().getAffineY().toByteArray();  
181 - if (y[0] == 0)  
182 - y = Arrays.copyOfRange(y, 1, y.length);  
183 -  
184 - /** Get Curves params */  
185 - String params = ((ECPublicKey) this.publicKey).getParams().toString();  
186 - log.info(  
187 - " \nBootstrap uses RPK : \n Elliptic Curve parameters : [{}] \n Public x coord : [{}] \n Public y coord : [{}] \n Public Key (Hex): [{}] \n Private Key (Hex): [{}]",  
188 - params, Hex.encodeHexString(x), Hex.encodeHexString(y),  
189 - Hex.encodeHexString(this.publicKey.getEncoded()),  
190 - Hex.encodeHexString(this.privateKey.getEncoded()));  
191 - } else {  
192 - throw new IllegalStateException("Unsupported Public Key Format (only ECPublicKey supported).");  
193 - }  
194 - }  
195 -  
196 -// private void getParamsX509() {  
197 -// try {  
198 -// log.info("BootStrap uses X509 : \n X509 Certificate (Hex): [{}] \n Private Key (Hex): [{}]",  
199 -// Hex.encodeHexString(this.certificate.getEncoded()),  
200 -// Hex.encodeHexString(this.privateKey.getEncoded()));  
201 -// } catch (CertificateEncodingException e) {  
202 -// e.printStackTrace();  
203 -// }  
204 -// }  
205 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.bootstrap.secure;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.core.request.Identity;  
20 -import org.eclipse.leshan.server.bootstrap.BootstrapSession;  
21 -import org.eclipse.leshan.server.bootstrap.DefaultBootstrapSession;  
22 -import org.eclipse.leshan.server.bootstrap.DefaultBootstrapSessionManager;  
23 -import org.eclipse.leshan.server.security.BootstrapSecurityStore;  
24 -import org.eclipse.leshan.server.security.SecurityChecker;  
25 -import org.eclipse.leshan.server.security.SecurityInfo;  
26 -  
27 -import java.util.Arrays;  
28 -import java.util.List;  
29 -  
30 -@Slf4j  
31 -public class LwM2mDefaultBootstrapSessionManager extends DefaultBootstrapSessionManager {  
32 -  
33 - private BootstrapSecurityStore bsSecurityStore;  
34 - private SecurityChecker securityChecker;  
35 -  
36 - /**  
37 - * Create a {@link DefaultBootstrapSessionManager} using a default {@link SecurityChecker} to accept or refuse new  
38 - * {@link BootstrapSession}.  
39 - *  
40 - * @param bsSecurityStore the {@link BootstrapSecurityStore} used by default {@link SecurityChecker}.  
41 - */  
42 - public LwM2mDefaultBootstrapSessionManager(BootstrapSecurityStore bsSecurityStore) {  
43 - this(bsSecurityStore, new SecurityChecker());  
44 - }  
45 -  
46 - public LwM2mDefaultBootstrapSessionManager(BootstrapSecurityStore bsSecurityStore, SecurityChecker securityChecker) {  
47 - super(bsSecurityStore);  
48 - this.bsSecurityStore = bsSecurityStore;  
49 - this.securityChecker = securityChecker;  
50 - }  
51 -  
52 - @Override  
53 - public BootstrapSession begin(String endpoint, Identity clientIdentity) {  
54 - boolean authorized;  
55 - if (bsSecurityStore != null) {  
56 - List<SecurityInfo> securityInfos = (clientIdentity.getPskIdentity() != null && !clientIdentity.getPskIdentity().isEmpty()) ? Arrays.asList(bsSecurityStore.getByIdentity(clientIdentity.getPskIdentity())) : bsSecurityStore.getAllByEndpoint(endpoint);  
57 - log.info("Bootstrap session started securityInfos: [{}]", securityInfos);  
58 - authorized = securityChecker.checkSecurityInfos(endpoint, clientIdentity, securityInfos);  
59 - } else {  
60 - authorized = true;  
61 - }  
62 - DefaultBootstrapSession session = new DefaultBootstrapSession(endpoint, clientIdentity, authorized);  
63 - log.info("Bootstrap session started : {}", session);  
64 - return session;  
65 - }  
66 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.secure;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.core.util.Hex;  
20 -import java.security.SecureRandom;  
21 -import java.security.KeyPairGenerator;  
22 -import java.security.KeyPair;  
23 -import java.security.PrivateKey;  
24 -import java.security.PublicKey;  
25 -import java.security.NoSuchAlgorithmException;  
26 -import java.security.NoSuchProviderException;  
27 -import java.security.InvalidAlgorithmParameterException;  
28 -import java.security.interfaces.ECPublicKey;  
29 -import java.security.spec.ECGenParameterSpec;  
30 -import java.util.Arrays;  
31 -  
32 -@Slf4j  
33 -public class LWM2MGenerationPSkRPkECC {  
34 -  
35 - public LWM2MGenerationPSkRPkECC(Integer dtlsMode) {  
36 - switch (LwM2MSecurityMode.fromSecurityMode(dtlsMode)) {  
37 - case PSK:  
38 - generationPSkKey();  
39 - break;  
40 - case RPK:  
41 - generationRPKECCKey();  
42 - }  
43 - }  
44 -  
45 - public LWM2MGenerationPSkRPkECC() {  
46 - generationPSkKey();  
47 - generationRPKECCKey();  
48 - }  
49 -  
50 - private void generationPSkKey() {  
51 - /** PSK */  
52 - int lenPSkKey = 32;  
53 - /** Start PSK  
54 - * Clients and Servers MUST support PSK keys of up to 64 bytes in length, as required by [RFC7925]  
55 - * SecureRandom object must be unpredictable, and all SecureRandom output sequences must be cryptographically strong, as described in [RFC4086]  
56 - * */  
57 - SecureRandom randomPSK = new SecureRandom();  
58 - byte bytesPSK[] = new byte[lenPSkKey];  
59 - randomPSK.nextBytes(bytesPSK);  
60 - log.info("\nCreating new PSK: \n for the next start PSK -> security key: [{}]", Hex.encodeHexString(bytesPSK));  
61 - }  
62 -  
63 - private void generationRPKECCKey() {  
64 - /** RPK */  
65 - String algorithm = "EC";  
66 - String provider = "SunEC";  
67 - String nameParameterSpec = "secp256r1";  
68 -  
69 - /** Start RPK  
70 - * Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)]  
71 - * */  
72 - KeyPairGenerator kpg = null;  
73 - try {  
74 - kpg = KeyPairGenerator.getInstance(algorithm, provider);  
75 - } catch (NoSuchAlgorithmException e) {  
76 - e.printStackTrace();  
77 - } catch (NoSuchProviderException e) {  
78 - e.printStackTrace();  
79 - }  
80 - ECGenParameterSpec ecsp = new ECGenParameterSpec(nameParameterSpec);  
81 - try {  
82 - kpg.initialize(ecsp);  
83 - } catch (InvalidAlgorithmParameterException e) {  
84 - e.printStackTrace();  
85 - }  
86 -  
87 - KeyPair kp = kpg.genKeyPair();  
88 - PrivateKey privKey = kp.getPrivate();  
89 - PublicKey pubKey = kp.getPublic();  
90 -  
91 - if (pubKey instanceof ECPublicKey) {  
92 - ECPublicKey ecPublicKey = (ECPublicKey) pubKey;  
93 - /** Get x coordinate */  
94 - byte[] x = ecPublicKey.getW().getAffineX().toByteArray();  
95 - if (x[0] == 0)  
96 - x = Arrays.copyOfRange(x, 1, x.length);  
97 -  
98 - /** Get Y coordinate */  
99 - byte[] y = ecPublicKey.getW().getAffineY().toByteArray();  
100 - if (y[0] == 0)  
101 - y = Arrays.copyOfRange(y, 1, y.length);  
102 -  
103 - /** Get Curves params */  
104 - String privHex = Hex.encodeHexString(privKey.getEncoded());  
105 - log.info("\nCreating new RPK for the next start... \n" +  
106 - " Elliptic Curve parameters : [{}] \n" +  
107 - " public_x : [{}] \n" +  
108 - " public_y : [{}] \n" +  
109 - " private_s : [{}] \n" +  
110 - " Public Key (Hex): [{}]\n" +  
111 - " Private Key (Hex): [{}]",  
112 - ecPublicKey.getParams().toString(),  
113 - Hex.encodeHexString(x),  
114 - Hex.encodeHexString(y),  
115 - privHex.substring(privHex.length() - 64),  
116 - Hex.encodeHexString(pubKey.getEncoded()),  
117 - Hex.encodeHexString(privKey.getEncoded()));  
118 - }  
119 - }  
120 -}  
121 -  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.secure;  
17 -  
18 -import com.google.gson.JsonObject;  
19 -import lombok.extern.slf4j.Slf4j;  
20 -import org.eclipse.leshan.core.util.Hex;  
21 -import org.eclipse.leshan.core.util.SecurityUtil;  
22 -import org.eclipse.leshan.server.security.SecurityInfo;  
23 -import org.springframework.beans.factory.annotation.Autowired;  
24 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
25 -import org.springframework.stereotype.Component;  
26 -import org.thingsboard.server.common.data.DeviceProfile;  
27 -import org.thingsboard.server.common.transport.TransportServiceCallback;  
28 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;  
29 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;  
30 -import org.thingsboard.server.transport.lwm2m.bootstrap.LwM2MTransportContextBootstrap;  
31 -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;  
32 -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler;  
33 -import org.thingsboard.server.transport.lwm2m.utils.TypeServer;  
34 -  
35 -import java.io.IOException;  
36 -import java.security.GeneralSecurityException;  
37 -import java.security.PublicKey;  
38 -import java.util.Optional;  
39 -import java.util.concurrent.CountDownLatch;  
40 -import java.util.concurrent.TimeUnit;  
41 -  
42 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.*;  
43 -  
44 -@Slf4j  
45 -@Component("LwM2MGetSecurityInfo")  
46 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
47 -public class LwM2MGetSecurityInfo {  
48 -  
49 - @Autowired  
50 - public LwM2MTransportContextServer contextS;  
51 -  
52 - @Autowired  
53 - public LwM2MTransportContextBootstrap contextBS;  
54 -  
55 -  
56 - public ReadResultSecurityStore getSecurityInfo(String endPoint, TypeServer keyValue) {  
57 - CountDownLatch latch = new CountDownLatch(1);  
58 - final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1];  
59 - contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endPoint).build(),  
60 - new TransportServiceCallback<ValidateDeviceCredentialsResponseMsg>() {  
61 - @Override  
62 - public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) {  
63 - String credentialsBody = msg.getCredentialsBody();  
64 - resultSecurityStore[0] = putSecurityInfo(endPoint, msg.getDeviceInfo().getDeviceName(), credentialsBody, keyValue);  
65 - resultSecurityStore[0].setMsg(msg);  
66 - Optional<DeviceProfile> deviceProfileOpt = LwM2MTransportHandler.decode(msg.getProfileBody().toByteArray());  
67 - deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile));  
68 - latch.countDown();  
69 - }  
70 -  
71 - @Override  
72 - public void onError(Throwable e) {  
73 - log.trace("[{}] Failed to process credentials PSK: {}", endPoint, e);  
74 - resultSecurityStore[0] = putSecurityInfo(endPoint, null, null, null);  
75 - latch.countDown();  
76 - }  
77 - });  
78 - try {  
79 - latch.await(contextS.getCtxServer().getTimeout(), TimeUnit.MILLISECONDS);  
80 - } catch (InterruptedException e) {  
81 - e.printStackTrace();  
82 - }  
83 - return resultSecurityStore[0];  
84 - }  
85 -  
86 - private ReadResultSecurityStore putSecurityInfo(String endPoint, String deviceName, String jsonStr, TypeServer keyValue) {  
87 - ReadResultSecurityStore result = new ReadResultSecurityStore();  
88 - JsonObject objectMsg = LwM2MTransportHandler.validateJson(jsonStr);  
89 - if (objectMsg != null && !objectMsg.isJsonNull()) {  
90 - JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null;  
91 - /**  
92 - * Only PSK  
93 - */  
94 - String endPointPsk = (objectMsg.has("client")  
95 - && objectMsg.get("client").getAsJsonObject().has("endpoint")  
96 - && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null;  
97 - endPoint = (endPointPsk == null || endPointPsk.isEmpty()) ? endPoint : endPointPsk;  
98 - if (object != null && !object.isJsonNull()) {  
99 - if (keyValue.equals(TypeServer.BOOTSTRAP)) {  
100 - result.setBootstrapJsonCredential(object);  
101 - result.setEndPoint(endPoint);  
102 - } else {  
103 - LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(object.get("securityConfigClientMode").getAsString().toLowerCase());  
104 - switch (lwM2MSecurityMode) {  
105 - case NO_SEC:  
106 - getClientSecurityInfoNoSec(result);  
107 - break;  
108 - case PSK:  
109 - getClientSecurityInfoPSK(result, endPoint, object);  
110 - break;  
111 - case RPK:  
112 - getClientSecurityInfoRPK(result, endPoint, object);  
113 - break;  
114 - case X509:  
115 - getClientSecurityInfoX509(result, endPoint);  
116 - break;  
117 - default:  
118 - break;  
119 - }  
120 - }  
121 - }  
122 - }  
123 - return result;  
124 - }  
125 -  
126 - private void getClientSecurityInfoNoSec(ReadResultSecurityStore result) {  
127 - result.setSecurityInfo(null);  
128 - result.setSecurityMode(NO_SEC.code);  
129 - }  
130 -  
131 - private void getClientSecurityInfoPSK(ReadResultSecurityStore result, String endPoint, JsonObject object) {  
132 - /** PSK Deserialization */  
133 - String identity = (object.has("identity") && object.get("identity").isJsonPrimitive()) ? object.get("identity").getAsString() : null;  
134 - if (identity != null && !identity.isEmpty()) {  
135 - try {  
136 - byte[] key = (object.has("key") && object.get("key").isJsonPrimitive()) ? Hex.decodeHex(object.get("key").getAsString().toCharArray()) : null;  
137 - if (key != null && key.length > 0) {  
138 - if (endPoint != null && !endPoint.isEmpty()) {  
139 - result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endPoint, identity, key));  
140 - result.setSecurityMode(PSK.code);  
141 - }  
142 - }  
143 - } catch (IllegalArgumentException e) {  
144 - log.error("Missing PSK key: " + e.getMessage());  
145 - }  
146 - } else {  
147 - log.error("Missing PSK identity");  
148 - }  
149 - }  
150 -  
151 - private void getClientSecurityInfoRPK(ReadResultSecurityStore result, String endpoint, JsonObject object) {  
152 - try {  
153 - if (object.has("key") && object.get("key").isJsonPrimitive()) {  
154 - byte[] rpkkey = Hex.decodeHex(object.get("key").getAsString().toLowerCase().toCharArray());  
155 - PublicKey key = SecurityUtil.publicKey.decode(rpkkey);  
156 - result.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(endpoint, key));  
157 - result.setSecurityMode(RPK.code);  
158 - } else {  
159 - log.error("Missing RPK key");  
160 - }  
161 - } catch (IllegalArgumentException | IOException | GeneralSecurityException e) {  
162 - log.error("RPK: Invalid security info content: " + e.getMessage());  
163 - }  
164 - }  
165 -  
166 - private void getClientSecurityInfoX509(ReadResultSecurityStore result, String endpoint) {  
167 - result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint));  
168 - result.setSecurityMode(X509.code);  
169 - }  
170 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.secure;  
17 -  
18 -public enum LwM2MSecurityMode {  
19 -  
20 - PSK(0, "psk"),  
21 - RPK(1, "rpk"),  
22 - X509(2, "x509"),  
23 - NO_SEC(3, "no_sec"),  
24 - X509_EST(4, "x509_est"),  
25 - REDIS(7, "redis"),  
26 - DEFAULT_MODE(255, "default_mode");  
27 -  
28 - public int code;  
29 - public String subEndpoint;  
30 -  
31 - LwM2MSecurityMode(int code, String subEndpoint) {  
32 - this.code = code;  
33 - this.subEndpoint = subEndpoint;  
34 - }  
35 -  
36 - public static LwM2MSecurityMode fromSecurityMode(long code) {  
37 - return fromSecurityMode((int) code);  
38 - }  
39 -  
40 - public static LwM2MSecurityMode fromSecurityMode(int code) {  
41 - for (LwM2MSecurityMode sm : LwM2MSecurityMode.values()) {  
42 - if (sm.code == code) {  
43 - return sm;  
44 - }  
45 - }  
46 - throw new IllegalArgumentException(String.format("Unsupported security code : %d", code));  
47 - }  
48 -  
49 -  
50 - public static LwM2MSecurityMode fromSecurityMode(String subEndpoint) {  
51 - for (LwM2MSecurityMode sm : LwM2MSecurityMode.values()) {  
52 - if (sm.subEndpoint.equals(subEndpoint)) {  
53 - return sm;  
54 - }  
55 - }  
56 - throw new IllegalArgumentException(String.format("Unsupported security subEndpoint : %d", subEndpoint));  
57 - }  
58 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.secure;  
17 -  
18 -import lombok.Data;  
19 -import lombok.extern.slf4j.Slf4j;  
20 -import org.eclipse.leshan.core.util.Hex;  
21 -import java.math.BigInteger;  
22 -import java.security.PrivateKey;  
23 -import java.security.PublicKey;  
24 -import java.security.AlgorithmParameters;  
25 -import java.security.KeyFactory;  
26 -import java.security.GeneralSecurityException;  
27 -import java.security.cert.Certificate;  
28 -import java.security.cert.X509Certificate;  
29 -import java.security.spec.ECGenParameterSpec;  
30 -import java.security.spec.ECParameterSpec;  
31 -import java.security.spec.ECPublicKeySpec;  
32 -import java.security.spec.KeySpec;  
33 -import java.security.spec.ECPrivateKeySpec;  
34 -import java.security.spec.ECPoint;  
35 -import java.util.List;  
36 -  
37 -@Slf4j  
38 -@Data  
39 -public class LwM2mRPkCredentials {  
40 - private PublicKey serverPublicKey;  
41 - private PrivateKey serverPrivateKey;  
42 - private X509Certificate certificate;  
43 - private List<Certificate> trustStore;  
44 -  
45 - /**  
46 - * create All key RPK credentials  
47 - * @param publX  
48 - * @param publY  
49 - * @param privS  
50 - */  
51 - public LwM2mRPkCredentials(String publX, String publY, String privS) {  
52 - generatePublicKeyRPK(publX, publY, privS);  
53 - }  
54 -  
55 - private void generatePublicKeyRPK(String publX, String publY, String privS) {  
56 - try {  
57 - /**Get Elliptic Curve Parameter spec for secp256r1 */  
58 - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");  
59 - algoParameters.init(new ECGenParameterSpec("secp256r1"));  
60 - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);  
61 - if (publX != null && !publX.isEmpty() && publY != null && !publY.isEmpty()) {  
62 - // Get point values  
63 - byte[] publicX = Hex.decodeHex(publX.toCharArray());  
64 - byte[] publicY = Hex.decodeHex(publY.toCharArray());  
65 - /** Create key specs */  
66 - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),  
67 - parameterSpec);  
68 - /** Get keys */  
69 - this.serverPublicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);  
70 - }  
71 - if (privS != null && !privS.isEmpty()) {  
72 - /** Get point values */  
73 - byte[] privateS = Hex.decodeHex(privS.toCharArray());  
74 - /** Create key specs */  
75 - KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec);  
76 - /** Get keys */  
77 - this.serverPrivateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec);  
78 - }  
79 - } catch (GeneralSecurityException | IllegalArgumentException e) {  
80 - log.error("[{}] Failed generate Server KeyRPK", e.getMessage());  
81 - throw new RuntimeException(e);  
82 - }  
83 - }  
84 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.secure;  
17 -  
18 -import com.google.gson.JsonObject;  
19 -import lombok.Builder;  
20 -import lombok.Data;  
21 -import org.eclipse.leshan.server.bootstrap.BootstrapConfig;  
22 -import org.eclipse.leshan.server.security.SecurityInfo;  
23 -import org.thingsboard.server.common.data.DeviceProfile;  
24 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;  
25 -  
26 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.DEFAULT_MODE;  
27 -  
28 -@Data  
29 -public class ReadResultSecurityStore {  
30 - private ValidateDeviceCredentialsResponseMsg msg;  
31 - private SecurityInfo securityInfo;  
32 - @Builder.Default  
33 - private int securityMode = DEFAULT_MODE.code;  
34 -  
35 - /** bootstrap */  
36 - DeviceProfile deviceProfile;  
37 - JsonObject bootstrapJsonCredential;  
38 - String endPoint;  
39 - BootstrapConfig bootstrapConfig;  
40 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import io.netty.util.concurrent.Future;  
19 -import io.netty.util.concurrent.GenericFutureListener;  
20 -import lombok.extern.slf4j.Slf4j;  
21 -import org.thingsboard.server.common.data.Device;  
22 -import org.thingsboard.server.common.data.DeviceProfile;  
23 -import org.thingsboard.server.common.transport.SessionMsgListener;  
24 -import org.thingsboard.server.gen.transport.TransportProtos;  
25 -import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;  
26 -import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;  
27 -import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;  
28 -import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;  
29 -import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;  
30 -import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;  
31 -  
32 -import java.util.Optional;  
33 -  
34 -@Slf4j  
35 -public class LwM2MSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener {  
36 - private LwM2MTransportService service;  
37 - private TransportProtos.SessionInfoProto sessionInfo;  
38 -  
39 - LwM2MSessionMsgListener(LwM2MTransportService service, TransportProtos.SessionInfoProto sessionInfo) {  
40 - this.service = service;  
41 - this.sessionInfo = sessionInfo;  
42 - }  
43 -  
44 - @Override  
45 - public void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse) {  
46 - log.info("[{}] attributesResponse", getAttributesResponse);  
47 - }  
48 -  
49 - @Override  
50 - public void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification) {  
51 - this.service.onAttributeUpdate(attributeUpdateNotification, this.sessionInfo);  
52 - }  
53 -  
54 - @Override  
55 - public void onRemoteSessionCloseCommand(SessionCloseNotificationProto sessionCloseNotification) {  
56 - log.info("[{}] sessionCloseNotification", sessionCloseNotification);  
57 - }  
58 -  
59 - @Override  
60 - public void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto updateCredentials) {  
61 - this.service.onToTransportUpdateCredentials(updateCredentials);  
62 - }  
63 -  
64 - @Override  
65 - public void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {  
66 - this.service.onDeviceProfileUpdate(sessionInfo, deviceProfile);  
67 - }  
68 -  
69 - @Override  
70 - public void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {  
71 - this.service.onDeviceUpdate(sessionInfo, device, deviceProfileOpt);  
72 - }  
73 -  
74 - @Override  
75 - public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) {  
76 - log.info("[{}] toDeviceRpcRequest", toDeviceRequest);  
77 - }  
78 -  
79 - @Override  
80 - public void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse) {  
81 - log.info("[{}] toServerRpcResponse", toServerResponse);  
82 - }  
83 -  
84 - @Override  
85 - public void operationComplete(Future<? super Void> future) throws Exception {  
86 - log.info("[{}] operationComplete", future);  
87 - }  
88 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -/**  
18 - * Copyright © 2016-2020 The Thingsboard Authors  
19 - *  
20 - * Licensed under the Apache License, Version 2.0 (the "License");  
21 - * you may not use this file except in compliance with the License.  
22 - * You may obtain a copy of the License at  
23 - *  
24 - * http://www.apache.org/licenses/LICENSE-2.0  
25 - *  
26 - * Unless required by applicable law or agreed to in writing, software  
27 - * distributed under the License is distributed on an "AS IS" BASIS,  
28 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
29 - * See the License for the specific language governing permissions and  
30 - * limitations under the License.  
31 - */  
32 -  
33 -import lombok.extern.slf4j.Slf4j;  
34 -import org.springframework.beans.factory.annotation.Autowired;  
35 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
36 -import org.springframework.stereotype.Component;  
37 -import org.thingsboard.server.common.transport.TransportContext;  
38 -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer;  
39 -  
40 -import javax.annotation.PostConstruct;  
41 -  
42 -@Slf4j  
43 -@Component  
44 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
45 -public class LwM2MTransportContextServer extends TransportContext {  
46 -  
47 - private LwM2MTransportConfigServer ctxServer;  
48 -  
49 - @Autowired  
50 - LwM2MTransportConfigServer lwM2MTransportConfigServer;  
51 -  
52 - @PostConstruct  
53 - public void init() {  
54 - this.ctxServer = lwM2MTransportConfigServer;  
55 - }  
56 -  
57 - public LwM2MTransportConfigServer getCtxServer () {  
58 - return this.ctxServer;  
59 - }  
60 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import com.fasterxml.jackson.databind.ObjectMapper;  
19 -import com.google.gson.Gson;  
20 -import com.google.gson.JsonObject;  
21 -import com.google.gson.JsonParser;  
22 -import com.google.gson.JsonSyntaxException;  
23 -import lombok.extern.slf4j.Slf4j;  
24 -import org.apache.commons.lang3.StringUtils;  
25 -import org.eclipse.californium.core.network.config.NetworkConfig;  
26 -import org.eclipse.leshan.core.model.ResourceModel;  
27 -import org.eclipse.leshan.core.node.LwM2mNode;  
28 -import org.eclipse.leshan.core.node.LwM2mObject;  
29 -import org.eclipse.leshan.core.node.LwM2mObjectInstance;  
30 -import org.eclipse.leshan.core.node.LwM2mSingleResource;  
31 -import org.eclipse.leshan.core.node.LwM2mMultipleResource;  
32 -import org.eclipse.leshan.core.util.Hex;  
33 -import org.eclipse.leshan.server.californium.LeshanServer;  
34 -import org.eclipse.leshan.server.californium.LeshanServerBuilder;  
35 -import org.nustaq.serialization.FSTConfiguration;  
36 -import org.springframework.beans.factory.annotation.Autowired;  
37 -import org.springframework.beans.factory.annotation.Qualifier;  
38 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
39 -import org.springframework.stereotype.Component;  
40 -import org.thingsboard.server.common.data.DeviceProfile;  
41 -import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;  
42 -import org.thingsboard.server.transport.lwm2m.server.client.AttrTelemetryObserveValue;  
43 -  
44 -import javax.annotation.PostConstruct;  
45 -import java.io.File;  
46 -import java.io.IOException;  
47 -import java.text.DateFormat;  
48 -import java.text.SimpleDateFormat;  
49 -import java.util.Date;  
50 -import java.util.Optional;  
51 -import java.util.Map;  
52 -import java.util.Arrays;  
53 -import java.util.List;  
54 -import java.util.ArrayList;  
55 -import java.util.LinkedList;  
56 -import java.util.Collections;  
57 -  
58 -@Slf4j  
59 -@Component("LwM2MTransportHandler")  
60 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
61 -public class LwM2MTransportHandler{  
62 -  
63 - // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to  
64 - // send a Confirmable message to the time when an acknowledgement is no longer expected.  
65 - public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000l; // 2min in ms  
66 - public static final String OBSERVE_ATTRIBUTE_TELEMETRY = "observeAttr";  
67 - public static final String KEYNAME = "keyName";  
68 - public static final String ATTRIBUTE = "attribute";  
69 - public static final String TELEMETRY = "telemetry";  
70 - public static final String OBSERVE = "observe";  
71 - public static final String BOOTSTRAP = "bootstrap";  
72 - public static final String SERVERS = "servers";  
73 - public static final String LWM2M_SERVER = "lwm2mServer";  
74 - public static final String BOOTSTRAP_SERVER = "bootstrapServer";  
75 - public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me";  
76 - public static final String DEVICE_ATTRIBUTES_TOPIC = BASE_DEVICE_API_TOPIC + "/attributes";  
77 - public static final String DEVICE_TELEMETRY_TOPIC = BASE_DEVICE_API_TOPIC + "/telemetry";  
78 - public static final String LOG_LW2M_TELEMETRY = "logLwm2m";  
79 - public static final String LOG_LW2M_INFO = "info";  
80 - public static final String LOG_LW2M_ERROR = "error";  
81 - public static final String LOG_LW2M_WARN = "warn";  
82 -  
83 -  
84 - public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";  
85 -  
86 - public static final String GET_TYPE_OPER_READ = "read";  
87 - public static final String GET_TYPE_OPER_DISCOVER = "discover";  
88 - public static final String GET_TYPE_OPER_OBSERVE = "observe";  
89 - public static final String POST_TYPE_OPER_OBSERVE_CANCEL = "observeCancel";  
90 - public static final String POST_TYPE_OPER_EXECUTE = "execute";  
91 - /**  
92 - * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see  
93 - * section 5.3.3 of the LW M2M spec).  
94 - */  
95 - public static final String POST_TYPE_OPER_WRITE_REPLACE = "replace";  
96 - /**  
97 - * Adds or updates Resources provided in the new value and leaves other existing Resources unchanged. (see section  
98 - * 5.3.3 of the LW M2M spec).  
99 - */  
100 - public static final String PUT_TYPE_OPER_WRITE_UPDATE = "update";  
101 - public static final String PUT_TYPE_OPER_WRITE_ATTRIBUTES = "wright-attributes";  
102 -  
103 - public static final String EVENT_AWAKE = "AWAKE";  
104 -  
105 - private static Gson gson = null;  
106 -  
107 - @Autowired  
108 - @Qualifier("LeshanServerCert")  
109 - private LeshanServer lhServerCert;  
110 -  
111 - @Autowired  
112 - @Qualifier("leshanServerNoSecPskRpk")  
113 - private LeshanServer lhServerNoSecPskRpk;  
114 -  
115 - @Autowired  
116 - private LwM2MTransportService service;  
117 -  
118 -  
119 - @PostConstruct  
120 - public void init() {  
121 - LwM2mServerListener lwM2mServerListener = new LwM2mServerListener(lhServerCert, service);  
122 - this.lhServerCert.getRegistrationService().addListener(lwM2mServerListener.registrationListener);  
123 - this.lhServerCert.getPresenceService().addListener(lwM2mServerListener.presenceListener);  
124 - this.lhServerCert.getObservationService().addListener(lwM2mServerListener.observationListener);  
125 - lwM2mServerListener = new LwM2mServerListener(lhServerNoSecPskRpk, service);  
126 - this.lhServerNoSecPskRpk.getRegistrationService().addListener(lwM2mServerListener.registrationListener);  
127 - this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener);  
128 - this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener);  
129 - }  
130 -  
131 - public static NetworkConfig getCoapConfig() {  
132 - NetworkConfig coapConfig;  
133 - File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME);  
134 - if (configFile.isFile()) {  
135 - coapConfig = new NetworkConfig();  
136 - coapConfig.load(configFile);  
137 - } else {  
138 - coapConfig = LeshanServerBuilder.createDefaultNetworkConfig();  
139 - coapConfig.store(configFile);  
140 - }  
141 - return coapConfig;  
142 - }  
143 -  
144 - public static String getValueTypeToString (Object value, ResourceModel.Type type) {  
145 - switch (type) {  
146 - case STRING: // String  
147 - case OBJLNK: // ObjectLink  
148 - return value.toString();  
149 - case INTEGER: // Long  
150 - return Long.toString((long) value);  
151 - case BOOLEAN: // Boolean  
152 - return Boolean.toString((Boolean) value);  
153 - case FLOAT: // Double  
154 - return Double.toString((Float)value);  
155 - case TIME: // Date  
156 - String DATE_FORMAT = "MMM d, yyyy HH:mm a";  
157 - DateFormat formatter = new SimpleDateFormat(DATE_FORMAT);  
158 - return formatter.format(new Date((Long) Integer.toUnsignedLong(Integer.valueOf((Integer) value))));  
159 - case OPAQUE: // byte[] value, base64  
160 - return Hex.encodeHexString((byte[])value);  
161 - default:  
162 - return null;  
163 - }  
164 - }  
165 -  
166 - public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) {  
167 - if (content instanceof LwM2mObject) {  
168 - return (LwM2mObject) content;  
169 - } else if (content instanceof LwM2mObjectInstance) {  
170 - return (LwM2mObjectInstance) content;  
171 - } else if (content instanceof LwM2mSingleResource) {  
172 - return (LwM2mSingleResource) content;  
173 - } else if (content instanceof LwM2mMultipleResource) {  
174 - return (LwM2mMultipleResource) content;  
175 - }  
176 - return null;  
177 - }  
178 -  
179 - public static AttrTelemetryObserveValue getNewProfileParameters(JsonObject profilesConfigData) {  
180 - AttrTelemetryObserveValue attrTelemetryObserveValue = new AttrTelemetryObserveValue();  
181 - attrTelemetryObserveValue.setPostKeyNameProfile(profilesConfigData.get(KEYNAME).getAsJsonObject());  
182 - attrTelemetryObserveValue.setPostAttributeProfile(profilesConfigData.get(ATTRIBUTE).getAsJsonArray());  
183 - attrTelemetryObserveValue.setPostTelemetryProfile(profilesConfigData.get(TELEMETRY).getAsJsonArray());  
184 - attrTelemetryObserveValue.setPostObserveProfile(profilesConfigData.get(OBSERVE).getAsJsonArray());  
185 - return attrTelemetryObserveValue;  
186 - }  
187 -  
188 - /**  
189 -  
190 - * @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard  
191 - * Example: with pathResource (use only pathResource)  
192 - * property: "observeAttr"  
193 - * {"keyName": {  
194 - * "/3/0/1": "modelNumber",  
195 - * "/3/0/0": "manufacturer",  
196 - * "/3/0/2": "serialNumber"  
197 - * },  
198 - * "attribute":["/2/0/1","/3/0/9"],  
199 - * "telemetry":["/1/0/1","/2/0/1","/6/0/1"],  
200 - * "observe":["/2/0","/2/0/0","/4/0/2"]}  
201 - */  
202 - public static JsonObject getObserveAttrTelemetryFromThingsboard(DeviceProfile deviceProfile) {  
203 - if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {  
204 - Lwm2mDeviceProfileTransportConfiguration lwm2mDeviceProfileTransportConfiguration = (Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();  
205 - Object observeAttr = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();  
206 - try {  
207 - ObjectMapper mapper = new ObjectMapper();  
208 - String observeAttrStr = mapper.writeValueAsString(observeAttr);  
209 - JsonObject objectMsg = (observeAttrStr != null) ? validateJson(observeAttrStr) : null;  
210 - return (getValidateCredentialsBodyFromThingsboard(objectMsg)) ? objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject() : null;  
211 - } catch (IOException e) {  
212 - e.printStackTrace();  
213 - }  
214 - }  
215 - return null;  
216 - }  
217 -  
218 - public static JsonObject getBootstrapParametersFromThingsboard(DeviceProfile deviceProfile) {  
219 - if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {  
220 - Lwm2mDeviceProfileTransportConfiguration lwm2mDeviceProfileTransportConfiguration = (Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();  
221 - Object bootstrap = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();  
222 - try {  
223 - ObjectMapper mapper = new ObjectMapper();  
224 - String bootstrapStr = mapper.writeValueAsString(bootstrap);  
225 - JsonObject objectMsg = (bootstrapStr != null) ? validateJson(bootstrapStr) : null;  
226 - return (getValidateBootstrapProfileFromThingsboard(objectMsg)) ? objectMsg.get(BOOTSTRAP).getAsJsonObject() : null;  
227 - } catch (IOException e) {  
228 - e.printStackTrace();  
229 - }  
230 - }  
231 - return null;  
232 - }  
233 -  
234 - private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) {  
235 - return (objectMsg != null &&  
236 - !objectMsg.isJsonNull() &&  
237 - objectMsg.has(OBSERVE_ATTRIBUTE_TELEMETRY) &&  
238 - !objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).isJsonNull() &&  
239 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).isJsonObject() &&  
240 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(KEYNAME) &&  
241 - !objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEYNAME).isJsonNull() &&  
242 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEYNAME).isJsonObject() &&  
243 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(ATTRIBUTE) &&  
244 - !objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).isJsonNull() &&  
245 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).isJsonArray() &&  
246 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(TELEMETRY) &&  
247 - !objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).isJsonNull() &&  
248 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).isJsonArray() &&  
249 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(OBSERVE) &&  
250 - !objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE).isJsonNull() &&  
251 - objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE).isJsonArray());  
252 - }  
253 -  
254 - private static boolean getValidateBootstrapProfileFromThingsboard(JsonObject objectMsg) {  
255 - return (objectMsg != null &&  
256 - !objectMsg.isJsonNull() &&  
257 - objectMsg.has(BOOTSTRAP) &&  
258 - objectMsg.get(BOOTSTRAP).isJsonObject() &&  
259 - !objectMsg.get(BOOTSTRAP).isJsonNull() &&  
260 - objectMsg.get(BOOTSTRAP).getAsJsonObject().has(SERVERS) &&  
261 - !objectMsg.get(BOOTSTRAP).getAsJsonObject().get(SERVERS).isJsonNull() &&  
262 - objectMsg.get(BOOTSTRAP).getAsJsonObject().get(SERVERS).isJsonObject() &&  
263 - objectMsg.get(BOOTSTRAP).getAsJsonObject().has(BOOTSTRAP_SERVER) &&  
264 - !objectMsg.get(BOOTSTRAP).getAsJsonObject().get(BOOTSTRAP_SERVER).isJsonNull() &&  
265 - objectMsg.get(BOOTSTRAP).getAsJsonObject().get(BOOTSTRAP_SERVER).isJsonObject() &&  
266 - objectMsg.get(BOOTSTRAP).getAsJsonObject().has(LWM2M_SERVER) &&  
267 - !objectMsg.get(BOOTSTRAP).getAsJsonObject().get(LWM2M_SERVER).isJsonNull() &&  
268 - objectMsg.get(BOOTSTRAP).getAsJsonObject().get(LWM2M_SERVER).isJsonObject());  
269 - }  
270 -  
271 -  
272 - public static JsonObject validateJson(String jsonStr) {  
273 - JsonObject object = null;  
274 - if (jsonStr != null && !jsonStr.isEmpty()) {  
275 - String jsonValidFlesh = jsonStr.replaceAll("\\\\", "");  
276 - jsonValidFlesh = jsonValidFlesh.replaceAll("\n", "");  
277 - jsonValidFlesh = jsonValidFlesh.replaceAll("\t", "");  
278 - jsonValidFlesh = jsonValidFlesh.replaceAll(" ", "");  
279 - String jsonValid = (jsonValidFlesh.substring(0, 1).equals("\"") && jsonValidFlesh.substring(jsonValidFlesh.length() - 1).equals("\"")) ? jsonValidFlesh.substring(1, jsonValidFlesh.length() - 1) : jsonValidFlesh;  
280 - try {  
281 - object = new JsonParser().parse(jsonValid).getAsJsonObject();  
282 - } catch (JsonSyntaxException e) {  
283 - log.error("[{}] Fail validateJson [{}]", jsonStr, e.getMessage());  
284 - }  
285 - }  
286 - return object;  
287 - }  
288 -  
289 - public static <T> Optional<T> decode(byte[] byteArray) {  
290 - try {  
291 - FSTConfiguration config = FSTConfiguration.createDefaultConfiguration();;  
292 - T msg = (T) config.asObject(byteArray);  
293 - return Optional.ofNullable(msg);  
294 - } catch (IllegalArgumentException e) {  
295 - log.error("Error during deserialization message, [{}]", e.getMessage());  
296 - return Optional.empty();  
297 - }  
298 - }  
299 -  
300 - /**  
301 - * Equals to Map for values  
302 - * @param map1  
303 - * @param map2  
304 - * @param <V>  
305 - * @return  
306 - */  
307 - public static <V extends Comparable<V>> boolean mapsEquals(Map<?,V> map1, Map<?,V> map2) {  
308 - List<V> values1 = new ArrayList<V>(map1.values());  
309 - List<V> values2 = new ArrayList<V>(map2.values());  
310 - Collections.sort(values1);  
311 - Collections.sort(values2);  
312 - return values1.equals(values2);  
313 - }  
314 -  
315 - public static String convertCamelCase (String str) {  
316 - str = str.toLowerCase().replace("/[^a-z ]+/g", " ");  
317 - str = str.replace("/^(.)|\\s(.)/g", "$1");  
318 - str = str.replace("/[^a-zA-Z]+/g", "");  
319 - return str;  
320 - }  
321 -  
322 - public static String splitCamelCaseString(String s){  
323 - LinkedList<String> linkedListOut = new LinkedList<String>();  
324 - LinkedList<String> linkedList = new LinkedList<String>((Arrays.asList(s.split(" "))));  
325 - linkedList.stream().forEach(str-> {  
326 - String strOut = str.replaceAll("\\W", "").replaceAll("_", "").toUpperCase();  
327 - if (strOut.length()>1) linkedListOut.add(strOut.substring(0, 1) + strOut.substring(1).toLowerCase());  
328 - else linkedListOut.add(strOut);  
329 - });  
330 - linkedListOut.set(0, (linkedListOut.get(0).substring(0, 1).toLowerCase() + linkedListOut.get(0).substring(1)));  
331 - return StringUtils.join(linkedListOut, "");  
332 - }  
333 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.californium.core.coap.Response;  
20 -import org.eclipse.leshan.core.attributes.Attribute;  
21 -import org.eclipse.leshan.core.attributes.AttributeSet;  
22 -import org.eclipse.leshan.core.model.ResourceModel;  
23 -import org.eclipse.leshan.core.node.LwM2mSingleResource;  
24 -import org.eclipse.leshan.core.node.ObjectLink;  
25 -import org.eclipse.leshan.core.observation.Observation;  
26 -import org.eclipse.leshan.core.request.ContentFormat;  
27 -import org.eclipse.leshan.core.request.WriteRequest;  
28 -import org.eclipse.leshan.core.request.DiscoverRequest;  
29 -import org.eclipse.leshan.core.request.DownlinkRequest;  
30 -import org.eclipse.leshan.core.request.ObserveRequest;  
31 -import org.eclipse.leshan.core.request.CancelObservationRequest;  
32 -import org.eclipse.leshan.core.request.ReadRequest;  
33 -import org.eclipse.leshan.core.request.ExecuteRequest;  
34 -import org.eclipse.leshan.core.request.WriteAttributesRequest;  
35 -import org.eclipse.leshan.core.response.ResponseCallback;  
36 -import org.eclipse.leshan.core.response.LwM2mResponse;  
37 -import org.eclipse.leshan.core.response.ObserveResponse;  
38 -import org.eclipse.leshan.core.response.ReadResponse;  
39 -import org.eclipse.leshan.core.response.CancelObservationResponse;  
40 -import org.eclipse.leshan.core.response.DeleteResponse;  
41 -import org.eclipse.leshan.core.response.ExecuteResponse;  
42 -import org.eclipse.leshan.core.response.DiscoverResponse;  
43 -import org.eclipse.leshan.core.response.WriteAttributesResponse;  
44 -import org.eclipse.leshan.core.response.WriteResponse;  
45 -import org.eclipse.leshan.core.util.Hex;  
46 -import org.eclipse.leshan.core.util.NamedThreadFactory;  
47 -import org.eclipse.leshan.server.californium.LeshanServer;  
48 -import org.eclipse.leshan.server.registration.Registration;  
49 -import org.springframework.beans.factory.annotation.Autowired;  
50 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
51 -import org.springframework.stereotype.Service;  
52 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;  
53 -  
54 -import javax.annotation.PostConstruct;  
55 -import java.util.ArrayList;  
56 -import java.util.Collection;  
57 -import java.util.Date;  
58 -import java.util.Iterator;  
59 -import java.util.concurrent.ExecutorService;  
60 -import java.util.concurrent.Executors;  
61 -  
62 -import static org.eclipse.californium.core.coap.CoAP.ResponseCode.isSuccess;  
63 -import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD;  
64 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEFAULT_TIMEOUT;  
65 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_DISCOVER;  
66 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_OBSERVE;  
67 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_READ;  
68 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES;  
69 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE;  
70 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_EXECUTE;  
71 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_OBSERVE_CANCEL;  
72 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;  
73 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR;  
74 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO;  
75 -  
76 -@Slf4j  
77 -@Service("LwM2MTransportRequest")  
78 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
79 -public class LwM2MTransportRequest {  
80 - private final ExecutorService executorService;  
81 - private static final String RESPONSE_CHANNEL = "THINGSBOARD_RESP";  
82 -  
83 - @Autowired  
84 - LwM2MTransportService service;  
85 -  
86 - public LwM2MTransportRequest() {  
87 - executorService = Executors.newCachedThreadPool(  
88 - new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));  
89 - }  
90 -  
91 -  
92 - @PostConstruct  
93 - public void init() {  
94 - }  
95 -  
96 - public Collection<Registration> doGetRegistrations(LeshanServer lwServer) {  
97 - Collection<Registration> registrations = new ArrayList<>();  
98 - for (Iterator<Registration> iterator = lwServer.getRegistrationService().getAllRegistrations(); iterator  
99 - .hasNext(); ) {  
100 - registrations.add(iterator.next());  
101 - }  
102 - return registrations;  
103 - }  
104 -  
105 - /**  
106 - * Device management and service enablement, including Read, Write, Execute, Discover, Create, Delete and Write-Attributes  
107 - *  
108 - * @param lwServer  
109 - * @param registration  
110 - * @param target  
111 - * @param typeOper  
112 - * @param contentFormatParam  
113 - * @param lwM2MClient  
114 - * @param observation  
115 - */  
116 - public void sendAllRequest(LeshanServer lwServer, Registration registration, String target, String typeOper,  
117 - String contentFormatParam, LwM2MClient lwM2MClient, Observation observation, Object params, long timeoutInMs) {  
118 - ResultIds resultIds = new ResultIds(target);  
119 - if (registration != null && resultIds.getObjectId() >= 0) {  
120 - DownlinkRequest request = null;  
121 - ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;  
122 - ResourceModel resource = (resultIds.resourceId >= 0) ? (lwM2MClient != null) ?  
123 - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.resourceId) : null : null;  
124 - ResourceModel.Type resType = (resource == null) ? null : resource.type;  
125 - boolean resMultiple = (resource == null) ? false : resource.multiple;  
126 - timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;  
127 - switch (typeOper) {  
128 - case GET_TYPE_OPER_READ:  
129 - request = new ReadRequest(contentFormat, target);  
130 - break;  
131 - case GET_TYPE_OPER_DISCOVER:  
132 - request = new DiscoverRequest(target);  
133 - break;  
134 - case GET_TYPE_OPER_OBSERVE:  
135 - if (resultIds.getResourceId() >= 0) {  
136 - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId());  
137 - } else if (resultIds.getInstanceId() >= 0) {  
138 - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId());  
139 - } else if (resultIds.getObjectId() >= 0) {  
140 - request = new ObserveRequest(resultIds.getObjectId());  
141 - }  
142 - break;  
143 - case POST_TYPE_OPER_OBSERVE_CANCEL:  
144 - request = new CancelObservationRequest(observation);  
145 - break;  
146 - case POST_TYPE_OPER_EXECUTE:  
147 - if (params != null && !resMultiple) {  
148 - request = new ExecuteRequest(target, LwM2MTransportHandler.getValueTypeToString(params, resType));  
149 - } else {  
150 - request = new ExecuteRequest(target);  
151 - }  
152 - break;  
153 - case POST_TYPE_OPER_WRITE_REPLACE:  
154 - // Request to write a <b>String Single-Instance Resource</b> using the TLV content format.  
155 - if (contentFormat.equals(ContentFormat.TLV) && !resMultiple) {  
156 - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), params, resType);  
157 - }  
158 - // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON)  
159 - else if (!contentFormat.equals(ContentFormat.TLV) && !resMultiple) {  
160 - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), params, resType);  
161 - }  
162 - break;  
163 - case PUT_TYPE_OPER_WRITE_UPDATE:  
164 - if (resultIds.getResourceId() >= 0) {  
165 - ResourceModel resourceModel = lwServer.getModelProvider().getObjectModel(registration).getObjectModel(resultIds.getObjectId()).resources.get(resultIds.getResourceId());  
166 - ResourceModel.Type typeRes = resourceModel.type;  
167 -// request = getWriteRequestResource(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), params, typeRes);  
168 - }  
169 - break;  
170 - case PUT_TYPE_OPER_WRITE_ATTRIBUTES:  
171 - /**  
172 - * As example:  
173 - * a)Write-Attributes/3/0/9?pmin=1 means the Battery Level value will be notified  
174 - * to the Server with a minimum interval of 1sec;  
175 - * this value is set at theResource level.  
176 - * b)Write-Attributes/3/0/9?pmin means the Battery Level will be notified  
177 - * to the Server with a minimum value (pmin) given by the default one  
178 - * (resource 2 of Object Server ID=1),  
179 - * or with another value if this Attribute has been set at another level  
180 - * (Object or Object Instance: see section5.1.1).  
181 - * c)Write-Attributes/3/0?pmin=10 means that all Resources of Instance 0 of the Object ‘Device (ID:3)’  
182 - * will be notified to the Server with a minimum interval of 10 sec;  
183 - * this value is set at the Object Instance level.  
184 - * d)Write-Attributes /3/0/9?gt=45&st=10 means the Battery Level will be notified to the Server  
185 - * when:  
186 - * a.old value is 20 and new value is 35 due to step condition  
187 - * b.old value is 45 and new value is 50 due to gt condition  
188 - * c.old value is 50 and new value is 40 due to both gt and step conditions  
189 - * d.old value is 35 and new value is 20 due to step conditione)  
190 - * Write-Attributes /3/0/9?lt=20&gt=85&st=10 means the Battery Level will be notified to the Server  
191 - * when:  
192 - * a.old value is 17 and new value is 24 due to lt condition  
193 - * b.old value is 75 and new value is 90 due to both gt and step conditions  
194 - * String uriQueries = "pmin=10&pmax=60";  
195 - * AttributeSet attributes = AttributeSet.parse(uriQueries);  
196 - * WriteAttributesRequest request = new WriteAttributesRequest(target, attributes);  
197 - * Attribute gt = new Attribute(GREATER_THAN, Double.valueOf("45"));  
198 - * Attribute st = new Attribute(LESSER_THAN, Double.valueOf("10"));  
199 - * Attribute pmax = new Attribute(MAXIMUM_PERIOD, "60");  
200 - * Attribute [] attrs = {gt, st};  
201 - */  
202 - Attribute pmin = new Attribute(MINIMUM_PERIOD, Integer.toUnsignedLong(Integer.valueOf("1")));  
203 - Attribute[] attrs = {pmin};  
204 - AttributeSet attrSet = new AttributeSet(attrs);  
205 - if (resultIds.getResourceId() >= 0) {  
206 - request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), attrSet);  
207 - } else if (resultIds.getInstanceId() >= 0) {  
208 - request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), attrSet);  
209 - } else if (resultIds.getObjectId() >= 0) {  
210 - request = new WriteAttributesRequest(resultIds.getObjectId(), attrSet);  
211 - }  
212 - break;  
213 - default:  
214 - }  
215 - if (request != null) sendRequest(lwServer, registration, request, lwM2MClient, timeoutInMs);  
216 - }  
217 - }  
218 -  
219 - /**  
220 - *  
221 - * @param lwServer  
222 - * @param registration  
223 - * @param request  
224 - * @param lwM2MClient  
225 - * @param timeoutInMs  
226 - */  
227 - private void sendRequest(LeshanServer lwServer, Registration registration, DownlinkRequest request, LwM2MClient lwM2MClient, long timeoutInMs) {  
228 - lwServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {  
229 - if (isSuccess(((Response)response.getCoapResponse()).getCode())) {  
230 - this.handleResponse(registration, request.getPath().toString(), response, request, lwM2MClient);  
231 - if (request instanceof WriteRequest && ((WriteRequest) request).isReplaceRequest()) {  
232 - String msg = String.format(LOG_LW2M_INFO + " sendRequest Replace: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s SendRequest to Client",  
233 - ((Response)response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString(),  
234 - ((LwM2mSingleResource)((WriteRequest) request).getNode()).getValue().toString());  
235 - service.sentLogsToThingsboard(msg, registration.getId());  
236 - log.info("[{}] - [{}] [{}] [{}] Update SendRequest", ((Response)response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), ((LwM2mSingleResource)((WriteRequest) request).getNode()).getValue());  
237 - }  
238 - }  
239 - else {  
240 - String msg = String.format(LOG_LW2M_ERROR + " sendRequest: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s SendRequest to Client",  
241 - ((Response)response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString());  
242 - service.sentLogsToThingsboard(msg, registration.getId());  
243 - log.error("[{}] - [{}] [{}] error SendRequest", ((Response)response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());  
244 - }  
245 - }, e -> {  
246 - String msg = String.format(LOG_LW2M_ERROR + " sendRequest: Resource path - %s msg error - %s SendRequest to Client",  
247 - request.getPath().toString(), e.toString());  
248 - service.sentLogsToThingsboard(msg, registration.getId());  
249 - log.error("[{}] - [{}] error SendRequest", request.getPath().toString(), e.toString());  
250 - });  
251 - }  
252 -  
253 - private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, Integer resourceId, Object value, ResourceModel.Type type) {  
254 - try {  
255 - switch (type) {  
256 - case STRING: // String  
257 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, value.toString()) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, value.toString());  
258 - case INTEGER: // Long  
259 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Integer.toUnsignedLong(Integer.valueOf(value.toString()))) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Integer.toUnsignedLong(Integer.valueOf(value.toString())));  
260 - case OBJLNK: // ObjectLink  
261 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, ObjectLink.fromPath(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, ObjectLink.fromPath(value.toString()));  
262 - case BOOLEAN: // Boolean  
263 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Boolean.valueOf(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Boolean.valueOf(value.toString()));  
264 - case FLOAT: // Double  
265 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Double.valueOf(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Double.valueOf(value.toString()));  
266 - case TIME: // Date  
267 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, new Date((Long) Integer.toUnsignedLong(Integer.valueOf(value.toString())))) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, new Date((Long) Integer.toUnsignedLong(Integer.valueOf(value.toString()))));  
268 - case OPAQUE: // byte[] value, base64  
269 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray()));  
270 - default:  
271 - }  
272 - return null;  
273 - } catch (NumberFormatException e) {  
274 - String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;  
275 - log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());  
276 - return null;  
277 - }  
278 - }  
279 -  
280 - private void handleResponse(Registration registration, final String path, LwM2mResponse response, DownlinkRequest request, LwM2MClient lwM2MClient) {  
281 - executorService.submit(new Runnable() {  
282 - @Override  
283 - public void run() {  
284 -  
285 - try {  
286 - sendResponse(registration, path, response, request, lwM2MClient);  
287 - } catch (RuntimeException t) {  
288 - log.error("[{}] endpoint [{}] path [{}] error Unable to after send response.", registration.getEndpoint(), path, t.toString());  
289 - }  
290 - }  
291 - });  
292 - }  
293 -  
294 - /**  
295 - * processing a response from a client  
296 - * @param registration -  
297 - * @param path -  
298 - * @param response -  
299 - * @param lwM2MClient -  
300 - */  
301 - private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request, LwM2MClient lwM2MClient) {  
302 - if (response instanceof ObserveResponse) {  
303 - service.onObservationResponse(registration, path, (ReadResponse) response);  
304 - } else if (response instanceof CancelObservationResponse) {  
305 - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", path, response);  
306 - } else if (response instanceof ReadResponse) {  
307 - /**  
308 - * Use only at the first start after registration  
309 - * Fill with data -> Model client  
310 - */  
311 - if (lwM2MClient != null) {  
312 - if (lwM2MClient.getPendingRequests().size() > 0) {  
313 - lwM2MClient.onSuccessHandler(path, response);  
314 - }  
315 - }  
316 - /**  
317 - * Use after registration on request  
318 - */  
319 - else {  
320 - service.onObservationResponse(registration, path, (ReadResponse) response);  
321 - }  
322 - } else if (response instanceof DeleteResponse) {  
323 - log.info("[{}] Path [{}] DeleteResponse 5_Send", path, response);  
324 - } else if (response instanceof DiscoverResponse) {  
325 - log.info("[{}] Path [{}] DiscoverResponse 6_Send", path, response);  
326 - } else if (response instanceof ExecuteResponse) {  
327 - log.info("[{}] Path [{}] ExecuteResponse 7_Send", path, response);  
328 - } else if (response instanceof WriteAttributesResponse) {  
329 - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", path, response);  
330 - } else if (response instanceof WriteResponse) {  
331 - log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", path, response);  
332 - service.onAttributeUpdateOk(registration, path, (WriteRequest) request);  
333 - }  
334 - }  
335 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.californium.scandium.config.DtlsConnectorConfig;  
20 -import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;  
21 -import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;  
22 -import org.eclipse.leshan.core.node.codec.LwM2mNodeDecoder;  
23 -import org.eclipse.leshan.server.californium.LeshanServer;  
24 -import org.eclipse.leshan.server.californium.LeshanServerBuilder;  
25 -import org.eclipse.leshan.server.model.LwM2mModelProvider;  
26 -import org.eclipse.leshan.server.model.VersionedModelProvider;  
27 -import org.springframework.beans.factory.annotation.Autowired;  
28 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
29 -import org.springframework.context.annotation.Bean;  
30 -import org.springframework.context.annotation.ComponentScan;  
31 -import org.springframework.context.annotation.Configuration;  
32 -import org.springframework.context.annotation.Primary;  
33 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
34 -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2MSetSecurityStoreServer;  
35 -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore;  
36 -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;  
37 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509;  
38 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RPK;  
39 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig;  
40 -  
41 -  
42 -@Slf4j  
43 -@ComponentScan("org.thingsboard.server.transport.lwm2m.server")  
44 -@ComponentScan("org.thingsboard.server.transport.lwm2m.utils")  
45 -@Configuration("LwM2MTransportServerConfiguration")  
46 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
47 -public class LwM2MTransportServerConfiguration {  
48 -  
49 - @Autowired  
50 - private LwM2MTransportContextServer context;  
51 -  
52 - @Autowired  
53 - private LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore;  
54 -  
55 - @Primary  
56 - @Bean(name = "LeshanServerCert")  
57 - public LeshanServer getLeshanServerCert() {  
58 - log.info("Starting LwM2M transport ServerCert... PostConstruct");  
59 - return getLeshanServer(this.context.getCtxServer().getServerPortCert(), this.context.getCtxServer().getServerSecurePortCert(), X509);  
60 - }  
61 -  
62 - @Bean(name = "leshanServerNoSecPskRpk")  
63 - public LeshanServer getLeshanServerNoSecPskRpk() {  
64 - log.info("Starting LwM2M transport ServerNoSecPskRpk... PostConstruct");  
65 - return getLeshanServer(this.context.getCtxServer().getServerPort(), this.context.getCtxServer().getServerSecurePort(), RPK);  
66 - }  
67 -  
68 - private LeshanServer getLeshanServer(Integer serverPort, Integer serverSecurePort, LwM2MSecurityMode dtlsMode) {  
69 -  
70 - LeshanServerBuilder builder = new LeshanServerBuilder();  
71 - builder.setLocalAddress(this.context.getCtxServer().getServerHost(), serverPort);  
72 - builder.setLocalSecureAddress(this.context.getCtxServer().getServerSecureHost(), serverSecurePort);  
73 - builder.setEncoder(new DefaultLwM2mNodeEncoder());  
74 - LwM2mNodeDecoder decoder = new DefaultLwM2mNodeDecoder();  
75 - builder.setDecoder(decoder);  
76 - builder.setEncoder(new DefaultLwM2mNodeEncoder(new LwM2mValueConverterImpl()));  
77 -  
78 - /** Create CoAP Config */  
79 - builder.setCoapConfig(getCoapConfig());  
80 -  
81 - /** Define model provider (Create Models )*/  
82 - LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getCtxServer().getModelsValue());  
83 - builder.setObjectModelProvider(modelProvider);  
84 -  
85 - /** Create DTLS Config */  
86 - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();  
87 - dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getCtxServer().isSupportDeprecatedCiphersEnable());  
88 - /** Set DTLS Config */  
89 - builder.setDtlsConfig(dtlsConfig);  
90 -  
91 - /** Use a magic converter to support bad type send by the UI. */  
92 - builder.setEncoder(new DefaultLwM2mNodeEncoder(new LwM2mValueConverterImpl()));  
93 -  
94 - /** Create DTLS security mode  
95 - * There can be only one DTLS security mode  
96 - */  
97 - new LwM2MSetSecurityStoreServer(builder, context, lwM2mInMemorySecurityStore, dtlsMode);  
98 -  
99 - /** Create LWM2M server */  
100 - return builder.build();  
101 - }  
102 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.server.californium.LeshanServer;  
20 -import org.springframework.beans.factory.annotation.Autowired;  
21 -import org.springframework.beans.factory.annotation.Qualifier;  
22 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
23 -import org.springframework.stereotype.Service;  
24 -import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;  
25 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
26 -import javax.annotation.PostConstruct;  
27 -import javax.annotation.PreDestroy;  
28 -  
29 -@Slf4j  
30 -@Service("LwM2MTransportServerInitializer")  
31 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
32 -public class LwM2MTransportServerInitializer {  
33 -  
34 - @Autowired  
35 - @Qualifier("LeshanServerCert")  
36 - private LeshanServer lhServerCert;  
37 -  
38 - @Autowired  
39 - @Qualifier("leshanServerNoSecPskRpk")  
40 - private LeshanServer lhServerNoSecPskRpk;  
41 -  
42 - @Autowired  
43 - private LwM2MTransportContextServer context;  
44 -  
45 - @PostConstruct  
46 - public void init() {  
47 - if (this.context.getCtxServer().getEnableGenPskRpk()) new LWM2MGenerationPSkRPkECC();  
48 - if (this.context.getCtxServer().isServerStartAll()) {  
49 - this.lhServerCert.start();  
50 - this.lhServerNoSecPskRpk.start();  
51 - }  
52 - else {  
53 - if (this.context.getCtxServer().getServerDtlsMode() == LwM2MSecurityMode.X509.code) {  
54 - this.lhServerCert.start();  
55 - }  
56 - else {  
57 - this.lhServerNoSecPskRpk.start();  
58 - }  
59 - }  
60 - }  
61 -  
62 - @PreDestroy  
63 - public void shutdown() {  
64 - log.info("Stopping LwM2M transport Server!");  
65 - try {  
66 - lhServerCert.destroy();  
67 - lhServerNoSecPskRpk.destroy();  
68 - } finally {  
69 - }  
70 - log.info("LwM2M transport Server stopped!");  
71 - }  
72 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import com.google.gson.*;  
19 -import lombok.SneakyThrows;  
20 -import lombok.extern.slf4j.Slf4j;  
21 -import org.eclipse.leshan.core.model.ResourceModel;  
22 -import org.eclipse.leshan.core.node.LwM2mMultipleResource;  
23 -import org.eclipse.leshan.core.node.LwM2mObject;  
24 -import org.eclipse.leshan.core.node.LwM2mObjectInstance;  
25 -import org.eclipse.leshan.core.node.LwM2mSingleResource;  
26 -import org.eclipse.leshan.core.node.LwM2mResource;  
27 -import org.eclipse.leshan.core.node.LwM2mPath;  
28 -import org.eclipse.leshan.core.observation.Observation;  
29 -import org.eclipse.leshan.core.request.ContentFormat;  
30 -import org.eclipse.leshan.core.request.WriteRequest;  
31 -import org.eclipse.leshan.core.response.ReadResponse;  
32 -import org.eclipse.leshan.core.util.Hex;  
33 -import org.eclipse.leshan.server.californium.LeshanServer;  
34 -import org.eclipse.leshan.server.registration.Registration;  
35 -import org.springframework.beans.factory.annotation.Autowired;  
36 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
37 -import org.springframework.stereotype.Service;  
38 -import org.thingsboard.server.common.data.Device;  
39 -import org.thingsboard.server.common.data.DeviceProfile;  
40 -import org.thingsboard.server.common.transport.TransportService;  
41 -import org.thingsboard.server.common.transport.TransportServiceCallback;  
42 -import org.thingsboard.server.common.transport.adaptor.AdaptorException;  
43 -import org.thingsboard.server.common.transport.adaptor.JsonConverter;  
44 -import org.thingsboard.server.common.transport.service.DefaultTransportService;  
45 -import org.thingsboard.server.gen.transport.TransportProtos;  
46 -import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;  
47 -import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;  
48 -import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;  
49 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;  
50 -import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;  
51 -import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;  
52 -import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;  
53 -import org.thingsboard.server.transport.lwm2m.server.client.AttrTelemetryObserveValue;  
54 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;  
55 -import org.thingsboard.server.transport.lwm2m.server.client.ModelObject;  
56 -import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;  
57 -import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;  
58 -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore;  
59 -  
60 -import javax.annotation.PostConstruct;  
61 -import java.util.Collection;  
62 -import java.util.UUID;  
63 -import java.util.Random;  
64 -import java.util.Map;  
65 -import java.util.HashMap;  
66 -import java.util.Arrays;  
67 -import java.util.Set;  
68 -import java.util.HashSet;  
69 -import java.util.NoSuchElementException;  
70 -import java.util.Optional;  
71 -import java.util.concurrent.ConcurrentHashMap;  
72 -import java.util.concurrent.ConcurrentMap;  
73 -import java.util.concurrent.CountDownLatch;  
74 -import java.util.concurrent.TimeUnit;  
75 -import java.util.concurrent.atomic.AtomicBoolean;  
76 -import java.util.function.Predicate;  
77 -import java.util.stream.Collectors;  
78 -import java.util.stream.Stream;  
79 -  
80 -import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;  
81 -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.*;  
82 -  
83 -@Slf4j  
84 -@Service("LwM2MTransportService")  
85 -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
86 -public class LwM2MTransportService {  
87 -  
88 - @Autowired  
89 - private LwM2MJsonAdaptor adaptor;  
90 -  
91 - @Autowired  
92 - private TransportService transportService;  
93 -  
94 - @Autowired  
95 - public LwM2MTransportContextServer context;  
96 -  
97 - @Autowired  
98 - private LwM2MTransportRequest lwM2MTransportRequest;  
99 -  
100 - @Autowired  
101 - LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore;  
102 -  
103 -  
104 - @PostConstruct  
105 - public void init() {  
106 - context.getScheduler().scheduleAtFixedRate(() -> checkInactivityAndReportActivity(), new Random().nextInt((int) context.getCtxServer().getSessionReportTimeout()), context.getCtxServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS);  
107 - }  
108 -  
109 - /**  
110 - * Start registration device  
111 - * Create session: Map<String <registrationId >, LwM2MClient>  
112 - * 1. replaceNewRegistration -> (solving the problem of incorrect termination of the previous session with this endpoint)  
113 - * 1.1 When we initialize the registration, we register the session by endpoint.  
114 - * 1.2 If the server has incomplete requests (canceling the registration of the previous session),  
115 - * delete the previous session only by the previous registration.getId  
116 - * 1.2 Add Model (Entity) for client (from registration & observe) by registration.getId  
117 - * 1.2 Remove from sessions Model by enpPoint  
118 - * Next -> Create new LwM2MClient for current session -> setModelClient...  
119 - *  
120 - * @param lwServer - LeshanServer  
121 - * @param registration - Registration LwM2M Client  
122 - * @param previousObsersations - may be null  
123 - */  
124 - public void onRegistered(LeshanServer lwServer, Registration registration, Collection<Observation> previousObsersations) {  
125 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(lwServer, registration);  
126 - if (lwM2MClient != null) {  
127 - lwM2MClient.setLwM2MTransportService(this);  
128 - lwM2MClient.setLwM2MTransportService(this);  
129 - lwM2MClient.setSessionUuid(UUID.randomUUID());  
130 - this.setLwM2MClient(lwServer, registration, lwM2MClient);  
131 - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration.getId());  
132 - if (sessionInfo != null) {  
133 - lwM2MClient.setDeviceUuid(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));  
134 - lwM2MClient.setProfileUuid(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));  
135 - lwM2MClient.setDeviceName(sessionInfo.getDeviceName());  
136 - lwM2MClient.setDeviceProfileName(sessionInfo.getDeviceType());  
137 - transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo));  
138 - transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);  
139 - transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);  
140 - this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client registration", registration.getId());  
141 - } else {  
142 - log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), sessionInfo);  
143 - }  
144 - } else {  
145 - log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), lwM2MClient);  
146 - }  
147 - }  
148 -  
149 - /**  
150 - * @param lwServer - LeshanServer  
151 - * @param registration - Registration LwM2M Client  
152 - */  
153 - public void updatedReg(LeshanServer lwServer, Registration registration) {  
154 - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration.getId());  
155 - if (sessionInfo != null) {  
156 - log.info("Client: [{}] updatedReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());  
157 - } else {  
158 - log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), sessionInfo);  
159 - }  
160 - }  
161 -  
162 - /**  
163 - * @param registration - Registration LwM2M Client  
164 - * @param observations - All paths observations before unReg  
165 - * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect  
166 - */  
167 - public void unReg(Registration registration, Collection<Observation> observations) {  
168 - this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());  
169 - this.closeClientSession(registration);  
170 - }  
171 -  
172 - private void closeClientSession(Registration registration) {  
173 - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration.getId());  
174 - if (sessionInfo != null) {  
175 - transportService.deregisterSession(sessionInfo);  
176 - this.doCloseSession(sessionInfo);  
177 - lwM2mInMemorySecurityStore.delRemoveSessionAndListener(registration.getId());  
178 - if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) {  
179 - this.syncSessionsAndProfiles();  
180 - }  
181 - log.info("Client: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());  
182 - } else {  
183 - log.error("Client: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), sessionInfo);  
184 - }  
185 - }  
186 -  
187 - public void onSleepingDev(Registration registration) {  
188 - log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint());  
189 - //TODO: associate endpointId with device information.  
190 - }  
191 -  
192 - /**  
193 - * Those methods are called by the protocol stage thread pool, this means that execution MUST be done in a short delay,  
194 - * * if you need to do long time processing use a dedicated thread pool.  
195 - *  
196 - * @param registration  
197 - */  
198 -  
199 - public void onAwakeDev(Registration registration) {  
200 - log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());  
201 - //TODO: associate endpointId with device information.  
202 - }  
203 -  
204 - /**  
205 - * This method is used to sync with sessions  
206 - * Removes a profile if not used in sessions  
207 - */  
208 - private void syncSessionsAndProfiles() {  
209 - Map<UUID, AttrTelemetryObserveValue> profilesClone = lwM2mInMemorySecurityStore.getProfiles().entrySet()  
210 - .stream()  
211 - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));  
212 - profilesClone.forEach((k, v) -> {  
213 - String registrationId = lwM2mInMemorySecurityStore.getSessions().entrySet()  
214 - .stream()  
215 - .filter(e -> e.getValue().getProfileUuid().equals(k))  
216 - .findFirst()  
217 - .map(Map.Entry::getKey) // return the key of the matching entry if found  
218 - .orElse("");  
219 - if (registrationId.isEmpty()) {  
220 - lwM2mInMemorySecurityStore.getProfiles().remove(k);  
221 - }  
222 - });  
223 - }  
224 -  
225 - /**  
226 - * Create new LwM2MClient for current session -> setModelClient...  
227 - * #1 Add all ObjectLinks (instance) to control the process of executing requests to the client  
228 - * to get the client model with current values  
229 - * #2 Get the client model with current values. Analyze the response in -> lwM2MTransportRequest.sendResponse  
230 - *  
231 - * @param lwServer - LeshanServer  
232 - * @param registration - Registration LwM2M Client  
233 - * @param lwM2MClient - object with All parameters off client  
234 - */  
235 - private void setLwM2MClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) {  
236 - // #1  
237 - Arrays.stream(registration.getObjectLinks()).forEach(url -> {  
238 - ResultIds pathIds = new ResultIds(url.getUrl());  
239 - if (pathIds.instanceId > -1 && pathIds.resourceId == -1) {  
240 - lwM2MClient.getPendingRequests().add(url.getUrl());  
241 - }  
242 - });  
243 - // #2  
244 - Arrays.stream(registration.getObjectLinks()).forEach(url -> {  
245 - ResultIds pathIds = new ResultIds(url.getUrl());  
246 - if (pathIds.instanceId > -1 && pathIds.resourceId == -1) {  
247 - lwM2MTransportRequest.sendAllRequest(lwServer, registration, url.getUrl(), GET_TYPE_OPER_READ,  
248 - ContentFormat.TLV.getName(), lwM2MClient, null, null, this.context.getCtxServer().getTimeout());  
249 - }  
250 - });  
251 - }  
252 -  
253 - /**  
254 - * @param registrationId - Id of Registration LwM2M Client  
255 - * @return - sessionInfo after access connect client  
256 - */  
257 - private SessionInfoProto getValidateSessionInfo(String registrationId) {  
258 - SessionInfoProto sessionInfo = null;  
259 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(registrationId);  
260 - if (lwM2MClient != null) {  
261 - ValidateDeviceCredentialsResponseMsg msg = lwM2MClient.getCredentialsResponse();  
262 - if (msg == null || msg.getDeviceInfo() == null) {  
263 - log.error("[{}] [{}]", lwM2MClient.getEndPoint(), CLIENT_NOT_AUTHORIZED);  
264 - this.closeClientSession(lwM2MClient.getRegistration());  
265 - } else {  
266 - sessionInfo = SessionInfoProto.newBuilder()  
267 - .setNodeId(this.context.getNodeId())  
268 - .setSessionIdMSB(lwM2MClient.getSessionUuid().getMostSignificantBits())  
269 - .setSessionIdLSB(lwM2MClient.getSessionUuid().getLeastSignificantBits())  
270 - .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB())  
271 - .setDeviceIdLSB(msg.getDeviceInfo().getDeviceIdLSB())  
272 - .setTenantIdMSB(msg.getDeviceInfo().getTenantIdMSB())  
273 - .setTenantIdLSB(msg.getDeviceInfo().getTenantIdLSB())  
274 - .setDeviceName(msg.getDeviceInfo().getDeviceName())  
275 - .setDeviceType(msg.getDeviceInfo().getDeviceType())  
276 - .setDeviceProfileIdLSB(msg.getDeviceInfo().getDeviceProfileIdLSB())  
277 - .setDeviceProfileIdMSB(msg.getDeviceInfo().getDeviceProfileIdMSB())  
278 - .build();  
279 - }  
280 - }  
281 - return sessionInfo;  
282 - }  
283 -  
284 - /**  
285 - * Add attribute/telemetry information from Client and credentials/Profile to client model and start observe  
286 - * !!! if the resource has an observation, but no telemetry or attribute - the observation will not use  
287 - * #1 Client`s starting info to send to thingsboard  
288 - * #2 Sending Attribute Telemetry with value to thingsboard only once at the start of the connection  
289 - * #3 Start observe  
290 - *  
291 - * @param lwServer - LeshanServer  
292 - * @param registration - Registration LwM2M Client  
293 - */  
294 -  
295 - public void updatesAndSentModelParameter(LeshanServer lwServer, Registration registration) {  
296 - // #1  
297 -// this.setParametersToModelClient(registration, modelClient, deviceProfile);  
298 - // #2  
299 - this.updateAttrTelemetry(registration, true, null);  
300 - // #3  
301 - this.onSentObserveToClient(lwServer, registration);  
302 - }  
303 -  
304 -  
305 - /**  
306 - * Sent Attribute and Telemetry to Thingsboard  
307 - * #1 - get AttrName/TelemetryName with value:  
308 - * #1.1 from Client  
309 - * #1.2 from LwM2MClient:  
310 - * -- resourceId == path from AttrTelemetryObserveValue.postAttributeProfile/postTelemetryProfile/postObserveProfile  
311 - * -- AttrName/TelemetryName == resourceName from ModelObject.objectModel, value from ModelObject.instance.resource(resourceId)  
312 - * #2 - set Attribute/Telemetry  
313 - *  
314 - * @param registration - Registration LwM2M Client  
315 - */  
316 - private void updateAttrTelemetry(Registration registration, boolean start, Set<String> paths) {  
317 - JsonObject attributes = new JsonObject();  
318 - JsonObject telemetrys = new JsonObject();  
319 - if (start) {  
320 - // #1.1  
321 - JsonObject attributeClient = this.getAttributeClient(registration);  
322 - if (attributeClient != null) {  
323 - attributeClient.entrySet().forEach(p -> {  
324 - attributes.add(p.getKey(), p.getValue());  
325 - });  
326 - }  
327 - }  
328 - // #1.2  
329 - CountDownLatch cancelLatch = new CountDownLatch(1);  
330 - this.getParametersFromProfile(attributes, telemetrys, registration, paths);  
331 - cancelLatch.countDown();  
332 - try {  
333 - cancelLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);  
334 - } catch (InterruptedException e) {  
335 - log.error("[{}] updateAttrTelemetry", e.toString());  
336 - }  
337 - if (attributes.getAsJsonObject().entrySet().size() > 0)  
338 - this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration.getId());  
339 - if (telemetrys.getAsJsonObject().entrySet().size() > 0)  
340 - this.updateParametersOnThingsboard(telemetrys, DEVICE_TELEMETRY_TOPIC, registration.getId());  
341 - }  
342 -  
343 - /**  
344 - * get AttrName/TelemetryName with value from Client  
345 - *  
346 - * @param registration -  
347 - * @return - JsonObject, format: {name: value}}  
348 - */  
349 - private JsonObject getAttributeClient(Registration registration) {  
350 - if (registration.getAdditionalRegistrationAttributes().size() > 0) {  
351 - JsonObject resNameValues = new JsonObject();  
352 - registration.getAdditionalRegistrationAttributes().entrySet().forEach(entry -> {  
353 - resNameValues.addProperty(entry.getKey(), entry.getValue());  
354 - });  
355 - return resNameValues;  
356 - }  
357 - return null;  
358 - }  
359 -  
360 - /**  
361 - * @param attributes - new JsonObject  
362 - * @param telemetry - new JsonObject  
363 - * @param registration - Registration LwM2M Client  
364 - * result: add to JsonObject those resources to which the user is subscribed and they have a value  
365 - * if path==null add All resources else only one  
366 - * (attributes/telemetry): new {name(Attr/Telemetry):value}  
367 - */  
368 - private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) {  
369 - AttrTelemetryObserveValue attrTelemetryObserveValue = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid());  
370 - attrTelemetryObserveValue.getPostAttributeProfile().forEach(p -> {  
371 - ResultIds pathIds = new ResultIds(p.getAsString().toString());  
372 - if (pathIds.getResourceId() > -1) {  
373 - if (path == null || path.contains(p.getAsString())) {  
374 - this.addParameters(pathIds, p.getAsString().toString(), attributes, registration);  
375 - }  
376 - }  
377 - });  
378 - attrTelemetryObserveValue.getPostTelemetryProfile().forEach(p -> {  
379 - ResultIds pathIds = new ResultIds(p.getAsString().toString());  
380 - if (pathIds.getResourceId() > -1) {  
381 - if (path == null || path.contains(p.getAsString())) {  
382 - this.addParameters(pathIds, p.getAsString().toString(), telemetry, registration);  
383 - }  
384 - }  
385 - });  
386 - }  
387 -  
388 - /**  
389 - * @param pathIds - path resource  
390 - * @param parameters - JsonObject attributes/telemetry  
391 - * @param registration - Registration LwM2M Client  
392 - */  
393 - private void addParameters(ResultIds pathIds, String path, JsonObject parameters, Registration registration) {  
394 - ModelObject modelObject = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getModelObjects().get(pathIds.getObjectId());  
395 - JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()).getPostKeyNameProfile();  
396 - String resName = String.valueOf(names.get(path));  
397 - if (modelObject != null && resName != null && !resName.isEmpty()) {  
398 - String resValue = this.getResourceValue(modelObject, pathIds);  
399 - if (resValue != null) {  
400 - parameters.addProperty(resName, resValue);  
401 - }  
402 - }  
403 - }  
404 -  
405 - /**  
406 - * @param modelObject - ModelObject of Client  
407 - * @param pathIds - path resource  
408 - * @return - value of Resource or null  
409 - */  
410 - private String getResourceValue(ModelObject modelObject, ResultIds pathIds) {  
411 - String resValue = null;  
412 - if (modelObject.getInstances().get(pathIds.getInstanceId()) != null) {  
413 - LwM2mObjectInstance instance = modelObject.getInstances().get(pathIds.getInstanceId());  
414 - if (instance.getResource(pathIds.getResourceId()) != null) {  
415 - resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ?  
416 - Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() :  
417 - (instance.getResource(pathIds.getResourceId()).isMultiInstances()) ?  
418 - instance.getResource(pathIds.getResourceId()).getValues().toString() :  
419 - instance.getResource(pathIds.getResourceId()).getValue().toString();  
420 - }  
421 - }  
422 - return resValue;  
423 - }  
424 -  
425 - /**  
426 - * Prepare Sent to Thigsboard callback - Attribute or Telemetry  
427 - *  
428 - * @param msg - JsonArray: [{name: value}]  
429 - * @param topicName - Api Attribute or Telemetry  
430 - * @param registrationId - Id of Registration LwM2M Client  
431 - */  
432 - public void updateParametersOnThingsboard(JsonElement msg, String topicName, String registrationId) {  
433 - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registrationId);  
434 - if (sessionInfo != null) {  
435 - try {  
436 - if (topicName.equals(LwM2MTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) {  
437 - PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg);  
438 - TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(-1, postAttributeMsg);  
439 - transportService.process(sessionInfo, postAttributeMsg, call);  
440 - } else if (topicName.equals(LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC)) {  
441 - PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg);  
442 - TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(-1, postTelemetryMsg);  
443 - transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSentAttrTelemetry(-1, call));  
444 - }  
445 - } catch (AdaptorException e) {  
446 - log.error("[{}] Failed to process publish msg [{}]", topicName, e);  
447 - log.info("[{}] Closing current session due to invalid publish", topicName);  
448 - }  
449 - } else {  
450 - log.error("Client: [{}] updateParametersOnThingsboard [{}] sessionInfo ", registrationId, sessionInfo);  
451 - }  
452 - }  
453 -  
454 - /**  
455 - * Sent to Thingsboard Attribute || Telemetry  
456 - *  
457 - * @param msgId - always == -1  
458 - * @param msg - JsonObject: [{name: value}]  
459 - * @return - dummy  
460 - */  
461 - private <T> TransportServiceCallback<Void> getPubAckCallbackSentAttrTelemetry(final int msgId, final T msg) {  
462 - return new TransportServiceCallback<Void>() {  
463 - @Override  
464 - public void onSuccess(Void dummy) {  
465 - log.trace("Success to publish msg: {}, dummy: {}", msg, dummy);  
466 - }  
467 -  
468 - @Override  
469 - public void onError(Throwable e) {  
470 - log.trace("[{}] Failed to publish msg: {}", msg, e);  
471 - }  
472 - };  
473 - }  
474 -  
475 -  
476 - /**  
477 - * Start observe  
478 - * #1 - Analyze:  
479 - * #1.1 path in observe == (attribute or telemetry)  
480 - * #1.2 recourseValue notNull  
481 - * #2 Analyze after sent request (response):  
482 - * #2.1 First: lwM2MTransportRequest.sendResponse -> ObservationListener.newObservation  
483 - * #2.2 Next: ObservationListener.onResponse *  
484 - *  
485 - * @param lwServer - LeshanServer  
486 - * @param registration - Registration LwM2M Client  
487 - */  
488 - private void onSentObserveToClient(LeshanServer lwServer, Registration registration) {  
489 - if (lwServer.getObservationService().getObservations(registration).size() > 0) {  
490 - this.setCancelObservations(lwServer, registration);  
491 - }  
492 - UUID profileUUid = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid();  
493 - AttrTelemetryObserveValue attrTelemetryObserveValue = lwM2mInMemorySecurityStore.getProfiles().get(profileUUid);  
494 - attrTelemetryObserveValue.getPostObserveProfile().forEach(p -> {  
495 - // #1.1  
496 - String target = (getValidateObserve(attrTelemetryObserveValue.getPostAttributeProfile(), p.getAsString().toString())) ?  
497 - p.getAsString().toString() : (getValidateObserve(attrTelemetryObserveValue.getPostTelemetryProfile(), p.getAsString().toString())) ?  
498 - p.getAsString().toString() : null;  
499 - if (target != null) {  
500 - // #1.2  
501 - ResultIds pathIds = new ResultIds(target);  
502 - ModelObject modelObject = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getModelObjects().get(pathIds.getObjectId());  
503 - // #2  
504 - if (modelObject != null) {  
505 - if (getResourceValue(modelObject, pathIds) != null) {  
506 - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, GET_TYPE_OPER_OBSERVE,  
507 - null, null, null, null, this.context.getCtxServer().getTimeout());  
508 - }  
509 - }  
510 - }  
511 - });  
512 - }  
513 -  
514 - public void setCancelObservations(LeshanServer lwServer, Registration registration) {  
515 - if (registration != null) {  
516 - Set<Observation> observations = lwServer.getObservationService().getObservations(registration);  
517 - observations.forEach(observation -> {  
518 - this.setCancelObservationRecourse(lwServer, registration, observation.getPath().toString());  
519 - });  
520 - }  
521 - }  
522 -  
523 - /**  
524 - * lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout());  
525 - * At server side this will not remove the observation from the observation store, to do it you need to use  
526 - * {@code ObservationService#cancelObservation()}  
527 - */  
528 - public void setCancelObservationRecourse(LeshanServer lwServer, Registration registration, String path) {  
529 - CountDownLatch cancelLatch = new CountDownLatch(1);  
530 - lwServer.getObservationService().cancelObservations(registration, path);  
531 - cancelLatch.countDown();  
532 - try {  
533 - cancelLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);  
534 - } catch (InterruptedException e) {  
535 - }  
536 - }  
537 -  
538 - /**  
539 - * @param parameters - JsonArray postAttributeProfile/postTelemetryProfile  
540 - * @param path - recourse from postObserveProfile  
541 - * @return rez - true if path observe is in attribute/telemetry  
542 - */  
543 - private boolean getValidateObserve(JsonElement parameters, String path) {  
544 - AtomicBoolean rez = new AtomicBoolean(false);  
545 - if (parameters.isJsonArray()) {  
546 - parameters.getAsJsonArray().forEach(p -> {  
547 - if (p.getAsString().toString().equals(path)) rez.set(true);  
548 - }  
549 - );  
550 - } else if (parameters.isJsonObject()) {  
551 - rez.set((parameters.getAsJsonObject().entrySet()).stream().map(json -> json.toString())  
552 - .filter(path::equals).findAny().orElse(null) != null);  
553 - }  
554 - return rez.get();  
555 - }  
556 -  
557 - /**  
558 - * Sending observe value to thingsboard from ObservationListener.onResponse: object, instance, SingleResource or MultipleResource  
559 - *  
560 - * @param registration - Registration LwM2M Client  
561 - * @param path - observe  
562 - * @param response - observe  
563 - */  
564 - @SneakyThrows  
565 - public void onObservationResponse(Registration registration, String path, ReadResponse response) {  
566 - if (response.getContent() != null) {  
567 - if (response.getContent() instanceof LwM2mObject) {  
568 - LwM2mObject content = (LwM2mObject) response.getContent();  
569 - String target = "/" + content.getId();  
570 - } else if (response.getContent() instanceof LwM2mObjectInstance) {  
571 - LwM2mObjectInstance content = (LwM2mObjectInstance) response.getContent();  
572 - } else if (response.getContent() instanceof LwM2mSingleResource) {  
573 - LwM2mSingleResource content = (LwM2mSingleResource) response.getContent();  
574 - this.onObservationSetResourcesValue(registration, content.getValue(), null, path);  
575 - } else if (response.getContent() instanceof LwM2mMultipleResource) {  
576 - LwM2mSingleResource content = (LwM2mSingleResource) response.getContent();  
577 - this.onObservationSetResourcesValue(registration, null, content.getValues(), path);  
578 - }  
579 - }  
580 - }  
581 -  
582 - /**  
583 - * Sending observe value of resources to thingsboard  
584 - * #1 Return old Resource from ModelObject  
585 - * #2 Create new Resource with value from observation  
586 - * #3 Create new Resources from old Resources  
587 - * #4 Update new Resources (replace old Resource on new Resource)  
588 - * #5 Remove old Instance from modelClient  
589 - * #6 Create new Instance with new Resources values  
590 - * #7 Update modelClient.getModelObjects(idObject) (replace old Instance on new Instance)  
591 - *  
592 - * @param registration - Registration LwM2M Client  
593 - * @param value - LwM2mSingleResource response.getContent()  
594 - * @param values - LwM2mSingleResource response.getContent()  
595 - * @param path - resource  
596 - */  
597 - private void onObservationSetResourcesValue(Registration registration, Object value, Map<Integer, ?> values, String path) {  
598 - ResultIds resultIds = new ResultIds(path);  
599 - // #1  
600 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(registration.getId());  
601 - ModelObject modelObject = lwM2MClient.getModelObjects().get(resultIds.getObjectId());  
602 - Map<Integer, LwM2mObjectInstance> instancesModelObject = modelObject.getInstances();  
603 - LwM2mObjectInstance instanceOld = (instancesModelObject.get(resultIds.instanceId) != null) ? instancesModelObject.get(resultIds.instanceId) : null;  
604 - Map<Integer, LwM2mResource> resourcesOld = (instanceOld != null) ? instanceOld.getResources() : null;  
605 - LwM2mResource resourceOld = (resourcesOld != null && resourcesOld.get(resultIds.getResourceId()) != null) ? resourcesOld.get(resultIds.getResourceId()) : null;  
606 - // #2  
607 - LwM2mResource resourceNew;  
608 - if (resourceOld.isMultiInstances()) {  
609 - resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resourceOld.getType());  
610 - } else {  
611 - resourceNew = LwM2mSingleResource.newResource(resultIds.getResourceId(), value, resourceOld.getType());  
612 - }  
613 - //#3  
614 - Map<Integer, LwM2mResource> resourcesNew = new HashMap<>(resourcesOld);  
615 - // #4  
616 - resourcesNew.remove(resourceOld);  
617 - // #5  
618 - resourcesNew.put(resultIds.getResourceId(), resourceNew);  
619 - // #6  
620 - LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.instanceId, resourcesNew.values());  
621 - // #7  
622 - CountDownLatch respLatch = new CountDownLatch(1);  
623 - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.instanceId);  
624 - instancesModelObject.put(resultIds.instanceId, instanceNew);  
625 - respLatch.countDown();  
626 - try {  
627 - respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);  
628 - } catch (InterruptedException ex) {  
629 - }  
630 - Set<String> paths = new HashSet<String>();  
631 - paths.add(path);  
632 - this.updateAttrTelemetry(registration, false, paths);  
633 - }  
634 -  
635 - /**  
636 - * @param updateCredentials - Credentials include config only security Client (without config attr/telemetry...)  
637 - * config attr/telemetry... in profile  
638 - */  
639 - public void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto updateCredentials) {  
640 - log.info("[{}] idList [{}] valueList updateCredentials", updateCredentials.getCredentialsIdList(), updateCredentials.getCredentialsValueList());  
641 - }  
642 -  
643 - /**  
644 - * Update - sent request in change value resources in Client (path to resources from profile by keyName)  
645 - * Only fo resources W  
646 - * Delete - nothing  
647 - *  
648 - * @param msg -  
649 - * @param sessionInfo -  
650 - */  
651 - public void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, SessionInfoProto sessionInfo) {  
652 - if (msg.getSharedUpdatedCount() > 0) {  
653 - JsonElement el = JsonConverter.toJson(msg);  
654 - el.getAsJsonObject().entrySet().forEach(de -> {  
655 - String profilePath = lwM2mInMemorySecurityStore.getProfiles().get(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()))  
656 - .getPostKeyNameProfile().getAsJsonObject().entrySet().stream()  
657 - .filter(e -> e.getValue().getAsString().equals(de.getKey())).findFirst().map(Map.Entry::getKey)  
658 - .orElse("");  
659 - String path = !profilePath.isEmpty() ? profilePath : this.getPathAttributeUpdate(sessionInfo, de.getKey());  
660 - if (path != null) {  
661 - ResultIds resultIds = new ResultIds(path);  
662 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue();  
663 - ResourceModel.Operations operations = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).operations;  
664 - String value = ((JsonPrimitive) de.getValue()).getAsString();  
665 - if (operations.isWritable()) {  
666 - lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,  
667 - ContentFormat.TLV.getName(), lwM2MClient, null, value, this.context.getCtxServer().getTimeout());  
668 - log.info("[{}] path onAttributeUpdate", path);  
669 - }  
670 - else {  
671 - log.error(LOG_LW2M_ERROR + ": Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value);  
672 - String logMsg = String.format(LOG_LW2M_ERROR + " attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", path, value);  
673 - this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());  
674 - }  
675 - }  
676 - });  
677 - } else if (msg.getSharedDeletedCount() > 0) {  
678 - log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);  
679 - }  
680 - }  
681 -  
682 - private String getPathAttributeUpdate(SessionInfoProto sessionInfo, String keyName) {  
683 - try {  
684 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue();  
685 - Predicate<Map.Entry<Integer, ResourceModel>> predicateRes = res -> keyName.equals(splitCamelCaseString(res.getValue().name));  
686 - Predicate<Map.Entry<Integer, ModelObject>> predicateObj = (obj -> {  
687 - return obj.getValue().getObjectModel().resources.entrySet().stream().filter(predicateRes).findFirst().isPresent();  
688 - });  
689 - Stream<Map.Entry<Integer, ModelObject>> objectStream = lwM2MClient.getModelObjects().entrySet().stream().filter(predicateObj);  
690 - Predicate<Map.Entry<Integer, ResourceModel>> predicateResFinal = (objectStream.count() > 0) ? predicateRes : res -> keyName.equals(res.getValue().name);  
691 - Predicate<Map.Entry<Integer, ModelObject>> predicateObjFinal = (obj -> {  
692 - return obj.getValue().getObjectModel().resources.entrySet().stream().filter(predicateResFinal).findFirst().isPresent();  
693 - });  
694 - Map.Entry<Integer, ModelObject> object = lwM2MClient.getModelObjects().entrySet().stream().filter(predicateObjFinal).findFirst().get();  
695 - ModelObject modelObject = object.getValue();  
696 - LwM2mObjectInstance instance = modelObject.getInstances().entrySet().stream().findFirst().get().getValue();  
697 - ResourceModel resource = modelObject.getObjectModel().resources.entrySet().stream().filter(predicateResFinal).findFirst().get().getValue();  
698 - return new LwM2mPath(object.getKey(), instance.getId(), resource.id).toString();  
699 - } catch (NoSuchElementException e) {  
700 - log.error("[{}] keyName [{}]", keyName, e.toString());  
701 - return null;  
702 - }  
703 - }  
704 -  
705 - public void onAttributeUpdateOk(Registration registration, String path, WriteRequest request) {  
706 - ResultIds resultIds = new ResultIds(path);  
707 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(registration.getId());  
708 - LwM2mResource resource = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances().get(resultIds.getInstanceId()).getResource(resultIds.getResourceId());  
709 - if (resource.isMultiInstances()) {  
710 - this.onObservationSetResourcesValue(registration, null, ((LwM2mSingleResource) request.getNode()).getValues(), path);  
711 - } else {  
712 - this.onObservationSetResourcesValue(registration, ((LwM2mSingleResource) request.getNode()).getValue(), null, path);  
713 - }  
714 - }  
715 -  
716 - /**  
717 - * @param sessionInfo -  
718 - * @param deviceProfile -  
719 - */  
720 - public void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {  
721 - String registrationId = lwM2mInMemorySecurityStore.getSessions().entrySet()  
722 - .stream()  
723 - .filter(e -> e.getValue().getDeviceUuid().equals(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())))  
724 - .findFirst()  
725 - .map(Map.Entry::getKey)  
726 - .orElse("");  
727 - if (!registrationId.isEmpty()) {  
728 - this.onDeviceUpdateChangeProfile(registrationId, deviceProfile);  
729 - }  
730 - }  
731 -  
732 - /**  
733 - * @param sessionInfo -  
734 - * @param device -  
735 - * @param deviceProfileOpt -  
736 - */  
737 - public void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {  
738 - Optional<String> registrationIdOpt = lwM2mInMemorySecurityStore.getSessions().entrySet().stream()  
739 - .filter(e -> device.getUuidId().equals(e.getValue().getDeviceUuid()))  
740 - .map(Map.Entry::getKey)  
741 - .findFirst();  
742 - registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt));  
743 - }  
744 -  
745 - /**  
746 - * Update parameters device in LwM2MClient  
747 - * If new deviceProfile != old deviceProfile => update deviceProfile  
748 - *  
749 - * @param registrationId -  
750 - * @param device -  
751 - */  
752 - private void onDeviceUpdateLwM2MClient(String registrationId, Device device, Optional<DeviceProfile> deviceProfileOpt) {  
753 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registrationId);  
754 - lwM2MClient.setDeviceName(device.getName());  
755 - if (!lwM2MClient.getProfileUuid().equals(device.getDeviceProfileId().getId())) {  
756 - deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceUpdateChangeProfile(registrationId, deviceProfile));  
757 - }  
758 - }  
759 -  
760 - /**  
761 - * #1 Read new, old Value (Attribute, Telemetry, Observe, KeyName)  
762 - * #2 Update in lwM2MClient: ...Profile  
763 - * #3 Equivalence test: old <> new Value (Attribute, Telemetry, Observe, KeyName)  
764 - * #3.1 Attribute isChange (add&del)  
765 - * #3.2 Telemetry isChange (add&del)  
766 - * #3.3 KeyName isChange (add)  
767 - * #4 update  
768 - * #4.1 add If #3 isChange, then analyze and update Value in Transport form Client and sent Value ti thingsboard  
769 - * #4.2 del  
770 - * -- if add attributes includes del telemetry - result del for observe  
771 - * #5  
772 - * #5.1 Observe isChange (add&del)  
773 - * #5.2 Observe.add  
774 - * -- path Attr/Telemetry includes newObserve and does not include oldObserve: sent Request observe to Client  
775 - * #5.3 Observe.del  
776 - * -- different between newObserve and oldObserve: sent Request cancel observe to client  
777 - *  
778 - * @param registrationId -  
779 - * @param deviceProfile -  
780 - */  
781 - public void onDeviceUpdateChangeProfile(String registrationId, DeviceProfile deviceProfile) {  
782 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(registrationId);  
783 - AttrTelemetryObserveValue attrTelemetryObserveValueOld = lwM2mInMemorySecurityStore.getProfiles().get(lwM2MClient.getProfileUuid());  
784 - if (lwM2mInMemorySecurityStore.addUpdateProfileParameters(deviceProfile)) {  
785 - LeshanServer lwServer = lwM2MClient.getLwServer();  
786 - Registration registration = lwM2mInMemorySecurityStore.getByRegistration(registrationId);  
787 - // #1  
788 - JsonArray attributeOld = attrTelemetryObserveValueOld.getPostAttributeProfile();  
789 - Set<String> attributeSetOld = new Gson().fromJson(attributeOld, Set.class);  
790 - JsonArray telemetryOld = attrTelemetryObserveValueOld.getPostTelemetryProfile();  
791 - Set<String> telemetrySetOld = new Gson().fromJson(telemetryOld, Set.class);  
792 - JsonArray observeOld = attrTelemetryObserveValueOld.getPostObserveProfile();  
793 - JsonObject keyNameOld = attrTelemetryObserveValueOld.getPostKeyNameProfile();  
794 -  
795 - AttrTelemetryObserveValue attrTelemetryObserveValueNew = lwM2mInMemorySecurityStore.getProfiles().get(deviceProfile.getUuidId());  
796 - JsonArray attributeNew = attrTelemetryObserveValueNew.getPostAttributeProfile();  
797 - Set<String> attributeSetNew = new Gson().fromJson(attributeNew, Set.class);  
798 - JsonArray telemetryNew = attrTelemetryObserveValueNew.getPostTelemetryProfile();  
799 - Set<String> telemetrySetNew = new Gson().fromJson(telemetryNew, Set.class);  
800 - JsonArray observeNew = attrTelemetryObserveValueNew.getPostObserveProfile();  
801 - JsonObject keyNameNew = attrTelemetryObserveValueNew.getPostKeyNameProfile();  
802 - // #2  
803 - lwM2MClient.setDeviceProfileName(deviceProfile.getName());  
804 - lwM2MClient.setProfileUuid(deviceProfile.getUuidId());  
805 -  
806 - // #3  
807 - ResultsAnalyzerParameters sentAttrToThingsboard = new ResultsAnalyzerParameters();  
808 - // #3.1  
809 - if (!attributeOld.equals(attributeNew)) {  
810 - ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld, Set.class), attributeSetNew);  
811 - sentAttrToThingsboard.getPathPostParametersAdd().addAll(postAttributeAnalyzer.getPathPostParametersAdd());  
812 - sentAttrToThingsboard.getPathPostParametersDel().addAll(postAttributeAnalyzer.getPathPostParametersDel());  
813 - }  
814 - // #3.2  
815 - if (!attributeOld.equals(attributeNew)) {  
816 - ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld, Set.class), telemetrySetNew);  
817 - sentAttrToThingsboard.getPathPostParametersAdd().addAll(postTelemetryAnalyzer.getPathPostParametersAdd());  
818 - sentAttrToThingsboard.getPathPostParametersDel().addAll(postTelemetryAnalyzer.getPathPostParametersDel());  
819 - }  
820 - // #3.3  
821 - if (!keyNameOld.equals(keyNameNew)) {  
822 - ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(), ConcurrentHashMap.class),  
823 - new Gson().fromJson(keyNameNew.toString(), ConcurrentHashMap.class));  
824 - sentAttrToThingsboard.getPathPostParametersAdd().addAll(keyNameChange.getPathPostParametersAdd());  
825 - }  
826 -  
827 - // #4.1 add  
828 - if (sentAttrToThingsboard.getPathPostParametersAdd().size() > 0) {  
829 - // update value in Resources  
830 - this.updateResourceValueObserve(lwServer, registration, lwM2MClient, sentAttrToThingsboard.getPathPostParametersAdd(), GET_TYPE_OPER_READ);  
831 - // sent attr/telemetry to tingsboard for new path  
832 - this.updateAttrTelemetry(registration, false, sentAttrToThingsboard.getPathPostParametersAdd());  
833 - }  
834 - // #4.2 del  
835 - if (sentAttrToThingsboard.getPathPostParametersDel().size() > 0) {  
836 - ResultsAnalyzerParameters sentAttrToThingsboardDel = this.getAnalyzerParameters(sentAttrToThingsboard.getPathPostParametersAdd(), sentAttrToThingsboard.getPathPostParametersDel());  
837 - sentAttrToThingsboard.setPathPostParametersDel(sentAttrToThingsboardDel.getPathPostParametersDel());  
838 - }  
839 -  
840 - // #5.1  
841 - if (!observeOld.equals(observeNew)) {  
842 - Set<String> observeSetOld = new Gson().fromJson(observeOld, Set.class);  
843 - Set<String> observeSetNew = new Gson().fromJson(observeNew, Set.class);  
844 - //#5.2 add  
845 - // path Attr/Telemetry includes newObserve  
846 - attributeSetOld.addAll(telemetrySetOld);  
847 - ResultsAnalyzerParameters sentObserveToClientOld = this.getAnalyzerParametersIn(attributeSetOld, observeSetOld); // add observe  
848 - attributeSetNew.addAll(telemetrySetNew);  
849 - ResultsAnalyzerParameters sentObserveToClientNew = this.getAnalyzerParametersIn(attributeSetNew, observeSetNew); // add observe  
850 - // does not include oldObserve  
851 - ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sentObserveToClientOld.getPathPostParametersAdd(), sentObserveToClientNew.getPathPostParametersAdd());  
852 - // sent Request observe to Client  
853 - this.updateResourceValueObserve(lwServer, registration, lwM2MClient, postObserveAnalyzer.getPathPostParametersAdd(), GET_TYPE_OPER_OBSERVE);  
854 - // 5.3 del  
855 - // sent Request cancel observe to Client  
856 - this.cancelObserveIsValue(lwServer, registration, postObserveAnalyzer.getPathPostParametersDel());  
857 - }  
858 - }  
859 - }  
860 -  
861 - /**  
862 - * Compare old list with new list after change AttrTelemetryObserve in config Profile  
863 - *  
864 - * @param parametersOld -  
865 - * @param parametersNew -  
866 - * @return ResultsAnalyzerParameters: add && new  
867 - */  
868 - private ResultsAnalyzerParameters getAnalyzerParameters(Set<String> parametersOld, Set<String> parametersNew) {  
869 - ResultsAnalyzerParameters analyzerParameters = null;  
870 - if (!parametersOld.equals(parametersNew)) {  
871 - analyzerParameters = new ResultsAnalyzerParameters();  
872 - analyzerParameters.setPathPostParametersAdd(parametersNew  
873 - .stream().filter(p -> !parametersOld.contains(p)).collect(Collectors.toSet()));  
874 - analyzerParameters.setPathPostParametersDel(parametersOld  
875 - .stream().filter(p -> !parametersNew.contains(p)).collect(Collectors.toSet()));  
876 - }  
877 - return analyzerParameters;  
878 - }  
879 -  
880 - private ResultsAnalyzerParameters getAnalyzerKeyName(ConcurrentMap<String, String> keyNameOld, ConcurrentMap<String, String> keyNameNew) {  
881 - ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();  
882 - Set<String> paths = keyNameNew.entrySet()  
883 - .stream()  
884 - .filter(e -> !e.getValue().equals(keyNameOld.get(e.getKey())))  
885 - .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue())).keySet();  
886 - analyzerParameters.setPathPostParametersAdd(paths);  
887 - return analyzerParameters;  
888 - }  
889 -  
890 - private ResultsAnalyzerParameters getAnalyzerParametersIn(Set<String> parametersObserve, Set<String> parameters) {  
891 - ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();  
892 - analyzerParameters.setPathPostParametersAdd(parametersObserve  
893 - .stream().filter(p -> parameters.contains(p)).collect(Collectors.toSet()));  
894 - return analyzerParameters;  
895 - }  
896 -  
897 - /**  
898 - * Update Resource value after change RezAttrTelemetry in config Profile  
899 - * sent response Read to Client and add path to pathResAttrTelemetry in LwM2MClient.getAttrTelemetryObserveValue()  
900 - *  
901 - * @param lwServer - LeshanServer  
902 - * @param registration - Registration LwM2M Client  
903 - * @param lwM2MClient - object with All parameters off client  
904 - * @param targets - path Resources == [ "/2/0/0", "/2/0/1"]  
905 - */  
906 - private void updateResourceValueObserve(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, Set<String> targets, String typeOper) {  
907 - targets.stream().forEach(target -> {  
908 - ResultIds pathIds = new ResultIds(target);  
909 - if (pathIds.resourceId >= 0 && lwM2MClient.getModelObjects().get(pathIds.getObjectId())  
910 - .getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) {  
911 - if (GET_TYPE_OPER_READ.equals(typeOper)) {  
912 - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,  
913 - ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout());  
914 - } else if (GET_TYPE_OPER_OBSERVE.equals(typeOper)) {  
915 - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,  
916 - null, null, null, null, this.context.getCtxServer().getTimeout());  
917 - }  
918 - }  
919 - });  
920 - }  
921 -  
922 - private void cancelObserveIsValue(LeshanServer lwServer, Registration registration, Set<String> paramAnallyzer) {  
923 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getlwM2MClient(registration.getId());  
924 - paramAnallyzer.forEach(p -> {  
925 - if (this.getResourceValue(lwM2MClient, p) != null) {  
926 - this.setCancelObservationRecourse(lwServer, registration, p);  
927 - }  
928 - }  
929 - );  
930 - }  
931 -  
932 - private ResourceValue getResourceValue(LwM2MClient lwM2MClient, String path) {  
933 - ResourceValue resourceValue = null;  
934 - ResultIds pathIds = new ResultIds(path);  
935 - if (pathIds.getResourceId() > -1) {  
936 - LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId());  
937 - if (resource.isMultiInstances()) {  
938 - Map<Integer, ?> values = resource.getValues();  
939 - if (resource.getValues().size() > 0) {  
940 - resourceValue = new ResourceValue();  
941 - resourceValue.setMultiInstances(resource.isMultiInstances());  
942 - resourceValue.setValues(resource.getValues());  
943 - }  
944 - } else {  
945 - if (resource.getValue() != null) {  
946 - resourceValue = new ResourceValue();  
947 - resourceValue.setMultiInstances(resource.isMultiInstances());  
948 - resourceValue.setValue(resource.getValue());  
949 - }  
950 - }  
951 - }  
952 - return resourceValue;  
953 - }  
954 -  
955 - /**  
956 - * Trigger Server path = "/1/0/8"  
957 - *  
958 - * Trigger bootStrap path = "/1/0/9" - have to implemented on client  
959 - */  
960 - public void doTrigger(LeshanServer lwServer, Registration registration, String path) {  
961 - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_EXECUTE,  
962 - ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout());  
963 - }  
964 -  
965 - /**  
966 - * Session device in thingsboard is closed  
967 - *  
968 - * @param sessionInfo - lwm2m client  
969 - */  
970 - private void doCloseSession(SessionInfoProto sessionInfo) {  
971 - TransportProtos.SessionEvent event = SessionEvent.CLOSED;  
972 - TransportProtos.SessionEventMsg msg = TransportProtos.SessionEventMsg.newBuilder()  
973 - .setSessionType(TransportProtos.SessionType.ASYNC)  
974 - .setEvent(event).build();  
975 - transportService.process(sessionInfo, msg, null);  
976 - }  
977 -  
978 - /**  
979 - * Deregister session in transport  
980 - * @param sessionInfo - lwm2m client  
981 - */  
982 - private void doDisconnect(SessionInfoProto sessionInfo) {  
983 - transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.CLOSED), null);  
984 - transportService.deregisterSession(sessionInfo);  
985 - }  
986 -  
987 - private void checkInactivityAndReportActivity() {  
988 - lwM2mInMemorySecurityStore.getSessions().forEach((key, value) -> transportService.reportActivity(this.getValidateSessionInfo(key)));  
989 - }  
990 -  
991 - public void sentLogsToThingsboard(String msg, String registrationId) {  
992 - if (msg != null) {  
993 - JsonObject telemetrys = new JsonObject();  
994 - telemetrys.addProperty(LOG_LW2M_TELEMETRY, msg);  
995 - this.updateParametersOnThingsboard(telemetrys, LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC, registrationId);  
996 - }  
997 - }  
998 -  
999 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.core.observation.Observation;  
20 -import org.eclipse.leshan.core.response.ObserveResponse;  
21 -import org.eclipse.leshan.server.californium.LeshanServer;  
22 -import org.eclipse.leshan.server.observation.ObservationListener;  
23 -import org.eclipse.leshan.server.queue.PresenceListener;  
24 -import org.eclipse.leshan.server.registration.Registration;  
25 -import org.eclipse.leshan.server.registration.RegistrationListener;  
26 -import org.eclipse.leshan.server.registration.RegistrationUpdate;  
27 -  
28 -import java.util.Collection;  
29 -  
30 -@Slf4j  
31 -public class LwM2mServerListener {  
32 - private LeshanServer lhServer;  
33 - private LwM2MTransportService service;  
34 -  
35 - public LwM2mServerListener(LeshanServer lhServer, LwM2MTransportService service) {  
36 - this.lhServer = lhServer;  
37 - this.service = service;  
38 - }  
39 -  
40 - public final RegistrationListener registrationListener = new RegistrationListener() {  
41 - /**  
42 - * Register – запрос, представленный в виде POST /rd?…  
43 - */  
44 - @Override  
45 - public void registered(Registration registration, Registration previousReg,  
46 - Collection<Observation> previousObsersations) {  
47 -  
48 - service.onRegistered(lhServer, registration, previousObsersations);  
49 - }  
50 -  
51 - /**  
52 - * Update – представляет из себя CoAP POST запрос на URL, полученный в ответ на Register.  
53 - */  
54 - @Override  
55 - public void updated(RegistrationUpdate update, Registration updatedRegistration,  
56 - Registration previousRegistration) {  
57 - service.updatedReg(lhServer, updatedRegistration);  
58 - }  
59 -  
60 - /**  
61 - * De-register (CoAP DELETE) – отправляется клиентом в случае инициирования процедуры выключения.  
62 - */  
63 - @Override  
64 - public void unregistered(Registration registration, Collection<Observation> observations, boolean expired,  
65 - Registration newReg) {  
66 - service.unReg(registration, observations);  
67 - }  
68 -  
69 - };  
70 -  
71 - public final PresenceListener presenceListener = new PresenceListener() {  
72 - @Override  
73 - public void onSleeping(Registration registration) {  
74 - service.onSleepingDev(registration);  
75 - }  
76 -  
77 - @Override  
78 - public void onAwake(Registration registration) {  
79 - service.onAwakeDev(registration);  
80 - }  
81 - };  
82 -  
83 - public final ObservationListener observationListener = new ObservationListener() {  
84 -  
85 - @Override  
86 - public void cancelled(Observation observation) {  
87 - log.info("Received notification cancelled from [{}] ", observation.getPath());  
88 - }  
89 -  
90 - @Override  
91 - public void onResponse(Observation observation, Registration registration, ObserveResponse response) {  
92 - if (registration != null) {  
93 - try {  
94 - service.onObservationResponse(registration, observation.getPath().toString(), response);  
95 - } catch (java.lang.NullPointerException e) {  
96 - log.error(e.toString());  
97 - }  
98 - }  
99 - }  
100 -  
101 - @Override  
102 - public void onError(Observation observation, Registration registration, Exception error) {  
103 - log.error(String.format("Unable to handle notification of [%s:%s]", observation.getRegistrationId(), observation.getPath()), error);  
104 - }  
105 -  
106 - @Override  
107 - public void newObservation(Observation observation, Registration registration) {  
108 - log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint());  
109 - }  
110 - };  
111 -}  
1 -/**  
2 - * Copyright © 2016-2020 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.transport.lwm2m.server;  
17 -  
18 -import lombok.Builder;  
19 -import lombok.Data;  
20 -  
21 -@Data  
22 -public class ResultIds {  
23 - @Builder.Default  
24 - int objectId = -1;  
25 - @Builder.Default  
26 - int instanceId = -1;  
27 - @Builder.Default  
28 - int resourceId = -1;  
29 -  
30 - public ResultIds (String path) {  
31 - String[] paths = path.split("/");  
32 - if (paths != null && paths.length > 1) {  
33 - this.objectId = (paths.length > 1) ? Integer.parseInt(paths[1]) : this.objectId;  
34 - this.instanceId = (paths.length > 2) ? Integer.parseInt(paths[2]) : this.instanceId;  
35 - this.resourceId = (paths.length > 3) ? Integer.parseInt(paths[3]) : this.resourceId;  
36 - }  
37 - }  
38 -}