Commit 24ccd2a2b54f5a6cf0de824c862178eb2cba9d63
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 | 86 | <artifactId>coap</artifactId> |
87 | 87 | </dependency> |
88 | 88 | <dependency> |
89 | - <groupId>org.thingsboard.common.transport</groupId> | |
90 | - <artifactId>lwm2m</artifactId> | |
91 | - </dependency> | |
92 | - <dependency> | |
93 | 89 | <groupId>org.thingsboard</groupId> |
94 | 90 | <artifactId>dao</artifactId> |
95 | 91 | </dependency> | ... | ... |
... | ... | @@ -62,7 +62,7 @@ public class DeviceActor extends ContextAwareActor { |
62 | 62 | processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg); |
63 | 63 | break; |
64 | 64 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
65 | - processor.processCredentialsUpdate(msg); | |
65 | + processor.processCredentialsUpdate(); | |
66 | 66 | break; |
67 | 67 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
68 | 68 | processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); | ... | ... |
... | ... | @@ -24,7 +24,6 @@ import lombok.extern.slf4j.Slf4j; |
24 | 24 | import org.apache.commons.collections.CollectionUtils; |
25 | 25 | import org.thingsboard.rule.engine.api.RpcError; |
26 | 26 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
27 | -import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; | |
28 | 27 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
29 | 28 | import org.thingsboard.server.actors.ActorSystemContext; |
30 | 29 | import org.thingsboard.server.actors.TbActorCtx; |
... | ... | @@ -37,9 +36,6 @@ import org.thingsboard.server.common.data.kv.AttributeKey; |
37 | 36 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
38 | 37 | import org.thingsboard.server.common.data.kv.KvEntry; |
39 | 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 | 39 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
44 | 40 | import org.thingsboard.server.common.msg.queue.TbCallback; |
45 | 41 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
... | ... | @@ -65,7 +61,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseM |
65 | 61 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; |
66 | 62 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
67 | 63 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
68 | -import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; | |
69 | 64 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
70 | 65 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
71 | 66 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
... | ... | @@ -455,19 +450,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
455 | 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 | 460 | private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) { |
... | ... | @@ -478,18 +465,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
478 | 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 | 468 | void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { |
494 | 469 | this.deviceName = msg.getDeviceName(); |
495 | 470 | this.deviceType = msg.getDeviceType(); | ... | ... |
... | ... | @@ -92,7 +92,6 @@ import org.thingsboard.server.queue.discovery.PartitionService; |
92 | 92 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
93 | 93 | import org.thingsboard.server.queue.util.TbCoreComponent; |
94 | 94 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
95 | -import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository; | |
96 | 95 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
97 | 96 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
98 | 97 | import org.thingsboard.server.service.queue.TbClusterService; |
... | ... | @@ -212,9 +211,6 @@ public abstract class BaseController { |
212 | 211 | @Autowired |
213 | 212 | protected TbDeviceProfileCache deviceProfileCache; |
214 | 213 | |
215 | - @Autowired | |
216 | - protected LwM2MModelsRepository lwM2MModelsRepository; | |
217 | - | |
218 | 214 | @Value("${server.log_controller_error_stack_trace}") |
219 | 215 | @Getter |
220 | 216 | private boolean logControllerErrorStackTrace; | ... | ... |
... | ... | @@ -278,8 +278,9 @@ public class DeviceController extends BaseController { |
278 | 278 | try { |
279 | 279 | Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); |
280 | 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 | 284 | logEntityAction(device.getId(), device, |
284 | 285 | device.getCustomerId(), |
285 | 286 | ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); | ... | ... |
application/src/main/java/org/thingsboard/server/controller/DeviceLwm2mController.java
deleted
100644 → 0
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 | -} |
application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java
deleted
100644 → 0
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 | 53 | return DeviceAuthResult.of(credentials.getDeviceId()); |
54 | 54 | case X509_CERTIFICATE: |
55 | 55 | return DeviceAuthResult.of(credentials.getDeviceId()); |
56 | - case LWM2M_CREDENTIALS: | |
57 | - return DeviceAuthResult.of(credentials.getDeviceId()); | |
58 | 56 | default: |
59 | 57 | return DeviceAuthResult.of("Credentials Type is not supported yet!"); |
60 | 58 | } |
... | ... | @@ -67,4 +65,4 @@ public class DefaultDeviceAuthService implements DeviceAuthService { |
67 | 65 | } |
68 | 66 | } |
69 | 67 | |
70 | -} | |
68 | +} | |
\ No newline at end of file | ... | ... |
... | ... | @@ -201,7 +201,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
201 | 201 | } |
202 | 202 | |
203 | 203 | @Override |
204 | - | |
205 | 204 | public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) { |
206 | 205 | saveAndNotify(tenantId, entityId, scope, attributes, true, callback); |
207 | 206 | } | ... | ... |
... | ... | @@ -69,7 +69,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponse |
69 | 69 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
70 | 70 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
71 | 71 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
72 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | |
73 | 72 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
74 | 73 | import org.thingsboard.server.queue.util.TbCoreComponent; |
75 | 74 | import org.thingsboard.server.dao.device.provision.ProvisionFailedException; |
... | ... | @@ -150,13 +149,6 @@ public class DefaultTransportApiService implements TransportApiService { |
150 | 149 | } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { |
151 | 150 | return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()), |
152 | 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 | 152 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { |
161 | 153 | return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), |
162 | 154 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); |
... | ... | @@ -404,40 +396,4 @@ public class DefaultTransportApiService implements TransportApiService { |
404 | 396 | return TransportApiResponseMsg.newBuilder() |
405 | 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 | 2 | :: ${application.title} :: ${application.formatted-version} |
10 | 3 | =================================================== | ... | ... |
... | ... | @@ -433,7 +433,7 @@ spring: |
433 | 433 | database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}" |
434 | 434 | datasource: |
435 | 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 | 437 | username: "${SPRING_DATASOURCE_USERNAME:postgres}" |
438 | 438 | password: "${SPRING_DATASOURCE_PASSWORD:postgres}" |
439 | 439 | hikari: |
... | ... | @@ -488,7 +488,7 @@ js: |
488 | 488 | # Built-in JVM JavaScript environment properties |
489 | 489 | local: |
490 | 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 | 492 | # Specify thread pool size for JavaScript sandbox resource monitor |
493 | 493 | monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" |
494 | 494 | # Maximum CPU time in milliseconds allowed for script execution |
... | ... | @@ -565,74 +565,6 @@ transport: |
565 | 565 | bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" |
566 | 566 | bind_port: "${COAP_BIND_PORT:5683}" |
567 | 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 | 569 | swagger: |
638 | 570 | api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}" | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java
deleted
100644 → 0
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 | -} |
common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mObject.java
deleted
100644 → 0
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 | -} |
common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResource.java
deleted
100644 → 0
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 | -} |
common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/ServerSecurityConfig.java
deleted
100644 → 0
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 | -} |
... | ... | @@ -183,47 +183,6 @@ message GetEntityProfileRequestMsg { |
183 | 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 | 186 | message GetEntityProfileResponseMsg { |
228 | 187 | string entityType = 1; |
229 | 188 | bytes data = 2; |
... | ... | @@ -520,10 +479,8 @@ message TransportApiRequestMsg { |
520 | 479 | ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2; |
521 | 480 | GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3; |
522 | 481 | GetEntityProfileRequestMsg entityProfileRequestMsg = 4; |
523 | - LwM2MRequestMsg lwM2MRequestMsg = 5; | |
524 | 482 | ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; |
525 | 483 | ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; |
526 | - ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; | |
527 | 484 | } |
528 | 485 | |
529 | 486 | /* Response from ThingsBoard Core Service to Transport Service */ |
... | ... | @@ -532,7 +489,6 @@ message TransportApiResponseMsg { |
532 | 489 | GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; |
533 | 490 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; |
534 | 491 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; |
535 | - LwM2MResponseMsg lwM2MResponseMsg = 6; | |
536 | 492 | } |
537 | 493 | |
538 | 494 | /* Messages that are handled by ThingsBoard Core Service */ |
... | ... | @@ -573,10 +529,10 @@ message ToTransportMsg { |
573 | 529 | AttributeUpdateNotificationMsg attributeUpdateNotification = 5; |
574 | 530 | ToDeviceRpcRequestMsg toDeviceRequest = 6; |
575 | 531 | ToServerRpcResponseMsg toServerResponse = 7; |
532 | + /* For Tenant, TenantProfile and DeviceProfile */ | |
576 | 533 | EntityUpdateMsg entityUpdateMsg = 8; |
577 | 534 | EntityDeleteMsg entityDeleteMsg = 9; |
578 | 535 | ProvisionDeviceResponseMsg provisionResponse = 10; |
579 | - ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11; | |
580 | 536 | } |
581 | 537 | |
582 | 538 | message UsageStatsKVProto{ | ... | ... |
... | ... | @@ -24,7 +24,6 @@ import org.springframework.stereotype.Component; |
24 | 24 | import org.thingsboard.server.common.transport.TransportContext; |
25 | 25 | import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; |
26 | 26 | |
27 | - | |
28 | 27 | /** |
29 | 28 | * Created by ashvayka on 18.10.18. |
30 | 29 | */ | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
... | ... | @@ -16,15 +16,14 @@ |
16 | 16 | package org.thingsboard.server.transport.coap; |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.eclipse.californium.core.CoapObserveRelation; | |
20 | 19 | import org.eclipse.californium.core.CoapResource; |
21 | -import org.eclipse.californium.core.coap.CoAP; | |
22 | 20 | import org.eclipse.californium.core.coap.CoAP.ResponseCode; |
23 | 21 | import org.eclipse.californium.core.coap.Request; |
24 | -import org.eclipse.californium.core.network.Endpoint; | |
25 | 22 | import org.eclipse.californium.core.network.Exchange; |
23 | +import org.eclipse.californium.core.network.ExchangeObserver; | |
26 | 24 | import org.eclipse.californium.core.server.resources.CoapExchange; |
27 | 25 | import org.eclipse.californium.core.server.resources.Resource; |
26 | +import org.springframework.util.ReflectionUtils; | |
28 | 27 | import org.thingsboard.server.common.data.DataConstants; |
29 | 28 | import org.thingsboard.server.common.data.DeviceTransportType; |
30 | 29 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
... | ... | @@ -41,26 +40,26 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes |
41 | 40 | import org.thingsboard.server.gen.transport.TransportProtos; |
42 | 41 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
43 | 42 | |
43 | +import java.lang.reflect.Field; | |
44 | 44 | import java.util.List; |
45 | 45 | import java.util.Optional; |
46 | 46 | import java.util.Set; |
47 | 47 | import java.util.UUID; |
48 | -import java.util.Timer; | |
49 | -import java.util.TimerTask; | |
50 | 48 | import java.util.concurrent.ConcurrentHashMap; |
51 | 49 | import java.util.concurrent.ConcurrentMap; |
52 | -import java.util.concurrent.ScheduledThreadPoolExecutor; | |
53 | 50 | import java.util.concurrent.atomic.AtomicInteger; |
54 | 51 | import java.util.function.Consumer; |
55 | 52 | |
56 | 53 | @Slf4j |
57 | 54 | public class CoapTransportResource extends CoapResource { |
55 | + // coap://localhost:port/api/v1/DEVICE_TOKEN/[attributes|telemetry|rpc[/requestId]] | |
58 | 56 | private static final int ACCESS_TOKEN_POSITION = 3; |
59 | 57 | private static final int FEATURE_TYPE_POSITION = 4; |
60 | 58 | private static final int REQUEST_ID_POSITION = 5; |
61 | 59 | |
62 | 60 | private final CoapTransportContext transportContext; |
63 | 61 | private final TransportService transportService; |
62 | + private final Field observerField; | |
64 | 63 | private final long timeout; |
65 | 64 | private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>(); |
66 | 65 | private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet(); |
... | ... | @@ -74,20 +73,9 @@ public class CoapTransportResource extends CoapResource { |
74 | 73 | // This is important to turn off existing observable logic in |
75 | 74 | // CoapResource. We will have our own observe monitoring due to 1:1 |
76 | 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 | 81 | @Override |
... | ... | @@ -199,7 +187,9 @@ public class CoapTransportResource extends CoapResource { |
199 | 187 | new CoapOkCallback(exchange)); |
200 | 188 | break; |
201 | 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 | 193 | transportService.process(sessionInfo, |
204 | 194 | TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), |
205 | 195 | new CoapNoOpCallback(exchange)); |
... | ... | @@ -216,6 +206,8 @@ public class CoapTransportResource extends CoapResource { |
216 | 206 | break; |
217 | 207 | case SUBSCRIBE_RPC_COMMANDS_REQUEST: |
218 | 208 | rpcSubscriptions.add(sessionId); |
209 | + advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced), | |
210 | + registerAsyncCoapSession(exchange, request, sessionInfo, sessionId))); | |
219 | 211 | transportService.process(sessionInfo, |
220 | 212 | TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), |
221 | 213 | new CoapNoOpCallback(exchange)); |
... | ... | @@ -251,6 +243,9 @@ public class CoapTransportResource extends CoapResource { |
251 | 243 | } catch (AdaptorException e) { |
252 | 244 | log.trace("[{}] Failed to decode message: ", sessionId, e); |
253 | 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 | 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 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.californium.core.CoapResource; |
20 | 20 | import org.eclipse.californium.core.CoapServer; |
21 | - | |
22 | 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 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
25 | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
26 | 25 | import org.springframework.stereotype.Service; |
... | ... | @@ -48,15 +47,11 @@ public class CoapTransportService { |
48 | 47 | public void init() throws UnknownHostException { |
49 | 48 | log.info("Starting CoAP transport..."); |
50 | 49 | log.info("Starting CoAP transport server"); |
51 | - this.server = new CoapServer(); | |
50 | + this.server = new CoapServer(NetworkConfig.createStandardWithoutFile()); | |
52 | 51 | createResources(); |
53 | 52 | InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); |
54 | 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 | 55 | server.start(); |
61 | 56 | log.info("CoAP transport started!"); |
62 | 57 | } | ... | ... |
... | ... | @@ -31,7 +31,6 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
31 | 31 | import org.thingsboard.server.gen.transport.TransportProtos; |
32 | 32 | import org.thingsboard.server.transport.coap.CoapTransportResource; |
33 | 33 | |
34 | - | |
35 | 34 | import java.util.Arrays; |
36 | 35 | import java.util.HashSet; |
37 | 36 | import java.util.List; | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DeviceEmulator.java
... | ... | @@ -28,7 +28,6 @@ import org.eclipse.californium.core.CoapClient; |
28 | 28 | import org.eclipse.californium.core.CoapHandler; |
29 | 29 | import org.eclipse.californium.core.CoapResponse; |
30 | 30 | import org.eclipse.californium.core.coap.MediaTypeRegistry; |
31 | -import org.eclipse.californium.elements.exception.ConnectorException; | |
32 | 31 | import org.thingsboard.server.common.msg.session.FeatureType; |
33 | 32 | import org.slf4j.Logger; |
34 | 33 | import org.slf4j.LoggerFactory; |
... | ... | @@ -62,7 +61,7 @@ public class DeviceEmulator { |
62 | 61 | this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES)); |
63 | 62 | this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY)); |
64 | 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 | 67 | public void start() { |
... | ... | @@ -73,8 +72,11 @@ public class DeviceEmulator { |
73 | 72 | try { |
74 | 73 | sendObserveRequest(rpcClient); |
75 | 74 | while (!Thread.interrupted()) { |
75 | + | |
76 | + | |
76 | 77 | sendRequest(attributesClient, createAttributesRequest()); |
77 | 78 | sendRequest(telemetryClient, createTelemetryRequest()); |
79 | + | |
78 | 80 | Thread.sleep(1000); |
79 | 81 | } |
80 | 82 | } catch (Exception e) { |
... | ... | @@ -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 | 89 | MediaTypeRegistry.APPLICATION_JSON); |
88 | 90 | log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText()); |
89 | 91 | } |
... | ... | @@ -111,7 +113,6 @@ public class DeviceEmulator { |
111 | 113 | |
112 | 114 | @Override |
113 | 115 | public void onError() { |
114 | - log.info("Command Response Ack Error, No connect"); | |
115 | 116 | //Do nothing |
116 | 117 | } |
117 | 118 | }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); |
... | ... | @@ -156,15 +157,6 @@ public class DeviceEmulator { |
156 | 157 | if (args.length != 4) { |
157 | 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 | 160 | final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]); |
169 | 161 | emulator.start(); |
170 | 162 | Runtime.getRuntime().addShutdownHook(new Thread() { |
... | ... | @@ -175,6 +167,7 @@ public class DeviceEmulator { |
175 | 167 | }); |
176 | 168 | } |
177 | 169 | |
170 | + | |
178 | 171 | private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) { |
179 | 172 | return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase(); |
180 | 173 | } | ... | ... |
... | ... | @@ -327,7 +327,6 @@ public class DeviceApiController { |
327 | 327 | public void onToServerRpcResponse(ToServerRpcResponseMsg msg) { |
328 | 328 | responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); |
329 | 329 | } |
330 | - | |
331 | 330 | } |
332 | 331 | |
333 | 332 | private void reportActivity(SessionInfoProto sessionInfo) { | ... | ... |
common/transport/lwm2m/pom.xml
deleted
100644 → 0
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> |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerInitializer.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportContextBootstrap.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapConfig.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapServers.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MInMemoryBootstrapConfigStore.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MServerBootstrap.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MSetSecurityStoreBootstrap.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2mDefaultBootstrapSessionManager.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LWM2MGenerationPSkRPkECC.java
deleted
100644 → 0
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 | - |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2MGetSecurityInfo.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2MSecurityMode.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mRPkCredentials.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/ReadResultSecurityStore.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MSessionMsgListener.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java
deleted
100644 → 0
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>=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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
deleted
100644 → 0
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 | -} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ResultIds.java
deleted
100644 → 0
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 | -} |