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,10 +86,6 @@ | ||
86 | <artifactId>coap</artifactId> | 86 | <artifactId>coap</artifactId> |
87 | </dependency> | 87 | </dependency> |
88 | <dependency> | 88 | <dependency> |
89 | - <groupId>org.thingsboard.common.transport</groupId> | ||
90 | - <artifactId>lwm2m</artifactId> | ||
91 | - </dependency> | ||
92 | - <dependency> | ||
93 | <groupId>org.thingsboard</groupId> | 89 | <groupId>org.thingsboard</groupId> |
94 | <artifactId>dao</artifactId> | 90 | <artifactId>dao</artifactId> |
95 | </dependency> | 91 | </dependency> |
@@ -62,7 +62,7 @@ public class DeviceActor extends ContextAwareActor { | @@ -62,7 +62,7 @@ public class DeviceActor extends ContextAwareActor { | ||
62 | processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg); | 62 | processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg); |
63 | break; | 63 | break; |
64 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 64 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
65 | - processor.processCredentialsUpdate(msg); | 65 | + processor.processCredentialsUpdate(); |
66 | break; | 66 | break; |
67 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: | 67 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
68 | processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); | 68 | processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); |
@@ -24,7 +24,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -24,7 +24,6 @@ import lombok.extern.slf4j.Slf4j; | ||
24 | import org.apache.commons.collections.CollectionUtils; | 24 | import org.apache.commons.collections.CollectionUtils; |
25 | import org.thingsboard.rule.engine.api.RpcError; | 25 | import org.thingsboard.rule.engine.api.RpcError; |
26 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 26 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
27 | -import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; | ||
28 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 27 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
29 | import org.thingsboard.server.actors.ActorSystemContext; | 28 | import org.thingsboard.server.actors.ActorSystemContext; |
30 | import org.thingsboard.server.actors.TbActorCtx; | 29 | import org.thingsboard.server.actors.TbActorCtx; |
@@ -37,9 +36,6 @@ import org.thingsboard.server.common.data.kv.AttributeKey; | @@ -37,9 +36,6 @@ import org.thingsboard.server.common.data.kv.AttributeKey; | ||
37 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 36 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
38 | import org.thingsboard.server.common.data.kv.KvEntry; | 37 | import org.thingsboard.server.common.data.kv.KvEntry; |
39 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | 38 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; |
40 | -import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
41 | -import org.thingsboard.server.common.data.security.DeviceCredentialsType; | ||
42 | -import org.thingsboard.server.common.msg.TbActorMsg; | ||
43 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 39 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
44 | import org.thingsboard.server.common.msg.queue.TbCallback; | 40 | import org.thingsboard.server.common.msg.queue.TbCallback; |
45 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 41 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
@@ -65,7 +61,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseM | @@ -65,7 +61,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseM | ||
65 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; | 61 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; |
66 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | 62 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
67 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; | 63 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
68 | -import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; | ||
69 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; | 64 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
70 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | 65 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
71 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; | 66 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
@@ -455,19 +450,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -455,19 +450,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
455 | dumpSessions(); | 450 | dumpSessions(); |
456 | } | 451 | } |
457 | 452 | ||
458 | - void processCredentialsUpdate(TbActorMsg msg) { | ||
459 | - if (((DeviceCredentialsUpdateNotificationMsg) msg).getDeviceCredentials().getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) { | ||
460 | - log.info("1) LwM2Mtype: "); | ||
461 | - sessions.forEach((k, v) -> { | ||
462 | - notifyTransportAboutProfileUpdate(k, v, ((DeviceCredentialsUpdateNotificationMsg) msg).getDeviceCredentials()); | ||
463 | - }); | ||
464 | - } else { | ||
465 | - sessions.forEach(this::notifyTransportAboutClosedSession); | ||
466 | - attributeSubscriptions.clear(); | ||
467 | - rpcSubscriptions.clear(); | ||
468 | - dumpSessions(); | ||
469 | - | ||
470 | - } | 453 | + void processCredentialsUpdate() { |
454 | + sessions.forEach(this::notifyTransportAboutClosedSession); | ||
455 | + attributeSubscriptions.clear(); | ||
456 | + rpcSubscriptions.clear(); | ||
457 | + dumpSessions(); | ||
471 | } | 458 | } |
472 | 459 | ||
473 | private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) { | 460 | private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) { |
@@ -478,18 +465,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -478,18 +465,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
478 | systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg); | 465 | systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg); |
479 | } | 466 | } |
480 | 467 | ||
481 | - void notifyTransportAboutProfileUpdate(UUID sessionId, SessionInfoMetaData sessionMd, DeviceCredentials deviceCredentials) { | ||
482 | - log.info("2) LwM2Mtype: "); | ||
483 | - TransportProtos.ToTransportUpdateCredentialsProto.Builder notification = TransportProtos.ToTransportUpdateCredentialsProto.newBuilder(); | ||
484 | - notification.addCredentialsId(deviceCredentials.getCredentialsId()); | ||
485 | - notification.addCredentialsValue(deviceCredentials.getCredentialsValue()); | ||
486 | - ToTransportMsg msg = ToTransportMsg.newBuilder() | ||
487 | - .setSessionIdMSB(sessionId.getMostSignificantBits()) | ||
488 | - .setSessionIdLSB(sessionId.getLeastSignificantBits()) | ||
489 | - .setToTransportUpdateCredentialsNotification(notification).build(); | ||
490 | - systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg); | ||
491 | - } | ||
492 | - | ||
493 | void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { | 468 | void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { |
494 | this.deviceName = msg.getDeviceName(); | 469 | this.deviceName = msg.getDeviceName(); |
495 | this.deviceType = msg.getDeviceType(); | 470 | this.deviceType = msg.getDeviceType(); |
@@ -92,7 +92,6 @@ import org.thingsboard.server.queue.discovery.PartitionService; | @@ -92,7 +92,6 @@ import org.thingsboard.server.queue.discovery.PartitionService; | ||
92 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; | 92 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
93 | import org.thingsboard.server.queue.util.TbCoreComponent; | 93 | import org.thingsboard.server.queue.util.TbCoreComponent; |
94 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 94 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
95 | -import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository; | ||
96 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; | 95 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
97 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 96 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
98 | import org.thingsboard.server.service.queue.TbClusterService; | 97 | import org.thingsboard.server.service.queue.TbClusterService; |
@@ -212,9 +211,6 @@ public abstract class BaseController { | @@ -212,9 +211,6 @@ public abstract class BaseController { | ||
212 | @Autowired | 211 | @Autowired |
213 | protected TbDeviceProfileCache deviceProfileCache; | 212 | protected TbDeviceProfileCache deviceProfileCache; |
214 | 213 | ||
215 | - @Autowired | ||
216 | - protected LwM2MModelsRepository lwM2MModelsRepository; | ||
217 | - | ||
218 | @Value("${server.log_controller_error_stack_trace}") | 214 | @Value("${server.log_controller_error_stack_trace}") |
219 | @Getter | 215 | @Getter |
220 | private boolean logControllerErrorStackTrace; | 216 | private boolean logControllerErrorStackTrace; |
@@ -278,8 +278,9 @@ public class DeviceController extends BaseController { | @@ -278,8 +278,9 @@ public class DeviceController extends BaseController { | ||
278 | try { | 278 | try { |
279 | Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); | 279 | Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); |
280 | DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); | 280 | DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); |
281 | - //log.info("0 LwM2M CredentialsUpdate start) | ||
282 | - tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null); | 281 | + |
282 | + tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null); | ||
283 | + | ||
283 | logEntityAction(device.getId(), device, | 284 | logEntityAction(device.getId(), device, |
284 | device.getCustomerId(), | 285 | device.getCustomerId(), |
285 | ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); | 286 | ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); |
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,8 +53,6 @@ public class DefaultDeviceAuthService implements DeviceAuthService { | ||
53 | return DeviceAuthResult.of(credentials.getDeviceId()); | 53 | return DeviceAuthResult.of(credentials.getDeviceId()); |
54 | case X509_CERTIFICATE: | 54 | case X509_CERTIFICATE: |
55 | return DeviceAuthResult.of(credentials.getDeviceId()); | 55 | return DeviceAuthResult.of(credentials.getDeviceId()); |
56 | - case LWM2M_CREDENTIALS: | ||
57 | - return DeviceAuthResult.of(credentials.getDeviceId()); | ||
58 | default: | 56 | default: |
59 | return DeviceAuthResult.of("Credentials Type is not supported yet!"); | 57 | return DeviceAuthResult.of("Credentials Type is not supported yet!"); |
60 | } | 58 | } |
@@ -67,4 +65,4 @@ public class DefaultDeviceAuthService implements DeviceAuthService { | @@ -67,4 +65,4 @@ public class DefaultDeviceAuthService implements DeviceAuthService { | ||
67 | } | 65 | } |
68 | } | 66 | } |
69 | 67 | ||
70 | -} | 68 | +} |
@@ -201,7 +201,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer | @@ -201,7 +201,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer | ||
201 | } | 201 | } |
202 | 202 | ||
203 | @Override | 203 | @Override |
204 | - | ||
205 | public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) { | 204 | public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) { |
206 | saveAndNotify(tenantId, entityId, scope, attributes, true, callback); | 205 | saveAndNotify(tenantId, entityId, scope, attributes, true, callback); |
207 | } | 206 | } |
@@ -69,7 +69,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponse | @@ -69,7 +69,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponse | ||
69 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | 69 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
70 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; | 70 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
71 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; | 71 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
72 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | ||
73 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 72 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
74 | import org.thingsboard.server.queue.util.TbCoreComponent; | 73 | import org.thingsboard.server.queue.util.TbCoreComponent; |
75 | import org.thingsboard.server.dao.device.provision.ProvisionFailedException; | 74 | import org.thingsboard.server.dao.device.provision.ProvisionFailedException; |
@@ -150,13 +149,6 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -150,13 +149,6 @@ public class DefaultTransportApiService implements TransportApiService { | ||
150 | } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { | 149 | } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { |
151 | return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()), | 150 | return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()), |
152 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 151 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); |
153 | - } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) { | ||
154 | - return Futures.transform(handle(transportApiRequestMsg.getLwM2MRequestMsg()), | ||
155 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | ||
156 | - } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) { | ||
157 | - ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg(); | ||
158 | - return Futures.transform(validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS), | ||
159 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | ||
160 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { | 152 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { |
161 | return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), | 153 | return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), |
162 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 154 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); |
@@ -404,40 +396,4 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -404,40 +396,4 @@ public class DefaultTransportApiService implements TransportApiService { | ||
404 | return TransportApiResponseMsg.newBuilder() | 396 | return TransportApiResponseMsg.newBuilder() |
405 | .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build(); | 397 | .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build(); |
406 | } | 398 | } |
407 | - | ||
408 | - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.LwM2MRequestMsg requestMsg) { | ||
409 | - if (requestMsg.hasRegistrationMsg()) { | ||
410 | - return handleRegistration(requestMsg.getRegistrationMsg()); | ||
411 | - } else { | ||
412 | - return Futures.immediateFailedFuture(new RuntimeException("Not supported!")); | ||
413 | - } | ||
414 | - } | ||
415 | - | ||
416 | - private ListenableFuture<TransportApiResponseMsg> handleRegistration(TransportProtos.LwM2MRegistrationRequestMsg msg) { | ||
417 | - TenantId tenantId = new TenantId(UUID.fromString(msg.getTenantId())); | ||
418 | - String deviceName = msg.getEndpoint(); | ||
419 | - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock()); | ||
420 | - deviceCreationLock.lock(); | ||
421 | - try { | ||
422 | - Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); | ||
423 | - if (device == null) { | ||
424 | - device = new Device(); | ||
425 | - device.setTenantId(tenantId); | ||
426 | - device.setName(deviceName); | ||
427 | - device.setType("LwM2M"); | ||
428 | - device = deviceService.saveDevice(device); | ||
429 | - deviceStateService.onDeviceAdded(device); | ||
430 | - } | ||
431 | - TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg = | ||
432 | - TransportProtos.LwM2MRegistrationResponseMsg.newBuilder() | ||
433 | - .setDeviceInfo(getDeviceInfoProto(device)).build(); | ||
434 | - TransportProtos.LwM2MResponseMsg responseMsg = TransportProtos.LwM2MResponseMsg.newBuilder().setRegistrationMsg(registrationResponseMsg).build(); | ||
435 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build()); | ||
436 | - } catch (JsonProcessingException e) { | ||
437 | - log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e); | ||
438 | - throw new RuntimeException(e); | ||
439 | - } finally { | ||
440 | - deviceCreationLock.unlock(); | ||
441 | - } | ||
442 | - } | ||
443 | } | 399 | } |
1 | - ______ __ _ __ __ | ||
2 | - /_ __/ / /_ (_) ____ ____ _ _____ / /_ ____ ____ _ _____ ____/ / | ||
3 | - / / / __ \ / / / __ \ / __ `/ / ___/ / __ \ / __ \ / __ `/ / ___/ / __ / | ||
4 | - / / / / / / / / / / / / / /_/ / (__ ) / /_/ // /_/ // /_/ / / / / /_/ / | ||
5 | -/_/ /_/ /_/ /_/ /_/ /_/ \__, / /____/ /_.___/ \____/ \__,_/ /_/ \__,_/ | ||
6 | - /____/ | ||
7 | - | ||
8 | =================================================== | 1 | =================================================== |
9 | :: ${application.title} :: ${application.formatted-version} | 2 | :: ${application.title} :: ${application.formatted-version} |
10 | =================================================== | 3 | =================================================== |
@@ -433,7 +433,7 @@ spring: | @@ -433,7 +433,7 @@ spring: | ||
433 | database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}" | 433 | database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}" |
434 | datasource: | 434 | datasource: |
435 | driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}" | 435 | driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}" |
436 | - url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_ce_3_2_2}" | 436 | + url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard}" |
437 | username: "${SPRING_DATASOURCE_USERNAME:postgres}" | 437 | username: "${SPRING_DATASOURCE_USERNAME:postgres}" |
438 | password: "${SPRING_DATASOURCE_PASSWORD:postgres}" | 438 | password: "${SPRING_DATASOURCE_PASSWORD:postgres}" |
439 | hikari: | 439 | hikari: |
@@ -488,7 +488,7 @@ js: | @@ -488,7 +488,7 @@ js: | ||
488 | # Built-in JVM JavaScript environment properties | 488 | # Built-in JVM JavaScript environment properties |
489 | local: | 489 | local: |
490 | # Use Sandboxed (secured) JVM JavaScript environment | 490 | # Use Sandboxed (secured) JVM JavaScript environment |
491 | - use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:false}" | 491 | + use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:true}" |
492 | # Specify thread pool size for JavaScript sandbox resource monitor | 492 | # Specify thread pool size for JavaScript sandbox resource monitor |
493 | monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" | 493 | monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" |
494 | # Maximum CPU time in milliseconds allowed for script execution | 494 | # Maximum CPU time in milliseconds allowed for script execution |
@@ -565,74 +565,6 @@ transport: | @@ -565,74 +565,6 @@ transport: | ||
565 | bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" | 565 | bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" |
566 | bind_port: "${COAP_BIND_PORT:5683}" | 566 | bind_port: "${COAP_BIND_PORT:5683}" |
567 | timeout: "${COAP_TIMEOUT:10000}" | 567 | timeout: "${COAP_TIMEOUT:10000}" |
568 | - # Local LwM2M transport parameters | ||
569 | - lwm2m: | ||
570 | - # Enable/disable lvm2m transport protocol. | ||
571 | - enabled: "${LWM2M_ENABLED:true}" | ||
572 | - # We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to | ||
573 | - # send a Confirmable message to the time when an acknowledgement is no longer expected. | ||
574 | - # DEFAULT_TIMEOUT = 2 * 60 * 1000l; 2 min in ms | ||
575 | - timeout: "${LWM2M_TIMEOUT:120000}" | ||
576 | -# model_path_file: "${LWM2M_MODEL_PATH_FILE:./common/transport/lwm2m/src/main/resources/models/}" | ||
577 | - model_path_file: "${LWM2M_MODEL_PATH_FILE:}" | ||
578 | - support_deprecated_ciphers_enable: "${LWM2M_SUPPORT_DEPRECATED_CIPHERS_ENABLED:true}" | ||
579 | - secure: | ||
580 | - # Only Certificate_x509: | ||
581 | - # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format | ||
582 | - # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh | ||
583 | - key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}" | ||
584 | - # key_store_type: "${LWM2M_KEYSTORE_TYPE:PKCS12}" | ||
585 | -# key_store_path_file: "${KEY_STORE_PATH_FILE:/usr/share/thingsboard/conf/credentials/serverKeyStore.jks}" | ||
586 | - key_store_path_file: "${KEY_STORE_PATH_FILE:}" | ||
587 | - key_store_password: "${LWM2M_KEYSTORE_PASSWORD_SERVER:server_ks_password}" | ||
588 | - root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}" | ||
589 | - enable_gen_psk_rpk: "${ENABLE_GEN_PSK_RPK:true}" | ||
590 | - server: | ||
591 | - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" | ||
592 | - bind_port: "${LWM2M_BIND_PORT:5685}" | ||
593 | - bind_port_cert: "${LWM2M_BIND_PORT_CERT:5687}" | ||
594 | - secure: | ||
595 | - start_all: "${START_SERVER_ALL:true}" | ||
596 | - #leshan.core (V1_1) | ||
597 | - #DTLS security modes: | ||
598 | - #0: Pre-Shared Key mode | ||
599 | - #1: Raw Public Key mode | ||
600 | - #2: Certificate mode X509 | ||
601 | - #3: NoSec mode * | ||
602 | - #OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A (add) | ||
603 | - #4: Certificate mode X509 with EST | ||
604 | - # If only startAll == false | ||
605 | - dtls_mode: "${LWM2M_SECURITY_MODE:1}" | ||
606 | - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" | ||
607 | - bind_port: "${LWM2M_BIND_PORT_SEC:5686}" | ||
608 | - bind_port_cert: "${LWM2M_BIND_PORT_SEC_CERT:5688}" | ||
609 | - # Only RPK: Public & Private Key | ||
610 | -# create_rpk: "${CREATE_RPK:}" | ||
611 | - public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}" | ||
612 | - public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}" | ||
613 | - private_s: "${LWM2M_SERVER_PRIVATE_S:274671fe40ce937b8a6352cf0a418e8a39e4bf0bb9bf74c910db953c20c73802}" | ||
614 | - # Only Certificate_x509: | ||
615 | - alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}" | ||
616 | - bootstrap: | ||
617 | - enable: "${BOOTSTRAP:true}" | ||
618 | - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" | ||
619 | - bind_port: "${LWM2M_BIND_PORT_BS:5689}" | ||
620 | - bind_port_cert: "${LWM2M_BIND_PORT_SER_BS:5691}" | ||
621 | - secure: | ||
622 | - start_all: "${START_BOOTSTRAP_ALL:true}" | ||
623 | - # If only startAll == false | ||
624 | - dtls_mode: "${LWM2M_SECURITY_MODE_BS:1}" | ||
625 | - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" | ||
626 | - bind_port: "${LWM2M_BIND_PORT_SEC_BS:5690}" | ||
627 | - bind_port_cert: "${LWM2M_BIND_PORT_SEC_CERT_BS:5692}" | ||
628 | - # Only RPK: Public & Private Key | ||
629 | - public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}" | ||
630 | - public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}" | ||
631 | - private_s: "${LWM2M_SERVER_PRIVATE_S_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}" | ||
632 | - # Only Certificate_x509: | ||
633 | - alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}" | ||
634 | - # Redis | ||
635 | - redis_url: "${LWM2M_REDIS_URL:''}" | ||
636 | 568 | ||
637 | swagger: | 569 | swagger: |
638 | api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}" | 570 | api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}" |
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,47 +183,6 @@ message GetEntityProfileRequestMsg { | ||
183 | int64 entityIdLSB = 3; | 183 | int64 entityIdLSB = 3; |
184 | } | 184 | } |
185 | 185 | ||
186 | -message LwM2MRegistrationRequestMsg { | ||
187 | - string tenantId = 1; | ||
188 | - string endpoint = 2; | ||
189 | -} | ||
190 | - | ||
191 | -message LwM2MRegistrationResponseMsg { | ||
192 | - DeviceInfoProto deviceInfo = 1; | ||
193 | -} | ||
194 | - | ||
195 | -message LwM2MRequestMsg { | ||
196 | - LwM2MRegistrationRequestMsg registrationMsg = 1; | ||
197 | -} | ||
198 | - | ||
199 | -message LwM2MResponseMsg { | ||
200 | - LwM2MRegistrationResponseMsg registrationMsg = 1; | ||
201 | -} | ||
202 | - | ||
203 | -message ValidateDeviceLwM2MCredentialsRequestMsg { | ||
204 | - string credentialsId = 1; | ||
205 | -} | ||
206 | - | ||
207 | -message ToTransportUpdateCredentialsProto { | ||
208 | - repeated string credentialsId = 1; | ||
209 | - repeated string credentialsValue = 2; | ||
210 | -} | ||
211 | - | ||
212 | -message GetTenantRoutingInfoRequestMsg { | ||
213 | - int64 tenantIdMSB = 1; | ||
214 | - int64 tenantIdLSB = 2; | ||
215 | -} | ||
216 | - | ||
217 | -message GetTenantRoutingInfoResponseMsg { | ||
218 | - bool isolatedTbCore = 1; | ||
219 | - bool isolatedTbRuleEngine = 2; | ||
220 | -} | ||
221 | - | ||
222 | -message GetDeviceProfileRequestMsg { | ||
223 | - int64 profileIdMSB = 1; | ||
224 | - int64 profileIdLSB = 2; | ||
225 | -} | ||
226 | - | ||
227 | message GetEntityProfileResponseMsg { | 186 | message GetEntityProfileResponseMsg { |
228 | string entityType = 1; | 187 | string entityType = 1; |
229 | bytes data = 2; | 188 | bytes data = 2; |
@@ -520,10 +479,8 @@ message TransportApiRequestMsg { | @@ -520,10 +479,8 @@ message TransportApiRequestMsg { | ||
520 | ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2; | 479 | ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2; |
521 | GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3; | 480 | GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3; |
522 | GetEntityProfileRequestMsg entityProfileRequestMsg = 4; | 481 | GetEntityProfileRequestMsg entityProfileRequestMsg = 4; |
523 | - LwM2MRequestMsg lwM2MRequestMsg = 5; | ||
524 | ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; | 482 | ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; |
525 | ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; | 483 | ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; |
526 | - ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; | ||
527 | } | 484 | } |
528 | 485 | ||
529 | /* Response from ThingsBoard Core Service to Transport Service */ | 486 | /* Response from ThingsBoard Core Service to Transport Service */ |
@@ -532,7 +489,6 @@ message TransportApiResponseMsg { | @@ -532,7 +489,6 @@ message TransportApiResponseMsg { | ||
532 | GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; | 489 | GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; |
533 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; | 490 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; |
534 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; | 491 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; |
535 | - LwM2MResponseMsg lwM2MResponseMsg = 6; | ||
536 | } | 492 | } |
537 | 493 | ||
538 | /* Messages that are handled by ThingsBoard Core Service */ | 494 | /* Messages that are handled by ThingsBoard Core Service */ |
@@ -573,10 +529,10 @@ message ToTransportMsg { | @@ -573,10 +529,10 @@ message ToTransportMsg { | ||
573 | AttributeUpdateNotificationMsg attributeUpdateNotification = 5; | 529 | AttributeUpdateNotificationMsg attributeUpdateNotification = 5; |
574 | ToDeviceRpcRequestMsg toDeviceRequest = 6; | 530 | ToDeviceRpcRequestMsg toDeviceRequest = 6; |
575 | ToServerRpcResponseMsg toServerResponse = 7; | 531 | ToServerRpcResponseMsg toServerResponse = 7; |
532 | + /* For Tenant, TenantProfile and DeviceProfile */ | ||
576 | EntityUpdateMsg entityUpdateMsg = 8; | 533 | EntityUpdateMsg entityUpdateMsg = 8; |
577 | EntityDeleteMsg entityDeleteMsg = 9; | 534 | EntityDeleteMsg entityDeleteMsg = 9; |
578 | ProvisionDeviceResponseMsg provisionResponse = 10; | 535 | ProvisionDeviceResponseMsg provisionResponse = 10; |
579 | - ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11; | ||
580 | } | 536 | } |
581 | 537 | ||
582 | message UsageStatsKVProto{ | 538 | message UsageStatsKVProto{ |
@@ -24,7 +24,6 @@ import org.springframework.stereotype.Component; | @@ -24,7 +24,6 @@ import org.springframework.stereotype.Component; | ||
24 | import org.thingsboard.server.common.transport.TransportContext; | 24 | import org.thingsboard.server.common.transport.TransportContext; |
25 | import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; | 25 | import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; |
26 | 26 | ||
27 | - | ||
28 | /** | 27 | /** |
29 | * Created by ashvayka on 18.10.18. | 28 | * Created by ashvayka on 18.10.18. |
30 | */ | 29 | */ |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
@@ -16,15 +16,14 @@ | @@ -16,15 +16,14 @@ | ||
16 | package org.thingsboard.server.transport.coap; | 16 | package org.thingsboard.server.transport.coap; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.eclipse.californium.core.CoapObserveRelation; | ||
20 | import org.eclipse.californium.core.CoapResource; | 19 | import org.eclipse.californium.core.CoapResource; |
21 | -import org.eclipse.californium.core.coap.CoAP; | ||
22 | import org.eclipse.californium.core.coap.CoAP.ResponseCode; | 20 | import org.eclipse.californium.core.coap.CoAP.ResponseCode; |
23 | import org.eclipse.californium.core.coap.Request; | 21 | import org.eclipse.californium.core.coap.Request; |
24 | -import org.eclipse.californium.core.network.Endpoint; | ||
25 | import org.eclipse.californium.core.network.Exchange; | 22 | import org.eclipse.californium.core.network.Exchange; |
23 | +import org.eclipse.californium.core.network.ExchangeObserver; | ||
26 | import org.eclipse.californium.core.server.resources.CoapExchange; | 24 | import org.eclipse.californium.core.server.resources.CoapExchange; |
27 | import org.eclipse.californium.core.server.resources.Resource; | 25 | import org.eclipse.californium.core.server.resources.Resource; |
26 | +import org.springframework.util.ReflectionUtils; | ||
28 | import org.thingsboard.server.common.data.DataConstants; | 27 | import org.thingsboard.server.common.data.DataConstants; |
29 | import org.thingsboard.server.common.data.DeviceTransportType; | 28 | import org.thingsboard.server.common.data.DeviceTransportType; |
30 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; | 29 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
@@ -41,26 +40,26 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes | @@ -41,26 +40,26 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes | ||
41 | import org.thingsboard.server.gen.transport.TransportProtos; | 40 | import org.thingsboard.server.gen.transport.TransportProtos; |
42 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | 41 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
43 | 42 | ||
43 | +import java.lang.reflect.Field; | ||
44 | import java.util.List; | 44 | import java.util.List; |
45 | import java.util.Optional; | 45 | import java.util.Optional; |
46 | import java.util.Set; | 46 | import java.util.Set; |
47 | import java.util.UUID; | 47 | import java.util.UUID; |
48 | -import java.util.Timer; | ||
49 | -import java.util.TimerTask; | ||
50 | import java.util.concurrent.ConcurrentHashMap; | 48 | import java.util.concurrent.ConcurrentHashMap; |
51 | import java.util.concurrent.ConcurrentMap; | 49 | import java.util.concurrent.ConcurrentMap; |
52 | -import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
53 | import java.util.concurrent.atomic.AtomicInteger; | 50 | import java.util.concurrent.atomic.AtomicInteger; |
54 | import java.util.function.Consumer; | 51 | import java.util.function.Consumer; |
55 | 52 | ||
56 | @Slf4j | 53 | @Slf4j |
57 | public class CoapTransportResource extends CoapResource { | 54 | public class CoapTransportResource extends CoapResource { |
55 | + // coap://localhost:port/api/v1/DEVICE_TOKEN/[attributes|telemetry|rpc[/requestId]] | ||
58 | private static final int ACCESS_TOKEN_POSITION = 3; | 56 | private static final int ACCESS_TOKEN_POSITION = 3; |
59 | private static final int FEATURE_TYPE_POSITION = 4; | 57 | private static final int FEATURE_TYPE_POSITION = 4; |
60 | private static final int REQUEST_ID_POSITION = 5; | 58 | private static final int REQUEST_ID_POSITION = 5; |
61 | 59 | ||
62 | private final CoapTransportContext transportContext; | 60 | private final CoapTransportContext transportContext; |
63 | private final TransportService transportService; | 61 | private final TransportService transportService; |
62 | + private final Field observerField; | ||
64 | private final long timeout; | 63 | private final long timeout; |
65 | private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>(); | 64 | private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>(); |
66 | private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet(); | 65 | private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet(); |
@@ -74,20 +73,9 @@ public class CoapTransportResource extends CoapResource { | @@ -74,20 +73,9 @@ public class CoapTransportResource extends CoapResource { | ||
74 | // This is important to turn off existing observable logic in | 73 | // This is important to turn off existing observable logic in |
75 | // CoapResource. We will have our own observe monitoring due to 1:1 | 74 | // CoapResource. We will have our own observe monitoring due to 1:1 |
76 | // observe relationship. | 75 | // observe relationship. |
77 | - this.setObservable(true); // enable observing | ||
78 | - this.setObserveType(CoAP.Type.CON); // configure the notification type to CONs | ||
79 | - this.getAttributes().setObservable(); // mark observable in the Link-Format | ||
80 | - // schedule a periodic update task, otherwise let events call changed() | ||
81 | - Timer timer = new Timer(); | ||
82 | - timer.schedule(new UpdateTask(), 0, 5000); | ||
83 | - } | ||
84 | - | ||
85 | - private class UpdateTask extends TimerTask { | ||
86 | - @Override | ||
87 | - public void run() { | ||
88 | - // .. periodic update of the resource | ||
89 | - changed(); // notify all observers | ||
90 | - } | 76 | + this.setObservable(false); |
77 | + observerField = ReflectionUtils.findField(Exchange.class, "observer"); | ||
78 | + observerField.setAccessible(true); | ||
91 | } | 79 | } |
92 | 80 | ||
93 | @Override | 81 | @Override |
@@ -199,7 +187,9 @@ public class CoapTransportResource extends CoapResource { | @@ -199,7 +187,9 @@ public class CoapTransportResource extends CoapResource { | ||
199 | new CoapOkCallback(exchange)); | 187 | new CoapOkCallback(exchange)); |
200 | break; | 188 | break; |
201 | case SUBSCRIBE_ATTRIBUTES_REQUEST: | 189 | case SUBSCRIBE_ATTRIBUTES_REQUEST: |
202 | - transportService.registerSyncSession(sessionInfo, new CoapSessionListener(sessionId, exchange), transportContext.getTimeout()); | 190 | + attributeSubscriptions.add(sessionId); |
191 | + advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced), | ||
192 | + registerAsyncCoapSession(exchange, request, sessionInfo, sessionId))); | ||
203 | transportService.process(sessionInfo, | 193 | transportService.process(sessionInfo, |
204 | TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), | 194 | TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), |
205 | new CoapNoOpCallback(exchange)); | 195 | new CoapNoOpCallback(exchange)); |
@@ -216,6 +206,8 @@ public class CoapTransportResource extends CoapResource { | @@ -216,6 +206,8 @@ public class CoapTransportResource extends CoapResource { | ||
216 | break; | 206 | break; |
217 | case SUBSCRIBE_RPC_COMMANDS_REQUEST: | 207 | case SUBSCRIBE_RPC_COMMANDS_REQUEST: |
218 | rpcSubscriptions.add(sessionId); | 208 | rpcSubscriptions.add(sessionId); |
209 | + advanced.setObserver(new CoapExchangeObserverProxy((ExchangeObserver) observerField.get(advanced), | ||
210 | + registerAsyncCoapSession(exchange, request, sessionInfo, sessionId))); | ||
219 | transportService.process(sessionInfo, | 211 | transportService.process(sessionInfo, |
220 | TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), | 212 | TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), |
221 | new CoapNoOpCallback(exchange)); | 213 | new CoapNoOpCallback(exchange)); |
@@ -251,6 +243,9 @@ public class CoapTransportResource extends CoapResource { | @@ -251,6 +243,9 @@ public class CoapTransportResource extends CoapResource { | ||
251 | } catch (AdaptorException e) { | 243 | } catch (AdaptorException e) { |
252 | log.trace("[{}] Failed to decode message: ", sessionId, e); | 244 | log.trace("[{}] Failed to decode message: ", sessionId, e); |
253 | exchange.respond(ResponseCode.BAD_REQUEST); | 245 | exchange.respond(ResponseCode.BAD_REQUEST); |
246 | + } catch (IllegalAccessException e) { | ||
247 | + log.trace("[{}] Failed to process message: ", sessionId, e); | ||
248 | + exchange.respond(ResponseCode.INTERNAL_SERVER_ERROR); | ||
254 | } | 249 | } |
255 | })); | 250 | })); |
256 | } | 251 | } |
@@ -464,17 +459,24 @@ public class CoapTransportResource extends CoapResource { | @@ -464,17 +459,24 @@ public class CoapTransportResource extends CoapResource { | ||
464 | } | 459 | } |
465 | } | 460 | } |
466 | 461 | ||
467 | - public class CoapExchangeObserverProxy extends CoapObserveRelation { | ||
468 | - | ||
469 | - /** | ||
470 | - * Constructs a new CoapObserveRelation with the specified request. | ||
471 | - * | ||
472 | - * @param request the request | ||
473 | - * @param endpoint the endpoint | ||
474 | - * @param executor | ||
475 | - */ | ||
476 | - protected CoapExchangeObserverProxy(Request request, Endpoint endpoint, ScheduledThreadPoolExecutor executor) { | ||
477 | - super(request, endpoint, executor); | 462 | + public class CoapExchangeObserverProxy implements ExchangeObserver { |
463 | + | ||
464 | + private final ExchangeObserver proxy; | ||
465 | + private final String token; | ||
466 | + | ||
467 | + CoapExchangeObserverProxy(ExchangeObserver proxy, String token) { | ||
468 | + super(); | ||
469 | + this.proxy = proxy; | ||
470 | + this.token = token; | ||
471 | + } | ||
472 | + | ||
473 | + @Override | ||
474 | + public void completed(Exchange exchange) { | ||
475 | + proxy.completed(exchange); | ||
476 | + TransportProtos.SessionInfoProto session = tokenToSessionIdMap.remove(token); | ||
477 | + if (session != null) { | ||
478 | + closeAndDeregister(session); | ||
479 | + } | ||
478 | } | 480 | } |
479 | } | 481 | } |
480 | 482 |
@@ -18,9 +18,8 @@ package org.thingsboard.server.transport.coap; | @@ -18,9 +18,8 @@ package org.thingsboard.server.transport.coap; | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.eclipse.californium.core.CoapResource; | 19 | import org.eclipse.californium.core.CoapResource; |
20 | import org.eclipse.californium.core.CoapServer; | 20 | import org.eclipse.californium.core.CoapServer; |
21 | - | ||
22 | import org.eclipse.californium.core.network.CoapEndpoint; | 21 | import org.eclipse.californium.core.network.CoapEndpoint; |
23 | -import org.eclipse.californium.core.network.CoapEndpoint.Builder; | 22 | +import org.eclipse.californium.core.network.config.NetworkConfig; |
24 | import org.springframework.beans.factory.annotation.Autowired; | 23 | import org.springframework.beans.factory.annotation.Autowired; |
25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
26 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
@@ -48,15 +47,11 @@ public class CoapTransportService { | @@ -48,15 +47,11 @@ public class CoapTransportService { | ||
48 | public void init() throws UnknownHostException { | 47 | public void init() throws UnknownHostException { |
49 | log.info("Starting CoAP transport..."); | 48 | log.info("Starting CoAP transport..."); |
50 | log.info("Starting CoAP transport server"); | 49 | log.info("Starting CoAP transport server"); |
51 | - this.server = new CoapServer(); | 50 | + this.server = new CoapServer(NetworkConfig.createStandardWithoutFile()); |
52 | createResources(); | 51 | createResources(); |
53 | InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); | 52 | InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); |
54 | InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort()); | 53 | InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort()); |
55 | - Builder builder = new Builder(); | ||
56 | - builder.setInetSocketAddress(sockAddr); | ||
57 | - CoapEndpoint coapEndpoint = builder.build(); | ||
58 | - | ||
59 | - server.addEndpoint(coapEndpoint); | 54 | + server.addEndpoint(new CoapEndpoint(sockAddr)); |
60 | server.start(); | 55 | server.start(); |
61 | log.info("CoAP transport started!"); | 56 | log.info("CoAP transport started!"); |
62 | } | 57 | } |
@@ -31,7 +31,6 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; | @@ -31,7 +31,6 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
31 | import org.thingsboard.server.gen.transport.TransportProtos; | 31 | import org.thingsboard.server.gen.transport.TransportProtos; |
32 | import org.thingsboard.server.transport.coap.CoapTransportResource; | 32 | import org.thingsboard.server.transport.coap.CoapTransportResource; |
33 | 33 | ||
34 | - | ||
35 | import java.util.Arrays; | 34 | import java.util.Arrays; |
36 | import java.util.HashSet; | 35 | import java.util.HashSet; |
37 | import java.util.List; | 36 | import java.util.List; |
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,7 +28,6 @@ import org.eclipse.californium.core.CoapClient; | ||
28 | import org.eclipse.californium.core.CoapHandler; | 28 | import org.eclipse.californium.core.CoapHandler; |
29 | import org.eclipse.californium.core.CoapResponse; | 29 | import org.eclipse.californium.core.CoapResponse; |
30 | import org.eclipse.californium.core.coap.MediaTypeRegistry; | 30 | import org.eclipse.californium.core.coap.MediaTypeRegistry; |
31 | -import org.eclipse.californium.elements.exception.ConnectorException; | ||
32 | import org.thingsboard.server.common.msg.session.FeatureType; | 31 | import org.thingsboard.server.common.msg.session.FeatureType; |
33 | import org.slf4j.Logger; | 32 | import org.slf4j.Logger; |
34 | import org.slf4j.LoggerFactory; | 33 | import org.slf4j.LoggerFactory; |
@@ -62,7 +61,7 @@ public class DeviceEmulator { | @@ -62,7 +61,7 @@ public class DeviceEmulator { | ||
62 | this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES)); | 61 | this.attributesClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.ATTRIBUTES)); |
63 | this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY)); | 62 | this.telemetryClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.TELEMETRY)); |
64 | this.rpcClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC)); | 63 | this.rpcClient = new CoapClient(getFeatureTokenUrl(host, port, token, FeatureType.RPC)); |
65 | - this.keys = (keys != null && !keys.isEmpty()) ? keys.split(",") : null; | 64 | + this.keys = keys.split(","); |
66 | } | 65 | } |
67 | 66 | ||
68 | public void start() { | 67 | public void start() { |
@@ -73,8 +72,11 @@ public class DeviceEmulator { | @@ -73,8 +72,11 @@ public class DeviceEmulator { | ||
73 | try { | 72 | try { |
74 | sendObserveRequest(rpcClient); | 73 | sendObserveRequest(rpcClient); |
75 | while (!Thread.interrupted()) { | 74 | while (!Thread.interrupted()) { |
75 | + | ||
76 | + | ||
76 | sendRequest(attributesClient, createAttributesRequest()); | 77 | sendRequest(attributesClient, createAttributesRequest()); |
77 | sendRequest(telemetryClient, createTelemetryRequest()); | 78 | sendRequest(telemetryClient, createTelemetryRequest()); |
79 | + | ||
78 | Thread.sleep(1000); | 80 | Thread.sleep(1000); |
79 | } | 81 | } |
80 | } catch (Exception e) { | 82 | } catch (Exception e) { |
@@ -82,8 +84,8 @@ public class DeviceEmulator { | @@ -82,8 +84,8 @@ public class DeviceEmulator { | ||
82 | } | 84 | } |
83 | } | 85 | } |
84 | 86 | ||
85 | - private void sendRequest(CoapClient client, JsonNode request) throws IOException, ConnectorException { | ||
86 | - CoapResponse telemetryResponse = client.setTimeout((long) 60000).post(mapper.writeValueAsString(request), | 87 | + private void sendRequest(CoapClient client, JsonNode request) throws JsonProcessingException { |
88 | + CoapResponse telemetryResponse = client.setTimeout(60000).post(mapper.writeValueAsString(request), | ||
87 | MediaTypeRegistry.APPLICATION_JSON); | 89 | MediaTypeRegistry.APPLICATION_JSON); |
88 | log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText()); | 90 | log.info("Response: {}, {}", telemetryResponse.getCode(), telemetryResponse.getResponseText()); |
89 | } | 91 | } |
@@ -111,7 +113,6 @@ public class DeviceEmulator { | @@ -111,7 +113,6 @@ public class DeviceEmulator { | ||
111 | 113 | ||
112 | @Override | 114 | @Override |
113 | public void onError() { | 115 | public void onError() { |
114 | - log.info("Command Response Ack Error, No connect"); | ||
115 | //Do nothing | 116 | //Do nothing |
116 | } | 117 | } |
117 | }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); | 118 | }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); |
@@ -156,15 +157,6 @@ public class DeviceEmulator { | @@ -156,15 +157,6 @@ public class DeviceEmulator { | ||
156 | if (args.length != 4) { | 157 | if (args.length != 4) { |
157 | System.out.println("Usage: java -jar " + DeviceEmulator.class.getSimpleName() + ".jar host port device_token keys"); | 158 | System.out.println("Usage: java -jar " + DeviceEmulator.class.getSimpleName() + ".jar host port device_token keys"); |
158 | } | 159 | } |
159 | - /** | ||
160 | - * DeviceEmulator(String host, int port, String token, String keys) | ||
161 | - * args[]: | ||
162 | - * host = "localhost", | ||
163 | - * port = 0, | ||
164 | - * token = "{Tokrn device from thingboard}"), kSzbDRGwaZqZ6Y25gTLF | ||
165 | - * keys = "{Telemetry}" | ||
166 | - * | ||
167 | - */ | ||
168 | final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]); | 160 | final DeviceEmulator emulator = new DeviceEmulator(args[0], Integer.parseInt(args[1]), args[2], args[3]); |
169 | emulator.start(); | 161 | emulator.start(); |
170 | Runtime.getRuntime().addShutdownHook(new Thread() { | 162 | Runtime.getRuntime().addShutdownHook(new Thread() { |
@@ -175,6 +167,7 @@ public class DeviceEmulator { | @@ -175,6 +167,7 @@ public class DeviceEmulator { | ||
175 | }); | 167 | }); |
176 | } | 168 | } |
177 | 169 | ||
170 | + | ||
178 | private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) { | 171 | private String getFeatureTokenUrl(String host, int port, String token, FeatureType featureType) { |
179 | return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase(); | 172 | return getBaseUrl(host, port) + token + "/" + featureType.name().toLowerCase(); |
180 | } | 173 | } |
@@ -327,7 +327,6 @@ public class DeviceApiController { | @@ -327,7 +327,6 @@ public class DeviceApiController { | ||
327 | public void onToServerRpcResponse(ToServerRpcResponseMsg msg) { | 327 | public void onToServerRpcResponse(ToServerRpcResponseMsg msg) { |
328 | responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); | 328 | responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK)); |
329 | } | 329 | } |
330 | - | ||
331 | } | 330 | } |
332 | 331 | ||
333 | private void reportActivity(SessionInfoProto sessionInfo) { | 332 | private void reportActivity(SessionInfoProto sessionInfo) { |
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 | -} |