Commit e96452cdcf527f6f4b624a8fa78b3086943d9191
Merge remote-tracking branch 'upstream/develop/3.3' into develop/3.3-edge
Showing
82 changed files
with
1999 additions
and
495 deletions
... | ... | @@ -30,7 +30,8 @@ import java.util.Arrays; |
30 | 30 | "org.thingsboard.server.service.component", |
31 | 31 | "org.thingsboard.server.service.install", |
32 | 32 | "org.thingsboard.server.dao", |
33 | - "org.thingsboard.server.common.stats"}) | |
33 | + "org.thingsboard.server.common.stats", | |
34 | + "org.thingsboard.server.cache"}) | |
34 | 35 | public class ThingsboardInstallApplication { |
35 | 36 | |
36 | 37 | private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name"; | ... | ... |
... | ... | @@ -47,8 +47,7 @@ import org.thingsboard.server.common.data.id.EdgeId; |
47 | 47 | import org.thingsboard.server.common.data.id.TenantId; |
48 | 48 | import org.thingsboard.server.common.data.page.PageData; |
49 | 49 | import org.thingsboard.server.common.data.page.PageLink; |
50 | -import org.thingsboard.server.common.data.page.TimePageLink; | |
51 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
50 | +import org.thingsboard.common.util.JacksonUtil; | |
52 | 51 | import org.thingsboard.server.queue.util.TbCoreComponent; |
53 | 52 | import org.thingsboard.server.service.security.model.SecurityUser; |
54 | 53 | import org.thingsboard.server.service.security.permission.Operation; | ... | ... |
... | ... | @@ -50,7 +50,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException; |
50 | 50 | import org.thingsboard.server.dao.device.provision.ProvisionRequest; |
51 | 51 | import org.thingsboard.server.dao.device.provision.ProvisionResponse; |
52 | 52 | import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
53 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
53 | +import org.thingsboard.common.util.JacksonUtil; | |
54 | 54 | import org.thingsboard.server.gen.transport.TransportProtos; |
55 | 55 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
56 | 56 | import org.thingsboard.server.queue.TbQueueCallback; | ... | ... |
... | ... | @@ -41,7 +41,7 @@ import org.thingsboard.server.dao.entityview.EntityViewService; |
41 | 41 | import org.thingsboard.server.dao.rule.RuleChainService; |
42 | 42 | import org.thingsboard.server.dao.tenant.TenantService; |
43 | 43 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
44 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
44 | +import org.thingsboard.common.util.JacksonUtil; | |
45 | 45 | import org.thingsboard.server.service.install.InstallScripts; |
46 | 46 | |
47 | 47 | import java.util.ArrayList; |
... | ... | @@ -51,7 +51,6 @@ import java.util.concurrent.ExecutionException; |
51 | 51 | import java.util.stream.Collectors; |
52 | 52 | |
53 | 53 | import static org.apache.commons.lang3.StringUtils.isBlank; |
54 | -import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper; | |
55 | 54 | |
56 | 55 | @Service |
57 | 56 | @Profile("install") | ... | ... |
... | ... | @@ -47,7 +47,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; |
47 | 47 | import org.thingsboard.server.dao.entity.EntityService; |
48 | 48 | import org.thingsboard.server.dao.model.ModelConstants; |
49 | 49 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
50 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
50 | +import org.thingsboard.common.util.JacksonUtil; | |
51 | 51 | import org.thingsboard.server.queue.util.TbCoreComponent; |
52 | 52 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
53 | 53 | import org.thingsboard.server.service.security.AccessValidator; | ... | ... |
... | ... | @@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; |
35 | 35 | import org.thingsboard.server.common.msg.queue.TbCallback; |
36 | 36 | import org.thingsboard.server.common.stats.StatsFactory; |
37 | 37 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; |
38 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
38 | +import org.thingsboard.common.util.JacksonUtil; | |
39 | 39 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; |
40 | 40 | import org.thingsboard.server.gen.transport.TransportProtos.EdgeNotificationMsgProto; |
41 | 41 | import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; | ... | ... |
... | ... | @@ -49,7 +49,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; |
49 | 49 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
50 | 50 | import org.thingsboard.server.dao.user.UserService; |
51 | 51 | import org.thingsboard.server.dao.user.UserServiceImpl; |
52 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
52 | +import org.thingsboard.common.util.JacksonUtil; | |
53 | 53 | import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; |
54 | 54 | import org.thingsboard.server.utils.MiscUtils; |
55 | 55 | ... | ... |
... | ... | @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; |
31 | 31 | import org.thingsboard.server.common.data.id.EntityId; |
32 | 32 | import org.thingsboard.server.common.data.id.TenantId; |
33 | 33 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
34 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
34 | +import org.thingsboard.common.util.JacksonUtil; | |
35 | 35 | import org.thingsboard.server.queue.usagestats.TbApiUsageClient; |
36 | 36 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
37 | 37 | ... | ... |
... | ... | @@ -52,7 +52,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; |
52 | 52 | import org.thingsboard.server.dao.device.DeviceService; |
53 | 53 | import org.thingsboard.server.dao.tenant.TenantService; |
54 | 54 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
55 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
55 | +import org.thingsboard.common.util.JacksonUtil; | |
56 | 56 | import org.thingsboard.server.gen.transport.TransportProtos; |
57 | 57 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
58 | 58 | import org.thingsboard.server.queue.discovery.PartitionService; | ... | ... |
... | ... | @@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback; |
39 | 39 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
40 | 40 | import org.thingsboard.server.dao.attributes.AttributesService; |
41 | 41 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
42 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
42 | +import org.thingsboard.common.util.JacksonUtil; | |
43 | 43 | import org.thingsboard.server.gen.transport.TransportProtos.*; |
44 | 44 | import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto; |
45 | 45 | import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdateProto; | ... | ... |
... | ... | @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.kv.KvEntry; |
30 | 30 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
31 | 31 | import org.thingsboard.server.common.data.kv.StringDataEntry; |
32 | 32 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
33 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
33 | +import org.thingsboard.common.util.JacksonUtil; | |
34 | 34 | import org.thingsboard.server.gen.transport.TransportProtos; |
35 | 35 | import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; |
36 | 36 | import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType; | ... | ... |
... | ... | @@ -54,7 +54,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionRequest; |
54 | 54 | import org.thingsboard.server.dao.device.provision.ProvisionResponse; |
55 | 55 | import org.thingsboard.server.dao.relation.RelationService; |
56 | 56 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
57 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
57 | +import org.thingsboard.common.util.JacksonUtil; | |
58 | 58 | import org.thingsboard.server.gen.transport.TransportProtos; |
59 | 59 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
60 | 60 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; | ... | ... |
... | ... | @@ -643,8 +643,8 @@ transport: |
643 | 643 | public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
644 | 644 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509: |
645 | 645 | alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}" |
646 | - # Redis | |
647 | - redis_url: "${LWM2M_REDIS_URL:''}" | |
646 | + # Use redis for Security and Registration stores | |
647 | + redis.enabled: "${LWM2M_REDIS_ENABLED:false}" | |
648 | 648 | |
649 | 649 | # Edges parameters |
650 | 650 | edges: | ... | ... |
... | ... | @@ -26,7 +26,7 @@ import org.junit.Before; |
26 | 26 | import org.junit.Test; |
27 | 27 | import org.thingsboard.server.common.data.Device; |
28 | 28 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
29 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
29 | +import org.thingsboard.common.util.JacksonUtil; | |
30 | 30 | import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; |
31 | 31 | |
32 | 32 | import java.nio.charset.StandardCharsets; | ... | ... |
... | ... | @@ -25,7 +25,7 @@ import org.junit.Test; |
25 | 25 | import org.thingsboard.server.common.data.Device; |
26 | 26 | import org.thingsboard.server.common.data.TransportPayloadType; |
27 | 27 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
28 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
28 | +import org.thingsboard.common.util.JacksonUtil; | |
29 | 29 | import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; |
30 | 30 | |
31 | 31 | import java.nio.charset.StandardCharsets; | ... | ... |
... | ... | @@ -37,7 +37,7 @@ import org.thingsboard.server.common.transport.util.JsonUtils; |
37 | 37 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
38 | 38 | import org.thingsboard.server.dao.device.DeviceService; |
39 | 39 | import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
40 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
40 | +import org.thingsboard.common.util.JacksonUtil; | |
41 | 41 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; |
42 | 42 | |
43 | 43 | import java.util.concurrent.CountDownLatch; | ... | ... |
... | ... | @@ -36,7 +36,7 @@ import org.thingsboard.server.common.msg.EncryptionUtil; |
36 | 36 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
37 | 37 | import org.thingsboard.server.dao.device.DeviceService; |
38 | 38 | import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
39 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
39 | +import org.thingsboard.common.util.JacksonUtil; | |
40 | 40 | import org.thingsboard.server.gen.transport.TransportProtos.CredentialsDataProto; |
41 | 41 | import org.thingsboard.server.gen.transport.TransportProtos.CredentialsType; |
42 | 42 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceCredentialsMsg; |
... | ... | @@ -47,7 +47,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenR |
47 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
48 | 48 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; |
49 | 49 | |
50 | -import java.util.UUID; | |
51 | 50 | import java.util.concurrent.CountDownLatch; |
52 | 51 | import java.util.concurrent.TimeUnit; |
53 | 52 | ... | ... |
... | ... | @@ -30,7 +30,7 @@ import org.junit.Assert; |
30 | 30 | import org.thingsboard.server.common.data.Device; |
31 | 31 | import org.thingsboard.server.common.data.TransportPayloadType; |
32 | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
33 | +import org.thingsboard.common.util.JacksonUtil; | |
34 | 34 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; |
35 | 35 | |
36 | 36 | import java.util.Arrays; | ... | ... |
common/cache/pom.xml
0 → 100644
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2021 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
20 | + <modelVersion>4.0.0</modelVersion> | |
21 | + <parent> | |
22 | + <groupId>org.thingsboard</groupId> | |
23 | + <version>3.3.0-SNAPSHOT</version> | |
24 | + <artifactId>common</artifactId> | |
25 | + </parent> | |
26 | + <groupId>org.thingsboard.common</groupId> | |
27 | + <artifactId>cache</artifactId> | |
28 | + <packaging>jar</packaging> | |
29 | + | |
30 | + <name>Thingsboard Server Common Cache</name> | |
31 | + <url>https://thingsboard.io</url> | |
32 | + | |
33 | + <properties> | |
34 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
35 | + <main.dir>${basedir}/../..</main.dir> | |
36 | + </properties> | |
37 | + | |
38 | + <dependencies> | |
39 | + <dependency> | |
40 | + <groupId>org.thingsboard.common</groupId> | |
41 | + <artifactId>data</artifactId> | |
42 | + </dependency> | |
43 | + <dependency> | |
44 | + <groupId>org.springframework.boot</groupId> | |
45 | + <artifactId>spring-boot-autoconfigure</artifactId> | |
46 | + </dependency> | |
47 | + <dependency> | |
48 | + <groupId>org.springframework.data</groupId> | |
49 | + <artifactId>spring-data-redis</artifactId> | |
50 | + </dependency> | |
51 | + <dependency> | |
52 | + <groupId>redis.clients</groupId> | |
53 | + <artifactId>jedis</artifactId> | |
54 | + </dependency> | |
55 | + <dependency> | |
56 | + <groupId>com.github.ben-manes.caffeine</groupId> | |
57 | + <artifactId>caffeine</artifactId> | |
58 | + </dependency> | |
59 | + <dependency> | |
60 | + <groupId>org.apache.commons</groupId> | |
61 | + <artifactId>commons-lang3</artifactId> | |
62 | + </dependency> | |
63 | + <dependency> | |
64 | + <groupId>org.slf4j</groupId> | |
65 | + <artifactId>slf4j-api</artifactId> | |
66 | + </dependency> | |
67 | + <dependency> | |
68 | + <groupId>org.slf4j</groupId> | |
69 | + <artifactId>log4j-over-slf4j</artifactId> | |
70 | + </dependency> | |
71 | + <dependency> | |
72 | + <groupId>ch.qos.logback</groupId> | |
73 | + <artifactId>logback-core</artifactId> | |
74 | + </dependency> | |
75 | + <dependency> | |
76 | + <groupId>ch.qos.logback</groupId> | |
77 | + <artifactId>logback-classic</artifactId> | |
78 | + </dependency> | |
79 | + <dependency> | |
80 | + <groupId>junit</groupId> | |
81 | + <artifactId>junit</artifactId> | |
82 | + <scope>test</scope> | |
83 | + </dependency> | |
84 | + <dependency> | |
85 | + <groupId>org.mockito</groupId> | |
86 | + <artifactId>mockito-core</artifactId> | |
87 | + <scope>test</scope> | |
88 | + </dependency> | |
89 | + </dependencies> | |
90 | + | |
91 | + <build> | |
92 | + <plugins> | |
93 | +<!-- <plugin>--> | |
94 | +<!-- <groupId>org.apache.maven.plugins</groupId>--> | |
95 | +<!-- <artifactId>maven-source-plugin</artifactId>--> | |
96 | +<!-- <executions>--> | |
97 | +<!-- <execution>--> | |
98 | +<!-- <id>attach-sources</id>--> | |
99 | +<!-- <goals>--> | |
100 | +<!-- <goal>jar</goal>--> | |
101 | +<!-- </goals>--> | |
102 | +<!-- </execution>--> | |
103 | +<!-- </executions>--> | |
104 | +<!-- </plugin>--> | |
105 | +<!-- <plugin>--> | |
106 | +<!-- <groupId>org.apache.maven.plugins</groupId>--> | |
107 | +<!-- <artifactId>maven-deploy-plugin</artifactId>--> | |
108 | +<!-- <configuration>--> | |
109 | +<!-- <skip>false</skip>--> | |
110 | +<!-- </configuration>--> | |
111 | +<!-- </plugin>--> | |
112 | + </plugins> | |
113 | + </build> | |
114 | + | |
115 | +</project> | ... | ... |
common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecs.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/CacheSpecs.java
common/cache/src/main/java/org/thingsboard/server/cache/CaffeineCacheConfiguration.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.cache; | |
16 | +package org.thingsboard.server.cache; | |
17 | 17 | |
18 | 18 | import com.github.benmanes.caffeine.cache.Caffeine; |
19 | 19 | import com.github.benmanes.caffeine.cache.RemovalCause; |
... | ... | @@ -26,7 +26,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; |
26 | 26 | import org.springframework.cache.CacheManager; |
27 | 27 | import org.springframework.cache.annotation.EnableCaching; |
28 | 28 | import org.springframework.cache.caffeine.CaffeineCache; |
29 | -import org.springframework.cache.interceptor.KeyGenerator; | |
30 | 29 | import org.springframework.cache.support.SimpleCacheManager; |
31 | 30 | import org.springframework.context.annotation.Bean; |
32 | 31 | import org.springframework.context.annotation.Configuration; |
... | ... | @@ -78,14 +77,9 @@ public class CaffeineCacheConfiguration { |
78 | 77 | return Ticker.systemTicker(); |
79 | 78 | } |
80 | 79 | |
81 | - @Bean | |
82 | - public KeyGenerator previousDeviceCredentialsId() { | |
83 | - return new PreviousDeviceCredentialsIdKeyGenerator(); | |
84 | - } | |
85 | - | |
86 | 80 | private Weigher<? super Object, ? super Object> collectionSafeWeigher() { |
87 | 81 | return (Weigher<Object, Object>) (key, value) -> { |
88 | - if(value instanceof Collection) { | |
82 | + if (value instanceof Collection) { | |
89 | 83 | return ((Collection) value).size(); |
90 | 84 | } |
91 | 85 | return 1; | ... | ... |
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java
... | ... | @@ -13,14 +13,13 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.cache; | |
16 | +package org.thingsboard.server.cache; | |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | 19 | import org.springframework.beans.factory.annotation.Value; |
20 | 20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
21 | 21 | import org.springframework.cache.CacheManager; |
22 | 22 | import org.springframework.cache.annotation.EnableCaching; |
23 | -import org.springframework.cache.interceptor.KeyGenerator; | |
24 | 23 | import org.springframework.context.annotation.Bean; |
25 | 24 | import org.springframework.context.annotation.Configuration; |
26 | 25 | import org.springframework.core.convert.converter.ConverterRegistry; |
... | ... | @@ -90,11 +89,6 @@ public abstract class TBRedisCacheConfiguration { |
90 | 89 | } |
91 | 90 | |
92 | 91 | @Bean |
93 | - public KeyGenerator previousDeviceCredentialsId() { | |
94 | - return new PreviousDeviceCredentialsIdKeyGenerator(); | |
95 | - } | |
96 | - | |
97 | - @Bean | |
98 | 92 | public RedisTemplate<String, Object> redisTemplate() { |
99 | 93 | RedisTemplate<String, Object> template = new RedisTemplate<>(); |
100 | 94 | template.setConnectionFactory(redisConnectionFactory()); | ... | ... |
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisClusterConfiguration.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.cache; | |
16 | +package org.thingsboard.server.cache; | |
17 | 17 | |
18 | 18 | import org.apache.commons.lang3.StringUtils; |
19 | 19 | import org.springframework.beans.factory.annotation.Value; | ... | ... |
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisStandaloneConfiguration.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.cache; | |
16 | +package org.thingsboard.server.cache; | |
17 | 17 | |
18 | 18 | import org.springframework.beans.factory.annotation.Value; |
19 | 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ... | ... |
common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2021 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.queue.util; | |
17 | + | |
18 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
19 | + | |
20 | +import java.lang.annotation.Retention; | |
21 | +import java.lang.annotation.RetentionPolicy; | |
22 | + | |
23 | +@Retention(RetentionPolicy.RUNTIME) | |
24 | +@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
25 | +public @interface TbLwM2mTransportComponent { | |
26 | +} | ... | ... |
... | ... | @@ -29,7 +29,7 @@ import org.springframework.stereotype.Component; |
29 | 29 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; |
30 | 30 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; |
31 | 31 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager; |
32 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer; | |
32 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | |
33 | 33 | |
34 | 34 | import java.math.BigInteger; |
35 | 35 | import java.security.AlgorithmParameters; |
... | ... | @@ -56,7 +56,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE |
56 | 56 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
57 | 57 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
58 | 58 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; |
59 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig; | |
59 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; | |
60 | 60 | |
61 | 61 | @Slf4j |
62 | 62 | @Component |
... | ... | @@ -70,7 +70,7 @@ public class LwM2MTransportBootstrapServerConfiguration { |
70 | 70 | private LwM2MTransportContextBootstrap contextBs; |
71 | 71 | |
72 | 72 | @Autowired |
73 | - private LwM2MTransportContextServer contextS; | |
73 | + private LwM2mTransportContextServer contextS; | |
74 | 74 | |
75 | 75 | @Autowired |
76 | 76 | private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore; |
... | ... | @@ -94,7 +94,7 @@ public class LwM2MTransportBootstrapServerConfiguration { |
94 | 94 | builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); |
95 | 95 | |
96 | 96 | /** Define model provider (Create Models )*/ |
97 | - builder.setModel(new StaticModel(contextS.getCtxServer().getModelsValue())); | |
97 | + builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValue())); | |
98 | 98 | |
99 | 99 | /** Create credentials */ |
100 | 100 | this.setServerWithCredentials(builder); |
... | ... | @@ -108,8 +108,8 @@ public class LwM2MTransportBootstrapServerConfiguration { |
108 | 108 | |
109 | 109 | /** Create and Set DTLS Config */ |
110 | 110 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); |
111 | - dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getCtxServer().isRecommendedSupportedGroups()); | |
112 | - dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getCtxServer().isRecommendedCiphers()); | |
111 | + dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedSupportedGroups()); | |
112 | + dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedCiphers()); | |
113 | 113 | if (this.pskMode) { |
114 | 114 | dtlsConfig.setSupportedCipherSuites( |
115 | 115 | TLS_PSK_WITH_AES_128_CCM_8, |
... | ... | @@ -135,10 +135,10 @@ public class LwM2MTransportBootstrapServerConfiguration { |
135 | 135 | |
136 | 136 | private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { |
137 | 137 | try { |
138 | - if (this.contextS.getCtxServer().getKeyStoreValue() != null) { | |
139 | - KeyStore keyStoreServer = this.contextS.getCtxServer().getKeyStoreValue(); | |
138 | + if (this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue() != null) { | |
139 | + KeyStore keyStoreServer = this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue(); | |
140 | 140 | if (this.setBuilderX509(builder)) { |
141 | - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getCtxServer().getRootAlias()); | |
141 | + X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getLwM2MTransportConfigServer().getRootAlias()); | |
142 | 142 | if (rootCAX509Cert != null) { |
143 | 143 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
144 | 144 | trustedCertificates[0] = rootCAX509Cert; |
... | ... | @@ -169,8 +169,8 @@ public class LwM2MTransportBootstrapServerConfiguration { |
169 | 169 | * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks |
170 | 170 | */ |
171 | 171 | try { |
172 | - X509Certificate serverCertificate = (X509Certificate) this.contextS.getCtxServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias()); | |
173 | - PrivateKey privateKey = (PrivateKey) this.contextS.getCtxServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getCtxServer().getKeyStorePasswordServer() == null ? null : this.contextS.getCtxServer().getKeyStorePasswordServer().toCharArray()); | |
172 | + X509Certificate serverCertificate = (X509Certificate) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias()); | |
173 | + PrivateKey privateKey = (PrivateKey) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray()); | |
174 | 174 | PublicKey publicKey = serverCertificate.getPublicKey(); |
175 | 175 | if (serverCertificate != null && |
176 | 176 | privateKey != null && privateKey.getEncoded().length > 0 && | ... | ... |
... | ... | @@ -31,30 +31,24 @@ package org.thingsboard.server.transport.lwm2m.bootstrap; |
31 | 31 | */ |
32 | 32 | |
33 | 33 | import lombok.extern.slf4j.Slf4j; |
34 | -import org.springframework.beans.factory.annotation.Autowired; | |
35 | 34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
36 | 35 | import org.springframework.stereotype.Component; |
37 | 36 | import org.thingsboard.server.common.transport.TransportContext; |
38 | 37 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; |
39 | 38 | |
40 | -import javax.annotation.PostConstruct; | |
41 | - | |
42 | 39 | |
43 | 40 | @Slf4j |
44 | 41 | @Component |
45 | 42 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'") |
46 | 43 | public class LwM2MTransportContextBootstrap extends TransportContext { |
47 | 44 | |
48 | - private LwM2MTransportConfigBootstrap ctxBootStrap; | |
49 | - @Autowired | |
50 | - LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstarp; | |
45 | + private final LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstrap; | |
51 | 46 | |
52 | - @PostConstruct | |
53 | - public void init() { | |
54 | - this.ctxBootStrap = lwM2MTransportConfigBootstarp; | |
47 | + public LwM2MTransportContextBootstrap(LwM2MTransportConfigBootstrap ctxBootStrap) { | |
48 | + this.lwM2MTransportConfigBootstrap = ctxBootStrap; | |
55 | 49 | } |
56 | 50 | |
57 | 51 | public LwM2MTransportConfigBootstrap getCtxBootStrap() { |
58 | - return this.ctxBootStrap; | |
52 | + return this.lwM2MTransportConfigBootstrap; | |
59 | 53 | } |
60 | 54 | } | ... | ... |
... | ... | @@ -27,16 +27,15 @@ import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore; |
27 | 27 | import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException; |
28 | 28 | import org.eclipse.leshan.server.security.BootstrapSecurityStore; |
29 | 29 | import org.eclipse.leshan.server.security.SecurityInfo; |
30 | -import org.springframework.beans.factory.annotation.Autowired; | |
31 | 30 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
32 | 31 | import org.springframework.stereotype.Service; |
33 | 32 | import org.thingsboard.server.gen.transport.TransportProtos; |
34 | 33 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
35 | 34 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
36 | 35 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
37 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MSessionMsgListener; | |
38 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer; | |
39 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler; | |
36 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; | |
37 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | |
38 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
40 | 39 | import org.thingsboard.server.transport.lwm2m.utils.TypeServer; |
41 | 40 | |
42 | 41 | import java.io.IOException; |
... | ... | @@ -45,12 +44,12 @@ import java.util.Arrays; |
45 | 44 | import java.util.List; |
46 | 45 | import java.util.UUID; |
47 | 46 | |
48 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.BOOTSTRAP_SERVER; | |
49 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR; | |
50 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO; | |
51 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LWM2M_SERVER; | |
52 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.SERVERS; | |
53 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getBootstrapParametersFromThingsboard; | |
47 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.BOOTSTRAP_SERVER; | |
48 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | |
49 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | |
50 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_SERVER; | |
51 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVERS; | |
52 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getBootstrapParametersFromThingsboard; | |
54 | 53 | |
55 | 54 | @Slf4j |
56 | 55 | @Service("LwM2MBootstrapSecurityStore") |
... | ... | @@ -59,14 +58,14 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
59 | 58 | |
60 | 59 | private final EditableBootstrapConfigStore bootstrapConfigStore; |
61 | 60 | |
62 | - @Autowired | |
63 | - LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; | |
61 | + private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; | |
64 | 62 | |
65 | - @Autowired | |
66 | - public LwM2MTransportContextServer context; | |
63 | + private final LwM2mTransportContextServer context; | |
67 | 64 | |
68 | - public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore) { | |
65 | + public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore, LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, LwM2mTransportContextServer context) { | |
69 | 66 | this.bootstrapConfigStore = bootstrapConfigStore; |
67 | + this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator; | |
68 | + this.context = context; | |
70 | 69 | } |
71 | 70 | |
72 | 71 | @Override |
... | ... | @@ -162,18 +161,18 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
162 | 161 | LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class); |
163 | 162 | UUID sessionUUiD = UUID.randomUUID(); |
164 | 163 | TransportProtos.SessionInfoProto sessionInfo = context.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits()); |
165 | - context.getTransportService().registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(null, sessionInfo)); | |
164 | + context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo)); | |
166 | 165 | if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) { |
167 | 166 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); |
168 | 167 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); |
169 | 168 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); |
170 | - context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
169 | + context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
171 | 170 | return lwM2MBootstrapConfig; |
172 | 171 | } else { |
173 | 172 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); |
174 | 173 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
175 | 174 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
176 | - context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
175 | + context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
177 | 176 | return null; |
178 | 177 | } |
179 | 178 | } | ... | ... |
... | ... | @@ -20,16 +20,14 @@ import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.eclipse.leshan.core.util.Hex; |
21 | 21 | import org.eclipse.leshan.core.util.SecurityUtil; |
22 | 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 | 23 | import org.springframework.stereotype.Component; |
26 | 24 | import org.thingsboard.server.common.data.DeviceProfile; |
27 | 25 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
28 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | |
29 | 26 | 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; | |
27 | +import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | |
28 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
29 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | |
30 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
33 | 31 | import org.thingsboard.server.transport.lwm2m.utils.TypeServer; |
34 | 32 | |
35 | 33 | import java.io.IOException; |
... | ... | @@ -45,47 +43,46 @@ import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RP |
45 | 43 | import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509; |
46 | 44 | |
47 | 45 | @Slf4j |
48 | -@Component("LwM2MGetSecurityInfo") | |
49 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
46 | +@Component | |
47 | +@TbLwM2mTransportComponent | |
50 | 48 | public class LwM2mCredentialsSecurityInfoValidator { |
51 | 49 | |
52 | - @Autowired | |
53 | - public LwM2MTransportContextServer contextS; | |
54 | - | |
55 | - @Autowired | |
56 | - public LwM2MTransportContextBootstrap contextBS; | |
50 | + private final LwM2mTransportContextServer contextS; | |
57 | 51 | |
52 | + public LwM2mCredentialsSecurityInfoValidator(LwM2mTransportContextServer contextS) { | |
53 | + this.contextS = contextS; | |
54 | + } | |
58 | 55 | |
59 | 56 | /** |
60 | 57 | * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials |
61 | - * @param endPoint - | |
58 | + * @param endpoint - | |
62 | 59 | * @param keyValue - |
63 | 60 | * @return ValidateDeviceCredentialsResponseMsg and SecurityInfo |
64 | 61 | */ |
65 | - public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endPoint, TypeServer keyValue) { | |
62 | + public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endpoint, TypeServer keyValue) { | |
66 | 63 | CountDownLatch latch = new CountDownLatch(1); |
67 | 64 | final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1]; |
68 | - contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endPoint).build(), | |
69 | - new TransportServiceCallback<ValidateDeviceCredentialsResponseMsg>() { | |
65 | + contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(), | |
66 | + new TransportServiceCallback<>() { | |
70 | 67 | @Override |
71 | 68 | public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) { |
72 | 69 | String credentialsBody = msg.getCredentialsBody(); |
73 | - resultSecurityStore[0] = createSecurityInfo(endPoint, credentialsBody, keyValue); | |
70 | + resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); | |
74 | 71 | resultSecurityStore[0].setMsg(msg); |
75 | - Optional<DeviceProfile> deviceProfileOpt = LwM2MTransportHandler.decode(msg.getProfileBody().toByteArray()); | |
72 | + Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandler.decode(msg.getProfileBody().toByteArray()); | |
76 | 73 | deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile)); |
77 | 74 | latch.countDown(); |
78 | 75 | } |
79 | 76 | |
80 | 77 | @Override |
81 | 78 | public void onError(Throwable e) { |
82 | - log.trace("[{}] [{}] Failed to process credentials ", endPoint, e); | |
83 | - resultSecurityStore[0] = createSecurityInfo(endPoint, null, null); | |
79 | + log.trace("[{}] [{}] Failed to process credentials ", endpoint, e); | |
80 | + resultSecurityStore[0] = createSecurityInfo(endpoint, null, null); | |
84 | 81 | latch.countDown(); |
85 | 82 | } |
86 | 83 | }); |
87 | 84 | try { |
88 | - latch.await(contextS.getCtxServer().getTimeout(), TimeUnit.MILLISECONDS); | |
85 | + latch.await(contextS.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); | |
89 | 86 | } catch (InterruptedException e) { |
90 | 87 | log.error("Failed to await credentials!", e); |
91 | 88 | } |
... | ... | @@ -101,7 +98,7 @@ public class LwM2mCredentialsSecurityInfoValidator { |
101 | 98 | */ |
102 | 99 | private ReadResultSecurityStore createSecurityInfo(String endPoint, String jsonStr, TypeServer keyValue) { |
103 | 100 | ReadResultSecurityStore result = new ReadResultSecurityStore(); |
104 | - JsonObject objectMsg = LwM2MTransportHandler.validateJson(jsonStr); | |
101 | + JsonObject objectMsg = LwM2mTransportHandler.validateJson(jsonStr); | |
105 | 102 | if (objectMsg != null && !objectMsg.isJsonNull()) { |
106 | 103 | JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null; |
107 | 104 | /** | ... | ... |
... | ... | @@ -31,9 +31,9 @@ import java.util.Collection; |
31 | 31 | public class LwM2mServerListener { |
32 | 32 | |
33 | 33 | private final LeshanServer lhServer; |
34 | - private final LwM2MTransportServiceImpl service; | |
34 | + private final LwM2mTransportServiceImpl service; | |
35 | 35 | |
36 | - public LwM2mServerListener(LeshanServer lhServer, LwM2MTransportServiceImpl service) { | |
36 | + public LwM2mServerListener(LeshanServer lhServer, LwM2mTransportServiceImpl service) { | |
37 | 37 | this.lhServer = lhServer; |
38 | 38 | this.service = service; |
39 | 39 | } | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MSessionMsgListener.java
... | ... | @@ -32,11 +32,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCre |
32 | 32 | import java.util.Optional; |
33 | 33 | |
34 | 34 | @Slf4j |
35 | -public class LwM2MSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | |
36 | - private LwM2MTransportServiceImpl service; | |
35 | +public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | |
36 | + private LwM2mTransportServiceImpl service; | |
37 | 37 | private TransportProtos.SessionInfoProto sessionInfo; |
38 | 38 | |
39 | - public LwM2MSessionMsgListener(LwM2MTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) { | |
39 | + public LwM2mSessionMsgListener(LwM2mTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) { | |
40 | 40 | this.service = service; |
41 | 41 | this.sessionInfo = sessionInfo; |
42 | 42 | } | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java
... | ... | @@ -34,8 +34,6 @@ import com.google.gson.JsonElement; |
34 | 34 | import com.google.gson.JsonObject; |
35 | 35 | import lombok.Getter; |
36 | 36 | import lombok.extern.slf4j.Slf4j; |
37 | -import org.springframework.beans.factory.annotation.Autowired; | |
38 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
39 | 37 | import org.springframework.stereotype.Component; |
40 | 38 | import org.thingsboard.server.common.transport.TransportContext; |
41 | 39 | import org.thingsboard.server.common.transport.TransportService; |
... | ... | @@ -43,40 +41,32 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; |
43 | 41 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
44 | 42 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; |
45 | 43 | import org.thingsboard.server.gen.transport.TransportProtos; |
44 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
46 | 45 | import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; |
47 | -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore; | |
48 | 46 | |
49 | -import javax.annotation.PostConstruct; | |
50 | - | |
51 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_TELEMETRY; | |
47 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; | |
52 | 48 | |
53 | 49 | @Slf4j |
54 | 50 | @Component |
55 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
56 | -public class LwM2MTransportContextServer extends TransportContext { | |
51 | +@TbLwM2mTransportComponent | |
52 | +public class LwM2mTransportContextServer extends TransportContext { | |
57 | 53 | |
58 | - private LwM2MTransportConfigServer ctxServer; | |
59 | 54 | |
60 | - @Autowired | |
61 | - protected LwM2MTransportConfigServer lwM2MTransportConfigServer; | |
55 | + private final LwM2MTransportConfigServer lwM2MTransportConfigServer; | |
62 | 56 | |
63 | - @Autowired | |
64 | - private TransportService transportService; | |
57 | + private final TransportService transportService; | |
65 | 58 | |
66 | 59 | @Getter |
67 | - @Autowired | |
68 | - private LwM2MJsonAdaptor adaptor; | |
69 | - | |
70 | - @Autowired | |
71 | - LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore; | |
60 | + private final LwM2MJsonAdaptor adaptor; | |
72 | 61 | |
73 | - @PostConstruct | |
74 | - public void init() { | |
75 | - this.ctxServer = lwM2MTransportConfigServer; | |
62 | + public LwM2mTransportContextServer(LwM2MTransportConfigServer lwM2MTransportConfigServer, TransportService transportService, LwM2MJsonAdaptor adaptor) { | |
63 | + this.lwM2MTransportConfigServer = lwM2MTransportConfigServer; | |
64 | + this.transportService = transportService; | |
65 | + this.adaptor = adaptor; | |
76 | 66 | } |
77 | 67 | |
78 | - public LwM2MTransportConfigServer getCtxServer() { | |
79 | - return this.ctxServer; | |
68 | + public LwM2MTransportConfigServer getLwM2MTransportConfigServer() { | |
69 | + return this.lwM2MTransportConfigServer; | |
80 | 70 | } |
81 | 71 | |
82 | 72 | /** |
... | ... | @@ -86,7 +76,7 @@ public class LwM2MTransportContextServer extends TransportContext { |
86 | 76 | * @return - dummy |
87 | 77 | */ |
88 | 78 | private <T> TransportServiceCallback<Void> getPubAckCallbackSentAttrTelemetry(final T msg) { |
89 | - return new TransportServiceCallback<Void>() { | |
79 | + return new TransportServiceCallback<>() { | |
90 | 80 | @Override |
91 | 81 | public void onSuccess(Void dummy) { |
92 | 82 | log.trace("Success to publish msg: {}, dummy: {}", msg, dummy); |
... | ... | @@ -101,11 +91,11 @@ public class LwM2MTransportContextServer extends TransportContext { |
101 | 91 | |
102 | 92 | public void sentParametersOnThingsboard(JsonElement msg, String topicName, TransportProtos.SessionInfoProto sessionInfo) { |
103 | 93 | try { |
104 | - if (topicName.equals(LwM2MTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) { | |
94 | + if (topicName.equals(LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) { | |
105 | 95 | TransportProtos.PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg); |
106 | 96 | TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postAttributeMsg); |
107 | 97 | transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSentAttrTelemetry(call)); |
108 | - } else if (topicName.equals(LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC)) { | |
98 | + } else if (topicName.equals(LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC)) { | |
109 | 99 | TransportProtos.PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg); |
110 | 100 | TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postTelemetryMsg); |
111 | 101 | transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSentAttrTelemetry(call)); | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java
... | ... | @@ -36,8 +36,8 @@ import org.nustaq.serialization.FSTConfiguration; |
36 | 36 | import org.thingsboard.server.common.data.DeviceProfile; |
37 | 37 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; |
38 | 38 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
39 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile; | |
40 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; | |
39 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | |
40 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
41 | 41 | |
42 | 42 | import java.io.File; |
43 | 43 | import java.io.IOException; |
... | ... | @@ -49,7 +49,7 @@ import java.util.Optional; |
49 | 49 | @Slf4j |
50 | 50 | //@Component("LwM2MTransportHandler") |
51 | 51 | //@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") |
52 | -public class LwM2MTransportHandler { | |
52 | +public class LwM2mTransportHandler { | |
53 | 53 | |
54 | 54 | // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to |
55 | 55 | // send a Confirmable message to the time when an acknowledgement is no longer expected. |
... | ... | @@ -188,8 +188,8 @@ public class LwM2MTransportHandler { |
188 | 188 | return null; |
189 | 189 | } |
190 | 190 | |
191 | - public static LwM2MClientProfile getNewProfileParameters(JsonObject profilesConfigData) { | |
192 | - LwM2MClientProfile lwM2MClientProfile = new LwM2MClientProfile(); | |
191 | + public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData) { | |
192 | + LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile(); | |
193 | 193 | lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject()); |
194 | 194 | lwM2MClientProfile.setPostKeyNameProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).getAsJsonObject()); |
195 | 195 | lwM2MClientProfile.setPostAttributeProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).getAsJsonArray()); |
... | ... | @@ -214,14 +214,14 @@ public class LwM2MTransportHandler { |
214 | 214 | * "telemetry":["/1/0/1","/2/0/1","/6/0/1"], |
215 | 215 | * "observe":["/2/0","/2/0/0","/4/0/2"]} |
216 | 216 | */ |
217 | - public static LwM2MClientProfile getLwM2MClientProfileFromThingsboard(DeviceProfile deviceProfile) { | |
217 | + public static LwM2mClientProfile getLwM2MClientProfileFromThingsboard(DeviceProfile deviceProfile) { | |
218 | 218 | if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) { |
219 | 219 | Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties(); |
220 | 220 | try { |
221 | 221 | ObjectMapper mapper = new ObjectMapper(); |
222 | 222 | String profileStr = mapper.writeValueAsString(profile); |
223 | 223 | JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; |
224 | - return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2MTransportHandler.getNewProfileParameters(profileJson) : null; | |
224 | + return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson) : null; | |
225 | 225 | } catch (IOException e) { |
226 | 226 | log.error("", e); |
227 | 227 | } |
... | ... | @@ -244,12 +244,12 @@ public class LwM2MTransportHandler { |
244 | 244 | return null; |
245 | 245 | } |
246 | 246 | |
247 | - public static boolean getClientUpdateValueAfterConnect (LwM2MClientProfile profile) { | |
247 | + public static boolean getClientUpdateValueAfterConnect (LwM2mClientProfile profile) { | |
248 | 248 | return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientUpdateValueAfterConnect") && |
249 | 249 | profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientUpdateValueAfterConnect").getAsBoolean(); |
250 | 250 | } |
251 | 251 | |
252 | - public static boolean getClientOnlyObserveAfterConnect (LwM2MClientProfile profile) { | |
252 | + public static boolean getClientOnlyObserveAfterConnect (LwM2mClientProfile profile) { | |
253 | 253 | return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") && |
254 | 254 | profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsBoolean(); |
255 | 255 | } |
... | ... | @@ -336,11 +336,11 @@ public class LwM2MTransportHandler { |
336 | 336 | return StringUtils.join(linkedListOut, ""); |
337 | 337 | } |
338 | 338 | |
339 | - public static <T> TransportServiceCallback<Void> getAckCallback(LwM2MClient lwM2MClient, int requestId, String typeTopic) { | |
339 | + public static <T> TransportServiceCallback<Void> getAckCallback(LwM2mClient lwM2MClient, int requestId, String typeTopic) { | |
340 | 340 | return new TransportServiceCallback<Void>() { |
341 | 341 | @Override |
342 | 342 | public void onSuccess(Void dummy) { |
343 | - log.trace("[{}] [{}] - requestId [{}] - EndPoint , Access AckCallback", typeTopic, requestId, lwM2MClient.getEndPoint()); | |
343 | + log.trace("[{}] [{}] - requestId [{}] - EndPoint , Access AckCallback", typeTopic, requestId, lwM2MClient.getEndpoint()); | |
344 | 344 | } |
345 | 345 | |
346 | 346 | @Override | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java
... | ... | @@ -48,9 +48,10 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; |
48 | 48 | import org.eclipse.leshan.server.californium.LeshanServer; |
49 | 49 | import org.eclipse.leshan.server.registration.Registration; |
50 | 50 | import org.springframework.beans.factory.annotation.Autowired; |
51 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
52 | 51 | import org.springframework.stereotype.Service; |
53 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; | |
52 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
53 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
54 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | |
54 | 55 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
55 | 56 | |
56 | 57 | import javax.annotation.PostConstruct; |
... | ... | @@ -63,40 +64,41 @@ import java.util.concurrent.Executors; |
63 | 64 | |
64 | 65 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.isSuccess; |
65 | 66 | import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD; |
66 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEFAULT_TIMEOUT; | |
67 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_DISCOVER; | |
68 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_OBSERVE; | |
69 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_READ; | |
70 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR; | |
71 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO; | |
72 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_EXECUTE; | |
73 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_OBSERVE_CANCEL; | |
74 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; | |
75 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; | |
76 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE; | |
77 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.RESPONSE_CHANNEL; | |
67 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT; | |
68 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_DISCOVER; | |
69 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_OBSERVE; | |
70 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_READ; | |
71 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | |
72 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | |
73 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE; | |
74 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_OBSERVE_CANCEL; | |
75 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; | |
76 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; | |
77 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE; | |
78 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL; | |
78 | 79 | |
79 | 80 | @Slf4j |
80 | -@Service("LwM2MTransportRequest") | |
81 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
82 | -public class LwM2MTransportRequest { | |
81 | +@Service("LwM2mTransportRequest") | |
82 | +@TbLwM2mTransportComponent | |
83 | +public class LwM2mTransportRequest { | |
83 | 84 | private ExecutorService executorResponse; |
84 | - private ExecutorService executorResponseError; | |
85 | + | |
85 | 86 | private LwM2mValueConverterImpl converter; |
86 | 87 | |
87 | 88 | @Autowired |
88 | - LwM2MTransportServiceImpl service; | |
89 | + private LwM2mTransportServiceImpl service; | |
90 | + | |
91 | + @Autowired | |
92 | + private LwM2mTransportContextServer context; | |
89 | 93 | |
90 | 94 | @Autowired |
91 | - public LwM2MTransportContextServer context; | |
95 | + private LwM2mClientContext lwM2mClientContext; | |
92 | 96 | |
93 | 97 | @PostConstruct |
94 | 98 | public void init() { |
95 | 99 | this.converter = LwM2mValueConverterImpl.getInstance(); |
96 | - executorResponse = Executors.newFixedThreadPool(this.context.getCtxServer().getRequestPoolSize(), | |
100 | + executorResponse = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRequestPoolSize(), | |
97 | 101 | new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); |
98 | - executorResponseError = Executors.newFixedThreadPool(this.context.getCtxServer().getRequestErrorPoolSize(), | |
99 | - new NamedThreadFactory(String.format("LwM2M %s channel response Error", RESPONSE_CHANNEL))); | |
100 | 102 | } |
101 | 103 | |
102 | 104 | public Collection<Registration> doGetRegistrations(LeshanServer lwServer) { |
... | ... | @@ -124,7 +126,7 @@ public class LwM2MTransportRequest { |
124 | 126 | if (registration != null && resultIds.getObjectId() >= 0) { |
125 | 127 | DownlinkRequest request = null; |
126 | 128 | ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; |
127 | - ResourceModel resource = service.context.getCtxServer().getResourceModel(registration, resultIds); | |
129 | + ResourceModel resource = service.context.getLwM2MTransportConfigServer().getResourceModel(registration, resultIds); | |
128 | 130 | timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; |
129 | 131 | switch (typeOper) { |
130 | 132 | case GET_TYPE_OPER_READ: |
... | ... | @@ -234,7 +236,7 @@ public class LwM2MTransportRequest { |
234 | 236 | |
235 | 237 | @SuppressWarnings("unchecked") |
236 | 238 | private void sendRequest(LeshanServer lwServer, Registration registration, DownlinkRequest request, long timeoutInMs) { |
237 | - LwM2MClient lwM2MClient = this.service.lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null); | |
239 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
238 | 240 | lwServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { |
239 | 241 | if (!lwM2MClient.isInit()) { |
240 | 242 | lwM2MClient.initValue(this.service, request.getPath().toString()); | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java
... | ... | @@ -22,15 +22,16 @@ import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; |
22 | 22 | import org.eclipse.leshan.core.util.Hex; |
23 | 23 | import org.eclipse.leshan.server.californium.LeshanServer; |
24 | 24 | import org.eclipse.leshan.server.californium.LeshanServerBuilder; |
25 | +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; | |
25 | 26 | import org.eclipse.leshan.server.model.LwM2mModelProvider; |
26 | 27 | import org.eclipse.leshan.server.model.VersionedModelProvider; |
27 | 28 | import org.eclipse.leshan.server.security.DefaultAuthorizer; |
29 | +import org.eclipse.leshan.server.security.EditableSecurityStore; | |
28 | 30 | import org.eclipse.leshan.server.security.SecurityChecker; |
29 | 31 | import org.springframework.beans.factory.annotation.Autowired; |
30 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
31 | 32 | import org.springframework.context.annotation.Bean; |
32 | 33 | import org.springframework.stereotype.Component; |
33 | -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore; | |
34 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
34 | 35 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
35 | 36 | |
36 | 37 | import java.math.BigInteger; |
... | ... | @@ -57,32 +58,35 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE |
57 | 58 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
58 | 59 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
59 | 60 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; |
60 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig; | |
61 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; | |
61 | 62 | |
62 | 63 | @Slf4j |
63 | 64 | @Component("LwM2MTransportServerConfiguration") |
64 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
65 | -public class LwM2MTransportServerConfiguration { | |
65 | +@TbLwM2mTransportComponent | |
66 | +public class LwM2mTransportServerConfiguration { | |
66 | 67 | private PublicKey publicKey; |
67 | 68 | private PrivateKey privateKey; |
68 | 69 | private boolean pskMode = false; |
69 | 70 | |
70 | 71 | @Autowired |
71 | - private LwM2MTransportContextServer context; | |
72 | + private LwM2mTransportContextServer context; | |
72 | 73 | |
73 | 74 | @Autowired |
74 | - private LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore; | |
75 | + private CaliforniumRegistrationStore registrationStore; | |
76 | + | |
77 | + @Autowired | |
78 | + private EditableSecurityStore securityStore; | |
75 | 79 | |
76 | 80 | @Bean |
77 | 81 | public LeshanServer getLeshanServer() { |
78 | 82 | log.info("Starting LwM2M transport Server... PostConstruct"); |
79 | - return this.getLhServer(this.context.getCtxServer().getServerPortNoSec(), this.context.getCtxServer().getServerPortSecurity()); | |
83 | + return this.getLhServer(this.context.getLwM2MTransportConfigServer().getServerPortNoSec(), this.context.getLwM2MTransportConfigServer().getServerPortSecurity()); | |
80 | 84 | } |
81 | 85 | |
82 | 86 | private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) { |
83 | 87 | LeshanServerBuilder builder = new LeshanServerBuilder(); |
84 | - builder.setLocalAddress(this.context.getCtxServer().getServerHost(), serverPortNoSec); | |
85 | - builder.setLocalSecureAddress(this.context.getCtxServer().getServerHostSecurity(), serverSecurePort); | |
88 | + builder.setLocalAddress(this.context.getLwM2MTransportConfigServer().getServerHost(), serverPortNoSec); | |
89 | + builder.setLocalSecureAddress(this.context.getLwM2MTransportConfigServer().getServerHostSecurity(), serverSecurePort); | |
86 | 90 | builder.setDecoder(new DefaultLwM2mNodeDecoder()); |
87 | 91 | /** Use a magic converter to support bad type send by the UI. */ |
88 | 92 | builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); |
... | ... | @@ -91,26 +95,26 @@ public class LwM2MTransportServerConfiguration { |
91 | 95 | builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); |
92 | 96 | |
93 | 97 | /** Define model provider (Create Models )*/ |
94 | - LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getCtxServer().getModelsValue()); | |
98 | + LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValue()); | |
95 | 99 | builder.setObjectModelProvider(modelProvider); |
96 | 100 | |
97 | 101 | /** Create credentials */ |
98 | 102 | this.setServerWithCredentials(builder); |
99 | 103 | |
100 | 104 | /** Set securityStore with new registrationStore */ |
101 | - builder.setSecurityStore(lwM2mInMemorySecurityStore); | |
105 | + builder.setSecurityStore(securityStore); | |
106 | + builder.setRegistrationStore(registrationStore); | |
102 | 107 | |
103 | 108 | |
104 | 109 | /** Create DTLS Config */ |
105 | 110 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); |
106 | - dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getCtxServer().isRecommendedSupportedGroups()); | |
107 | - dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getCtxServer().isRecommendedCiphers()); | |
111 | + dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups()); | |
112 | + dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers()); | |
108 | 113 | if (this.pskMode) { |
109 | 114 | dtlsConfig.setSupportedCipherSuites( |
110 | 115 | TLS_PSK_WITH_AES_128_CCM_8, |
111 | 116 | TLS_PSK_WITH_AES_128_CBC_SHA256); |
112 | - } | |
113 | - else { | |
117 | + } else { | |
114 | 118 | dtlsConfig.setSupportedCipherSuites( |
115 | 119 | TLS_PSK_WITH_AES_128_CCM_8, |
116 | 120 | TLS_PSK_WITH_AES_128_CBC_SHA256, |
... | ... | @@ -118,7 +122,6 @@ public class LwM2MTransportServerConfiguration { |
118 | 122 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256); |
119 | 123 | } |
120 | 124 | |
121 | - | |
122 | 125 | /** Set DTLS Config */ |
123 | 126 | builder.setDtlsConfig(dtlsConfig); |
124 | 127 | |
... | ... | @@ -128,9 +131,9 @@ public class LwM2MTransportServerConfiguration { |
128 | 131 | |
129 | 132 | private void setServerWithCredentials(LeshanServerBuilder builder) { |
130 | 133 | try { |
131 | - if (this.context.getCtxServer().getKeyStoreValue() != null) { | |
134 | + if (this.context.getLwM2MTransportConfigServer().getKeyStoreValue() != null) { | |
132 | 135 | if (this.setBuilderX509(builder)) { |
133 | - X509Certificate rootCAX509Cert = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getRootAlias()); | |
136 | + X509Certificate rootCAX509Cert = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getRootAlias()); | |
134 | 137 | if (rootCAX509Cert != null) { |
135 | 138 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
136 | 139 | trustedCertificates[0] = rootCAX509Cert; |
... | ... | @@ -140,7 +143,7 @@ public class LwM2MTransportServerConfiguration { |
140 | 143 | builder.setTrustedCertificates(new X509Certificate[0]); |
141 | 144 | } |
142 | 145 | /** Set securityStore with registrationStore*/ |
143 | - builder.setAuthorizer(new DefaultAuthorizer(lwM2mInMemorySecurityStore, new SecurityChecker() { | |
146 | + builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { | |
144 | 147 | @Override |
145 | 148 | protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, |
146 | 149 | String expectedX509CommonName) { |
... | ... | @@ -169,8 +172,8 @@ public class LwM2MTransportServerConfiguration { |
169 | 172 | * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks |
170 | 173 | */ |
171 | 174 | try { |
172 | - X509Certificate serverCertificate = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getServerAlias()); | |
173 | - PrivateKey privateKey = (PrivateKey) this.context.getCtxServer().getKeyStoreValue().getKey(this.context.getCtxServer().getServerAlias(), this.context.getCtxServer().getKeyStorePasswordServer() == null ? null : this.context.getCtxServer().getKeyStorePasswordServer().toCharArray()); | |
175 | + X509Certificate serverCertificate = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getServerAlias()); | |
176 | + PrivateKey privateKey = (PrivateKey) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.context.getLwM2MTransportConfigServer().getServerAlias(), this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray()); | |
174 | 177 | PublicKey publicKey = serverCertificate.getPublicKey(); |
175 | 178 | if (serverCertificate != null && |
176 | 179 | privateKey != null && privateKey.getEncoded().length > 0 && |
... | ... | @@ -203,8 +206,8 @@ public class LwM2MTransportServerConfiguration { |
203 | 206 | private void infoPramsUri(String mode) { |
204 | 207 | log.info("Server uses [{}]: serverNoSecureURI : [{}], serverSecureURI : [{}]", |
205 | 208 | mode, |
206 | - this.context.getCtxServer().getServerHost() + ":" + this.context.getCtxServer().getServerPortNoSec(), | |
207 | - this.context.getCtxServer().getServerHostSecurity() + ":" + this.context.getCtxServer().getServerPortSecurity()); | |
209 | + this.context.getLwM2MTransportConfigServer().getServerHost() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortNoSec(), | |
210 | + this.context.getLwM2MTransportConfigServer().getServerHostSecurity() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortSecurity()); | |
208 | 211 | } |
209 | 212 | |
210 | 213 | private boolean setServerRPK(LeshanServerBuilder builder) { |
... | ... | @@ -234,27 +237,27 @@ public class LwM2MTransportServerConfiguration { |
234 | 237 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
235 | 238 | algoParameters.init(new ECGenParameterSpec("secp256r1")); |
236 | 239 | ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); |
237 | - if (this.context.getCtxServer().getServerPublicX() != null && | |
238 | - !this.context.getCtxServer().getServerPublicX().isEmpty() && | |
239 | - this.context.getCtxServer().getServerPublicY() != null && | |
240 | - !this.context.getCtxServer().getServerPublicY().isEmpty()) { | |
240 | + if (this.context.getLwM2MTransportConfigServer().getServerPublicX() != null && | |
241 | + !this.context.getLwM2MTransportConfigServer().getServerPublicX().isEmpty() && | |
242 | + this.context.getLwM2MTransportConfigServer().getServerPublicY() != null && | |
243 | + !this.context.getLwM2MTransportConfigServer().getServerPublicY().isEmpty()) { | |
241 | 244 | /** Get point values */ |
242 | - byte[] publicX = Hex.decodeHex(this.context.getCtxServer().getServerPublicX().toCharArray()); | |
243 | - byte[] publicY = Hex.decodeHex(this.context.getCtxServer().getServerPublicY().toCharArray()); | |
245 | + byte[] publicX = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicX().toCharArray()); | |
246 | + byte[] publicY = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicY().toCharArray()); | |
244 | 247 | /** Create key specs */ |
245 | 248 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
246 | 249 | parameterSpec); |
247 | 250 | /** Get keys */ |
248 | 251 | this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); |
249 | 252 | } |
250 | - if (this.context.getCtxServer().getServerPrivateEncoded() != null && | |
251 | - !this.context.getCtxServer().getServerPrivateEncoded().isEmpty()) { | |
253 | + if (this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded() != null && | |
254 | + !this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().isEmpty()) { | |
252 | 255 | /** Get private key */ |
253 | - byte[] privateS = Hex.decodeHex(this.context.getCtxServer().getServerPrivateEncoded().toCharArray()); | |
256 | + byte[] privateS = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().toCharArray()); | |
254 | 257 | try { |
255 | 258 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); |
256 | 259 | } catch (InvalidKeySpecException ignore2) { |
257 | - log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.context.getCtxServer().getServerPrivateEncoded()); | |
260 | + log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded()); | |
258 | 261 | } |
259 | 262 | } |
260 | 263 | } | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerInitializer.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java
... | ... | @@ -18,8 +18,8 @@ package org.thingsboard.server.transport.lwm2m.server; |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.leshan.server.californium.LeshanServer; |
20 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
21 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
22 | 21 | import org.springframework.stereotype.Component; |
22 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
23 | 23 | import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; |
24 | 24 | |
25 | 25 | import javax.annotation.PostConstruct; |
... | ... | @@ -27,21 +27,21 @@ import javax.annotation.PreDestroy; |
27 | 27 | |
28 | 28 | @Slf4j |
29 | 29 | @Component("LwM2MTransportServerInitializer") |
30 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
31 | -public class LwM2MTransportServerInitializer { | |
30 | +@TbLwM2mTransportComponent | |
31 | +public class LwM2mTransportServerInitializer { | |
32 | 32 | |
33 | 33 | @Autowired |
34 | - private LwM2MTransportServiceImpl service; | |
34 | + private LwM2mTransportServiceImpl service; | |
35 | 35 | |
36 | 36 | @Autowired(required = false) |
37 | 37 | private LeshanServer leshanServer; |
38 | 38 | |
39 | 39 | @Autowired |
40 | - private LwM2MTransportContextServer context; | |
40 | + private LwM2mTransportContextServer context; | |
41 | 41 | |
42 | 42 | @PostConstruct |
43 | 43 | public void init() { |
44 | - if (this.context.getCtxServer().getEnableGenNewKeyPskRpk()) { | |
44 | + if (this.context.getLwM2MTransportConfigServer().getEnableGenNewKeyPskRpk()) { | |
45 | 45 | new LWM2MGenerationPSkRPkECC(); |
46 | 46 | } |
47 | 47 | this.startLhServer(); | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java
... | ... | @@ -26,7 +26,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; |
26 | 26 | import java.util.Collection; |
27 | 27 | import java.util.Optional; |
28 | 28 | |
29 | -public interface LwM2MTransportService { | |
29 | +public interface LwM2mTransportService { | |
30 | 30 | |
31 | 31 | void onRegistered(LeshanServer lwServer, Registration registration, Collection<Observation> previousObsersations); |
32 | 32 | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServiceImpl.java
... | ... | @@ -36,7 +36,6 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; |
36 | 36 | import org.eclipse.leshan.server.californium.LeshanServer; |
37 | 37 | import org.eclipse.leshan.server.registration.Registration; |
38 | 38 | import org.springframework.beans.factory.annotation.Autowired; |
39 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
40 | 39 | import org.springframework.stereotype.Service; |
41 | 40 | import org.thingsboard.server.common.data.Device; |
42 | 41 | import org.thingsboard.server.common.data.DeviceProfile; |
... | ... | @@ -48,11 +47,12 @@ import org.thingsboard.server.gen.transport.TransportProtos; |
48 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
49 | 48 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; |
50 | 49 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
51 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; | |
52 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile; | |
50 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
51 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
52 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | |
53 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | |
53 | 54 | import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; |
54 | 55 | import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; |
55 | -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore; | |
56 | 56 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
57 | 57 | |
58 | 58 | import javax.annotation.PostConstruct; |
... | ... | @@ -79,24 +79,24 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; |
79 | 79 | import java.util.stream.Collectors; |
80 | 80 | |
81 | 81 | import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject; |
82 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.CLIENT_NOT_AUTHORIZED; | |
83 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_ATTRIBUTES_REQUEST; | |
84 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_ATTRIBUTES_TOPIC; | |
85 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC; | |
86 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_OBSERVE; | |
87 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_READ; | |
88 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR; | |
89 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO; | |
90 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_TELEMETRY; | |
91 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_EXECUTE; | |
92 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; | |
93 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.SERVICE_CHANNEL; | |
94 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getAckCallback; | |
82 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED; | |
83 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST; | |
84 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC; | |
85 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC; | |
86 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_OBSERVE; | |
87 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_READ; | |
88 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | |
89 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | |
90 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; | |
91 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE; | |
92 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; | |
93 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL; | |
94 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback; | |
95 | 95 | |
96 | 96 | @Slf4j |
97 | -@Service("LwM2MTransportService") | |
98 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
99 | -public class LwM2MTransportServiceImpl implements LwM2MTransportService { | |
97 | +@Service | |
98 | +@TbLwM2mTransportComponent | |
99 | +public class LwM2mTransportServiceImpl implements LwM2mTransportService { | |
100 | 100 | |
101 | 101 | private ExecutorService executorRegistered; |
102 | 102 | private ExecutorService executorUpdateRegistered; |
... | ... | @@ -105,27 +105,29 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
105 | 105 | protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); |
106 | 106 | protected final Lock writeLock = readWriteLock.writeLock(); |
107 | 107 | |
108 | - | |
109 | 108 | @Autowired |
110 | 109 | private TransportService transportService; |
111 | 110 | |
112 | 111 | @Autowired |
113 | - public LwM2MTransportContextServer context; | |
112 | + public LwM2mTransportContextServer context; | |
114 | 113 | |
115 | 114 | @Autowired |
116 | - private LwM2MTransportRequest lwM2MTransportRequest; | |
115 | + private LwM2mTransportRequest lwM2mTransportRequest; | |
117 | 116 | |
118 | 117 | @Autowired |
119 | - LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore; | |
118 | + private LwM2mClientContext lwM2mClientContext; | |
119 | + | |
120 | + @Autowired(required = false) | |
121 | + private LeshanServer leshanServer; | |
120 | 122 | |
121 | 123 | @PostConstruct |
122 | 124 | public void init() { |
123 | - this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getCtxServer().getSessionReportTimeout()), context.getCtxServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS); | |
124 | - this.executorRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getRegisteredPoolSize(), | |
125 | + this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getLwM2MTransportConfigServer().getSessionReportTimeout()), context.getLwM2MTransportConfigServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS); | |
126 | + this.executorRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRegisteredPoolSize(), | |
125 | 127 | new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL))); |
126 | - this.executorUpdateRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getUpdateRegisteredPoolSize(), | |
128 | + this.executorUpdateRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getUpdateRegisteredPoolSize(), | |
127 | 129 | new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL))); |
128 | - this.executorUnRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getUnRegisteredPoolSize(), | |
130 | + this.executorUnRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getUnRegisteredPoolSize(), | |
129 | 131 | new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL))); |
130 | 132 | this.converter = LwM2mValueConverterImpl.getInstance(); |
131 | 133 | } |
... | ... | @@ -149,17 +151,16 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
149 | 151 | executorRegistered.submit(() -> { |
150 | 152 | try { |
151 | 153 | log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); |
152 | - LwM2MClient lwM2MClient = this.lwM2mInMemorySecurityStore.updateInSessionsLwM2MClient(lwServer, registration); | |
154 | + LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration); | |
153 | 155 | if (lwM2MClient != null) { |
154 | - lwM2MClient.setLwM2MTransportServiceImpl(this); | |
155 | 156 | this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client Registered", registration); |
156 | 157 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); |
157 | 158 | if (sessionInfo != null) { |
158 | - lwM2MClient.setDeviceUuid(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | |
159 | - lwM2MClient.setProfileUuid(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
159 | + lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | |
160 | + lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
160 | 161 | lwM2MClient.setDeviceName(sessionInfo.getDeviceName()); |
161 | 162 | lwM2MClient.setDeviceProfileName(sessionInfo.getDeviceType()); |
162 | - transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo)); | |
163 | + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); | |
163 | 164 | transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); |
164 | 165 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); |
165 | 166 | this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration); |
... | ... | @@ -221,8 +222,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
221 | 222 | if (sessionInfo != null) { |
222 | 223 | transportService.deregisterSession(sessionInfo); |
223 | 224 | this.doCloseSession(sessionInfo); |
224 | - lwM2mInMemorySecurityStore.delRemoveSessionAndListener(registration.getId()); | |
225 | - if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) { | |
225 | + lwM2mClientContext.delRemoveSessionAndListener(registration.getId()); | |
226 | + if (lwM2mClientContext.getProfiles().size() > 0) { | |
226 | 227 | this.syncSessionsAndProfiles(); |
227 | 228 | } |
228 | 229 | log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType()); |
... | ... | @@ -292,13 +293,13 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
292 | 293 | el.getAsJsonObject().entrySet().forEach(de -> { |
293 | 294 | String path = this.getPathAttributeUpdate(sessionInfo, de.getKey()); |
294 | 295 | String value = de.getValue().getAsString(); |
295 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue(); | |
296 | - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
297 | - ResourceModel resourceModel = context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path)); | |
296 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); | |
297 | + LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
298 | + ResourceModel resourceModel = context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path)); | |
298 | 299 | if (!path.isEmpty() && (this.validatePathInAttrProfile(profile, path) || this.validatePathInTelemetryProfile(profile, path))) { |
299 | 300 | if (resourceModel != null && resourceModel.operations.isWritable()) { |
300 | - lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, | |
301 | - ContentFormat.TLV.getName(), null, value, this.context.getCtxServer().getTimeout()); | |
301 | + lwM2mTransportRequest.sendAllRequest(leshanServer, lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, | |
302 | + ContentFormat.TLV.getName(), null, value, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
302 | 303 | } else { |
303 | 304 | log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); |
304 | 305 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", |
... | ... | @@ -323,9 +324,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
323 | 324 | */ |
324 | 325 | @Override |
325 | 326 | public void onDeviceProfileUpdate(SessionInfoProto sessionInfo, DeviceProfile deviceProfile) { |
326 | - Set<String> registrationIds = lwM2mInMemorySecurityStore.getSessions().entrySet() | |
327 | + Set<String> registrationIds = lwM2mClientContext.getLwM2mClients().entrySet() | |
327 | 328 | .stream() |
328 | - .filter(e -> e.getValue().getProfileUuid().equals(deviceProfile.getUuidId())) | |
329 | + .filter(e -> e.getValue().getProfileId().equals(deviceProfile.getUuidId())) | |
329 | 330 | .map(Map.Entry::getKey).sorted().collect(Collectors.toCollection(LinkedHashSet::new)); |
330 | 331 | if (registrationIds.size() > 0) { |
331 | 332 | this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile); |
... | ... | @@ -339,8 +340,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
339 | 340 | */ |
340 | 341 | @Override |
341 | 342 | public void onDeviceUpdate(SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) { |
342 | - Optional<String> registrationIdOpt = lwM2mInMemorySecurityStore.getSessions().entrySet().stream() | |
343 | - .filter(e -> device.getUuidId().equals(e.getValue().getDeviceUuid())) | |
343 | + Optional<String> registrationIdOpt = lwM2mClientContext.getLwM2mClients().entrySet().stream() | |
344 | + .filter(e -> device.getUuidId().equals(e.getValue().getDeviceId())) | |
344 | 345 | .map(Map.Entry::getKey) |
345 | 346 | .findFirst(); |
346 | 347 | registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt)); |
... | ... | @@ -353,8 +354,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
353 | 354 | */ |
354 | 355 | @Override |
355 | 356 | public void doTrigger(LeshanServer lwServer, Registration registration, String path) { |
356 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_EXECUTE, | |
357 | - ContentFormat.TLV.getName(), null, null, this.context.getCtxServer().getTimeout()); | |
357 | + lwM2mTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_EXECUTE, | |
358 | + ContentFormat.TLV.getName(), null, null, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
358 | 359 | } |
359 | 360 | |
360 | 361 | /** |
... | ... | @@ -397,18 +398,18 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
397 | 398 | * Removes a profile if not used in sessions |
398 | 399 | */ |
399 | 400 | private void syncSessionsAndProfiles() { |
400 | - Map<UUID, LwM2MClientProfile> profilesClone = lwM2mInMemorySecurityStore.getProfiles().entrySet() | |
401 | + Map<UUID, LwM2mClientProfile> profilesClone = lwM2mClientContext.getProfiles().entrySet() | |
401 | 402 | .stream() |
402 | 403 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
403 | 404 | profilesClone.forEach((k, v) -> { |
404 | - String registrationId = lwM2mInMemorySecurityStore.getSessions().entrySet() | |
405 | + String registrationId = lwM2mClientContext.getLwM2mClients().entrySet() | |
405 | 406 | .stream() |
406 | - .filter(e -> e.getValue().getProfileUuid().equals(k)) | |
407 | + .filter(e -> e.getValue().getProfileId().equals(k)) | |
407 | 408 | .findFirst() |
408 | 409 | .map(Map.Entry::getKey) // return the key of the matching entry if found |
409 | 410 | .orElse(""); |
410 | 411 | if (registrationId.isEmpty()) { |
411 | - lwM2mInMemorySecurityStore.getProfiles().remove(k); | |
412 | + lwM2mClientContext.getProfiles().remove(k); | |
412 | 413 | } |
413 | 414 | }); |
414 | 415 | } |
... | ... | @@ -458,12 +459,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
458 | 459 | * @param registration - Registration LwM2M Client |
459 | 460 | * @param lwM2MClient - object with All parameters off client |
460 | 461 | */ |
461 | - private void initLwM2mFromClientValue(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) { | |
462 | - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId()); | |
462 | + private void initLwM2mFromClientValue(LeshanServer lwServer, Registration registration, LwM2mClient lwM2MClient) { | |
463 | + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | |
463 | 464 | Set<String> clientObjects = this.getAllOjectsInClient(registration); |
464 | - if (clientObjects != null && !LwM2MTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
465 | + if (clientObjects != null && !LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
465 | 466 | // #2 |
466 | - if (!LwM2MTransportHandler.getClientUpdateValueAfterConnect(lwM2MClientProfile)) { | |
467 | + if (!LwM2mTransportHandler.getClientUpdateValueAfterConnect(lwM2MClientProfile)) { | |
467 | 468 | this.initReadAttrTelemetryObserveToClient(lwServer, registration, lwM2MClient, GET_TYPE_OPER_READ); |
468 | 469 | |
469 | 470 | } |
... | ... | @@ -471,8 +472,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
471 | 472 | else { |
472 | 473 | lwM2MClient.getPendingRequests().addAll(clientObjects); |
473 | 474 | clientObjects.forEach(path -> { |
474 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), | |
475 | - null, null, this.context.getCtxServer().getTimeout()); | |
475 | + lwM2mTransportRequest.sendAllRequest(lwServer, registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), | |
476 | + null, null, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
476 | 477 | }); |
477 | 478 | } |
478 | 479 | } |
... | ... | @@ -517,7 +518,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
517 | 518 | * @param path - resource |
518 | 519 | */ |
519 | 520 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { |
520 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null); | |
521 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
521 | 522 | lwM2MClient.updateResourceValue(path, lwM2mResource); |
522 | 523 | Set<String> paths = new HashSet<>(); |
523 | 524 | paths.add(path); |
... | ... | @@ -565,8 +566,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
565 | 566 | * @param path - |
566 | 567 | * @return true if path isPresent in postAttributeProfile |
567 | 568 | */ |
568 | - private boolean validatePathInAttrProfile(LwM2MClientProfile profile, String path) { | |
569 | - Set<String> attributesSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>(){}.getType()); | |
569 | + private boolean validatePathInAttrProfile(LwM2mClientProfile profile, String path) { | |
570 | + Set<String> attributesSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>() { | |
571 | + }.getType()); | |
570 | 572 | return attributesSet.stream().filter(p -> p.equals(path)).findFirst().isPresent(); |
571 | 573 | } |
572 | 574 | |
... | ... | @@ -575,8 +577,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
575 | 577 | * @param path - |
576 | 578 | * @return true if path isPresent in postAttributeProfile |
577 | 579 | */ |
578 | - private boolean validatePathInTelemetryProfile(LwM2MClientProfile profile, String path) { | |
579 | - Set<String> telemetriesSet = new Gson().fromJson(profile.getPostTelemetryProfile(), new TypeToken<>(){}.getType()); | |
580 | + private boolean validatePathInTelemetryProfile(LwM2mClientProfile profile, String path) { | |
581 | + Set<String> telemetriesSet = new Gson().fromJson(profile.getPostTelemetryProfile(), new TypeToken<>() { | |
582 | + }.getType()); | |
580 | 583 | return telemetriesSet.stream().filter(p -> p.equals(path)).findFirst().isPresent(); |
581 | 584 | } |
582 | 585 | |
... | ... | @@ -588,16 +591,19 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
588 | 591 | * @param lwServer - |
589 | 592 | * @param registration - |
590 | 593 | */ |
591 | - private void initReadAttrTelemetryObserveToClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, String typeOper) { | |
594 | + private void initReadAttrTelemetryObserveToClient(LeshanServer lwServer, Registration registration, LwM2mClient lwM2MClient, String typeOper) { | |
592 | 595 | try { |
593 | - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId()); | |
596 | + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | |
594 | 597 | Set<String> clientInstances = this.getAllInstancesInClient(registration); |
595 | 598 | Set<String> result; |
596 | 599 | if (GET_TYPE_OPER_READ.equals(typeOper)) { |
597 | - result = new ObjectMapper().readValue(lwM2MClientProfile.getPostAttributeProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {}); | |
598 | - result.addAll(new ObjectMapper().readValue(lwM2MClientProfile.getPostTelemetryProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {})); | |
600 | + result = new ObjectMapper().readValue(lwM2MClientProfile.getPostAttributeProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() { | |
601 | + }); | |
602 | + result.addAll(new ObjectMapper().readValue(lwM2MClientProfile.getPostTelemetryProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() { | |
603 | + })); | |
599 | 604 | } else { |
600 | - result = new ObjectMapper().readValue(lwM2MClientProfile.getPostObserveProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {}); | |
605 | + result = new ObjectMapper().readValue(lwM2MClientProfile.getPostObserveProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() { | |
606 | + }); | |
601 | 607 | } |
602 | 608 | Set<String> pathSent = ConcurrentHashMap.newKeySet(); |
603 | 609 | result.forEach(p -> { |
... | ... | @@ -611,8 +617,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
611 | 617 | }); |
612 | 618 | lwM2MClient.getPendingRequests().addAll(pathSent); |
613 | 619 | pathSent.forEach(target -> { |
614 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(), | |
615 | - null, null, this.context.getCtxServer().getTimeout()); | |
620 | + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(), | |
621 | + null, null, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
616 | 622 | }); |
617 | 623 | if (GET_TYPE_OPER_OBSERVE.equals(typeOper)) { |
618 | 624 | lwM2MClient.initValue(this, null); |
... | ... | @@ -630,15 +636,15 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
630 | 636 | * @param device - |
631 | 637 | */ |
632 | 638 | private void onDeviceUpdateLwM2MClient(String registrationId, Device device, Optional<DeviceProfile> deviceProfileOpt) { |
633 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registrationId); | |
639 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClients().get(registrationId); | |
634 | 640 | lwM2MClient.setDeviceName(device.getName()); |
635 | - if (!lwM2MClient.getProfileUuid().equals(device.getDeviceProfileId().getId())) { | |
641 | + if (!lwM2MClient.getProfileId().equals(device.getDeviceProfileId().getId())) { | |
636 | 642 | Set<String> registrationIds = new HashSet<>(); |
637 | 643 | registrationIds.add(registrationId); |
638 | 644 | deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile)); |
639 | 645 | } |
640 | 646 | |
641 | - lwM2MClient.setProfileUuid(device.getDeviceProfileId().getId()); | |
647 | + lwM2MClient.setProfileId(device.getDeviceProfileId().getId()); | |
642 | 648 | } |
643 | 649 | |
644 | 650 | /** |
... | ... | @@ -693,20 +699,20 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
693 | 699 | * @param path |
694 | 700 | */ |
695 | 701 | private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) { |
696 | - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId()); | |
702 | + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | |
697 | 703 | lwM2MClientProfile.getPostAttributeProfile().forEach(p -> { |
698 | - LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); | |
704 | + LwM2mPath pathIds = new LwM2mPath(p.getAsString()); | |
699 | 705 | if (pathIds.isResource()) { |
700 | 706 | if (path == null || path.contains(p.getAsString())) { |
701 | - this.addParameters(p.getAsString().toString(), attributes, registration); | |
707 | + this.addParameters(p.getAsString(), attributes, registration); | |
702 | 708 | } |
703 | 709 | } |
704 | 710 | }); |
705 | 711 | lwM2MClientProfile.getPostTelemetryProfile().forEach(p -> { |
706 | - LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); | |
712 | + LwM2mPath pathIds = new LwM2mPath(p.getAsString()); | |
707 | 713 | if (pathIds.isResource()) { |
708 | 714 | if (path == null || path.contains(p.getAsString())) { |
709 | - this.addParameters(p.getAsString().toString(), telemetry, registration); | |
715 | + this.addParameters(p.getAsString(), telemetry, registration); | |
710 | 716 | } |
711 | 717 | } |
712 | 718 | }); |
... | ... | @@ -717,8 +723,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
717 | 723 | * @param registration - Registration LwM2M Client |
718 | 724 | */ |
719 | 725 | private void addParameters(String path, JsonObject parameters, Registration registration) { |
720 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()); | |
721 | - JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2MClient.getProfileUuid()).getPostKeyNameProfile(); | |
726 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
727 | + JsonObject names = lwM2mClientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile(); | |
722 | 728 | String resName = String.valueOf(names.get(path)); |
723 | 729 | if (resName != null && !resName.isEmpty()) { |
724 | 730 | try { |
... | ... | @@ -727,7 +733,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
727 | 733 | parameters.addProperty(resName, resValue); |
728 | 734 | } |
729 | 735 | } catch (Exception e) { |
730 | - log.error(e.getStackTrace().toString()); | |
736 | + log.error("Failed to add parameters.", e); | |
731 | 737 | } |
732 | 738 | } |
733 | 739 | } |
... | ... | @@ -736,11 +742,11 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
736 | 742 | * @param path - path resource |
737 | 743 | * @return - value of Resource or null |
738 | 744 | */ |
739 | - private String getResourceValueToString(LwM2MClient lwM2MClient, String path) { | |
745 | + private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { | |
740 | 746 | LwM2mPath pathIds = new LwM2mPath(path); |
741 | 747 | ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, pathIds); |
742 | - return (resourceValue == null) ? null : | |
743 | - (String) this.converter.convertValue(resourceValue.getResourceValue(), this.context.getCtxServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds); | |
748 | + return resourceValue == null ? null : | |
749 | + this.converter.convertValue(resourceValue.getResourceValue(), this.context.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString(); | |
744 | 750 | } |
745 | 751 | |
746 | 752 | /** |
... | ... | @@ -749,7 +755,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
749 | 755 | * @param pathIds - |
750 | 756 | * @return - return value of Resource by idPath |
751 | 757 | */ |
752 | - private ResourceValue returnResourceValueFromLwM2MClient(LwM2MClient lwM2MClient, LwM2mPath pathIds) { | |
758 | + private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, LwM2mPath pathIds) { | |
753 | 759 | ResourceValue resourceValue = null; |
754 | 760 | if (pathIds.isResource()) { |
755 | 761 | resourceValue = lwM2MClient.getResources().get(pathIds.toString()); |
... | ... | @@ -790,23 +796,25 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
790 | 796 | * @param deviceProfile - |
791 | 797 | */ |
792 | 798 | private void onDeviceUpdateChangeProfile(Set<String> registrationIds, DeviceProfile deviceProfile) { |
793 | - | |
794 | - LwM2MClientProfile lwM2MClientProfileOld = lwM2mInMemorySecurityStore.getProfiles().get(deviceProfile.getUuidId()); | |
795 | - if (lwM2mInMemorySecurityStore.addUpdateProfileParameters(deviceProfile)) { | |
796 | - | |
799 | + LwM2mClientProfile lwM2MClientProfileOld = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId()); | |
800 | + if (lwM2mClientContext.addUpdateProfileParameters(deviceProfile)) { | |
797 | 801 | // #1 |
798 | 802 | JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile(); |
799 | - Set<String> attributeSetOld = new Gson().fromJson(attributeOld, new TypeToken<>(){}.getType()); | |
803 | + Set<String> attributeSetOld = new Gson().fromJson(attributeOld, new TypeToken<>() { | |
804 | + }.getType()); | |
800 | 805 | JsonArray telemetryOld = lwM2MClientProfileOld.getPostTelemetryProfile(); |
801 | - Set<String> telemetrySetOld = new Gson().fromJson(telemetryOld, new TypeToken<>(){}.getType()); | |
806 | + Set<String> telemetrySetOld = new Gson().fromJson(telemetryOld, new TypeToken<>() { | |
807 | + }.getType()); | |
802 | 808 | JsonArray observeOld = lwM2MClientProfileOld.getPostObserveProfile(); |
803 | 809 | JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile(); |
804 | 810 | |
805 | - LwM2MClientProfile lwM2MClientProfileNew = lwM2mInMemorySecurityStore.getProfiles().get(deviceProfile.getUuidId()); | |
811 | + LwM2mClientProfile lwM2MClientProfileNew = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId()); | |
806 | 812 | JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile(); |
807 | - Set<String> attributeSetNew = new Gson().fromJson(attributeNew, new TypeToken<>(){}.getType()); | |
813 | + Set<String> attributeSetNew = new Gson().fromJson(attributeNew, new TypeToken<>() { | |
814 | + }.getType()); | |
808 | 815 | JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile(); |
809 | - Set<String> telemetrySetNew = new Gson().fromJson(telemetryNew, new TypeToken<>(){}.getType()); | |
816 | + Set<String> telemetrySetNew = new Gson().fromJson(telemetryNew, new TypeToken<>() { | |
817 | + }.getType()); | |
810 | 818 | JsonArray observeNew = lwM2MClientProfileNew.getPostObserveProfile(); |
811 | 819 | JsonObject keyNameNew = lwM2MClientProfileNew.getPostKeyNameProfile(); |
812 | 820 | |
... | ... | @@ -814,20 +822,24 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
814 | 822 | ResultsAnalyzerParameters sentAttrToThingsboard = new ResultsAnalyzerParameters(); |
815 | 823 | // #3.1 |
816 | 824 | if (!attributeOld.equals(attributeNew)) { |
817 | - ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld, new TypeToken<Set<String>>(){}.getType()), attributeSetNew); | |
825 | + ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld, new TypeToken<Set<String>>() { | |
826 | + }.getType()), attributeSetNew); | |
818 | 827 | sentAttrToThingsboard.getPathPostParametersAdd().addAll(postAttributeAnalyzer.getPathPostParametersAdd()); |
819 | 828 | sentAttrToThingsboard.getPathPostParametersDel().addAll(postAttributeAnalyzer.getPathPostParametersDel()); |
820 | 829 | } |
821 | 830 | // #3.2 |
822 | - if (!attributeOld.equals(attributeNew)) { | |
823 | - ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld, new TypeToken<Set<String>>(){}.getType()), telemetrySetNew); | |
831 | + if (!telemetryOld.equals(telemetryNew)) { | |
832 | + ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld, new TypeToken<Set<String>>() { | |
833 | + }.getType()), telemetrySetNew); | |
824 | 834 | sentAttrToThingsboard.getPathPostParametersAdd().addAll(postTelemetryAnalyzer.getPathPostParametersAdd()); |
825 | 835 | sentAttrToThingsboard.getPathPostParametersDel().addAll(postTelemetryAnalyzer.getPathPostParametersDel()); |
826 | 836 | } |
827 | 837 | // #3.3 |
828 | 838 | if (!keyNameOld.equals(keyNameNew)) { |
829 | - ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType()), | |
830 | - new Gson().fromJson(keyNameNew.toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType())); | |
839 | + ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(), new TypeToken<ConcurrentHashMap<String, String>>() { | |
840 | + }.getType()), | |
841 | + new Gson().fromJson(keyNameNew.toString(), new TypeToken<ConcurrentHashMap<String, String>>() { | |
842 | + }.getType())); | |
831 | 843 | sentAttrToThingsboard.getPathPostParametersAdd().addAll(keyNameChange.getPathPostParametersAdd()); |
832 | 844 | } |
833 | 845 | |
... | ... | @@ -835,9 +847,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
835 | 847 | if (sentAttrToThingsboard.getPathPostParametersAdd().size() > 0) { |
836 | 848 | // update value in Resources |
837 | 849 | registrationIds.forEach(registrationId -> { |
838 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(null, registrationId); | |
839 | - LeshanServer lwServer = lwM2MClient.getLwServer(); | |
840 | - Registration registration = lwM2mInMemorySecurityStore.getByRegistration(registrationId); | |
850 | + LeshanServer lwServer = leshanServer; | |
851 | + Registration registration = lwM2mClientContext.getRegistration(registrationId); | |
841 | 852 | this.readResourceValueObserve(lwServer, registration, sentAttrToThingsboard.getPathPostParametersAdd(), GET_TYPE_OPER_READ); |
842 | 853 | // sent attr/telemetry to tingsboard for new path |
843 | 854 | this.updateAttrTelemetry(registration, false, sentAttrToThingsboard.getPathPostParametersAdd()); |
... | ... | @@ -851,8 +862,10 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
851 | 862 | |
852 | 863 | // #5.1 |
853 | 864 | if (!observeOld.equals(observeNew)) { |
854 | - Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>(){}.getType()); | |
855 | - Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>(){}.getType()); | |
865 | + Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() { | |
866 | + }.getType()); | |
867 | + Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() { | |
868 | + }.getType()); | |
856 | 869 | //#5.2 add |
857 | 870 | // path Attr/Telemetry includes newObserve |
858 | 871 | attributeSetOld.addAll(telemetrySetOld); |
... | ... | @@ -863,9 +876,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
863 | 876 | ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sentObserveToClientOld.getPathPostParametersAdd(), sentObserveToClientNew.getPathPostParametersAdd()); |
864 | 877 | // sent Request observe to Client |
865 | 878 | registrationIds.forEach(registrationId -> { |
866 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(null, registrationId); | |
867 | - LeshanServer lwServer = lwM2MClient.getLwServer(); | |
868 | - Registration registration = lwM2mInMemorySecurityStore.getByRegistration(registrationId); | |
879 | + LeshanServer lwServer = leshanServer; | |
880 | + Registration registration = lwM2mClientContext.getRegistration(registrationId); | |
869 | 881 | this.readResourceValueObserve(lwServer, registration, postObserveAnalyzer.getPathPostParametersAdd(), GET_TYPE_OPER_OBSERVE); |
870 | 882 | // 5.3 del |
871 | 883 | // sent Request cancel observe to Client |
... | ... | @@ -914,11 +926,11 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
914 | 926 | LwM2mPath pathIds = new LwM2mPath(target); |
915 | 927 | if (pathIds.isResource()) { |
916 | 928 | if (GET_TYPE_OPER_READ.equals(typeOper)) { |
917 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, | |
918 | - ContentFormat.TLV.getName(), null, null, this.context.getCtxServer().getTimeout()); | |
929 | + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, | |
930 | + ContentFormat.TLV.getName(), null, null, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
919 | 931 | } else if (GET_TYPE_OPER_OBSERVE.equals(typeOper)) { |
920 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, | |
921 | - null, null, null, this.context.getCtxServer().getTimeout()); | |
932 | + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, | |
933 | + null, null, null, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
922 | 934 | } |
923 | 935 | } |
924 | 936 | }); |
... | ... | @@ -935,7 +947,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
935 | 947 | } |
936 | 948 | |
937 | 949 | private void cancelObserveIsValue(LeshanServer lwServer, Registration registration, Set<String> paramAnallyzer) { |
938 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null); | |
950 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
939 | 951 | paramAnallyzer.forEach(p -> { |
940 | 952 | if (this.returnResourceValueFromLwM2MClient(lwM2MClient, new LwM2mPath(p)) != null) { |
941 | 953 | this.setCancelObservationRecourse(lwServer, registration, p); |
... | ... | @@ -944,10 +956,10 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
944 | 956 | ); |
945 | 957 | } |
946 | 958 | |
947 | - private void putDelayedUpdateResourcesClient(LwM2MClient lwM2MClient, Object valueOld, Object valueNew, String path) { | |
959 | + private void putDelayedUpdateResourcesClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) { | |
948 | 960 | if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { |
949 | - lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, | |
950 | - ContentFormat.TLV.getName(), null, valueNew, this.context.getCtxServer().getTimeout()); | |
961 | + lwM2mTransportRequest.sendAllRequest(leshanServer, lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, | |
962 | + ContentFormat.TLV.getName(), null, valueNew, this.context.getLwM2MTransportConfigServer().getTimeout()); | |
951 | 963 | } else { |
952 | 964 | log.error("05 delayError"); |
953 | 965 | } |
... | ... | @@ -982,7 +994,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
982 | 994 | * @return - |
983 | 995 | */ |
984 | 996 | private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { |
985 | - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
997 | + LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
986 | 998 | return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() |
987 | 999 | .filter(e -> e.getValue().getAsString().equals(name)).findFirst().map(Map.Entry::getKey) |
988 | 1000 | .orElse(""); |
... | ... | @@ -1002,7 +1014,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1002 | 1014 | */ |
1003 | 1015 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { |
1004 | 1016 | try { |
1005 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(sessionInfo); | |
1017 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo); | |
1006 | 1018 | attributesResponse.getSharedAttributeListList().forEach(attr -> { |
1007 | 1019 | String path = this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey()); |
1008 | 1020 | // #1.1 |
... | ... | @@ -1027,18 +1039,18 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1027 | 1039 | * @param lwM2MClient - |
1028 | 1040 | * @return |
1029 | 1041 | */ |
1030 | - private SessionInfoProto getNewSessionInfoProto(LwM2MClient lwM2MClient) { | |
1042 | + private SessionInfoProto getNewSessionInfoProto(LwM2mClient lwM2MClient) { | |
1031 | 1043 | if (lwM2MClient != null) { |
1032 | 1044 | TransportProtos.ValidateDeviceCredentialsResponseMsg msg = lwM2MClient.getCredentialsResponse(); |
1033 | 1045 | if (msg == null || msg.getDeviceInfo() == null) { |
1034 | - log.error("[{}] [{}]", lwM2MClient.getEndPoint(), CLIENT_NOT_AUTHORIZED); | |
1046 | + log.error("[{}] [{}]", lwM2MClient.getEndpoint(), CLIENT_NOT_AUTHORIZED); | |
1035 | 1047 | this.closeClientSession(lwM2MClient.getRegistration()); |
1036 | 1048 | return null; |
1037 | 1049 | } else { |
1038 | 1050 | return SessionInfoProto.newBuilder() |
1039 | 1051 | .setNodeId(this.context.getNodeId()) |
1040 | - .setSessionIdMSB(lwM2MClient.getSessionUuid().getMostSignificantBits()) | |
1041 | - .setSessionIdLSB(lwM2MClient.getSessionUuid().getLeastSignificantBits()) | |
1052 | + .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits()) | |
1053 | + .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits()) | |
1042 | 1054 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) |
1043 | 1055 | .setDeviceIdLSB(msg.getDeviceInfo().getDeviceIdLSB()) |
1044 | 1056 | .setTenantIdMSB(msg.getDeviceInfo().getTenantIdMSB()) |
... | ... | @@ -1053,13 +1065,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1053 | 1065 | return null; |
1054 | 1066 | } |
1055 | 1067 | |
1056 | - | |
1057 | 1068 | /** |
1058 | 1069 | * @param registration - Registration LwM2M Client |
1059 | 1070 | * @return - sessionInfo after access connect client |
1060 | 1071 | */ |
1061 | 1072 | private SessionInfoProto getValidateSessionInfo(Registration registration) { |
1062 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null); | |
1073 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
1063 | 1074 | return getNewSessionInfoProto(lwM2MClient); |
1064 | 1075 | } |
1065 | 1076 | |
... | ... | @@ -1068,7 +1079,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1068 | 1079 | * @return - |
1069 | 1080 | */ |
1070 | 1081 | private SessionInfoProto getValidateSessionInfo(String registrationId) { |
1071 | - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(null, registrationId); | |
1082 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId); | |
1072 | 1083 | return getNewSessionInfoProto(lwM2MClient); |
1073 | 1084 | } |
1074 | 1085 | |
... | ... | @@ -1079,12 +1090,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1079 | 1090 | */ |
1080 | 1091 | private void checkInactivity(SessionInfoProto sessionInfo) { |
1081 | 1092 | if (transportService.reportActivity(sessionInfo) == null) { |
1082 | - transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo)); | |
1093 | + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); | |
1083 | 1094 | } |
1084 | 1095 | } |
1085 | 1096 | |
1086 | 1097 | private void checkInactivityAndReportActivity() { |
1087 | - lwM2mInMemorySecurityStore.getSessions().forEach((key, value) -> this.checkInactivity(this.getValidateSessionInfo(key))); | |
1098 | + lwM2mClientContext.getLwM2mClients().forEach((key, value) -> this.checkInactivity(this.getValidateSessionInfo(key))); | |
1088 | 1099 | } |
1089 | 1100 | |
1090 | 1101 | /** |
... | ... | @@ -1095,7 +1106,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1095 | 1106 | * |
1096 | 1107 | * @param lwM2MClient - LwM2M Client |
1097 | 1108 | */ |
1098 | - public void putDelayedUpdateResourcesThingsboard(LwM2MClient lwM2MClient) { | |
1109 | + public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { | |
1099 | 1110 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); |
1100 | 1111 | if (sessionInfo != null) { |
1101 | 1112 | //#1.1 + #1.2 |
... | ... | @@ -1119,15 +1130,16 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService { |
1119 | 1130 | * @param lwM2MClient - |
1120 | 1131 | * @return ArrayList keyNames from profile attr resources shared!!!! && IsWritable |
1121 | 1132 | */ |
1122 | - private List<String> getNamesAttrFromProfileIsWritable(LwM2MClient lwM2MClient) { | |
1123 | - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(lwM2MClient.getProfileUuid()); | |
1133 | + private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) { | |
1134 | + LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); | |
1124 | 1135 | Set attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), Set.class); |
1125 | - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType()); | |
1136 | + ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>() { | |
1137 | + }.getType()); | |
1126 | 1138 | |
1127 | 1139 | ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet() |
1128 | 1140 | .stream() |
1129 | - .filter(e -> (attrSet.contains(e.getKey()) && context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null && | |
1130 | - context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable())) | |
1141 | + .filter(e -> (attrSet.contains(e.getKey()) && context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null && | |
1142 | + context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable())) | |
1131 | 1143 | .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); |
1132 | 1144 | |
1133 | 1145 | Set<String> namesIsWritable = ConcurrentHashMap.newKeySet(); | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java
... | ... | @@ -20,13 +20,11 @@ import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.eclipse.leshan.core.node.LwM2mMultipleResource; |
21 | 21 | import org.eclipse.leshan.core.node.LwM2mResource; |
22 | 22 | import org.eclipse.leshan.core.node.LwM2mSingleResource; |
23 | -import org.eclipse.leshan.server.californium.LeshanServer; | |
24 | 23 | import org.eclipse.leshan.server.registration.Registration; |
25 | 24 | import org.eclipse.leshan.server.security.SecurityInfo; |
26 | 25 | import org.thingsboard.server.gen.transport.TransportProtos; |
27 | 26 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
28 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportServiceImpl; | |
29 | -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; | |
27 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl; | |
30 | 28 | |
31 | 29 | import java.util.List; |
32 | 30 | import java.util.Map; |
... | ... | @@ -36,42 +34,36 @@ import java.util.concurrent.CopyOnWriteArrayList; |
36 | 34 | |
37 | 35 | @Slf4j |
38 | 36 | @Data |
39 | -public class LwM2MClient implements Cloneable { | |
37 | +public class LwM2mClient implements Cloneable { | |
40 | 38 | private String deviceName; |
41 | 39 | private String deviceProfileName; |
42 | - private String endPoint; | |
40 | + private String endpoint; | |
43 | 41 | private String identity; |
44 | 42 | private SecurityInfo securityInfo; |
45 | - private UUID deviceUuid; | |
46 | - private UUID sessionUuid; | |
47 | - private UUID profileUuid; | |
48 | - private LeshanServer lwServer; | |
49 | - private LwM2MTransportServiceImpl lwM2MTransportServiceImpl; | |
43 | + private UUID deviceId; | |
44 | + private UUID sessionId; | |
45 | + private UUID profileId; | |
50 | 46 | private Registration registration; |
51 | 47 | private ValidateDeviceCredentialsResponseMsg credentialsResponse; |
52 | - private final Map<String, String> attributes; | |
53 | 48 | private final Map<String, ResourceValue> resources; |
54 | 49 | private final Map<String, TransportProtos.TsKvProto> delayedRequests; |
55 | 50 | private final List<String> pendingRequests; |
56 | 51 | private boolean init; |
57 | - private final LwM2mValueConverterImpl converter; | |
58 | 52 | |
59 | 53 | public Object clone() throws CloneNotSupportedException { |
60 | 54 | return super.clone(); |
61 | 55 | } |
62 | 56 | |
63 | - public LwM2MClient(String endPoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileUuid, UUID sessionUuid) { | |
64 | - this.endPoint = endPoint; | |
57 | + public LwM2mClient(String endpoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileId, UUID sessionId) { | |
58 | + this.endpoint = endpoint; | |
65 | 59 | this.identity = identity; |
66 | 60 | this.securityInfo = securityInfo; |
67 | 61 | this.credentialsResponse = credentialsResponse; |
68 | - this.attributes = new ConcurrentHashMap<>(); | |
69 | 62 | this.delayedRequests = new ConcurrentHashMap<>(); |
70 | 63 | this.pendingRequests = new CopyOnWriteArrayList<>(); |
71 | 64 | this.resources = new ConcurrentHashMap<>(); |
72 | - this.profileUuid = profileUuid; | |
73 | - this.sessionUuid = sessionUuid; | |
74 | - this.converter = LwM2mValueConverterImpl.getInstance(); | |
65 | + this.profileId = profileId; | |
66 | + this.sessionId = sessionId; | |
75 | 67 | this.init = false; |
76 | 68 | } |
77 | 69 | |
... | ... | @@ -83,7 +75,7 @@ public class LwM2MClient implements Cloneable { |
83 | 75 | } |
84 | 76 | } |
85 | 77 | |
86 | - public void initValue(LwM2MTransportServiceImpl lwM2MTransportService, String path) { | |
78 | + public void initValue(LwM2mTransportServiceImpl lwM2MTransportService, String path) { | |
87 | 79 | if (path != null) { |
88 | 80 | this.pendingRequests.remove(path); |
89 | 81 | } |
... | ... | @@ -93,8 +85,8 @@ public class LwM2MClient implements Cloneable { |
93 | 85 | } |
94 | 86 | } |
95 | 87 | |
96 | - public LwM2MClient copy() { | |
97 | - return new LwM2MClient(this.endPoint, this.identity, this.securityInfo, this.credentialsResponse, this.profileUuid, this.sessionUuid); | |
88 | + public LwM2mClient copy() { | |
89 | + return new LwM2mClient(this.endpoint, this.identity, this.securityInfo, this.credentialsResponse, this.profileId, this.sessionId); | |
98 | 90 | } |
99 | 91 | } |
100 | 92 | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.client; | |
17 | + | |
18 | +import org.eclipse.leshan.server.registration.Registration; | |
19 | +import org.thingsboard.server.common.data.DeviceProfile; | |
20 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
21 | + | |
22 | +import java.util.Map; | |
23 | +import java.util.UUID; | |
24 | + | |
25 | +public interface LwM2mClientContext { | |
26 | + | |
27 | + void delRemoveSessionAndListener(String registrationId); | |
28 | + | |
29 | + LwM2mClient getLwM2MClient(String endPoint, String identity); | |
30 | + | |
31 | + LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo); | |
32 | + | |
33 | + LwM2mClient getLwM2mClient(UUID sessionId); | |
34 | + | |
35 | + LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId); | |
36 | + | |
37 | + LwM2mClient updateInSessionsLwM2MClient(Registration registration); | |
38 | + | |
39 | + LwM2mClient addLwM2mClientToSession(String identity); | |
40 | + | |
41 | + Registration getRegistration(String registrationId); | |
42 | + | |
43 | + Map<String, LwM2mClient> getLwM2mClients(); | |
44 | + | |
45 | + Map<UUID, LwM2mClientProfile> getProfiles(); | |
46 | + | |
47 | + LwM2mClientProfile getProfile(UUID profileUuId); | |
48 | + | |
49 | + LwM2mClientProfile getProfile(Registration registration); | |
50 | + | |
51 | + Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles); | |
52 | + | |
53 | + boolean addUpdateProfileParameters(DeviceProfile deviceProfile); | |
54 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.client; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.eclipse.leshan.server.registration.Registration; | |
20 | +import org.eclipse.leshan.server.security.EditableSecurityStore; | |
21 | +import org.springframework.stereotype.Service; | |
22 | +import org.thingsboard.server.common.data.DeviceProfile; | |
23 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
24 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
25 | +import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | |
26 | +import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; | |
27 | +import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; | |
28 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
29 | +import org.thingsboard.server.transport.lwm2m.utils.TypeServer; | |
30 | + | |
31 | +import java.util.Map; | |
32 | +import java.util.UUID; | |
33 | +import java.util.concurrent.ConcurrentHashMap; | |
34 | + | |
35 | +import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; | |
36 | + | |
37 | +@Service | |
38 | +@TbLwM2mTransportComponent | |
39 | +public class LwM2mClientContextImpl implements LwM2mClientContext { | |
40 | + private static final boolean INFOS_ARE_COMPROMISED = false; | |
41 | + | |
42 | + private final Map<String /** registrationId */, LwM2mClient> lwM2mClients = new ConcurrentHashMap<>(); | |
43 | + private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>(); | |
44 | + | |
45 | + private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; | |
46 | + | |
47 | + private final EditableSecurityStore securityStore; | |
48 | + | |
49 | + public LwM2mClientContextImpl(LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, EditableSecurityStore securityStore) { | |
50 | + this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator; | |
51 | + this.securityStore = securityStore; | |
52 | + } | |
53 | + | |
54 | + public void delRemoveSessionAndListener(String registrationId) { | |
55 | + LwM2mClient lwM2MClient = lwM2mClients.get(registrationId); | |
56 | + if (lwM2MClient != null) { | |
57 | + securityStore.remove(lwM2MClient.getEndpoint(), INFOS_ARE_COMPROMISED); | |
58 | + lwM2mClients.remove(registrationId); | |
59 | + } | |
60 | + } | |
61 | + | |
62 | + @Override | |
63 | + public LwM2mClient getLwM2MClient(String endPoint, String identity) { | |
64 | + Map.Entry<String, LwM2mClient> modelClients = endPoint != null ? | |
65 | + this.lwM2mClients.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) : | |
66 | + this.lwM2mClients.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null); | |
67 | + return modelClients != null ? modelClients.getValue() : null; | |
68 | + } | |
69 | + | |
70 | + @Override | |
71 | + public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) { | |
72 | + return getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); | |
73 | + } | |
74 | + | |
75 | + @Override | |
76 | + public LwM2mClient getLwM2mClient(UUID sessionId) { | |
77 | + return lwM2mClients.values().stream().filter(c -> c.getSessionId().equals(sessionId)).findAny().get(); | |
78 | + } | |
79 | + | |
80 | + @Override | |
81 | + public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) { | |
82 | + LwM2mClient client = registrationId != null ? | |
83 | + this.lwM2mClients.get(registrationId) : | |
84 | + this.lwM2mClients.containsKey(registration.getId()) ? | |
85 | + this.lwM2mClients.get(registration.getId()) : | |
86 | + this.lwM2mClients.get(registration.getEndpoint()); | |
87 | + return client != null ? client : updateInSessionsLwM2MClient(registration); | |
88 | + } | |
89 | + | |
90 | + @Override | |
91 | + public LwM2mClient updateInSessionsLwM2MClient(Registration registration) { | |
92 | + if (this.lwM2mClients.get(registration.getEndpoint()) == null) { | |
93 | + addLwM2mClientToSession(registration.getEndpoint()); | |
94 | + } | |
95 | + LwM2mClient lwM2MClient = lwM2mClients.get(registration.getEndpoint()); | |
96 | + lwM2MClient.setRegistration(registration); | |
97 | + this.lwM2mClients.remove(registration.getEndpoint()); | |
98 | + this.lwM2mClients.put(registration.getId(), lwM2MClient); | |
99 | + return lwM2MClient; | |
100 | + } | |
101 | + | |
102 | + public Registration getRegistration(String registrationId) { | |
103 | + return this.lwM2mClients.get(registrationId).getRegistration(); | |
104 | + } | |
105 | + | |
106 | + /** | |
107 | + * Add new LwM2MClient to session | |
108 | + * @param identity- | |
109 | + * @return SecurityInfo. If error - SecurityInfoError | |
110 | + * and log: | |
111 | + * - FORBIDDEN - if there is no authorization | |
112 | + * - profileUuid - if the device does not have a profile | |
113 | + * - device - if the thingsboard does not have a device with a name equal to the identity | |
114 | + */ | |
115 | + @Override | |
116 | + public LwM2mClient addLwM2mClientToSession(String identity) { | |
117 | + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, TypeServer.CLIENT); | |
118 | + if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | |
119 | + UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; | |
120 | + LwM2mClient client; | |
121 | + if (store.getSecurityInfo() != null && profileUuid != null) { | |
122 | + String endpoint = store.getSecurityInfo().getEndpoint(); | |
123 | + client = new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID()); | |
124 | + lwM2mClients.put(endpoint, client); | |
125 | + } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) { | |
126 | + client = new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID()); | |
127 | + lwM2mClients.put(identity, client); | |
128 | + } else { | |
129 | + throw new RuntimeException(String.format("Registration failed: FORBIDDEN/profileUuid/device %s , endpointId: %s [PSK]", profileUuid, identity)); | |
130 | + } | |
131 | + return client; | |
132 | + } else { | |
133 | + throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", identity)); | |
134 | + } | |
135 | + } | |
136 | + | |
137 | + @Override | |
138 | + public Map<String, LwM2mClient> getLwM2mClients() { | |
139 | + return lwM2mClients; | |
140 | + } | |
141 | + | |
142 | + @Override | |
143 | + public Map<UUID, LwM2mClientProfile> getProfiles() { | |
144 | + return profiles; | |
145 | + } | |
146 | + | |
147 | + @Override | |
148 | + public LwM2mClientProfile getProfile(UUID profileId) { | |
149 | + return profiles.get(profileId); | |
150 | + } | |
151 | + | |
152 | + @Override | |
153 | + public LwM2mClientProfile getProfile(Registration registration) { | |
154 | + return this.getProfiles().get(getLwM2mClientWithReg(registration, null).getProfileId()); | |
155 | + } | |
156 | + | |
157 | + @Override | |
158 | + public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) { | |
159 | + return this.profiles = profiles; | |
160 | + } | |
161 | + | |
162 | + @Override | |
163 | + public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { | |
164 | + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
165 | + if (lwM2MClientProfile != null) { | |
166 | + profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); | |
167 | + return true; | |
168 | + } | |
169 | + return false; | |
170 | + } | |
171 | +} | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClientProfile.java
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/LwM2mInMemorySecurityStore.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java
... | ... | @@ -13,30 +13,26 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.transport.lwm2m.server.secure; | |
16 | +package org.thingsboard.server.transport.lwm2m.server.store; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.leshan.core.util.Hex; |
20 | -import org.eclipse.leshan.server.californium.LeshanServer; | |
21 | 20 | import org.eclipse.leshan.server.registration.Registration; |
22 | 21 | import org.eclipse.leshan.server.security.InMemorySecurityStore; |
23 | 22 | import org.eclipse.leshan.server.security.SecurityInfo; |
24 | 23 | import org.eclipse.leshan.server.security.SecurityStoreListener; |
25 | 24 | import org.springframework.beans.factory.annotation.Autowired; |
26 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
27 | -import org.springframework.stereotype.Service; | |
28 | 25 | import org.thingsboard.server.common.data.DeviceProfile; |
29 | 26 | import org.thingsboard.server.gen.transport.TransportProtos; |
30 | 27 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
31 | 28 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
32 | 29 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
33 | -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler; | |
34 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; | |
35 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile; | |
30 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
31 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
32 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | |
36 | 33 | import org.thingsboard.server.transport.lwm2m.utils.TypeServer; |
37 | 34 | |
38 | 35 | import java.util.Collection; |
39 | -import java.util.Collections; | |
40 | 36 | import java.util.List; |
41 | 37 | import java.util.Map; |
42 | 38 | import java.util.UUID; |
... | ... | @@ -49,8 +45,9 @@ import java.util.stream.Collectors; |
49 | 45 | import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; |
50 | 46 | |
51 | 47 | @Slf4j |
52 | -@Service("LwM2mInMemorySecurityStore") | |
53 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
48 | +//@Service("LwM2mInMemorySecurityStore") | |
49 | +//@TbLwM2mTransportComponent | |
50 | +@Deprecated | |
54 | 51 | public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
55 | 52 | private static final boolean INFOS_ARE_COMPROMISED = false; |
56 | 53 | |
... | ... | @@ -58,8 +55,8 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
58 | 55 | private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); |
59 | 56 | private final Lock readLock = readWriteLock.readLock(); |
60 | 57 | private final Lock writeLock = readWriteLock.writeLock(); |
61 | - private final Map<String /** registrationId */, LwM2MClient> sessions = new ConcurrentHashMap<>(); | |
62 | - private Map<UUID /** profileUUid */, LwM2MClientProfile> profiles = new ConcurrentHashMap<>(); | |
58 | + private final Map<String /** registrationId */, LwM2mClient> sessions = new ConcurrentHashMap<>(); | |
59 | + private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>(); | |
63 | 60 | private SecurityStoreListener listener; |
64 | 61 | |
65 | 62 | @Autowired |
... | ... | @@ -102,7 +99,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
102 | 99 | public Collection<SecurityInfo> getAll() { |
103 | 100 | readLock.lock(); |
104 | 101 | try { |
105 | - return Collections.unmodifiableCollection(this.sessions.values().stream().map(LwM2MClient::getSecurityInfo).collect(Collectors.toList())); | |
102 | + return this.sessions.values().stream().map(LwM2mClient::getSecurityInfo).collect(Collectors.toUnmodifiableList()); | |
106 | 103 | } finally { |
107 | 104 | readLock.unlock(); |
108 | 105 | } |
... | ... | @@ -115,7 +112,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
115 | 112 | public void delRemoveSessionAndListener(String registrationId) { |
116 | 113 | writeLock.lock(); |
117 | 114 | try { |
118 | - LwM2MClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null; | |
115 | + LwM2mClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null; | |
119 | 116 | if (lwM2MClient != null) { |
120 | 117 | if (listener != null) { |
121 | 118 | listener.securityInfoRemoved(INFOS_ARE_COMPROMISED, lwM2MClient.getSecurityInfo()); |
... | ... | @@ -132,14 +129,14 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
132 | 129 | this.listener = listener; |
133 | 130 | } |
134 | 131 | |
135 | - public LwM2MClient getLwM2MClient(String endPoint, String identity) { | |
136 | - Map.Entry<String, LwM2MClient> modelClients = (endPoint != null) ? | |
137 | - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndPoint())).findAny().orElse(null) : | |
132 | + public LwM2mClient getLwM2MClient(String endPoint, String identity) { | |
133 | + Map.Entry<String, LwM2mClient> modelClients = endPoint != null ? | |
134 | + this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) : | |
138 | 135 | this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null); |
139 | - return (modelClients != null) ? modelClients.getValue() : null; | |
136 | + return modelClients != null ? modelClients.getValue() : null; | |
140 | 137 | } |
141 | 138 | |
142 | - public LwM2MClient getLwM2MClientWithReg(Registration registration, String registrationId) { | |
139 | + public LwM2mClient getLwM2MClientWithReg(Registration registration, String registrationId) { | |
143 | 140 | return registrationId != null ? |
144 | 141 | this.sessions.get(registrationId) : |
145 | 142 | this.sessions.containsKey(registration.getId()) ? |
... | ... | @@ -147,28 +144,25 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
147 | 144 | this.sessions.get(registration.getEndpoint()); |
148 | 145 | } |
149 | 146 | |
150 | - public LwM2MClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) { | |
147 | + public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) { | |
151 | 148 | return this.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue(); |
152 | - | |
153 | 149 | } |
154 | 150 | |
155 | 151 | /** |
156 | 152 | * Update in sessions (LwM2MClient for key registration_Id) after starting registration LwM2MClient in LwM2MTransportServiceImpl |
157 | 153 | * Remove from sessions LwM2MClient with key registration_Endpoint |
158 | - * @param lwServer - | |
159 | 154 | * @param registration - |
160 | 155 | * @return LwM2MClient after adding it to session |
161 | 156 | */ |
162 | - public LwM2MClient updateInSessionsLwM2MClient(LeshanServer lwServer, Registration registration) { | |
157 | + public LwM2mClient updateInSessionsLwM2MClient(Registration registration) { | |
163 | 158 | writeLock.lock(); |
164 | 159 | try { |
165 | 160 | if (this.sessions.get(registration.getEndpoint()) == null) { |
166 | 161 | this.addLwM2MClientToSession(registration.getEndpoint()); |
167 | 162 | } |
168 | - LwM2MClient lwM2MClient = this.sessions.get(registration.getEndpoint()); | |
169 | - lwM2MClient.setLwServer(lwServer); | |
163 | + LwM2mClient lwM2MClient = this.sessions.get(registration.getEndpoint()); | |
170 | 164 | lwM2MClient.setRegistration(registration); |
171 | - lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes()); | |
165 | +// lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes()); | |
172 | 166 | this.sessions.remove(registration.getEndpoint()); |
173 | 167 | this.sessions.put(registration.getId(), lwM2MClient); |
174 | 168 | return lwM2MClient; |
... | ... | @@ -179,7 +173,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
179 | 173 | |
180 | 174 | private String getRegistrationId(String endPoint, String identity) { |
181 | 175 | List<String> registrationIds = (endPoint != null) ? |
182 | - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndPoint())).map(Map.Entry::getKey).collect(Collectors.toList()) : | |
176 | + this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).map(Map.Entry::getKey).collect(Collectors.toList()) : | |
183 | 177 | this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).map(Map.Entry::getKey).collect(Collectors.toList()); |
184 | 178 | return (registrationIds != null && registrationIds.size() > 0) ? registrationIds.get(0) : null; |
185 | 179 | } |
... | ... | @@ -203,49 +197,51 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { |
203 | 197 | UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; |
204 | 198 | if (store.getSecurityInfo() != null && profileUuid != null) { |
205 | 199 | String endpoint = store.getSecurityInfo().getEndpoint(); |
206 | - sessions.put(endpoint, new LwM2MClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID())); | |
200 | + sessions.put(endpoint, new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID())); | |
207 | 201 | } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) { |
208 | - sessions.put(identity, new LwM2MClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID())); | |
202 | + sessions.put(identity, new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID())); | |
209 | 203 | } else { |
210 | - log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity); | |
211 | - /** | |
212 | - * Return Error securityInfo | |
213 | - */ | |
214 | - byte[] preSharedKey = Hex.decodeHex("0A0B".toCharArray()); | |
215 | - SecurityInfo infoError = SecurityInfo.newPreSharedKeyInfo("error", "error_identity", preSharedKey); | |
216 | - return infoError; | |
217 | - } | |
204 | + log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity); | |
205 | + /** | |
206 | + * Return Error securityInfo | |
207 | + */ | |
208 | + byte[] preSharedKey = Hex.decodeHex("0A0B".toCharArray()); | |
209 | + SecurityInfo infoError = SecurityInfo.newPreSharedKeyInfo("error", "error_identity", preSharedKey); | |
210 | + return infoError; | |
218 | 211 | } |
219 | - return store.getSecurityInfo(); | |
212 | + } | |
213 | + return store.getSecurityInfo(); | |
220 | 214 | } |
221 | 215 | |
222 | - public Map<String, LwM2MClient> getSession(UUID sessionUuId) { | |
223 | - return this.sessions.entrySet().stream().filter(e -> e.getValue().getSessionUuid().equals(sessionUuId)).collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue())); | |
216 | + public Map<String, LwM2mClient> getSession(UUID sessionUuId) { | |
217 | + return this.sessions.entrySet().stream() | |
218 | + .filter(e -> e.getValue().getSessionId().equals(sessionUuId)) | |
219 | + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | |
224 | 220 | } |
225 | 221 | |
226 | - public Map<String, LwM2MClient> getSessions() { | |
222 | + public Map<String, LwM2mClient> getSessions() { | |
227 | 223 | return this.sessions; |
228 | 224 | } |
229 | 225 | |
230 | - public Map<UUID, LwM2MClientProfile> getProfiles() { | |
226 | + public Map<UUID, LwM2mClientProfile> getProfiles() { | |
231 | 227 | return this.profiles; |
232 | 228 | } |
233 | 229 | |
234 | - public LwM2MClientProfile getProfile(UUID profileUuId) { | |
230 | + public LwM2mClientProfile getProfile(UUID profileUuId) { | |
235 | 231 | return this.profiles.get(profileUuId); |
236 | 232 | } |
237 | 233 | |
238 | - public LwM2MClientProfile getProfile(String registrationId) { | |
239 | - UUID profileUUid = this.getSessions().get(registrationId).getProfileUuid(); | |
234 | + public LwM2mClientProfile getProfile(String registrationId) { | |
235 | + UUID profileUUid = this.getSessions().get(registrationId).getProfileId(); | |
240 | 236 | return this.getProfiles().get(profileUUid); |
241 | 237 | } |
242 | 238 | |
243 | - public Map<UUID, LwM2MClientProfile> setProfiles(Map<UUID, LwM2MClientProfile> profiles) { | |
239 | + public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) { | |
244 | 240 | return this.profiles = profiles; |
245 | 241 | } |
246 | 242 | |
247 | 243 | public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { |
248 | - LwM2MClientProfile lwM2MClientProfile = LwM2MTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
244 | + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
249 | 245 | if (lwM2MClientProfile != null) { |
250 | 246 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); |
251 | 247 | return true; | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.store; | |
17 | + | |
18 | +import org.eclipse.californium.core.coap.Token; | |
19 | +import org.eclipse.californium.core.observe.ObservationStoreException; | |
20 | +import org.eclipse.californium.elements.EndpointContext; | |
21 | +import org.eclipse.leshan.core.observation.Observation; | |
22 | +import org.eclipse.leshan.core.util.NamedThreadFactory; | |
23 | +import org.eclipse.leshan.core.util.Validate; | |
24 | +import org.eclipse.leshan.server.Destroyable; | |
25 | +import org.eclipse.leshan.server.Startable; | |
26 | +import org.eclipse.leshan.server.Stoppable; | |
27 | +import org.eclipse.leshan.server.californium.observation.ObserveUtil; | |
28 | +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; | |
29 | +import org.eclipse.leshan.server.redis.JedisLock; | |
30 | +import org.eclipse.leshan.server.redis.RedisRegistrationStore; | |
31 | +import org.eclipse.leshan.server.redis.SingleInstanceJedisLock; | |
32 | +import org.eclipse.leshan.server.redis.serialization.ObservationSerDes; | |
33 | +import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; | |
34 | +import org.eclipse.leshan.server.registration.Deregistration; | |
35 | +import org.eclipse.leshan.server.registration.ExpirationListener; | |
36 | +import org.eclipse.leshan.server.registration.Registration; | |
37 | +import org.eclipse.leshan.server.registration.RegistrationUpdate; | |
38 | +import org.eclipse.leshan.server.registration.UpdatedRegistration; | |
39 | +import org.slf4j.Logger; | |
40 | +import org.slf4j.LoggerFactory; | |
41 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
42 | +import redis.clients.jedis.Jedis; | |
43 | +import redis.clients.jedis.ScanParams; | |
44 | +import redis.clients.jedis.ScanResult; | |
45 | +import redis.clients.jedis.Transaction; | |
46 | + | |
47 | +import java.net.InetSocketAddress; | |
48 | +import java.util.ArrayList; | |
49 | +import java.util.Arrays; | |
50 | +import java.util.Collection; | |
51 | +import java.util.Collections; | |
52 | +import java.util.Iterator; | |
53 | +import java.util.List; | |
54 | +import java.util.NoSuchElementException; | |
55 | +import java.util.Set; | |
56 | +import java.util.concurrent.Executors; | |
57 | +import java.util.concurrent.ScheduledExecutorService; | |
58 | +import java.util.concurrent.ScheduledFuture; | |
59 | +import java.util.concurrent.TimeUnit; | |
60 | + | |
61 | +import static java.nio.charset.StandardCharsets.UTF_8; | |
62 | + | |
63 | +public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationStore, Startable, Stoppable, Destroyable { | |
64 | + /** Default time in seconds between 2 cleaning tasks (used to remove expired registration). */ | |
65 | + public static final long DEFAULT_CLEAN_PERIOD = 60; | |
66 | + public static final int DEFAULT_CLEAN_LIMIT = 500; | |
67 | + /** Defaut Extra time for registration lifetime in seconds */ | |
68 | + public static final long DEFAULT_GRACE_PERIOD = 0; | |
69 | + | |
70 | + private static final Logger LOG = LoggerFactory.getLogger(RedisRegistrationStore.class); | |
71 | + | |
72 | + // Redis key prefixes | |
73 | + private static final String REG_EP = "REG:EP:"; // (Endpoint => Registration) | |
74 | + private static final String REG_EP_REGID_IDX = "EP:REGID:"; // secondary index key (Registration ID => Endpoint) | |
75 | + private static final String REG_EP_ADDR_IDX = "EP:ADDR:"; // secondary index key (Socket Address => Endpoint) | |
76 | + private static final String LOCK_EP = "LOCK:EP:"; | |
77 | + private static final byte[] OBS_TKN = "OBS:TKN:".getBytes(UTF_8); | |
78 | + private static final String OBS_TKNS_REGID_IDX = "TKNS:REGID:"; // secondary index (token list by registration) | |
79 | + private static final byte[] EXP_EP = "EXP:EP".getBytes(UTF_8); // a sorted set used for registration expiration | |
80 | + // (expiration date, Endpoint) | |
81 | + | |
82 | + private final RedisConnectionFactory connectionFactory; | |
83 | + | |
84 | + // Listener use to notify when a registration expires | |
85 | + private ExpirationListener expirationListener; | |
86 | + | |
87 | + private final ScheduledExecutorService schedExecutor; | |
88 | + private ScheduledFuture<?> cleanerTask; | |
89 | + private boolean started = false; | |
90 | + | |
91 | + private final long cleanPeriod; // in seconds | |
92 | + private final int cleanLimit; // maximum number to clean in a clean period | |
93 | + private final long gracePeriod; // in seconds | |
94 | + | |
95 | + private final JedisLock lock; | |
96 | + | |
97 | + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory) { | |
98 | + this(connectionFactory, DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT); // default clean period 60s | |
99 | + } | |
100 | + | |
101 | + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, long cleanPeriodInSec, long lifetimeGracePeriodInSec, int cleanLimit) { | |
102 | + this(connectionFactory, Executors.newScheduledThreadPool(1, | |
103 | + new NamedThreadFactory(String.format("RedisRegistrationStore Cleaner (%ds)", cleanPeriodInSec))), | |
104 | + cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit); | |
105 | + } | |
106 | + | |
107 | + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, | |
108 | + long lifetimeGracePeriodInSec, int cleanLimit) { | |
109 | + this(connectionFactory, schedExecutor, cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit, new SingleInstanceJedisLock()); | |
110 | + } | |
111 | + | |
112 | + /** | |
113 | + * @since 1.1 | |
114 | + */ | |
115 | + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, | |
116 | + long lifetimeGracePeriodInSec, int cleanLimit, JedisLock redisLock) { | |
117 | + this.connectionFactory = connectionFactory; | |
118 | + this.schedExecutor = schedExecutor; | |
119 | + this.cleanPeriod = cleanPeriodInSec; | |
120 | + this.cleanLimit = cleanLimit; | |
121 | + this.gracePeriod = lifetimeGracePeriodInSec; | |
122 | + this.lock = redisLock; | |
123 | + } | |
124 | + | |
125 | + /* *************** Redis Key utility function **************** */ | |
126 | + | |
127 | + private byte[] toKey(byte[] prefix, byte[] key) { | |
128 | + byte[] result = new byte[prefix.length + key.length]; | |
129 | + System.arraycopy(prefix, 0, result, 0, prefix.length); | |
130 | + System.arraycopy(key, 0, result, prefix.length, key.length); | |
131 | + return result; | |
132 | + } | |
133 | + | |
134 | + private byte[] toKey(String prefix, String registrationID) { | |
135 | + return (prefix + registrationID).getBytes(); | |
136 | + } | |
137 | + | |
138 | + private byte[] toLockKey(String endpoint) { | |
139 | + return toKey(LOCK_EP, endpoint); | |
140 | + } | |
141 | + | |
142 | + private byte[] toLockKey(byte[] endpoint) { | |
143 | + return toKey(LOCK_EP.getBytes(UTF_8), endpoint); | |
144 | + } | |
145 | + | |
146 | + /* *************** Leshan Registration API **************** */ | |
147 | + | |
148 | + @Override | |
149 | + public Deregistration addRegistration(Registration registration) { | |
150 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
151 | + byte[] lockValue = null; | |
152 | + byte[] lockKey = toLockKey(registration.getEndpoint()); | |
153 | + | |
154 | + try { | |
155 | + lockValue = lock.acquire(j, lockKey); | |
156 | + | |
157 | + // add registration | |
158 | + byte[] k = toEndpointKey(registration.getEndpoint()); | |
159 | + byte[] old = j.getSet(k, serializeReg(registration)); | |
160 | + | |
161 | + // add registration: secondary indexes | |
162 | + byte[] regid_idx = toRegIdKey(registration.getId()); | |
163 | + j.set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); | |
164 | + byte[] addr_idx = toRegAddrKey(registration.getSocketAddress()); | |
165 | + j.set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); | |
166 | + | |
167 | + // Add or update expiration | |
168 | + addOrUpdateExpiration(j, registration); | |
169 | + | |
170 | + if (old != null) { | |
171 | + Registration oldRegistration = deserializeReg(old); | |
172 | + // remove old secondary index | |
173 | + if (!registration.getId().equals(oldRegistration.getId())) | |
174 | + j.del(toRegIdKey(oldRegistration.getId())); | |
175 | + if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { | |
176 | + removeAddrIndex(j, oldRegistration); | |
177 | + } | |
178 | + // remove old observation | |
179 | + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, oldRegistration.getId()); | |
180 | + | |
181 | + return new Deregistration(oldRegistration, obsRemoved); | |
182 | + } | |
183 | + | |
184 | + return null; | |
185 | + } finally { | |
186 | + lock.release(j, lockKey, lockValue); | |
187 | + } | |
188 | + } | |
189 | + } | |
190 | + | |
191 | + @Override | |
192 | + public UpdatedRegistration updateRegistration(RegistrationUpdate update) { | |
193 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
194 | + | |
195 | + // Fetch the registration ep by registration ID index | |
196 | + byte[] ep = j.get(toRegIdKey(update.getRegistrationId())); | |
197 | + if (ep == null) { | |
198 | + return null; | |
199 | + } | |
200 | + | |
201 | + byte[] lockValue = null; | |
202 | + byte[] lockKey = toLockKey(ep); | |
203 | + try { | |
204 | + lockValue = lock.acquire(j, lockKey); | |
205 | + | |
206 | + // Fetch the registration | |
207 | + byte[] data = j.get(toEndpointKey(ep)); | |
208 | + if (data == null) { | |
209 | + return null; | |
210 | + } | |
211 | + | |
212 | + Registration r = deserializeReg(data); | |
213 | + | |
214 | + Registration updatedRegistration = update.update(r); | |
215 | + | |
216 | + // Store the new registration | |
217 | + j.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration)); | |
218 | + | |
219 | + // Add or update expiration | |
220 | + addOrUpdateExpiration(j, updatedRegistration); | |
221 | + | |
222 | + // Update secondary index : | |
223 | + // If registration is already associated to this address we don't care as we only want to keep the most | |
224 | + // recent binding. | |
225 | + byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress()); | |
226 | + j.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8)); | |
227 | + if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { | |
228 | + removeAddrIndex(j, r); | |
229 | + } | |
230 | + | |
231 | + return new UpdatedRegistration(r, updatedRegistration); | |
232 | + | |
233 | + } finally { | |
234 | + lock.release(j, lockKey, lockValue); | |
235 | + } | |
236 | + } | |
237 | + } | |
238 | + | |
239 | + @Override | |
240 | + public Registration getRegistration(String registrationId) { | |
241 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
242 | + return getRegistration(j, registrationId); | |
243 | + } | |
244 | + } | |
245 | + | |
246 | + @Override | |
247 | + public Registration getRegistrationByEndpoint(String endpoint) { | |
248 | + Validate.notNull(endpoint); | |
249 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
250 | + byte[] data = j.get(toEndpointKey(endpoint)); | |
251 | + if (data == null) { | |
252 | + return null; | |
253 | + } | |
254 | + return deserializeReg(data); | |
255 | + } | |
256 | + } | |
257 | + | |
258 | + @Override | |
259 | + public Registration getRegistrationByAdress(InetSocketAddress address) { | |
260 | + Validate.notNull(address); | |
261 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
262 | + byte[] ep = j.get(toRegAddrKey(address)); | |
263 | + if (ep == null) { | |
264 | + return null; | |
265 | + } | |
266 | + byte[] data = j.get(toEndpointKey(ep)); | |
267 | + if (data == null) { | |
268 | + return null; | |
269 | + } | |
270 | + return deserializeReg(data); | |
271 | + } | |
272 | + } | |
273 | + | |
274 | + @Override | |
275 | + public Iterator<Registration> getAllRegistrations() { | |
276 | + return new TbLwM2mRedisRegistrationStore.RedisIterator(connectionFactory, new ScanParams().match(REG_EP + "*").count(100)); | |
277 | + } | |
278 | + | |
279 | + protected class RedisIterator implements Iterator<Registration> { | |
280 | + | |
281 | + private RedisConnectionFactory connectionFactory; | |
282 | + private ScanParams scanParams; | |
283 | + | |
284 | + private String cursor; | |
285 | + private List<Registration> scanResult; | |
286 | + | |
287 | + public RedisIterator(RedisConnectionFactory connectionFactory, ScanParams scanParams) { | |
288 | + this.connectionFactory = connectionFactory; | |
289 | + this.scanParams = scanParams; | |
290 | + // init scan result | |
291 | + scanNext("0"); | |
292 | + } | |
293 | + | |
294 | + private void scanNext(String cursor) { | |
295 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
296 | + do { | |
297 | + ScanResult<byte[]> sr = j.scan(cursor.getBytes(), scanParams); | |
298 | + | |
299 | + this.scanResult = new ArrayList<>(); | |
300 | + if (sr.getResult() != null && !sr.getResult().isEmpty()) { | |
301 | + for (byte[] value : j.mget(sr.getResult().toArray(new byte[][]{}))) { | |
302 | + this.scanResult.add(deserializeReg(value)); | |
303 | + } | |
304 | + } | |
305 | + | |
306 | + cursor = sr.getCursor(); | |
307 | + } while (!"0".equals(cursor) && scanResult.isEmpty()); | |
308 | + | |
309 | + this.cursor = cursor; | |
310 | + } | |
311 | + } | |
312 | + | |
313 | + @Override | |
314 | + public boolean hasNext() { | |
315 | + if (!scanResult.isEmpty()) { | |
316 | + return true; | |
317 | + } | |
318 | + if ("0".equals(cursor)) { | |
319 | + // no more elements to scan | |
320 | + return false; | |
321 | + } | |
322 | + | |
323 | + // read more elements | |
324 | + scanNext(cursor); | |
325 | + return !scanResult.isEmpty(); | |
326 | + } | |
327 | + | |
328 | + @Override | |
329 | + public Registration next() { | |
330 | + if (!hasNext()) { | |
331 | + throw new NoSuchElementException(); | |
332 | + } | |
333 | + return scanResult.remove(0); | |
334 | + } | |
335 | + | |
336 | + @Override | |
337 | + public void remove() { | |
338 | + throw new UnsupportedOperationException(); | |
339 | + } | |
340 | + } | |
341 | + | |
342 | + @Override | |
343 | + public Deregistration removeRegistration(String registrationId) { | |
344 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
345 | + return removeRegistration(j, registrationId, false); | |
346 | + } | |
347 | + } | |
348 | + | |
349 | + private Deregistration removeRegistration(Jedis j, String registrationId, boolean removeOnlyIfNotAlive) { | |
350 | + // fetch the client ep by registration ID index | |
351 | + byte[] ep = j.get(toRegIdKey(registrationId)); | |
352 | + if (ep == null) { | |
353 | + return null; | |
354 | + } | |
355 | + | |
356 | + byte[] lockValue = null; | |
357 | + byte[] lockKey = toLockKey(ep); | |
358 | + try { | |
359 | + lockValue = lock.acquire(j, lockKey); | |
360 | + | |
361 | + // fetch the client | |
362 | + byte[] data = j.get(toEndpointKey(ep)); | |
363 | + if (data == null) { | |
364 | + return null; | |
365 | + } | |
366 | + Registration r = deserializeReg(data); | |
367 | + | |
368 | + if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) { | |
369 | + long nbRemoved = j.del(toRegIdKey(r.getId())); | |
370 | + if (nbRemoved > 0) { | |
371 | + j.del(toEndpointKey(r.getEndpoint())); | |
372 | + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, r.getId()); | |
373 | + removeAddrIndex(j, r); | |
374 | + removeExpiration(j, r); | |
375 | + return new Deregistration(r, obsRemoved); | |
376 | + } | |
377 | + } | |
378 | + return null; | |
379 | + } finally { | |
380 | + lock.release(j, lockKey, lockValue); | |
381 | + } | |
382 | + } | |
383 | + | |
384 | + private void removeAddrIndex(Jedis j, Registration registration) { | |
385 | + // Watch the key to remove. | |
386 | + byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress()); | |
387 | + j.watch(regAddrKey); | |
388 | + | |
389 | + byte[] epFromAddr = j.get(regAddrKey); | |
390 | + // Delete the key if needed. | |
391 | + if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) { | |
392 | + // Try to delete the key | |
393 | + Transaction transaction = j.multi(); | |
394 | + transaction.del(regAddrKey); | |
395 | + transaction.exec(); | |
396 | + // if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to | |
397 | + // delete it anymore. | |
398 | + } else { | |
399 | + // the key must not be deleted. | |
400 | + j.unwatch(); | |
401 | + } | |
402 | + } | |
403 | + | |
404 | + private void addOrUpdateExpiration(Jedis j, Registration registration) { | |
405 | + j.zadd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8)); | |
406 | + } | |
407 | + | |
408 | + private void removeExpiration(Jedis j, Registration registration) { | |
409 | + j.zrem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); | |
410 | + } | |
411 | + | |
412 | + private byte[] toRegIdKey(String registrationId) { | |
413 | + return toKey(REG_EP_REGID_IDX, registrationId); | |
414 | + } | |
415 | + | |
416 | + private byte[] toRegAddrKey(InetSocketAddress addr) { | |
417 | + return toKey(REG_EP_ADDR_IDX, addr.getAddress().toString() + ":" + addr.getPort()); | |
418 | + } | |
419 | + | |
420 | + private byte[] toEndpointKey(String endpoint) { | |
421 | + return toKey(REG_EP, endpoint); | |
422 | + } | |
423 | + | |
424 | + private byte[] toEndpointKey(byte[] endpoint) { | |
425 | + return toKey(REG_EP.getBytes(UTF_8), endpoint); | |
426 | + } | |
427 | + | |
428 | + private byte[] serializeReg(Registration registration) { | |
429 | + return RegistrationSerDes.bSerialize(registration); | |
430 | + } | |
431 | + | |
432 | + private Registration deserializeReg(byte[] data) { | |
433 | + return RegistrationSerDes.deserialize(data); | |
434 | + } | |
435 | + | |
436 | + /* *************** Leshan Observation API **************** */ | |
437 | + | |
438 | + /* | |
439 | + * The observation is not persisted here, it is done by the Californium layer (in the implementation of the | |
440 | + * org.eclipse.californium.core.observe.ObservationStore#add method) | |
441 | + */ | |
442 | + @Override | |
443 | + public Collection<Observation> addObservation(String registrationId, Observation observation) { | |
444 | + | |
445 | + List<Observation> removed = new ArrayList<>(); | |
446 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
447 | + | |
448 | + // fetch the client ep by registration ID index | |
449 | + byte[] ep = j.get(toRegIdKey(registrationId)); | |
450 | + if (ep == null) { | |
451 | + return null; | |
452 | + } | |
453 | + | |
454 | + byte[] lockValue = null; | |
455 | + byte[] lockKey = toLockKey(ep); | |
456 | + | |
457 | + try { | |
458 | + lockValue = lock.acquire(j, lockKey); | |
459 | + | |
460 | + // cancel existing observations for the same path and registration id. | |
461 | + for (Observation obs : getObservations(j, registrationId)) { | |
462 | + if (observation.getPath().equals(obs.getPath()) | |
463 | + && !Arrays.equals(observation.getId(), obs.getId())) { | |
464 | + removed.add(obs); | |
465 | + unsafeRemoveObservation(j, registrationId, obs.getId()); | |
466 | + } | |
467 | + } | |
468 | + | |
469 | + } finally { | |
470 | + lock.release(j, lockKey, lockValue); | |
471 | + } | |
472 | + } | |
473 | + return removed; | |
474 | + } | |
475 | + | |
476 | + @Override | |
477 | + public Observation removeObservation(String registrationId, byte[] observationId) { | |
478 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
479 | + | |
480 | + // fetch the client ep by registration ID index | |
481 | + byte[] ep = j.get(toRegIdKey(registrationId)); | |
482 | + if (ep == null) { | |
483 | + return null; | |
484 | + } | |
485 | + | |
486 | + // remove observation | |
487 | + byte[] lockValue = null; | |
488 | + byte[] lockKey = toLockKey(ep); | |
489 | + try { | |
490 | + lockValue = lock.acquire(j, lockKey); | |
491 | + | |
492 | + Observation observation = build(get(new Token(observationId))); | |
493 | + if (observation != null && registrationId.equals(observation.getRegistrationId())) { | |
494 | + unsafeRemoveObservation(j, registrationId, observationId); | |
495 | + return observation; | |
496 | + } | |
497 | + return null; | |
498 | + | |
499 | + } finally { | |
500 | + lock.release(j, lockKey, lockValue); | |
501 | + } | |
502 | + } | |
503 | + } | |
504 | + | |
505 | + @Override | |
506 | + public Observation getObservation(String registrationId, byte[] observationId) { | |
507 | + return build(get(new Token(observationId))); | |
508 | + } | |
509 | + | |
510 | + @Override | |
511 | + public Collection<Observation> getObservations(String registrationId) { | |
512 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
513 | + return getObservations(j, registrationId); | |
514 | + } | |
515 | + } | |
516 | + | |
517 | + private Collection<Observation> getObservations(Jedis j, String registrationId) { | |
518 | + Collection<Observation> result = new ArrayList<>(); | |
519 | + for (byte[] token : j.lrange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) { | |
520 | + byte[] obs = j.get(toKey(OBS_TKN, token)); | |
521 | + if (obs != null) { | |
522 | + result.add(build(deserializeObs(obs))); | |
523 | + } | |
524 | + } | |
525 | + return result; | |
526 | + } | |
527 | + | |
528 | + @Override | |
529 | + public Collection<Observation> removeObservations(String registrationId) { | |
530 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
531 | + // check registration exists | |
532 | + Registration registration = getRegistration(j, registrationId); | |
533 | + if (registration == null) | |
534 | + return Collections.emptyList(); | |
535 | + | |
536 | + // get endpoint and create lock | |
537 | + String endpoint = registration.getEndpoint(); | |
538 | + byte[] lockValue = null; | |
539 | + byte[] lockKey = toKey(LOCK_EP, endpoint); | |
540 | + try { | |
541 | + lockValue = lock.acquire(j, lockKey); | |
542 | + | |
543 | + return unsafeRemoveAllObservations(j, registrationId); | |
544 | + } finally { | |
545 | + lock.release(j, lockKey, lockValue); | |
546 | + } | |
547 | + } | |
548 | + } | |
549 | + | |
550 | + /* *************** Californium ObservationStore API **************** */ | |
551 | + | |
552 | + @Override | |
553 | + public org.eclipse.californium.core.observe.Observation putIfAbsent(Token token, | |
554 | + org.eclipse.californium.core.observe.Observation obs) throws ObservationStoreException { | |
555 | + return add(token, obs, true); | |
556 | + } | |
557 | + | |
558 | + @Override | |
559 | + public org.eclipse.californium.core.observe.Observation put(Token token, | |
560 | + org.eclipse.californium.core.observe.Observation obs) throws ObservationStoreException { | |
561 | + return add(token, obs, false); | |
562 | + } | |
563 | + | |
564 | + private org.eclipse.californium.core.observe.Observation add(Token token, | |
565 | + org.eclipse.californium.core.observe.Observation obs, boolean ifAbsent) throws ObservationStoreException { | |
566 | + String endpoint = ObserveUtil.validateCoapObservation(obs); | |
567 | + org.eclipse.californium.core.observe.Observation previousObservation = null; | |
568 | + | |
569 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
570 | + byte[] lockValue = null; | |
571 | + byte[] lockKey = toKey(LOCK_EP, endpoint); | |
572 | + try { | |
573 | + lockValue = lock.acquire(j, lockKey); | |
574 | + | |
575 | + String registrationId = ObserveUtil.extractRegistrationId(obs); | |
576 | + if (!j.exists(toRegIdKey(registrationId))) | |
577 | + throw new ObservationStoreException("no registration for this Id"); | |
578 | + byte[] key = toKey(OBS_TKN, obs.getRequest().getToken().getBytes()); | |
579 | + byte[] serializeObs = serializeObs(obs); | |
580 | + byte[] previousValue = null; | |
581 | + if (ifAbsent) { | |
582 | + previousValue = j.get(key); | |
583 | + if (previousValue == null || previousValue.length == 0) { | |
584 | + j.set(key, serializeObs); | |
585 | + } else { | |
586 | + return deserializeObs(previousValue); | |
587 | + } | |
588 | + } else { | |
589 | + previousValue = j.getSet(key, serializeObs); | |
590 | + } | |
591 | + | |
592 | + // secondary index to get the list by registrationId | |
593 | + j.lpush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes()); | |
594 | + | |
595 | + // log any collisions | |
596 | + if (previousValue != null && previousValue.length != 0) { | |
597 | + previousObservation = deserializeObs(previousValue); | |
598 | + LOG.warn( | |
599 | + "Token collision ? observation from request [{}] will be replaced by observation from request [{}] ", | |
600 | + previousObservation.getRequest(), obs.getRequest()); | |
601 | + } | |
602 | + } finally { | |
603 | + lock.release(j, lockKey, lockValue); | |
604 | + } | |
605 | + } | |
606 | + return previousObservation; | |
607 | + } | |
608 | + | |
609 | + @Override | |
610 | + public void remove(Token token) { | |
611 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
612 | + byte[] tokenKey = toKey(OBS_TKN, token.getBytes()); | |
613 | + | |
614 | + // fetch the observation by token | |
615 | + byte[] serializedObs = j.get(tokenKey); | |
616 | + if (serializedObs == null) | |
617 | + return; | |
618 | + | |
619 | + org.eclipse.californium.core.observe.Observation obs = deserializeObs(serializedObs); | |
620 | + String registrationId = ObserveUtil.extractRegistrationId(obs); | |
621 | + Registration registration = getRegistration(j, registrationId); | |
622 | + if (registration == null) { | |
623 | + LOG.warn("Unable to remove observation {}, registration {} does not exist anymore", obs.getRequest(), | |
624 | + registrationId); | |
625 | + return; | |
626 | + } | |
627 | + | |
628 | + String endpoint = registration.getEndpoint(); | |
629 | + byte[] lockValue = null; | |
630 | + byte[] lockKey = toKey(LOCK_EP, endpoint); | |
631 | + try { | |
632 | + lockValue = lock.acquire(j, lockKey); | |
633 | + | |
634 | + unsafeRemoveObservation(j, registrationId, token.getBytes()); | |
635 | + } finally { | |
636 | + lock.release(j, lockKey, lockValue); | |
637 | + } | |
638 | + } | |
639 | + | |
640 | + } | |
641 | + | |
642 | + @Override | |
643 | + public org.eclipse.californium.core.observe.Observation get(Token token) { | |
644 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
645 | + byte[] obs = j.get(toKey(OBS_TKN, token.getBytes())); | |
646 | + if (obs == null) { | |
647 | + return null; | |
648 | + } else { | |
649 | + return deserializeObs(obs); | |
650 | + } | |
651 | + } | |
652 | + } | |
653 | + | |
654 | + /* *************** Observation utility functions **************** */ | |
655 | + | |
656 | + private Registration getRegistration(Jedis j, String registrationId) { | |
657 | + byte[] ep = j.get(toRegIdKey(registrationId)); | |
658 | + if (ep == null) { | |
659 | + return null; | |
660 | + } | |
661 | + byte[] data = j.get(toEndpointKey(ep)); | |
662 | + if (data == null) { | |
663 | + return null; | |
664 | + } | |
665 | + | |
666 | + return deserializeReg(data); | |
667 | + } | |
668 | + | |
669 | + private void unsafeRemoveObservation(Jedis j, String registrationId, byte[] observationId) { | |
670 | + if (j.del(toKey(OBS_TKN, observationId)) > 0L) { | |
671 | + j.lrem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId); | |
672 | + } | |
673 | + } | |
674 | + | |
675 | + private Collection<Observation> unsafeRemoveAllObservations(Jedis j, String registrationId) { | |
676 | + Collection<Observation> removed = new ArrayList<>(); | |
677 | + byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId); | |
678 | + | |
679 | + // fetch all observations by token | |
680 | + for (byte[] token : j.lrange(regIdKey, 0, -1)) { | |
681 | + byte[] obs = j.get(toKey(OBS_TKN, token)); | |
682 | + if (obs != null) { | |
683 | + removed.add(build(deserializeObs(obs))); | |
684 | + } | |
685 | + j.del(toKey(OBS_TKN, token)); | |
686 | + } | |
687 | + j.del(regIdKey); | |
688 | + | |
689 | + return removed; | |
690 | + } | |
691 | + | |
692 | + @Override | |
693 | + public void setContext(Token token, EndpointContext correlationContext) { | |
694 | + // In Leshan we always set context when we send the request, so this should not be needed to implement this. | |
695 | + } | |
696 | + | |
697 | + private byte[] serializeObs(org.eclipse.californium.core.observe.Observation obs) { | |
698 | + return ObservationSerDes.serialize(obs); | |
699 | + } | |
700 | + | |
701 | + private org.eclipse.californium.core.observe.Observation deserializeObs(byte[] data) { | |
702 | + return ObservationSerDes.deserialize(data); | |
703 | + } | |
704 | + | |
705 | + private Observation build(org.eclipse.californium.core.observe.Observation cfObs) { | |
706 | + if (cfObs == null) | |
707 | + return null; | |
708 | + | |
709 | + return ObserveUtil.createLwM2mObservation(cfObs.getRequest()); | |
710 | + } | |
711 | + | |
712 | + /* *************** Expiration handling **************** */ | |
713 | + | |
714 | + /** | |
715 | + * Start regular cleanup of dead registrations. | |
716 | + */ | |
717 | + @Override | |
718 | + public synchronized void start() { | |
719 | + if (!started) { | |
720 | + started = true; | |
721 | + cleanerTask = schedExecutor.scheduleAtFixedRate(new TbLwM2mRedisRegistrationStore.Cleaner(), cleanPeriod, cleanPeriod, TimeUnit.SECONDS); | |
722 | + } | |
723 | + } | |
724 | + | |
725 | + /** | |
726 | + * Stop the underlying cleanup of the registrations. | |
727 | + */ | |
728 | + @Override | |
729 | + public synchronized void stop() { | |
730 | + if (started) { | |
731 | + started = false; | |
732 | + if (cleanerTask != null) { | |
733 | + cleanerTask.cancel(false); | |
734 | + cleanerTask = null; | |
735 | + } | |
736 | + } | |
737 | + } | |
738 | + | |
739 | + /** | |
740 | + * Destroy "cleanup" scheduler. | |
741 | + */ | |
742 | + @Override | |
743 | + public synchronized void destroy() { | |
744 | + started = false; | |
745 | + schedExecutor.shutdownNow(); | |
746 | + try { | |
747 | + schedExecutor.awaitTermination(5, TimeUnit.SECONDS); | |
748 | + } catch (InterruptedException e) { | |
749 | + LOG.warn("Destroying RedisRegistrationStore was interrupted.", e); | |
750 | + } | |
751 | + } | |
752 | + | |
753 | + private class Cleaner implements Runnable { | |
754 | + | |
755 | + @Override | |
756 | + public void run() { | |
757 | + | |
758 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
759 | + Set<byte[]> endpointsExpired = j.zrangeByScore(EXP_EP, Double.NEGATIVE_INFINITY, | |
760 | + System.currentTimeMillis(), 0, cleanLimit); | |
761 | + | |
762 | + for (byte[] endpoint : endpointsExpired) { | |
763 | + Registration r = deserializeReg(j.get(toEndpointKey(endpoint))); | |
764 | + if (!r.isAlive(gracePeriod)) { | |
765 | + Deregistration dereg = removeRegistration(j, r.getId(), true); | |
766 | + if (dereg != null) | |
767 | + expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); | |
768 | + } | |
769 | + } | |
770 | + } catch (Exception e) { | |
771 | + LOG.warn("Unexpected Exception while registration cleaning", e); | |
772 | + } | |
773 | + } | |
774 | + } | |
775 | + | |
776 | + @Override | |
777 | + public void setExpirationListener(ExpirationListener listener) { | |
778 | + expirationListener = listener; | |
779 | + } | |
780 | + | |
781 | + @Override | |
782 | + public void setExecutor(ScheduledExecutorService executor) { | |
783 | + // TODO should we reuse californium executor ? | |
784 | + } | |
785 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.store; | |
17 | + | |
18 | +import org.eclipse.leshan.server.redis.serialization.SecurityInfoSerDes; | |
19 | +import org.eclipse.leshan.server.security.EditableSecurityStore; | |
20 | +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; | |
21 | +import org.eclipse.leshan.server.security.SecurityInfo; | |
22 | +import org.eclipse.leshan.server.security.SecurityStoreListener; | |
23 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
24 | +import org.springframework.stereotype.Service; | |
25 | +import redis.clients.jedis.Jedis; | |
26 | +import redis.clients.jedis.ScanParams; | |
27 | +import redis.clients.jedis.ScanResult; | |
28 | + | |
29 | +import java.util.Collection; | |
30 | +import java.util.LinkedList; | |
31 | + | |
32 | +@Service | |
33 | +public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | |
34 | + private static final String SEC_EP = "SEC#EP#"; | |
35 | + | |
36 | + private static final String PSKID_SEC = "PSKID#SEC"; | |
37 | + | |
38 | + private final RedisConnectionFactory connectionFactory; | |
39 | + private SecurityStoreListener listener; | |
40 | + | |
41 | + public TbLwM2mRedisSecurityStore(RedisConnectionFactory connectionFactory) { | |
42 | + this.connectionFactory = connectionFactory; | |
43 | + } | |
44 | + | |
45 | + @Override | |
46 | + public SecurityInfo getByEndpoint(String endpoint) { | |
47 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
48 | + byte[] data = j.get((SEC_EP + endpoint).getBytes()); | |
49 | + if (data == null) { | |
50 | + return null; | |
51 | + } else { | |
52 | + return deserialize(data); | |
53 | + } | |
54 | + } | |
55 | + } | |
56 | + | |
57 | + @Override | |
58 | + public SecurityInfo getByIdentity(String identity) { | |
59 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
60 | + String ep = j.hget(PSKID_SEC, identity); | |
61 | + if (ep == null) { | |
62 | + return null; | |
63 | + } else { | |
64 | + byte[] data = j.get((SEC_EP + ep).getBytes()); | |
65 | + if (data == null) { | |
66 | + return null; | |
67 | + } else { | |
68 | + return deserialize(data); | |
69 | + } | |
70 | + } | |
71 | + } | |
72 | + } | |
73 | + | |
74 | + @Override | |
75 | + public Collection<SecurityInfo> getAll() { | |
76 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
77 | + ScanParams params = new ScanParams().match(SEC_EP + "*").count(100); | |
78 | + Collection<SecurityInfo> list = new LinkedList<>(); | |
79 | + String cursor = "0"; | |
80 | + do { | |
81 | + ScanResult<byte[]> res = j.scan(cursor.getBytes(), params); | |
82 | + for (byte[] key : res.getResult()) { | |
83 | + byte[] element = j.get(key); | |
84 | + list.add(deserialize(element)); | |
85 | + } | |
86 | + cursor = res.getCursor(); | |
87 | + } while (!"0".equals(cursor)); | |
88 | + return list; | |
89 | + } | |
90 | + } | |
91 | + | |
92 | + @Override | |
93 | + public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { | |
94 | + byte[] data = serialize(info); | |
95 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
96 | + if (info.getIdentity() != null) { | |
97 | + // populate the secondary index (security info by PSK id) | |
98 | + String oldEndpoint = j.hget(PSKID_SEC, info.getIdentity()); | |
99 | + if (oldEndpoint != null && !oldEndpoint.equals(info.getEndpoint())) { | |
100 | + throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used"); | |
101 | + } | |
102 | + j.hset(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes()); | |
103 | + } | |
104 | + | |
105 | + byte[] previousData = j.getSet((SEC_EP + info.getEndpoint()).getBytes(), data); | |
106 | + SecurityInfo previous = previousData == null ? null : deserialize(previousData); | |
107 | + String previousIdentity = previous == null ? null : previous.getIdentity(); | |
108 | + if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) { | |
109 | + j.hdel(PSKID_SEC, previousIdentity); | |
110 | + } | |
111 | + | |
112 | + return previous; | |
113 | + } | |
114 | + } | |
115 | + | |
116 | + @Override | |
117 | + public SecurityInfo remove(String endpoint, boolean infosAreCompromised) { | |
118 | + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | |
119 | + byte[] data = j.get((SEC_EP + endpoint).getBytes()); | |
120 | + | |
121 | + if (data != null) { | |
122 | + SecurityInfo info = deserialize(data); | |
123 | + if (info.getIdentity() != null) { | |
124 | + j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); | |
125 | + } | |
126 | + j.del((SEC_EP + endpoint).getBytes()); | |
127 | + if (listener != null) { | |
128 | + listener.securityInfoRemoved(infosAreCompromised, info); | |
129 | + } | |
130 | + return info; | |
131 | + } | |
132 | + } | |
133 | + return null; | |
134 | + } | |
135 | + | |
136 | + private byte[] serialize(SecurityInfo secInfo) { | |
137 | + return SecurityInfoSerDes.serialize(secInfo); | |
138 | + } | |
139 | + | |
140 | + private SecurityInfo deserialize(byte[] data) { | |
141 | + return SecurityInfoSerDes.deserialize(data); | |
142 | + } | |
143 | + | |
144 | + @Override | |
145 | + public void setListener(SecurityStoreListener listener) { | |
146 | + this.listener = listener; | |
147 | + } | |
148 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 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.store; | |
17 | + | |
18 | +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; | |
19 | +import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore; | |
20 | +import org.eclipse.leshan.server.security.EditableSecurityStore; | |
21 | +import org.eclipse.leshan.server.security.InMemorySecurityStore; | |
22 | +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; | |
23 | +import org.eclipse.leshan.server.security.SecurityInfo; | |
24 | +import org.eclipse.leshan.server.security.SecurityStoreListener; | |
25 | +import org.springframework.beans.factory.annotation.Autowired; | |
26 | +import org.springframework.beans.factory.annotation.Value; | |
27 | +import org.springframework.context.annotation.Bean; | |
28 | +import org.springframework.context.annotation.Lazy; | |
29 | +import org.springframework.stereotype.Service; | |
30 | +import org.thingsboard.server.cache.TBRedisCacheConfiguration; | |
31 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
32 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | |
33 | + | |
34 | +import java.util.Collection; | |
35 | +import java.util.Optional; | |
36 | + | |
37 | +@Service | |
38 | +@TbLwM2mTransportComponent | |
39 | +public class TbLwM2mStoreConfiguration { | |
40 | + | |
41 | + @Autowired(required = false) | |
42 | + private Optional<TBRedisCacheConfiguration> redisConfiguration; | |
43 | + | |
44 | + @Autowired | |
45 | + @Lazy | |
46 | + private LwM2mClientContext clientContext; | |
47 | + | |
48 | + @Value("${transport.lwm2m.redis.enabled:false}") | |
49 | + private boolean useRedis; | |
50 | + | |
51 | + @Bean | |
52 | + private CaliforniumRegistrationStore registrationStore() { | |
53 | + return redisConfiguration.isPresent() && useRedis ? | |
54 | + new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore(); | |
55 | + } | |
56 | + | |
57 | + @Bean | |
58 | + private EditableSecurityStore securityStore() { | |
59 | + return new TbLwM2mSecurityStoreWrapper(redisConfiguration.isPresent() && useRedis ? | |
60 | + new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore()); | |
61 | + } | |
62 | + | |
63 | + public class TbLwM2mSecurityStoreWrapper implements EditableSecurityStore { | |
64 | + | |
65 | + private final EditableSecurityStore securityStore; | |
66 | + | |
67 | + public TbLwM2mSecurityStoreWrapper(EditableSecurityStore securityStore) { | |
68 | + this.securityStore = securityStore; | |
69 | + } | |
70 | + | |
71 | + @Override | |
72 | + public Collection<SecurityInfo> getAll() { | |
73 | + return securityStore.getAll(); | |
74 | + } | |
75 | + | |
76 | + @Override | |
77 | + public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { | |
78 | + return securityStore.add(info); | |
79 | + } | |
80 | + | |
81 | + @Override | |
82 | + public SecurityInfo remove(String endpoint, boolean infosAreCompromised) { | |
83 | + return securityStore.remove(endpoint, infosAreCompromised); | |
84 | + } | |
85 | + | |
86 | + @Override | |
87 | + public void setListener(SecurityStoreListener listener) { | |
88 | + securityStore.setListener(listener); | |
89 | + } | |
90 | + | |
91 | + @Override | |
92 | + public SecurityInfo getByEndpoint(String endpoint) { | |
93 | + SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint); | |
94 | + if (securityInfo == null) { | |
95 | + securityInfo = clientContext.addLwM2mClientToSession(endpoint).getSecurityInfo(); | |
96 | + try { | |
97 | + if (securityInfo != null) { | |
98 | + add(securityInfo); | |
99 | + } | |
100 | + } catch (NonUniqueSecurityInfoException e) { | |
101 | + e.printStackTrace(); | |
102 | + } | |
103 | + } | |
104 | + return securityInfo; | |
105 | + } | |
106 | + | |
107 | + @Override | |
108 | + public SecurityInfo getByIdentity(String pskIdentity) { | |
109 | + SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity); | |
110 | + if (securityInfo == null) { | |
111 | + securityInfo = clientContext.addLwM2mClientToSession(pskIdentity).getSecurityInfo(); | |
112 | + try { | |
113 | + if (securityInfo != null) { | |
114 | + add(securityInfo); | |
115 | + } | |
116 | + } catch (NonUniqueSecurityInfoException e) { | |
117 | + e.printStackTrace(); | |
118 | + } | |
119 | + } | |
120 | + return securityInfo; | |
121 | + } | |
122 | + } | |
123 | +} | ... | ... |
... | ... | @@ -54,6 +54,10 @@ |
54 | 54 | </dependency> |
55 | 55 | <dependency> |
56 | 56 | <groupId>org.thingsboard.common</groupId> |
57 | + <artifactId>cache</artifactId> | |
58 | + </dependency> | |
59 | + <dependency> | |
60 | + <groupId>org.thingsboard.common</groupId> | |
57 | 61 | <artifactId>util</artifactId> |
58 | 62 | </dependency> |
59 | 63 | <dependency> | ... | ... |
... | ... | @@ -20,10 +20,10 @@ import lombok.Data; |
20 | 20 | import lombok.Getter; |
21 | 21 | import lombok.extern.slf4j.Slf4j; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
24 | 23 | import org.springframework.stereotype.Service; |
25 | 24 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
26 | 25 | import org.thingsboard.server.queue.scheduler.SchedulerComponent; |
26 | +import org.thingsboard.server.queue.util.TbTransportComponent; | |
27 | 27 | |
28 | 28 | import javax.annotation.PostConstruct; |
29 | 29 | import javax.annotation.PreDestroy; |
... | ... | @@ -35,8 +35,6 @@ import java.util.concurrent.Executors; |
35 | 35 | */ |
36 | 36 | @Slf4j |
37 | 37 | @Data |
38 | -@Service | |
39 | -@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true')") | |
40 | 38 | public abstract class TransportContext { |
41 | 39 | |
42 | 40 | protected final ObjectMapper mapper = new ObjectMapper(); | ... | ... |
... | ... | @@ -186,10 +186,6 @@ public class LwM2MTransportConfigServer { |
186 | 186 | @Value("${transport.lwm2m.server.secure.alias:}") |
187 | 187 | private String serverAlias; |
188 | 188 | |
189 | - @Getter | |
190 | - @Value("${transport.lwm2m.secure.redis_url:}") | |
191 | - private String redisUrl; | |
192 | - | |
193 | 189 | @PostConstruct |
194 | 190 | public void init() { |
195 | 191 | modelsValue = ObjectLoader.loadDefault(); | ... | ... |
... | ... | @@ -46,6 +46,10 @@ |
46 | 46 | <artifactId>javax.annotation-api</artifactId> |
47 | 47 | </dependency> |
48 | 48 | <dependency> |
49 | + <groupId>com.fasterxml.jackson.core</groupId> | |
50 | + <artifactId>jackson-databind</artifactId> | |
51 | + </dependency> | |
52 | + <dependency> | |
49 | 53 | <groupId>org.slf4j</groupId> |
50 | 54 | <artifactId>slf4j-api</artifactId> |
51 | 55 | </dependency> | ... | ... |
common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java
renamed from
common/dao-api/src/main/java/org/thingsboard/server/dao/util/mapping/JacksonUtil.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.util.mapping; | |
16 | +package org.thingsboard.common.util; | |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
19 | 19 | import com.fasterxml.jackson.core.type.TypeReference; | ... | ... |
... | ... | @@ -41,6 +41,10 @@ |
41 | 41 | </dependency> |
42 | 42 | <dependency> |
43 | 43 | <groupId>org.thingsboard.common</groupId> |
44 | + <artifactId>cache</artifactId> | |
45 | + </dependency> | |
46 | + <dependency> | |
47 | + <groupId>org.thingsboard.common</groupId> | |
44 | 48 | <artifactId>message</artifactId> |
45 | 49 | </dependency> |
46 | 50 | <dependency> | ... | ... |
... | ... | @@ -49,7 +49,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionRequest; |
49 | 49 | import org.thingsboard.server.dao.entity.EntityService; |
50 | 50 | import org.thingsboard.server.dao.exception.DataValidationException; |
51 | 51 | import org.thingsboard.server.dao.service.DataValidator; |
52 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
52 | +import org.thingsboard.common.util.JacksonUtil; | |
53 | 53 | |
54 | 54 | import java.io.PrintWriter; |
55 | 55 | import java.io.StringWriter; | ... | ... |
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.server.dao.cache; |
17 | 17 | |
18 | 18 | import org.springframework.cache.interceptor.KeyGenerator; |
19 | +import org.springframework.stereotype.Component; | |
19 | 20 | import org.thingsboard.server.common.data.id.TenantId; |
20 | 21 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
21 | 22 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
... | ... | @@ -24,6 +25,7 @@ import java.lang.reflect.Method; |
24 | 25 | |
25 | 26 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE; |
26 | 27 | |
28 | +@Component("previousDeviceCredentialsId") | |
27 | 29 | public class PreviousDeviceCredentialsIdKeyGenerator implements KeyGenerator { |
28 | 30 | |
29 | 31 | private static final String NOT_VALID_DEVICE = DEVICE_CREDENTIALS_CACHE + "_notValidDeviceCredentialsId"; | ... | ... |
... | ... | @@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.EncryptionUtil; |
33 | 33 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
34 | 34 | import org.thingsboard.server.dao.exception.DataValidationException; |
35 | 35 | import org.thingsboard.server.dao.service.DataValidator; |
36 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
36 | +import org.thingsboard.common.util.JacksonUtil; | |
37 | 37 | |
38 | 38 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE; |
39 | 39 | import static org.thingsboard.server.dao.service.Validator.validateId; | ... | ... |
... | ... | @@ -75,7 +75,7 @@ import org.thingsboard.server.dao.service.DataValidator; |
75 | 75 | import org.thingsboard.server.dao.service.PaginatedRemover; |
76 | 76 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
77 | 77 | import org.thingsboard.server.dao.tenant.TenantDao; |
78 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
78 | +import org.thingsboard.common.util.JacksonUtil; | |
79 | 79 | |
80 | 80 | import javax.annotation.Nullable; |
81 | 81 | import java.util.ArrayList; | ... | ... |
... | ... | @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
31 | 31 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
32 | 32 | import org.thingsboard.server.dao.model.ModelConstants; |
33 | 33 | import org.thingsboard.server.dao.model.SearchTextEntity; |
34 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
34 | +import org.thingsboard.common.util.JacksonUtil; | |
35 | 35 | import org.thingsboard.server.dao.util.mapping.JsonBinaryType; |
36 | 36 | import org.thingsboard.server.dao.util.mapping.JsonStringType; |
37 | 37 | ... | ... |
... | ... | @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
32 | 32 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
33 | 33 | import org.thingsboard.server.dao.model.ModelConstants; |
34 | 34 | import org.thingsboard.server.dao.model.SearchTextEntity; |
35 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
35 | +import org.thingsboard.common.util.JacksonUtil; | |
36 | 36 | import org.thingsboard.server.dao.util.mapping.JsonBinaryType; |
37 | 37 | |
38 | 38 | import javax.persistence.Column; | ... | ... |
... | ... | @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; |
27 | 27 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
28 | 28 | import org.thingsboard.server.dao.model.ModelConstants; |
29 | 29 | import org.thingsboard.server.dao.model.SearchTextEntity; |
30 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
30 | +import org.thingsboard.common.util.JacksonUtil; | |
31 | 31 | import org.thingsboard.server.dao.util.mapping.JsonBinaryType; |
32 | 32 | |
33 | 33 | import javax.persistence.Column; | ... | ... |
... | ... | @@ -48,7 +48,7 @@ import org.thingsboard.server.dao.service.DataValidator; |
48 | 48 | import org.thingsboard.server.dao.service.PaginatedRemover; |
49 | 49 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
50 | 50 | import org.thingsboard.server.dao.tenant.TenantDao; |
51 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
51 | +import org.thingsboard.common.util.JacksonUtil; | |
52 | 52 | |
53 | 53 | import java.util.HashMap; |
54 | 54 | import java.util.Map; | ... | ... |
... | ... | @@ -19,6 +19,7 @@ import org.hibernate.type.descriptor.WrapperOptions; |
19 | 19 | import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; |
20 | 20 | import org.hibernate.type.descriptor.java.MutableMutabilityPlan; |
21 | 21 | import org.hibernate.usertype.DynamicParameterizedType; |
22 | +import org.thingsboard.common.util.JacksonUtil; | |
22 | 23 | |
23 | 24 | import java.util.Properties; |
24 | 25 | ... | ... |
... | ... | @@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.query.EntityKeyType; |
46 | 46 | import org.thingsboard.server.common.data.relation.EntityRelation; |
47 | 47 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
48 | 48 | import org.thingsboard.server.dao.alarm.AlarmOperationResult; |
49 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
49 | +import org.thingsboard.common.util.JacksonUtil; | |
50 | 50 | |
51 | 51 | import java.util.Arrays; |
52 | 52 | import java.util.Collections; | ... | ... |
... | ... | @@ -854,6 +854,11 @@ |
854 | 854 | </dependency> |
855 | 855 | <dependency> |
856 | 856 | <groupId>org.thingsboard.common</groupId> |
857 | + <artifactId>cache</artifactId> | |
858 | + <version>${project.version}</version> | |
859 | + </dependency> | |
860 | + <dependency> | |
861 | + <groupId>org.thingsboard.common</groupId> | |
857 | 862 | <artifactId>actor</artifactId> |
858 | 863 | <version>${project.version}</version> |
859 | 864 | </dependency> | ... | ... |
... | ... | @@ -23,7 +23,7 @@ import org.mockito.junit.MockitoJUnitRunner; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 24 | import org.thingsboard.server.common.msg.TbMsg; |
25 | 25 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
26 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
26 | +import org.thingsboard.common.util.JacksonUtil; | |
27 | 27 | |
28 | 28 | @RunWith(MockitoJUnitRunner.class) |
29 | 29 | public class TbNodeUtilsTest { | ... | ... |
... | ... | @@ -28,7 +28,7 @@ import org.thingsboard.rule.engine.api.TbNodeException; |
28 | 28 | import org.thingsboard.server.common.data.DataConstants; |
29 | 29 | import org.thingsboard.server.common.msg.TbMsg; |
30 | 30 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
31 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
31 | +import org.thingsboard.common.util.JacksonUtil; | |
32 | 32 | |
33 | 33 | import static org.thingsboard.common.util.DonAsynchron.withCallback; |
34 | 34 | ... | ... |
... | ... | @@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; |
35 | 35 | import org.thingsboard.server.common.msg.TbMsg; |
36 | 36 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
37 | 37 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
38 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
38 | +import org.thingsboard.common.util.JacksonUtil; | |
39 | 39 | |
40 | 40 | import java.math.BigDecimal; |
41 | 41 | import java.math.RoundingMode; | ... | ... |
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java
... | ... | @@ -25,20 +25,17 @@ import org.thingsboard.rule.engine.api.TbContext; |
25 | 25 | import org.thingsboard.rule.engine.profile.state.PersistedAlarmRuleState; |
26 | 26 | import org.thingsboard.rule.engine.profile.state.PersistedAlarmState; |
27 | 27 | import org.thingsboard.server.common.data.DataConstants; |
28 | -import org.thingsboard.server.common.data.Tenant; | |
29 | 28 | import org.thingsboard.server.common.data.alarm.Alarm; |
30 | 29 | import org.thingsboard.server.common.data.alarm.AlarmSeverity; |
31 | 30 | import org.thingsboard.server.common.data.alarm.AlarmStatus; |
32 | 31 | import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; |
33 | -import org.thingsboard.server.common.data.id.CustomerId; | |
34 | 32 | import org.thingsboard.server.common.data.id.EntityId; |
35 | -import org.thingsboard.server.common.data.id.TenantId; | |
36 | 33 | import org.thingsboard.server.common.data.query.EntityKeyType; |
37 | 34 | import org.thingsboard.server.common.data.query.KeyFilter; |
38 | 35 | import org.thingsboard.server.common.msg.TbMsg; |
39 | 36 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
40 | 37 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
41 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
38 | +import org.thingsboard.common.util.JacksonUtil; | |
42 | 39 | |
43 | 40 | import java.util.ArrayList; |
44 | 41 | import java.util.Comparator; | ... | ... |
... | ... | @@ -40,7 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg; |
40 | 40 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
41 | 41 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
42 | 42 | import org.thingsboard.server.dao.sql.query.EntityKeyMapping; |
43 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
43 | +import org.thingsboard.common.util.JacksonUtil; | |
44 | 44 | |
45 | 45 | import java.util.ArrayList; |
46 | 46 | import java.util.HashMap; | ... | ... |
... | ... | @@ -38,7 +38,7 @@ import org.thingsboard.server.common.data.rule.RuleNodeState; |
38 | 38 | import org.thingsboard.server.common.msg.TbMsg; |
39 | 39 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
40 | 40 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
41 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
41 | +import org.thingsboard.common.util.JacksonUtil; | |
42 | 42 | |
43 | 43 | import java.util.Map; |
44 | 44 | import java.util.UUID; | ... | ... |
... | ... | @@ -16,31 +16,8 @@ |
16 | 16 | package org.thingsboard.rule.engine.profile; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | -import lombok.extern.slf4j.Slf4j; | |
20 | 19 | import org.codehaus.jackson.annotate.JsonIgnoreProperties; |
21 | -import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; | |
22 | 20 | import org.thingsboard.rule.engine.api.NodeConfiguration; |
23 | -import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; | |
24 | -import org.thingsboard.rule.engine.api.RuleNode; | |
25 | -import org.thingsboard.rule.engine.api.TbContext; | |
26 | -import org.thingsboard.rule.engine.api.TbNode; | |
27 | -import org.thingsboard.rule.engine.api.TbNodeConfiguration; | |
28 | -import org.thingsboard.rule.engine.api.TbNodeException; | |
29 | -import org.thingsboard.server.common.data.DataConstants; | |
30 | -import org.thingsboard.server.common.data.Device; | |
31 | -import org.thingsboard.server.common.data.DeviceProfile; | |
32 | -import org.thingsboard.server.common.data.EntityType; | |
33 | -import org.thingsboard.server.common.data.id.DeviceId; | |
34 | -import org.thingsboard.server.common.data.id.DeviceProfileId; | |
35 | -import org.thingsboard.server.common.data.plugin.ComponentType; | |
36 | -import org.thingsboard.server.common.msg.TbMsg; | |
37 | -import org.thingsboard.server.common.msg.TbMsgMetaData; | |
38 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | |
39 | - | |
40 | -import java.util.Map; | |
41 | -import java.util.concurrent.ConcurrentHashMap; | |
42 | -import java.util.concurrent.ExecutionException; | |
43 | -import java.util.concurrent.TimeUnit; | |
44 | 21 | |
45 | 22 | @Data |
46 | 23 | @JsonIgnoreProperties(ignoreUnknown = true) | ... | ... |
... | ... | @@ -45,9 +45,21 @@ |
45 | 45 | </properties> |
46 | 46 | |
47 | 47 | <dependencies> |
48 | +<!-- <dependency>--> | |
49 | +<!-- <groupId>org.thingsboard.common.transport</groupId>--> | |
50 | +<!-- <artifactId>transport-api</artifactId>--> | |
51 | +<!-- </dependency>--> | |
48 | 52 | <dependency> |
49 | 53 | <groupId>org.thingsboard.common.transport</groupId> |
50 | - <artifactId>transport-api</artifactId> | |
54 | + <artifactId>lwm2m</artifactId> | |
55 | + </dependency> | |
56 | + <dependency> | |
57 | + <groupId>org.thingsboard.common</groupId> | |
58 | + <artifactId>queue</artifactId> | |
59 | + </dependency> | |
60 | + <dependency> | |
61 | + <groupId>org.thingsboard.common</groupId> | |
62 | + <artifactId>cache</artifactId> | |
51 | 63 | </dependency> |
52 | 64 | <dependency> |
53 | 65 | <groupId>org.springframework</groupId> | ... | ... |
transport/lwm2m/src/main/java/org/thingsboard/server/lwm2m/ThingsboardLwm2mTransportApplication.java
... | ... | @@ -26,7 +26,7 @@ import java.util.Arrays; |
26 | 26 | @SpringBootConfiguration |
27 | 27 | @EnableAsync |
28 | 28 | @EnableScheduling |
29 | -@ComponentScan({"org.thingsboard.server.lwm2m", "org.thingsboard.server.common", "org.thingsboard.server.transport.lwm2m", "org.thingsboard.server.queue"}) | |
29 | +@ComponentScan({"org.thingsboard.server.lwm2m", "org.thingsboard.server.common", "org.thingsboard.server.transport.lwm2m", "org.thingsboard.server.queue", "org.thingsboard.server.cache"}) | |
30 | 30 | public class ThingsboardLwm2mTransportApplication { |
31 | 31 | |
32 | 32 | private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name"; | ... | ... |
... | ... | @@ -40,6 +40,83 @@ zk: |
40 | 40 | # Name of the directory in zookeeper 'filesystem' |
41 | 41 | zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" |
42 | 42 | |
43 | +cache: | |
44 | + # caffeine or redis | |
45 | + type: "${CACHE_TYPE:caffeine}" | |
46 | + | |
47 | +caffeine: | |
48 | + specs: | |
49 | + relations: | |
50 | + timeToLiveInMinutes: 1440 | |
51 | + maxSize: 0 | |
52 | + deviceCredentials: | |
53 | + timeToLiveInMinutes: 1440 | |
54 | + maxSize: 0 | |
55 | + devices: | |
56 | + timeToLiveInMinutes: 1440 | |
57 | + maxSize: 0 | |
58 | + sessions: | |
59 | + timeToLiveInMinutes: 1440 | |
60 | + maxSize: 0 | |
61 | + assets: | |
62 | + timeToLiveInMinutes: 1440 | |
63 | + maxSize: 0 | |
64 | + entityViews: | |
65 | + timeToLiveInMinutes: 1440 | |
66 | + maxSize: 0 | |
67 | + claimDevices: | |
68 | + timeToLiveInMinutes: 1 | |
69 | + maxSize: 0 | |
70 | + securitySettings: | |
71 | + timeToLiveInMinutes: 1440 | |
72 | + maxSize: 0 | |
73 | + tenantProfiles: | |
74 | + timeToLiveInMinutes: 1440 | |
75 | + maxSize: 0 | |
76 | + deviceProfiles: | |
77 | + timeToLiveInMinutes: 1440 | |
78 | + maxSize: 0 | |
79 | + | |
80 | +redis: | |
81 | + # standalone or cluster | |
82 | + connection: | |
83 | + type: "${REDIS_CONNECTION_TYPE:standalone}" | |
84 | + standalone: | |
85 | + host: "${REDIS_HOST:localhost}" | |
86 | + port: "${REDIS_PORT:6379}" | |
87 | + useDefaultClientConfig: "${REDIS_USE_DEFAULT_CLIENT_CONFIG:true}" | |
88 | + # this value may be used only if you used not default ClientConfig | |
89 | + clientName: "${REDIS_CLIENT_NAME:standalone}" | |
90 | + # this value may be used only if you used not default ClientConfig | |
91 | + connectTimeout: "${REDIS_CLIENT_CONNECT_TIMEOUT:30000}" | |
92 | + # this value may be used only if you used not default ClientConfig | |
93 | + readTimeout: "${REDIS_CLIENT_READ_TIMEOUT:60000}" | |
94 | + # this value may be used only if you used not default ClientConfig | |
95 | + usePoolConfig: "${REDIS_CLIENT_USE_POOL_CONFIG:false}" | |
96 | + cluster: | |
97 | + # Comma-separated list of "host:port" pairs to bootstrap from. | |
98 | + nodes: "${REDIS_NODES:}" | |
99 | + # Maximum number of redirects to follow when executing commands across the cluster. | |
100 | + max-redirects: "${REDIS_MAX_REDIRECTS:12}" | |
101 | + useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" | |
102 | + # db index | |
103 | + db: "${REDIS_DB:0}" | |
104 | + # db password | |
105 | + password: "${REDIS_PASSWORD:}" | |
106 | + # pool config | |
107 | + pool_config: | |
108 | + maxTotal: "${REDIS_POOL_CONFIG_MAX_TOTAL:128}" | |
109 | + maxIdle: "${REDIS_POOL_CONFIG_MAX_IDLE:128}" | |
110 | + minIdle: "${REDIS_POOL_CONFIG_MIN_IDLE:16}" | |
111 | + testOnBorrow: "${REDIS_POOL_CONFIG_TEST_ON_BORROW:true}" | |
112 | + testOnReturn: "${REDIS_POOL_CONFIG_TEST_ON_RETURN:true}" | |
113 | + testWhileIdle: "${REDIS_POOL_CONFIG_TEST_WHILE_IDLE:true}" | |
114 | + minEvictableMs: "${REDIS_POOL_CONFIG_MIN_EVICTABLE_MS:60000}" | |
115 | + evictionRunsMs: "${REDIS_POOL_CONFIG_EVICTION_RUNS_MS:30000}" | |
116 | + maxWaitMills: "${REDIS_POOL_CONFIG_MAX_WAIT_MS:60000}" | |
117 | + numberTestsPerEvictionRun: "${REDIS_POOL_CONFIG_NUMBER_TESTS_PER_EVICTION_RUN:3}" | |
118 | + blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}" | |
119 | + | |
43 | 120 | # LWM2M server parameters |
44 | 121 | transport: |
45 | 122 | # Local LwM2M transport parameters |
... | ... | @@ -102,8 +179,8 @@ transport: |
102 | 179 | public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
103 | 180 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509: |
104 | 181 | alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}" |
105 | - # Redis | |
106 | - redis_url: "${LWM2M_REDIS_URL:''}" | |
182 | + # Use redis for Security and Registration stores | |
183 | + redis.enabled: "${LWM2M_REDIS_ENABLED:false}" | |
107 | 184 | |
108 | 185 | sessions: |
109 | 186 | inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" | ... | ... |
... | ... | @@ -88,6 +88,9 @@ |
88 | 88 | <mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('required')"> |
89 | 89 | {{ 'device.lwm2m-value-required' | translate }} |
90 | 90 | </mat-error> |
91 | + <mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('jsonError')"> | |
92 | + {{ 'device.lwm2m-value-json-error' | translate }} | |
93 | + </mat-error> | |
91 | 94 | <div mat-dialog-actions fxLayoutAlign="center center"> |
92 | 95 | <button mat-raised-button color="primary" |
93 | 96 | matTooltip="{{'device.lwm2m-value-edit-tip' | translate }}" | ... | ... |
... | ... | @@ -14,7 +14,7 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; | |
17 | +import {Component, forwardRef, Input, OnDestroy, OnInit} from '@angular/core'; | |
18 | 18 | import { |
19 | 19 | ControlValueAccessor, |
20 | 20 | FormBuilder, |
... | ... | @@ -33,19 +33,19 @@ import { |
33 | 33 | DeviceCredentials, |
34 | 34 | DeviceCredentialsType |
35 | 35 | } from '@shared/models/device.models'; |
36 | -import { Subscription } from 'rxjs'; | |
37 | -import { distinctUntilChanged } from 'rxjs/operators'; | |
38 | -import { SecurityConfigComponent } from '@home/pages/device/lwm2m/security-config.component'; | |
36 | +import {Subscription} from 'rxjs'; | |
37 | +import {distinctUntilChanged} from 'rxjs/operators'; | |
38 | +import {SecurityConfigComponent} from '@home/pages/device/lwm2m/security-config.component'; | |
39 | 39 | import { |
40 | 40 | DEFAULT_END_POINT, |
41 | 41 | DeviceCredentialsDialogLwm2mData, |
42 | 42 | END_POINT, |
43 | 43 | getDefaultSecurityConfig, |
44 | - JSON_ALL_CONFIG | |
44 | + JSON_ALL_CONFIG, SecurityConfigModels, validateSecurityConfig | |
45 | 45 | } from '@home/pages/device/lwm2m/security-config.models'; |
46 | -import { TranslateService } from '@ngx-translate/core'; | |
47 | -import { MatDialog } from '@angular/material/dialog'; | |
48 | -import { isDefinedAndNotNull } from '@core/utils'; | |
46 | +import {TranslateService} from '@ngx-translate/core'; | |
47 | +import {MatDialog} from '@angular/material/dialog'; | |
48 | +import {isDefinedAndNotNull} from '@core/utils'; | |
49 | 49 | |
50 | 50 | @Component({ |
51 | 51 | selector: 'tb-device-credentials', |
... | ... | @@ -196,13 +196,19 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, |
196 | 196 | this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false}); |
197 | 197 | break; |
198 | 198 | case DeviceCredentialsType.X509_CERTIFICATE: |
199 | - case DeviceCredentialsType.LWM2M_CREDENTIALS: | |
200 | 199 | this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required]); |
201 | 200 | this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false}); |
202 | 201 | this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]); |
203 | 202 | this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false}); |
204 | 203 | this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false}); |
205 | 204 | break; |
205 | + case DeviceCredentialsType.LWM2M_CREDENTIALS: | |
206 | + this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required, this.jsonValidator]); | |
207 | + this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false}); | |
208 | + this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]); | |
209 | + this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false}); | |
210 | + this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false}); | |
211 | + break; | |
206 | 212 | case DeviceCredentialsType.MQTT_BASIC: |
207 | 213 | this.deviceCredentialsFormGroup.get('credentialsBasic').enable({emitEvent: false}); |
208 | 214 | this.deviceCredentialsFormGroup.get('credentialsBasic').updateValueAndValidity({emitEvent: false}); |
... | ... | @@ -247,7 +253,11 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, |
247 | 253 | if (credentialsValue === null || credentialsValue.length === 0) { |
248 | 254 | credentialsValue = getDefaultSecurityConfig(); |
249 | 255 | } else { |
250 | - credentialsValue = JSON.parse(credentialsValue); | |
256 | + try { | |
257 | + credentialsValue = JSON.parse(credentialsValue); | |
258 | + } catch (e) { | |
259 | + credentialsValue = getDefaultSecurityConfig(); | |
260 | + } | |
251 | 261 | } |
252 | 262 | const credentialsId = this.deviceCredentialsFormGroup.get('credentialsId').value || DEFAULT_END_POINT; |
253 | 263 | this.dialog.open<SecurityConfigComponent, DeviceCredentialsDialogLwm2mData, object>(SecurityConfigComponent, { |
... | ... | @@ -273,4 +283,8 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, |
273 | 283 | private isDefautLw2mResponse(response: object): boolean { |
274 | 284 | return Object.keys(response).length === 0 || JSON.stringify(response) === '[{}]'; |
275 | 285 | } |
286 | + | |
287 | + private jsonValidator(control: FormControl) { | |
288 | + return validateSecurityConfig(control.value) ? null: {jsonError: {parsedJson: "error"}}; | |
289 | + } | |
276 | 290 | } | ... | ... |
... | ... | @@ -395,21 +395,4 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
395 | 395 | } |
396 | 396 | }); |
397 | 397 | } |
398 | - | |
399 | - isPathInJson(path: string): boolean { | |
400 | - let isPath = this.findPathInJson(path, ATTRIBUTE); | |
401 | - if (!isPath) { | |
402 | - isPath = this.findPathInJson(path, TELEMETRY); | |
403 | - } | |
404 | - return !!isPath; | |
405 | - } | |
406 | - | |
407 | - private findPathInJson = (path: string, side: string): string => { | |
408 | - if (this.configurationValue.observeAttr) { | |
409 | - if (this.configurationValue.observeAttr[side]) { | |
410 | - return this.configurationValue.bootstrap[side].find( | |
411 | - pathJs => pathJs === path); | |
412 | - } | |
413 | - } | |
414 | - } | |
415 | 398 | } | ... | ... |
... | ... | @@ -134,7 +134,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V |
134 | 134 | } |
135 | 135 | |
136 | 136 | private add(object: ObjectLwM2M): void { |
137 | - if (this.modelValue.indexOf(object.id) === -1) { | |
137 | + if (isDefinedAndNotNull(this.modelValue) && this.modelValue.indexOf(object.id) === -1) { | |
138 | 138 | this.modelValue.push(object.id); |
139 | 139 | this.objectsList.push(object); |
140 | 140 | this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList); |
... | ... | @@ -151,9 +151,6 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V |
151 | 151 | index = this.modelValue.indexOf(object.id); |
152 | 152 | this.modelValue.splice(index, 1); |
153 | 153 | this.removeList.next(object); |
154 | - if (!this.modelValue.length) { | |
155 | - this.modelValue = null; | |
156 | - } | |
157 | 154 | this.clear(); |
158 | 155 | } |
159 | 156 | } | ... | ... |
... | ... | @@ -27,7 +27,7 @@ export const DEFAULT_ID_SERVER = 123; |
27 | 27 | export const DEFAULT_ID_BOOTSTRAP = 111; |
28 | 28 | export const DEFAULT_HOST_NAME = 'localhost'; |
29 | 29 | export const DEFAULT_PORT_SERVER_NO_SEC = 5685; |
30 | -export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5686; | |
30 | +export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5687; | |
31 | 31 | export const DEFAULT_CLIENT_HOLD_OFF_TIME = 1; |
32 | 32 | export const DEFAULT_LIFE_TIME = 300; |
33 | 33 | export const DEFAULT_MIN_PERIOD = 1; | ... | ... |
... | ... | @@ -20,7 +20,6 @@ export const DEFAULT_END_POINT = 'default_client_lwm2m_end_point_no_sec'; |
20 | 20 | export const BOOTSTRAP_SERVERS = 'servers'; |
21 | 21 | export const BOOTSTRAP_SERVER = 'bootstrapServer'; |
22 | 22 | export const LWM2M_SERVER = 'lwm2mServer'; |
23 | -export const JSON_OBSERVE = 'jsonObserve'; | |
24 | 23 | export const LEN_MAX_PSK = 64; |
25 | 24 | export const LEN_MAX_PRIVATE_KEY = 134; |
26 | 25 | export const LEN_MAX_PUBLIC_KEY_RPK = 182; |
... | ... | @@ -148,4 +147,41 @@ export function getDefaultSecurityConfig(): SecurityConfigModels { |
148 | 147 | return securityConfigModels; |
149 | 148 | } |
150 | 149 | |
150 | +const isSecurityConfigModels = (p: any): p is SecurityConfigModels => | |
151 | + p.hasOwnProperty('client') && | |
152 | + isClientSecurityConfigType(p['client']) && | |
153 | + p.hasOwnProperty('bootstrap') && | |
154 | + isBootstrapSecurityConfig(p['bootstrap']); | |
155 | + | |
156 | +const isClientSecurityConfigType = (p: any): p is ClientSecurityConfigType => | |
157 | + p.hasOwnProperty('securityConfigClientMode') && | |
158 | + p.hasOwnProperty('endpoint') && | |
159 | + p.hasOwnProperty('identity') && | |
160 | + p.hasOwnProperty('key') && | |
161 | + p.hasOwnProperty('x509'); | |
162 | + | |
163 | +const isBootstrapSecurityConfig = (p: any): p is BootstrapSecurityConfig => | |
164 | + p.hasOwnProperty('bootstrapServer') && | |
165 | + isServerSecurityConfig(p['bootstrapServer']) && | |
166 | + p.hasOwnProperty('lwm2mServer') && | |
167 | + isServerSecurityConfig(p['lwm2mServer']); | |
168 | + | |
169 | +const isServerSecurityConfig = (p: any): p is ServerSecurityConfig => | |
170 | + p.hasOwnProperty('securityMode') && | |
171 | + p.hasOwnProperty('clientPublicKeyOrId') && | |
172 | + p.hasOwnProperty('clientSecretKey'); | |
173 | + | |
174 | +export function validateSecurityConfig(config: string): boolean { | |
175 | + try { | |
176 | + const securityConfig= JSON.parse(config); | |
177 | + if (isSecurityConfigModels(securityConfig)) { | |
178 | + return true; | |
179 | + } else { | |
180 | + return false; | |
181 | + } | |
182 | + } catch (e) { | |
183 | + return false; | |
184 | + } | |
185 | +} | |
186 | + | |
151 | 187 | ... | ... |
... | ... | @@ -912,6 +912,7 @@ |
912 | 912 | "lwm2m-key-required": "LwM2M Security config key is required.", |
913 | 913 | "lwm2m-value": "LwM2M Security config", |
914 | 914 | "lwm2m-value-required": "LwM2M Security config value is required.", |
915 | + "lwm2m-value-json-error": "LwM2M Security config value is not json format.", | |
915 | 916 | "lwm2m-endpoint": "Client endpoint/identity", |
916 | 917 | "lwm2m-security-info": "Security Config Info", |
917 | 918 | "lwm2m-value-edit": "Edit Security config", | ... | ... |