Commit e3292e89c15e604211fcb33a7ab45229462dd2ff
Committed by
GitHub
Merge pull request #4301 from thingsboard/develop/snmp
SNMP Transport
Showing
125 changed files
with
4868 additions
and
110 deletions
@@ -90,6 +90,10 @@ | @@ -90,6 +90,10 @@ | ||
90 | <artifactId>lwm2m</artifactId> | 90 | <artifactId>lwm2m</artifactId> |
91 | </dependency> | 91 | </dependency> |
92 | <dependency> | 92 | <dependency> |
93 | + <groupId>org.thingsboard.common.transport</groupId> | ||
94 | + <artifactId>snmp</artifactId> | ||
95 | + </dependency> | ||
96 | + <dependency> | ||
93 | <groupId>org.thingsboard</groupId> | 97 | <groupId>org.thingsboard</groupId> |
94 | <artifactId>dao</artifactId> | 98 | <artifactId>dao</artifactId> |
95 | </dependency> | 99 | </dependency> |
@@ -25,7 +25,6 @@ import org.springframework.stereotype.Service; | @@ -25,7 +25,6 @@ import org.springframework.stereotype.Service; | ||
25 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 25 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
26 | import org.thingsboard.server.actors.ActorSystemContext; | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
27 | import org.thingsboard.server.actors.DefaultTbActorSystem; | 27 | import org.thingsboard.server.actors.DefaultTbActorSystem; |
28 | -import org.thingsboard.server.actors.TbActorId; | ||
29 | import org.thingsboard.server.actors.TbActorRef; | 28 | import org.thingsboard.server.actors.TbActorRef; |
30 | import org.thingsboard.server.actors.TbActorSystem; | 29 | import org.thingsboard.server.actors.TbActorSystem; |
31 | import org.thingsboard.server.actors.TbActorSystemSettings; | 30 | import org.thingsboard.server.actors.TbActorSystemSettings; |
@@ -33,14 +32,13 @@ import org.thingsboard.server.actors.app.AppActor; | @@ -33,14 +32,13 @@ import org.thingsboard.server.actors.app.AppActor; | ||
33 | import org.thingsboard.server.actors.app.AppInitMsg; | 32 | import org.thingsboard.server.actors.app.AppInitMsg; |
34 | import org.thingsboard.server.actors.stats.StatsActor; | 33 | import org.thingsboard.server.actors.stats.StatsActor; |
35 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 34 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
36 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | ||
37 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 35 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
36 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; | ||
38 | 37 | ||
39 | import javax.annotation.PostConstruct; | 38 | import javax.annotation.PostConstruct; |
40 | import javax.annotation.PreDestroy; | 39 | import javax.annotation.PreDestroy; |
41 | import java.util.concurrent.ExecutorService; | 40 | import java.util.concurrent.ExecutorService; |
42 | import java.util.concurrent.Executors; | 41 | import java.util.concurrent.Executors; |
43 | -import java.util.concurrent.ScheduledExecutorService; | ||
44 | 42 | ||
45 | @Service | 43 | @Service |
46 | @Slf4j | 44 | @Slf4j |
application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java
@@ -56,7 +56,7 @@ import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; | @@ -56,7 +56,7 @@ import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; | ||
56 | import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; | 56 | import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
57 | import org.thingsboard.server.gen.transport.TransportProtos.UsageStatsKVProto; | 57 | import org.thingsboard.server.gen.transport.TransportProtos.UsageStatsKVProto; |
58 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 58 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
59 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 59 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
60 | import org.thingsboard.server.queue.discovery.PartitionService; | 60 | import org.thingsboard.server.queue.discovery.PartitionService; |
61 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 61 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
62 | import org.thingsboard.server.queue.scheduler.SchedulerComponent; | 62 | import org.thingsboard.server.queue.scheduler.SchedulerComponent; |
@@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantProfileId; | @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantProfileId; | ||
23 | import org.thingsboard.server.common.msg.queue.TbCallback; | 23 | import org.thingsboard.server.common.msg.queue.TbCallback; |
24 | import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; | 24 | import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
25 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 25 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
26 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 26 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
27 | 27 | ||
28 | public interface TbApiUsageStateService extends ApplicationListener<PartitionChangeEvent> { | 28 | public interface TbApiUsageStateService extends ApplicationListener<PartitionChangeEvent> { |
29 | 29 |
@@ -55,7 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceM | @@ -55,7 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceM | ||
55 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; | 55 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
56 | import org.thingsboard.server.queue.TbQueueConsumer; | 56 | import org.thingsboard.server.queue.TbQueueConsumer; |
57 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 57 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
58 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 58 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
59 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; | 59 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; |
60 | import org.thingsboard.server.queue.util.TbCoreComponent; | 60 | import org.thingsboard.server.queue.util.TbCoreComponent; |
61 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; | 61 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
@@ -38,7 +38,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | @@ -38,7 +38,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | ||
38 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; | 38 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
39 | import org.thingsboard.server.queue.TbQueueConsumer; | 39 | import org.thingsboard.server.queue.TbQueueConsumer; |
40 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 40 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
41 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 41 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
42 | import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory; | 42 | import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory; |
43 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | 43 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
44 | import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; | 44 | import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | package org.thingsboard.server.service.queue; | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | ||
18 | import org.springframework.context.ApplicationListener; | 18 | import org.springframework.context.ApplicationListener; |
19 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 19 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
20 | 20 | ||
21 | public interface TbCoreConsumerService extends ApplicationListener<PartitionChangeEvent> { | 21 | public interface TbCoreConsumerService extends ApplicationListener<PartitionChangeEvent> { |
22 | 22 |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | package org.thingsboard.server.service.queue; | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | ||
18 | import org.springframework.context.ApplicationListener; | 18 | import org.springframework.context.ApplicationListener; |
19 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 19 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
20 | 20 | ||
21 | public interface TbRuleEngineConsumerService extends ApplicationListener<PartitionChangeEvent> { | 21 | public interface TbRuleEngineConsumerService extends ApplicationListener<PartitionChangeEvent> { |
22 | 22 |
@@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; | @@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; | ||
35 | import org.thingsboard.server.common.msg.queue.TbCallback; | 35 | import org.thingsboard.server.common.msg.queue.TbCallback; |
36 | import org.thingsboard.server.queue.TbQueueConsumer; | 36 | import org.thingsboard.server.queue.TbQueueConsumer; |
37 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 37 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
38 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 38 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
39 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; | 39 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; |
40 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 40 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
41 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; | 41 | import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
@@ -54,7 +54,7 @@ import org.thingsboard.server.dao.tenant.TenantService; | @@ -54,7 +54,7 @@ import org.thingsboard.server.dao.tenant.TenantService; | ||
54 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 54 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
55 | import org.thingsboard.common.util.JacksonUtil; | 55 | import org.thingsboard.common.util.JacksonUtil; |
56 | import org.thingsboard.server.gen.transport.TransportProtos; | 56 | import org.thingsboard.server.gen.transport.TransportProtos; |
57 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 57 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
58 | import org.thingsboard.server.queue.discovery.PartitionService; | 58 | import org.thingsboard.server.queue.discovery.PartitionService; |
59 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 59 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
60 | import org.thingsboard.server.queue.util.TbCoreComponent; | 60 | import org.thingsboard.server.queue.util.TbCoreComponent; |
@@ -18,7 +18,7 @@ package org.thingsboard.server.service.state; | @@ -18,7 +18,7 @@ package org.thingsboard.server.service.state; | ||
18 | import org.springframework.context.ApplicationListener; | 18 | import org.springframework.context.ApplicationListener; |
19 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
20 | import org.thingsboard.server.common.data.id.DeviceId; | 20 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 21 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
22 | import org.thingsboard.server.gen.transport.TransportProtos; | 22 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | import org.thingsboard.server.common.msg.queue.TbCallback; | 23 | import org.thingsboard.server.common.msg.queue.TbCallback; |
24 | 24 |
@@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdate | @@ -46,7 +46,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdate | ||
46 | import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdateValueListProto; | 46 | import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdateValueListProto; |
47 | import org.thingsboard.server.queue.TbQueueProducer; | 47 | import org.thingsboard.server.queue.TbQueueProducer; |
48 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 48 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
49 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 49 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
50 | import org.thingsboard.server.queue.discovery.PartitionService; | 50 | import org.thingsboard.server.queue.discovery.PartitionService; |
51 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 51 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
52 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; | 52 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
@@ -20,10 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -20,10 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
20 | import org.springframework.context.annotation.Lazy; | 20 | import org.springframework.context.annotation.Lazy; |
21 | import org.springframework.context.event.EventListener; | 21 | import org.springframework.context.event.EventListener; |
22 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
23 | -import org.thingsboard.common.util.ThingsBoardThreadFactory; | ||
24 | import org.thingsboard.server.gen.transport.TransportProtos; | 23 | import org.thingsboard.server.gen.transport.TransportProtos; |
25 | -import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent; | ||
26 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 24 | +import org.thingsboard.server.queue.discovery.event.ClusterTopologyChangeEvent; |
25 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; | ||
27 | import org.thingsboard.server.queue.discovery.PartitionService; | 26 | import org.thingsboard.server.queue.discovery.PartitionService; |
28 | import org.thingsboard.server.common.msg.queue.ServiceType; | 27 | import org.thingsboard.server.common.msg.queue.ServiceType; |
29 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 28 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
@@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
22 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 22 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
23 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 23 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
24 | import org.thingsboard.server.common.msg.queue.TbCallback; | 24 | import org.thingsboard.server.common.msg.queue.TbCallback; |
25 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 25 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
26 | 26 | ||
27 | import java.util.List; | 27 | import java.util.List; |
28 | 28 |
@@ -15,8 +15,8 @@ | @@ -15,8 +15,8 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.subscription; | 16 | package org.thingsboard.server.service.subscription; |
17 | 17 | ||
18 | -import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent; | ||
19 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 18 | +import org.thingsboard.server.queue.discovery.event.ClusterTopologyChangeEvent; |
19 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; | ||
20 | import org.thingsboard.server.common.msg.queue.TbCallback; | 20 | import org.thingsboard.server.common.msg.queue.TbCallback; |
21 | import org.thingsboard.server.service.telemetry.sub.AlarmSubscriptionUpdate; | 21 | import org.thingsboard.server.service.telemetry.sub.AlarmSubscriptionUpdate; |
22 | import org.thingsboard.server.service.telemetry.sub.TelemetrySubscriptionUpdate; | 22 | import org.thingsboard.server.service.telemetry.sub.TelemetrySubscriptionUpdate; |
@@ -22,35 +22,18 @@ import lombok.extern.slf4j.Slf4j; | @@ -22,35 +22,18 @@ import lombok.extern.slf4j.Slf4j; | ||
22 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | import org.springframework.context.ApplicationListener; | 23 | import org.springframework.context.ApplicationListener; |
24 | import org.springframework.context.event.EventListener; | 24 | import org.springframework.context.event.EventListener; |
25 | -import org.springframework.stereotype.Service; | ||
26 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 25 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
27 | -import org.thingsboard.server.common.data.id.EntityId; | ||
28 | -import org.thingsboard.server.common.data.id.TenantId; | ||
29 | -import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
30 | -import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | ||
31 | -import org.thingsboard.server.common.data.kv.BooleanDataEntry; | ||
32 | -import org.thingsboard.server.common.data.kv.DoubleDataEntry; | ||
33 | -import org.thingsboard.server.common.data.kv.LongDataEntry; | ||
34 | -import org.thingsboard.server.common.data.kv.StringDataEntry; | ||
35 | -import org.thingsboard.server.common.data.kv.TsKvEntry; | ||
36 | import org.thingsboard.server.common.msg.queue.ServiceType; | 26 | import org.thingsboard.server.common.msg.queue.ServiceType; |
37 | -import org.thingsboard.server.common.msg.queue.TbCallback; | ||
38 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 27 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
39 | -import org.thingsboard.server.dao.attributes.AttributesService; | ||
40 | -import org.thingsboard.server.dao.timeseries.TimeseriesService; | ||
41 | -import org.thingsboard.server.gen.transport.TransportProtos; | ||
42 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 28 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
43 | import org.thingsboard.server.queue.discovery.PartitionService; | 29 | import org.thingsboard.server.queue.discovery.PartitionService; |
44 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | 30 | import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
45 | import org.thingsboard.server.service.queue.TbClusterService; | 31 | import org.thingsboard.server.service.queue.TbClusterService; |
46 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; | 32 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; |
47 | -import org.thingsboard.server.service.subscription.TbSubscriptionUtils; | ||
48 | 33 | ||
49 | import javax.annotation.Nullable; | 34 | import javax.annotation.Nullable; |
50 | import javax.annotation.PostConstruct; | 35 | import javax.annotation.PostConstruct; |
51 | import javax.annotation.PreDestroy; | 36 | import javax.annotation.PreDestroy; |
52 | -import java.util.Collections; | ||
53 | -import java.util.List; | ||
54 | import java.util.Optional; | 37 | import java.util.Optional; |
55 | import java.util.Set; | 38 | import java.util.Set; |
56 | import java.util.concurrent.ConcurrentHashMap; | 39 | import java.util.concurrent.ConcurrentHashMap; |
@@ -17,8 +17,7 @@ package org.thingsboard.server.service.telemetry; | @@ -17,8 +17,7 @@ package org.thingsboard.server.service.telemetry; | ||
17 | 17 | ||
18 | import org.springframework.context.ApplicationListener; | 18 | import org.springframework.context.ApplicationListener; |
19 | import org.thingsboard.rule.engine.api.RuleEngineAlarmService; | 19 | import org.thingsboard.rule.engine.api.RuleEngineAlarmService; |
20 | -import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; | ||
21 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 20 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
22 | 21 | ||
23 | /** | 22 | /** |
24 | * Created by ashvayka on 27.03.18. | 23 | * Created by ashvayka on 27.03.18. |
application/src/main/java/org/thingsboard/server/service/telemetry/TelemetrySubscriptionService.java
@@ -16,8 +16,7 @@ | @@ -16,8 +16,7 @@ | ||
16 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
17 | 17 | ||
18 | import org.springframework.context.ApplicationListener; | 18 | import org.springframework.context.ApplicationListener; |
19 | -import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; | ||
20 | -import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 19 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
21 | 20 | ||
22 | /** | 21 | /** |
23 | * Created by ashvayka on 27.03.18. | 22 | * Created by ashvayka on 27.03.18. |
@@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.ApiUsageState; | @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.ApiUsageState; | ||
31 | import org.thingsboard.server.common.data.DataConstants; | 31 | import org.thingsboard.server.common.data.DataConstants; |
32 | import org.thingsboard.server.common.data.Device; | 32 | import org.thingsboard.server.common.data.Device; |
33 | import org.thingsboard.server.common.data.DeviceProfile; | 33 | import org.thingsboard.server.common.data.DeviceProfile; |
34 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
34 | import org.thingsboard.server.common.data.EntityType; | 35 | import org.thingsboard.server.common.data.EntityType; |
35 | import org.thingsboard.server.common.data.Firmware; | 36 | import org.thingsboard.server.common.data.Firmware; |
36 | import org.thingsboard.server.common.data.FirmwareInfo; | 37 | import org.thingsboard.server.common.data.FirmwareInfo; |
@@ -45,6 +46,8 @@ import org.thingsboard.server.common.data.id.DeviceId; | @@ -45,6 +46,8 @@ import org.thingsboard.server.common.data.id.DeviceId; | ||
45 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 46 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
46 | import org.thingsboard.server.common.data.id.FirmwareId; | 47 | import org.thingsboard.server.common.data.id.FirmwareId; |
47 | import org.thingsboard.server.common.data.id.TenantId; | 48 | import org.thingsboard.server.common.data.id.TenantId; |
49 | +import org.thingsboard.server.common.data.page.PageData; | ||
50 | +import org.thingsboard.server.common.data.page.PageLink; | ||
48 | import org.thingsboard.server.common.data.relation.EntityRelation; | 51 | import org.thingsboard.server.common.data.relation.EntityRelation; |
49 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 52 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
50 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 53 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
@@ -64,11 +67,15 @@ import org.thingsboard.server.dao.relation.RelationService; | @@ -64,11 +67,15 @@ import org.thingsboard.server.dao.relation.RelationService; | ||
64 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 67 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
65 | import org.thingsboard.server.gen.transport.TransportProtos; | 68 | import org.thingsboard.server.gen.transport.TransportProtos; |
66 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; | 69 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
70 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceCredentialsRequestMsg; | ||
71 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceRequestMsg; | ||
67 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; | 72 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; |
68 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; | 73 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; |
69 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; | 74 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; |
70 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg; | 75 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg; |
71 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg; | 76 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg; |
77 | +import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRequestMsg; | ||
78 | +import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesResponseMsg; | ||
72 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; | 79 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
73 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | 80 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
74 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; | 81 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
@@ -91,6 +98,7 @@ import java.util.concurrent.ConcurrentHashMap; | @@ -91,6 +98,7 @@ import java.util.concurrent.ConcurrentHashMap; | ||
91 | import java.util.concurrent.ConcurrentMap; | 98 | import java.util.concurrent.ConcurrentMap; |
92 | import java.util.concurrent.locks.Lock; | 99 | import java.util.concurrent.locks.Lock; |
93 | import java.util.concurrent.locks.ReentrantLock; | 100 | import java.util.concurrent.locks.ReentrantLock; |
101 | +import java.util.stream.Collectors; | ||
94 | 102 | ||
95 | /** | 103 | /** |
96 | * Created by ashvayka on 05.10.18. | 104 | * Created by ashvayka on 05.10.18. |
@@ -144,43 +152,43 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -144,43 +152,43 @@ public class DefaultTransportApiService implements TransportApiService { | ||
144 | @Override | 152 | @Override |
145 | public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle(TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) { | 153 | public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle(TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) { |
146 | TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue(); | 154 | TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue(); |
155 | + ListenableFuture<TransportApiResponseMsg> result = null; | ||
156 | + | ||
147 | if (transportApiRequestMsg.hasValidateTokenRequestMsg()) { | 157 | if (transportApiRequestMsg.hasValidateTokenRequestMsg()) { |
148 | ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg(); | 158 | ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg(); |
149 | - return Futures.transform(validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN), | ||
150 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 159 | + result = validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN); |
151 | } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) { | 160 | } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) { |
152 | TransportProtos.ValidateBasicMqttCredRequestMsg msg = transportApiRequestMsg.getValidateBasicMqttCredRequestMsg(); | 161 | TransportProtos.ValidateBasicMqttCredRequestMsg msg = transportApiRequestMsg.getValidateBasicMqttCredRequestMsg(); |
153 | - return Futures.transform(validateCredentials(msg), | ||
154 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 162 | + result = validateCredentials(msg); |
155 | } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) { | 163 | } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) { |
156 | ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg(); | 164 | ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg(); |
157 | - return Futures.transform(validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE), | ||
158 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 165 | + result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE); |
159 | } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) { | 166 | } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) { |
160 | - return Futures.transform(handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg()), | ||
161 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 167 | + result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg()); |
162 | } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { | 168 | } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { |
163 | - return Futures.transform(handle(transportApiRequestMsg.getEntityProfileRequestMsg()), | ||
164 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 169 | + result = handle(transportApiRequestMsg.getEntityProfileRequestMsg()); |
165 | } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) { | 170 | } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) { |
166 | - return Futures.transform(handle(transportApiRequestMsg.getLwM2MRequestMsg()), | ||
167 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 171 | + result = handle(transportApiRequestMsg.getLwM2MRequestMsg()); |
168 | } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) { | 172 | } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) { |
169 | ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg(); | 173 | ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg(); |
170 | - return Futures.transform(validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS), | ||
171 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 174 | + result = validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS); |
172 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { | 175 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { |
173 | - return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), | ||
174 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 176 | + result = handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()); |
175 | } else if (transportApiRequestMsg.hasResourceRequestMsg()) { | 177 | } else if (transportApiRequestMsg.hasResourceRequestMsg()) { |
176 | - return Futures.transform(handle(transportApiRequestMsg.getResourceRequestMsg()), | ||
177 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 178 | + result = handle(transportApiRequestMsg.getResourceRequestMsg()); |
179 | + } else if (transportApiRequestMsg.hasSnmpDevicesRequestMsg()) { | ||
180 | + result = handle(transportApiRequestMsg.getSnmpDevicesRequestMsg()); | ||
181 | + } else if (transportApiRequestMsg.hasDeviceRequestMsg()) { | ||
182 | + result = handle(transportApiRequestMsg.getDeviceRequestMsg()); | ||
183 | + } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) { | ||
184 | + result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg()); | ||
178 | } else if (transportApiRequestMsg.hasFirmwareRequestMsg()) { | 185 | } else if (transportApiRequestMsg.hasFirmwareRequestMsg()) { |
179 | - return Futures.transform(handle(transportApiRequestMsg.getFirmwareRequestMsg()), | ||
180 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 186 | + result = handle(transportApiRequestMsg.getFirmwareRequestMsg()); |
181 | } | 187 | } |
182 | - return Futures.transform(getEmptyTransportApiResponseFuture(), | ||
183 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 188 | + |
189 | + return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture), | ||
190 | + value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), | ||
191 | + MoreExecutors.directExecutor()); | ||
184 | } | 192 | } |
185 | 193 | ||
186 | private ListenableFuture<TransportApiResponseMsg> validateCredentials(String credentialsId, DeviceCredentialsType credentialsType) { | 194 | private ListenableFuture<TransportApiResponseMsg> validateCredentials(String credentialsId, DeviceCredentialsType credentialsType) { |
@@ -374,6 +382,39 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -374,6 +382,39 @@ public class DefaultTransportApiService implements TransportApiService { | ||
374 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); | 382 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); |
375 | } | 383 | } |
376 | 384 | ||
385 | + private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceRequestMsg requestMsg) { | ||
386 | + DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
387 | + Device device = deviceService.findDeviceById(TenantId.SYS_TENANT_ID, deviceId); | ||
388 | + | ||
389 | + TransportApiResponseMsg responseMsg; | ||
390 | + if (device != null) { | ||
391 | + UUID deviceProfileId = device.getDeviceProfileId().getId(); | ||
392 | + responseMsg = TransportApiResponseMsg.newBuilder() | ||
393 | + .setDeviceResponseMsg(TransportProtos.GetDeviceResponseMsg.newBuilder() | ||
394 | + .setDeviceProfileIdMSB(deviceProfileId.getMostSignificantBits()) | ||
395 | + .setDeviceProfileIdLSB(deviceProfileId.getLeastSignificantBits()) | ||
396 | + .setDeviceTransportConfiguration(ByteString.copyFrom( | ||
397 | + dataDecodingEncodingService.encode(device.getDeviceData().getTransportConfiguration()) | ||
398 | + ))) | ||
399 | + .build(); | ||
400 | + } else { | ||
401 | + responseMsg = TransportApiResponseMsg.getDefaultInstance(); | ||
402 | + } | ||
403 | + | ||
404 | + return Futures.immediateFuture(responseMsg); | ||
405 | + } | ||
406 | + | ||
407 | + private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceCredentialsRequestMsg requestMsg) { | ||
408 | + DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
409 | + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId); | ||
410 | + | ||
411 | + return Futures.immediateFuture(TransportApiResponseMsg.newBuilder() | ||
412 | + .setDeviceCredentialsResponseMsg(TransportProtos.GetDeviceCredentialsResponseMsg.newBuilder() | ||
413 | + .setDeviceCredentialsData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceCredentials)))) | ||
414 | + .build()); | ||
415 | + } | ||
416 | + | ||
417 | + | ||
377 | private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) { | 418 | private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) { |
378 | TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | 419 | TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); |
379 | ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType()); | 420 | ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType()); |
@@ -392,6 +433,22 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -392,6 +433,22 @@ public class DefaultTransportApiService implements TransportApiService { | ||
392 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build()); | 433 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build()); |
393 | } | 434 | } |
394 | 435 | ||
436 | + private ListenableFuture<TransportApiResponseMsg> handle(GetSnmpDevicesRequestMsg requestMsg) { | ||
437 | + PageLink pageLink = new PageLink(requestMsg.getPageSize(), requestMsg.getPage()); | ||
438 | + PageData<UUID> result = deviceService.findDevicesIdsByDeviceProfileTransportType(DeviceTransportType.SNMP, pageLink); | ||
439 | + | ||
440 | + GetSnmpDevicesResponseMsg responseMsg = GetSnmpDevicesResponseMsg.newBuilder() | ||
441 | + .addAllIds(result.getData().stream() | ||
442 | + .map(UUID::toString) | ||
443 | + .collect(Collectors.toList())) | ||
444 | + .setHasNextPage(result.hasNext()) | ||
445 | + .build(); | ||
446 | + | ||
447 | + return Futures.immediateFuture(TransportApiResponseMsg.newBuilder() | ||
448 | + .setSnmpDevicesResponseMsg(responseMsg) | ||
449 | + .build()); | ||
450 | + } | ||
451 | + | ||
395 | private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { | 452 | private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { |
396 | return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { | 453 | return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { |
397 | if (device == null) { | 454 | if (device == null) { |
@@ -26,6 +26,7 @@ | @@ -26,6 +26,7 @@ | ||
26 | </appender> | 26 | </appender> |
27 | 27 | ||
28 | <logger name="org.thingsboard.server" level="INFO" /> | 28 | <logger name="org.thingsboard.server" level="INFO" /> |
29 | + <logger name="org.thingsboard.server.transport.snmp" level="TRACE" /> | ||
29 | 30 | ||
30 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> | 31 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> |
31 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> | 32 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> |
@@ -686,6 +686,13 @@ transport: | @@ -686,6 +686,13 @@ transport: | ||
686 | alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" | 686 | alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" |
687 | # Use redis for Security and Registration stores | 687 | # Use redis for Security and Registration stores |
688 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" | 688 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" |
689 | + snmp: | ||
690 | + enabled: "${SNMP_ENABLED:true}" | ||
691 | + response_processing: | ||
692 | + # parallelism level for executor (workStealingPool) that is responsible for handling responses from SNMP devices | ||
693 | + parallelism_level: "${SNMP_RESPONSE_PROCESSING_PARALLELISM_LEVEL:20}" | ||
694 | + # to configure SNMP to work over UDP or TCP | ||
695 | + underlying_protocol: "${SNMP_UNDERLYING_PROTOCOL:udp}" | ||
689 | 696 | ||
690 | # Edges parameters | 697 | # Edges parameters |
691 | edges: | 698 | edges: |
@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
19 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
20 | import org.thingsboard.server.common.data.DeviceInfo; | 20 | import org.thingsboard.server.common.data.DeviceInfo; |
21 | import org.thingsboard.server.common.data.DeviceProfile; | 21 | import org.thingsboard.server.common.data.DeviceProfile; |
22 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
22 | import org.thingsboard.server.common.data.EntitySubtype; | 23 | import org.thingsboard.server.common.data.EntitySubtype; |
23 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 24 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
24 | import org.thingsboard.server.common.data.id.CustomerId; | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
@@ -32,6 +33,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; | @@ -32,6 +33,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
32 | import org.thingsboard.server.dao.device.provision.ProvisionRequest; | 33 | import org.thingsboard.server.dao.device.provision.ProvisionRequest; |
33 | 34 | ||
34 | import java.util.List; | 35 | import java.util.List; |
36 | +import java.util.UUID; | ||
35 | 37 | ||
36 | public interface DeviceService { | 38 | public interface DeviceService { |
37 | 39 | ||
@@ -93,6 +95,8 @@ public interface DeviceService { | @@ -93,6 +95,8 @@ public interface DeviceService { | ||
93 | 95 | ||
94 | Device saveDevice(ProvisionRequest provisionRequest, DeviceProfile profile); | 96 | Device saveDevice(ProvisionRequest provisionRequest, DeviceProfile profile); |
95 | 97 | ||
98 | + PageData<UUID> findDevicesIdsByDeviceProfileTransportType(DeviceTransportType transportType, PageLink pageLink); | ||
99 | + | ||
96 | Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); | 100 | Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); |
97 | 101 | ||
98 | Device unassignDeviceFromEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); | 102 | Device unassignDeviceFromEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); |
@@ -87,6 +87,10 @@ | @@ -87,6 +87,10 @@ | ||
87 | <groupId>org.thingsboard</groupId> | 87 | <groupId>org.thingsboard</groupId> |
88 | <artifactId>protobuf-dynamic</artifactId> | 88 | <artifactId>protobuf-dynamic</artifactId> |
89 | </dependency> | 89 | </dependency> |
90 | + <dependency> | ||
91 | + <groupId>org.apache.commons</groupId> | ||
92 | + <artifactId>commons-lang3</artifactId> | ||
93 | + </dependency> | ||
90 | </dependencies> | 94 | </dependencies> |
91 | 95 | ||
92 | <build> | 96 | <build> |
@@ -18,6 +18,7 @@ package org.thingsboard.server.common.data; | @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data; | ||
18 | public enum DeviceTransportType { | 18 | public enum DeviceTransportType { |
19 | DEFAULT, | 19 | DEFAULT, |
20 | MQTT, | 20 | MQTT, |
21 | + COAP, | ||
21 | LWM2M, | 22 | LWM2M, |
22 | - COAP | 23 | + SNMP |
23 | } | 24 | } |
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.common.data; | ||
17 | + | ||
18 | +public interface TbTransportService { | ||
19 | + String getName(); | ||
20 | +} |
@@ -21,6 +21,8 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; | @@ -21,6 +21,8 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; | ||
21 | import com.fasterxml.jackson.annotation.JsonTypeInfo; | 21 | import com.fasterxml.jackson.annotation.JsonTypeInfo; |
22 | import org.thingsboard.server.common.data.DeviceTransportType; | 22 | import org.thingsboard.server.common.data.DeviceTransportType; |
23 | 23 | ||
24 | +import java.io.Serializable; | ||
25 | + | ||
24 | @JsonIgnoreProperties(ignoreUnknown = true) | 26 | @JsonIgnoreProperties(ignoreUnknown = true) |
25 | @JsonTypeInfo( | 27 | @JsonTypeInfo( |
26 | use = JsonTypeInfo.Id.NAME, | 28 | use = JsonTypeInfo.Id.NAME, |
@@ -29,11 +31,14 @@ import org.thingsboard.server.common.data.DeviceTransportType; | @@ -29,11 +31,14 @@ import org.thingsboard.server.common.data.DeviceTransportType; | ||
29 | @JsonSubTypes({ | 31 | @JsonSubTypes({ |
30 | @JsonSubTypes.Type(value = DefaultDeviceTransportConfiguration.class, name = "DEFAULT"), | 32 | @JsonSubTypes.Type(value = DefaultDeviceTransportConfiguration.class, name = "DEFAULT"), |
31 | @JsonSubTypes.Type(value = MqttDeviceTransportConfiguration.class, name = "MQTT"), | 33 | @JsonSubTypes.Type(value = MqttDeviceTransportConfiguration.class, name = "MQTT"), |
34 | + @JsonSubTypes.Type(value = CoapDeviceTransportConfiguration.class, name = "COAP"), | ||
32 | @JsonSubTypes.Type(value = Lwm2mDeviceTransportConfiguration.class, name = "LWM2M"), | 35 | @JsonSubTypes.Type(value = Lwm2mDeviceTransportConfiguration.class, name = "LWM2M"), |
33 | - @JsonSubTypes.Type(value = CoapDeviceTransportConfiguration.class, name = "COAP")}) | ||
34 | -public interface DeviceTransportConfiguration { | ||
35 | - | 36 | + @JsonSubTypes.Type(value = SnmpDeviceTransportConfiguration.class, name = "SNMP")}) |
37 | +public interface DeviceTransportConfiguration extends Serializable { | ||
36 | @JsonIgnore | 38 | @JsonIgnore |
37 | DeviceTransportType getType(); | 39 | DeviceTransportType getType(); |
38 | 40 | ||
41 | + default void validate() { | ||
42 | + } | ||
43 | + | ||
39 | } | 44 | } |
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.common.data.device.data; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.ToString; | ||
21 | +import org.apache.commons.lang3.ObjectUtils; | ||
22 | +import org.apache.commons.lang3.StringUtils; | ||
23 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
24 | +import org.thingsboard.server.common.data.transport.snmp.AuthenticationProtocol; | ||
25 | +import org.thingsboard.server.common.data.transport.snmp.PrivacyProtocol; | ||
26 | +import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion; | ||
27 | + | ||
28 | +import java.util.Objects; | ||
29 | + | ||
30 | +@Data | ||
31 | +@ToString(of = {"host", "port", "protocolVersion"}) | ||
32 | +public class SnmpDeviceTransportConfiguration implements DeviceTransportConfiguration { | ||
33 | + private String host; | ||
34 | + private Integer port; | ||
35 | + private SnmpProtocolVersion protocolVersion; | ||
36 | + | ||
37 | + /* | ||
38 | + * For SNMP v1 and v2c | ||
39 | + * */ | ||
40 | + private String community; | ||
41 | + | ||
42 | + /* | ||
43 | + * For SNMP v3 | ||
44 | + * */ | ||
45 | + private String username; | ||
46 | + private String securityName; | ||
47 | + private String contextName; | ||
48 | + private AuthenticationProtocol authenticationProtocol; | ||
49 | + private String authenticationPassphrase; | ||
50 | + private PrivacyProtocol privacyProtocol; | ||
51 | + private String privacyPassphrase; | ||
52 | + private String engineId; | ||
53 | + | ||
54 | + @Override | ||
55 | + public DeviceTransportType getType() { | ||
56 | + return DeviceTransportType.SNMP; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public void validate() { | ||
61 | + if (!isValid()) { | ||
62 | + throw new IllegalArgumentException("Transport configuration is not valid"); | ||
63 | + } | ||
64 | + } | ||
65 | + | ||
66 | + @JsonIgnore | ||
67 | + private boolean isValid() { | ||
68 | + boolean isValid = StringUtils.isNotBlank(host) && port != null && protocolVersion != null; | ||
69 | + if (isValid) { | ||
70 | + switch (protocolVersion) { | ||
71 | + case V1: | ||
72 | + case V2C: | ||
73 | + isValid = StringUtils.isNotEmpty(community); | ||
74 | + break; | ||
75 | + case V3: | ||
76 | + isValid = StringUtils.isNotBlank(username) && StringUtils.isNotBlank(securityName) | ||
77 | + && contextName != null && authenticationProtocol != null | ||
78 | + && StringUtils.isNotBlank(authenticationPassphrase) | ||
79 | + && privacyProtocol != null && privacyPassphrase != null && engineId != null; | ||
80 | + break; | ||
81 | + } | ||
82 | + } | ||
83 | + return isValid; | ||
84 | + } | ||
85 | +} |
@@ -29,13 +29,18 @@ import java.io.Serializable; | @@ -29,13 +29,18 @@ import java.io.Serializable; | ||
29 | include = JsonTypeInfo.As.PROPERTY, | 29 | include = JsonTypeInfo.As.PROPERTY, |
30 | property = "type") | 30 | property = "type") |
31 | @JsonSubTypes({ | 31 | @JsonSubTypes({ |
32 | - @JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"), | ||
33 | - @JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"), | ||
34 | - @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M"), | ||
35 | - @JsonSubTypes.Type(value = CoapDeviceProfileTransportConfiguration.class, name = "COAP")}) | 32 | + @JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"), |
33 | + @JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"), | ||
34 | + @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M"), | ||
35 | + @JsonSubTypes.Type(value = CoapDeviceProfileTransportConfiguration.class, name = "COAP"), | ||
36 | + @JsonSubTypes.Type(value = SnmpDeviceProfileTransportConfiguration.class, name = "SNMP") | ||
37 | +}) | ||
36 | public interface DeviceProfileTransportConfiguration extends Serializable { | 38 | public interface DeviceProfileTransportConfiguration extends Serializable { |
37 | 39 | ||
38 | @JsonIgnore | 40 | @JsonIgnore |
39 | DeviceTransportType getType(); | 41 | DeviceTransportType getType(); |
40 | 42 | ||
43 | + default void validate() { | ||
44 | + } | ||
45 | + | ||
41 | } | 46 | } |
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.common.data.device.profile; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import lombok.Data; | ||
20 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
21 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; | ||
22 | +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig; | ||
23 | + | ||
24 | +import java.util.List; | ||
25 | + | ||
26 | +@Data | ||
27 | +public class SnmpDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { | ||
28 | + private Integer timeoutMs; | ||
29 | + private Integer retries; | ||
30 | + private List<SnmpCommunicationConfig> communicationConfigs; | ||
31 | + | ||
32 | + @Override | ||
33 | + public DeviceTransportType getType() { | ||
34 | + return DeviceTransportType.SNMP; | ||
35 | + } | ||
36 | + | ||
37 | + @Override | ||
38 | + public void validate() { | ||
39 | + if (!isValid()) { | ||
40 | + throw new IllegalArgumentException("SNMP transport configuration is not valid"); | ||
41 | + } | ||
42 | + } | ||
43 | + | ||
44 | + @JsonIgnore | ||
45 | + private boolean isValid() { | ||
46 | + return timeoutMs != null && timeoutMs >= 0 && retries != null && retries >= 0 | ||
47 | + && communicationConfigs != null | ||
48 | + && communicationConfigs.stream().allMatch(config -> config != null && config.isValid()) | ||
49 | + && communicationConfigs.stream().flatMap(config -> config.getAllMappings().stream()).map(SnmpMapping::getOid) | ||
50 | + .distinct().count() == communicationConfigs.stream().mapToInt(config -> config.getAllMappings().size()).sum(); | ||
51 | + } | ||
52 | +} |
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.common.data.transport.snmp; | ||
17 | + | ||
18 | +import java.util.Arrays; | ||
19 | +import java.util.Optional; | ||
20 | + | ||
21 | +public enum AuthenticationProtocol { | ||
22 | + SHA_1("1.3.6.1.6.3.10.1.1.3"), | ||
23 | + SHA_224("1.3.6.1.6.3.10.1.1.4"), | ||
24 | + SHA_256("1.3.6.1.6.3.10.1.1.5"), | ||
25 | + SHA_384("1.3.6.1.6.3.10.1.1.6"), | ||
26 | + SHA_512("1.3.6.1.6.3.10.1.1.7"), | ||
27 | + MD5("1.3.6.1.6.3.10.1.1.2"); | ||
28 | + | ||
29 | + // oids taken from org.snmp4j.security.SecurityProtocol implementations | ||
30 | + private final String oid; | ||
31 | + | ||
32 | + AuthenticationProtocol(String oid) { | ||
33 | + this.oid = oid; | ||
34 | + } | ||
35 | + | ||
36 | + public String getOid() { | ||
37 | + return oid; | ||
38 | + } | ||
39 | + | ||
40 | + public static Optional<AuthenticationProtocol> forName(String name) { | ||
41 | + return Arrays.stream(values()) | ||
42 | + .filter(protocol -> protocol.name().equalsIgnoreCase(name)) | ||
43 | + .findFirst(); | ||
44 | + } | ||
45 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/PrivacyProtocol.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.common.data.transport.snmp; | ||
17 | + | ||
18 | +import java.util.Arrays; | ||
19 | +import java.util.Optional; | ||
20 | + | ||
21 | +public enum PrivacyProtocol { | ||
22 | + DES("1.3.6.1.6.3.10.1.2.2"), | ||
23 | + AES_128("1.3.6.1.6.3.10.1.2.4"), | ||
24 | + AES_192("1.3.6.1.4.1.4976.2.2.1.1.1"), | ||
25 | + AES_256("1.3.6.1.4.1.4976.2.2.1.1.2"); | ||
26 | + | ||
27 | + // oids taken from org.snmp4j.security.SecurityProtocol implementations | ||
28 | + private final String oid; | ||
29 | + | ||
30 | + PrivacyProtocol(String oid) { | ||
31 | + this.oid = oid; | ||
32 | + } | ||
33 | + | ||
34 | + public String getOid() { | ||
35 | + return oid; | ||
36 | + } | ||
37 | + | ||
38 | + public static Optional<PrivacyProtocol> forName(String name) { | ||
39 | + return Arrays.stream(values()) | ||
40 | + .filter(protocol -> protocol.name().equalsIgnoreCase(name)) | ||
41 | + .findFirst(); | ||
42 | + } | ||
43 | +} |
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.common.data.transport.snmp; | ||
17 | + | ||
18 | +public enum SnmpCommunicationSpec { | ||
19 | + TELEMETRY_QUERYING, | ||
20 | + | ||
21 | + CLIENT_ATTRIBUTES_QUERYING, | ||
22 | + SHARED_ATTRIBUTES_SETTING, | ||
23 | + | ||
24 | + TO_DEVICE_RPC_REQUEST, | ||
25 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.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.common.data.transport.snmp; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import lombok.AllArgsConstructor; | ||
20 | +import lombok.Data; | ||
21 | +import lombok.NoArgsConstructor; | ||
22 | +import org.apache.commons.lang3.StringUtils; | ||
23 | +import org.thingsboard.server.common.data.kv.DataType; | ||
24 | + | ||
25 | +import java.util.regex.Pattern; | ||
26 | + | ||
27 | +@Data | ||
28 | +@AllArgsConstructor | ||
29 | +@NoArgsConstructor | ||
30 | +public class SnmpMapping { | ||
31 | + private String oid; | ||
32 | + private String key; | ||
33 | + private DataType dataType; | ||
34 | + | ||
35 | + private static final Pattern OID_PATTERN = Pattern.compile("^\\.?([0-2])((\\.0)|(\\.[1-9][0-9]*))*$"); | ||
36 | + | ||
37 | + @JsonIgnore | ||
38 | + public boolean isValid() { | ||
39 | + return StringUtils.isNotEmpty(oid) && OID_PATTERN.matcher(oid).matches() && StringUtils.isNotBlank(key); | ||
40 | + } | ||
41 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMethod.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.common.data.transport.snmp; | ||
17 | + | ||
18 | +public enum SnmpMethod { | ||
19 | + GET(-96), | ||
20 | + SET(-93); | ||
21 | + | ||
22 | + // codes taken from org.snmp4j.PDU class | ||
23 | + private final int code; | ||
24 | + | ||
25 | + SnmpMethod(int code) { | ||
26 | + this.code = code; | ||
27 | + } | ||
28 | + | ||
29 | + public int getCode() { | ||
30 | + return code; | ||
31 | + } | ||
32 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpProtocolVersion.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.common.data.transport.snmp; | ||
17 | + | ||
18 | +public enum SnmpProtocolVersion { | ||
19 | + V1(0), | ||
20 | + V2C(1), | ||
21 | + V3(3); | ||
22 | + | ||
23 | + private final int code; | ||
24 | + | ||
25 | + SnmpProtocolVersion(int code) { | ||
26 | + this.code = code; | ||
27 | + } | ||
28 | + | ||
29 | + public int getCode() { | ||
30 | + return code; | ||
31 | + } | ||
32 | +} |
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.common.data.transport.snmp.config; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; | ||
20 | + | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +@Data | ||
24 | +public abstract class MultipleMappingsSnmpCommunicationConfig implements SnmpCommunicationConfig { | ||
25 | + protected List<SnmpMapping> mappings; | ||
26 | + | ||
27 | + @Override | ||
28 | + public boolean isValid() { | ||
29 | + return mappings != null && !mappings.isEmpty() && mappings.stream().allMatch(mapping -> mapping != null && mapping.isValid()); | ||
30 | + } | ||
31 | + | ||
32 | + @Override | ||
33 | + public List<SnmpMapping> getAllMappings() { | ||
34 | + return mappings; | ||
35 | + } | ||
36 | +} |
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.common.data.transport.snmp.config; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod; | ||
21 | + | ||
22 | +@EqualsAndHashCode(callSuper = true) | ||
23 | +@Data | ||
24 | +public abstract class RepeatingQueryingSnmpCommunicationConfig extends MultipleMappingsSnmpCommunicationConfig { | ||
25 | + private Long queryingFrequencyMs; | ||
26 | + | ||
27 | + @Override | ||
28 | + public SnmpMethod getMethod() { | ||
29 | + return SnmpMethod.GET; | ||
30 | + } | ||
31 | + | ||
32 | + @Override | ||
33 | + public boolean isValid() { | ||
34 | + return queryingFrequencyMs != null && queryingFrequencyMs > 0 && super.isValid(); | ||
35 | + } | ||
36 | +} |
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.common.data.transport.snmp.config; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
20 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | ||
21 | +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; | ||
22 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
23 | +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; | ||
24 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; | ||
25 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod; | ||
26 | +import org.thingsboard.server.common.data.transport.snmp.config.impl.ClientAttributesQueryingSnmpCommunicationConfig; | ||
27 | +import org.thingsboard.server.common.data.transport.snmp.config.impl.SharedAttributesSettingSnmpCommunicationConfig; | ||
28 | +import org.thingsboard.server.common.data.transport.snmp.config.impl.TelemetryQueryingSnmpCommunicationConfig; | ||
29 | + | ||
30 | +import java.util.List; | ||
31 | + | ||
32 | +@JsonIgnoreProperties(ignoreUnknown = true) | ||
33 | +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "spec") | ||
34 | +@JsonSubTypes({ | ||
35 | + @Type(value = TelemetryQueryingSnmpCommunicationConfig.class, name = "TELEMETRY_QUERYING"), | ||
36 | + @Type(value = ClientAttributesQueryingSnmpCommunicationConfig.class, name = "CLIENT_ATTRIBUTES_QUERYING"), | ||
37 | + @Type(value = SharedAttributesSettingSnmpCommunicationConfig.class, name = "SHARED_ATTRIBUTES_SETTING") | ||
38 | +}) | ||
39 | +public interface SnmpCommunicationConfig { | ||
40 | + | ||
41 | + SnmpCommunicationSpec getSpec(); | ||
42 | + | ||
43 | + @JsonIgnore | ||
44 | + default SnmpMethod getMethod() { | ||
45 | + return null; | ||
46 | + } | ||
47 | + | ||
48 | + @JsonIgnore | ||
49 | + List<SnmpMapping> getAllMappings(); | ||
50 | + | ||
51 | + @JsonIgnore | ||
52 | + boolean isValid(); | ||
53 | + | ||
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.common.data.transport.snmp.config.impl; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; | ||
19 | +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig; | ||
20 | + | ||
21 | +public class ClientAttributesQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig { | ||
22 | + | ||
23 | + @Override | ||
24 | + public SnmpCommunicationSpec getSpec() { | ||
25 | + return SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING; | ||
26 | + } | ||
27 | + | ||
28 | +} |
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.common.data.transport.snmp.config.impl; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; | ||
19 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod; | ||
20 | +import org.thingsboard.server.common.data.transport.snmp.config.MultipleMappingsSnmpCommunicationConfig; | ||
21 | + | ||
22 | +public class SharedAttributesSettingSnmpCommunicationConfig extends MultipleMappingsSnmpCommunicationConfig { | ||
23 | + | ||
24 | + @Override | ||
25 | + public SnmpCommunicationSpec getSpec() { | ||
26 | + return SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING; | ||
27 | + } | ||
28 | + | ||
29 | + @Override | ||
30 | + public SnmpMethod getMethod() { | ||
31 | + return SnmpMethod.SET; | ||
32 | + } | ||
33 | + | ||
34 | +} |
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.common.data.transport.snmp.config.impl; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; | ||
21 | +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig; | ||
22 | + | ||
23 | +@EqualsAndHashCode(callSuper = true) | ||
24 | +@Data | ||
25 | +public class TelemetryQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig { | ||
26 | + | ||
27 | + @Override | ||
28 | + public SnmpCommunicationSpec getSpec() { | ||
29 | + return SnmpCommunicationSpec.TELEMETRY_QUERYING; | ||
30 | + } | ||
31 | + | ||
32 | +} |
@@ -19,19 +19,23 @@ import lombok.Getter; | @@ -19,19 +19,23 @@ import lombok.Getter; | ||
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
21 | import org.springframework.beans.factory.annotation.Value; | 21 | import org.springframework.beans.factory.annotation.Value; |
22 | +import org.springframework.context.ApplicationContext; | ||
22 | import org.springframework.stereotype.Component; | 23 | import org.springframework.stereotype.Component; |
23 | import org.springframework.util.StringUtils; | 24 | import org.springframework.util.StringUtils; |
25 | +import org.thingsboard.server.common.data.TbTransportService; | ||
24 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
25 | import org.thingsboard.server.common.msg.queue.ServiceType; | 27 | import org.thingsboard.server.common.msg.queue.ServiceType; |
26 | import org.thingsboard.server.gen.transport.TransportProtos; | 28 | import org.thingsboard.server.gen.transport.TransportProtos; |
27 | import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; | 29 | import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; |
28 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | 30 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
29 | import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; | 31 | import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; |
32 | +import org.thingsboard.server.queue.util.AfterContextReady; | ||
30 | 33 | ||
31 | import javax.annotation.PostConstruct; | 34 | import javax.annotation.PostConstruct; |
32 | import java.net.InetAddress; | 35 | import java.net.InetAddress; |
33 | import java.net.UnknownHostException; | 36 | import java.net.UnknownHostException; |
34 | import java.util.Arrays; | 37 | import java.util.Arrays; |
38 | +import java.util.Collection; | ||
35 | import java.util.Collections; | 39 | import java.util.Collections; |
36 | import java.util.List; | 40 | import java.util.List; |
37 | import java.util.Optional; | 41 | import java.util.Optional; |
@@ -56,6 +60,8 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { | @@ -56,6 +60,8 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { | ||
56 | 60 | ||
57 | @Autowired(required = false) | 61 | @Autowired(required = false) |
58 | private TbQueueRuleEngineSettings ruleEngineSettings; | 62 | private TbQueueRuleEngineSettings ruleEngineSettings; |
63 | + @Autowired | ||
64 | + private ApplicationContext applicationContext; | ||
59 | 65 | ||
60 | private List<ServiceType> serviceTypes; | 66 | private List<ServiceType> serviceTypes; |
61 | private ServiceInfo serviceInfo; | 67 | private ServiceInfo serviceInfo; |
@@ -102,6 +108,19 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { | @@ -102,6 +108,19 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { | ||
102 | serviceInfo = builder.build(); | 108 | serviceInfo = builder.build(); |
103 | } | 109 | } |
104 | 110 | ||
111 | + @AfterContextReady | ||
112 | + public void setTransports() { | ||
113 | + serviceInfo = ServiceInfo.newBuilder(serviceInfo) | ||
114 | + .addAllTransports(getTransportServices().stream() | ||
115 | + .map(TbTransportService::getName) | ||
116 | + .collect(Collectors.toSet())) | ||
117 | + .build(); | ||
118 | + } | ||
119 | + | ||
120 | + private Collection<TbTransportService> getTransportServices() { | ||
121 | + return applicationContext.getBeansOfType(TbTransportService.class).values(); | ||
122 | + } | ||
123 | + | ||
105 | @Override | 124 | @Override |
106 | public ServiceInfo getServiceInfo() { | 125 | public ServiceInfo getServiceInfo() { |
107 | return serviceInfo; | 126 | return serviceInfo; |
@@ -15,26 +15,27 @@ | @@ -15,26 +15,27 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.queue.discovery; | 16 | package org.thingsboard.server.queue.discovery; |
17 | 17 | ||
18 | -import com.google.common.hash.HashCode; | ||
19 | import com.google.common.hash.HashFunction; | 18 | import com.google.common.hash.HashFunction; |
19 | +import com.google.common.hash.Hasher; | ||
20 | import com.google.common.hash.Hashing; | 20 | import com.google.common.hash.Hashing; |
21 | -import lombok.Getter; | ||
22 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
23 | import org.springframework.beans.factory.annotation.Value; | 22 | import org.springframework.beans.factory.annotation.Value; |
24 | import org.springframework.context.ApplicationEventPublisher; | 23 | import org.springframework.context.ApplicationEventPublisher; |
25 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
26 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
27 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
28 | -import org.thingsboard.server.common.msg.queue.ServiceQueueKey; | ||
29 | import org.thingsboard.server.common.msg.queue.ServiceQueue; | 27 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
28 | +import org.thingsboard.server.common.msg.queue.ServiceQueueKey; | ||
30 | import org.thingsboard.server.common.msg.queue.ServiceType; | 29 | import org.thingsboard.server.common.msg.queue.ServiceType; |
31 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 30 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
32 | import org.thingsboard.server.gen.transport.TransportProtos; | 31 | import org.thingsboard.server.gen.transport.TransportProtos; |
33 | import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; | 32 | import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; |
33 | +import org.thingsboard.server.queue.discovery.event.ClusterTopologyChangeEvent; | ||
34 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; | ||
35 | +import org.thingsboard.server.queue.discovery.event.ServiceListChangedEvent; | ||
34 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | 36 | import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
35 | 37 | ||
36 | import javax.annotation.PostConstruct; | 38 | import javax.annotation.PostConstruct; |
37 | -import java.nio.charset.StandardCharsets; | ||
38 | import java.util.ArrayList; | 39 | import java.util.ArrayList; |
39 | import java.util.Collections; | 40 | import java.util.Collections; |
40 | import java.util.Comparator; | 41 | import java.util.Comparator; |
@@ -46,7 +47,6 @@ import java.util.Set; | @@ -46,7 +47,6 @@ import java.util.Set; | ||
46 | import java.util.UUID; | 47 | import java.util.UUID; |
47 | import java.util.concurrent.ConcurrentHashMap; | 48 | import java.util.concurrent.ConcurrentHashMap; |
48 | import java.util.concurrent.ConcurrentMap; | 49 | import java.util.concurrent.ConcurrentMap; |
49 | -import java.util.concurrent.ConcurrentNavigableMap; | ||
50 | import java.util.stream.Collectors; | 50 | import java.util.stream.Collectors; |
51 | 51 | ||
52 | @Service | 52 | @Service |
@@ -186,6 +186,8 @@ public class HashPartitionService implements PartitionService { | @@ -186,6 +186,8 @@ public class HashPartitionService implements PartitionService { | ||
186 | applicationEventPublisher.publishEvent(new ClusterTopologyChangeEvent(this, changes)); | 186 | applicationEventPublisher.publishEvent(new ClusterTopologyChangeEvent(this, changes)); |
187 | } | 187 | } |
188 | } | 188 | } |
189 | + | ||
190 | + applicationEventPublisher.publishEvent(new ServiceListChangedEvent(otherServices, currentService)); | ||
189 | } | 191 | } |
190 | 192 | ||
191 | @Override | 193 | @Override |
@@ -219,6 +221,14 @@ public class HashPartitionService implements PartitionService { | @@ -219,6 +221,14 @@ public class HashPartitionService implements PartitionService { | ||
219 | } | 221 | } |
220 | } | 222 | } |
221 | 223 | ||
224 | + @Override | ||
225 | + public int resolvePartitionIndex(UUID entityId, int partitions) { | ||
226 | + int hash = hashFunction.newHasher() | ||
227 | + .putLong(entityId.getMostSignificantBits()) | ||
228 | + .putLong(entityId.getLeastSignificantBits()).hash().asInt(); | ||
229 | + return Math.abs(hash % partitions); | ||
230 | + } | ||
231 | + | ||
222 | private Map<ServiceQueueKey, List<ServiceInfo>> getServiceKeyListMap(List<ServiceInfo> services) { | 232 | private Map<ServiceQueueKey, List<ServiceInfo>> getServiceKeyListMap(List<ServiceInfo> services) { |
223 | final Map<ServiceQueueKey, List<ServiceInfo>> currentMap = new HashMap<>(); | 233 | final Map<ServiceQueueKey, List<ServiceInfo>> currentMap = new HashMap<>(); |
224 | services.forEach(serviceInfo -> { | 234 | services.forEach(serviceInfo -> { |
@@ -20,9 +20,11 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -20,9 +20,11 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
20 | import org.thingsboard.server.common.msg.queue.ServiceType; | 20 | import org.thingsboard.server.common.msg.queue.ServiceType; |
21 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 21 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
22 | import org.thingsboard.server.gen.transport.TransportProtos; | 22 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | +import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; | ||
23 | 24 | ||
24 | import java.util.List; | 25 | import java.util.List; |
25 | import java.util.Set; | 26 | import java.util.Set; |
27 | +import java.util.UUID; | ||
26 | 28 | ||
27 | /** | 29 | /** |
28 | * Once application is ready or cluster topology changes, this Service will produce {@link PartitionChangeEvent} | 30 | * Once application is ready or cluster topology changes, this Service will produce {@link PartitionChangeEvent} |
@@ -55,4 +57,6 @@ public interface PartitionService { | @@ -55,4 +57,6 @@ public interface PartitionService { | ||
55 | * @return | 57 | * @return |
56 | */ | 58 | */ |
57 | TopicPartitionInfo getNotificationsTopic(ServiceType serviceType, String serviceId); | 59 | TopicPartitionInfo getNotificationsTopic(ServiceType serviceType, String serviceId); |
60 | + | ||
61 | + int resolvePartitionIndex(UUID entityId, int partitions); | ||
58 | } | 62 | } |
@@ -17,6 +17,7 @@ package org.thingsboard.server.queue.discovery; | @@ -17,6 +17,7 @@ package org.thingsboard.server.queue.discovery; | ||
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.springframework.context.ApplicationListener; | 19 | import org.springframework.context.ApplicationListener; |
20 | +import org.thingsboard.server.queue.discovery.event.TbApplicationEvent; | ||
20 | 21 | ||
21 | import java.util.concurrent.locks.Lock; | 22 | import java.util.concurrent.locks.Lock; |
22 | import java.util.concurrent.locks.ReentrantLock; | 23 | import java.util.concurrent.locks.ReentrantLock; |
@@ -33,12 +33,14 @@ import org.apache.zookeeper.KeeperException; | @@ -33,12 +33,14 @@ import org.apache.zookeeper.KeeperException; | ||
33 | import org.springframework.beans.factory.annotation.Value; | 33 | import org.springframework.beans.factory.annotation.Value; |
34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
35 | import org.springframework.boot.context.event.ApplicationReadyEvent; | 35 | import org.springframework.boot.context.event.ApplicationReadyEvent; |
36 | +import org.springframework.context.ApplicationEventPublisher; | ||
36 | import org.springframework.context.event.EventListener; | 37 | import org.springframework.context.event.EventListener; |
37 | import org.springframework.core.annotation.Order; | 38 | import org.springframework.core.annotation.Order; |
38 | import org.springframework.stereotype.Service; | 39 | import org.springframework.stereotype.Service; |
39 | import org.springframework.util.Assert; | 40 | import org.springframework.util.Assert; |
40 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 41 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
41 | import org.thingsboard.server.gen.transport.TransportProtos; | 42 | import org.thingsboard.server.gen.transport.TransportProtos; |
43 | +import org.thingsboard.server.queue.discovery.event.ServiceListChangedEvent; | ||
42 | 44 | ||
43 | import javax.annotation.PostConstruct; | 45 | import javax.annotation.PostConstruct; |
44 | import javax.annotation.PreDestroy; | 46 | import javax.annotation.PreDestroy; |
@@ -77,7 +79,8 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi | @@ -77,7 +79,8 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi | ||
77 | 79 | ||
78 | private volatile boolean stopped = true; | 80 | private volatile boolean stopped = true; |
79 | 81 | ||
80 | - public ZkDiscoveryService(TbServiceInfoProvider serviceInfoProvider, PartitionService partitionService) { | 82 | + public ZkDiscoveryService(TbServiceInfoProvider serviceInfoProvider, |
83 | + PartitionService partitionService) { | ||
81 | this.serviceInfoProvider = serviceInfoProvider; | 84 | this.serviceInfoProvider = serviceInfoProvider; |
82 | this.partitionService = partitionService; | 85 | this.partitionService = partitionService; |
83 | } | 86 | } |
common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/ClusterTopologyChangeEvent.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/discovery/ClusterTopologyChangeEvent.java
@@ -13,10 +13,9 @@ | @@ -13,10 +13,9 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.queue.discovery; | 16 | +package org.thingsboard.server.queue.discovery.event; |
17 | 17 | ||
18 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | -import org.springframework.context.ApplicationEvent; | ||
20 | import org.thingsboard.server.common.msg.queue.ServiceQueueKey; | 19 | import org.thingsboard.server.common.msg.queue.ServiceQueueKey; |
21 | 20 | ||
22 | import java.util.Set; | 21 | import java.util.Set; |
common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/PartitionChangeEvent.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/discovery/PartitionChangeEvent.java
@@ -13,10 +13,9 @@ | @@ -13,10 +13,9 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.queue.discovery; | 16 | +package org.thingsboard.server.queue.discovery.event; |
17 | 17 | ||
18 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | -import org.springframework.context.ApplicationEvent; | ||
20 | import org.thingsboard.server.common.msg.queue.ServiceQueueKey; | 19 | import org.thingsboard.server.common.msg.queue.ServiceQueueKey; |
21 | import org.thingsboard.server.common.msg.queue.ServiceType; | 20 | import org.thingsboard.server.common.msg.queue.ServiceType; |
22 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 21 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/ServiceListChangedEvent.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.discovery.event; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.ToString; | ||
20 | +import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; | ||
21 | + | ||
22 | +import java.util.List; | ||
23 | + | ||
24 | +@Getter | ||
25 | +@ToString | ||
26 | +public class ServiceListChangedEvent extends TbApplicationEvent { | ||
27 | + private final List<ServiceInfo> otherServices; | ||
28 | + private final ServiceInfo currentService; | ||
29 | + | ||
30 | + public ServiceListChangedEvent(List<ServiceInfo> otherServices, ServiceInfo currentService) { | ||
31 | + super(otherServices); | ||
32 | + this.otherServices = otherServices; | ||
33 | + this.currentService = currentService; | ||
34 | + } | ||
35 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/TbApplicationEvent.java
renamed from
common/queue/src/main/java/org/thingsboard/server/queue/discovery/TbApplicationEvent.java
@@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.queue.discovery; | 16 | +package org.thingsboard.server.queue.discovery.event; |
17 | 17 | ||
18 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | import org.springframework.context.ApplicationEvent; | 19 | import org.springframework.context.ApplicationEvent; |
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.context.event.ContextRefreshedEvent; | ||
19 | +import org.springframework.context.event.EventListener; | ||
20 | +import org.springframework.core.annotation.AliasFor; | ||
21 | +import org.springframework.core.annotation.Order; | ||
22 | + | ||
23 | +import java.lang.annotation.ElementType; | ||
24 | +import java.lang.annotation.Retention; | ||
25 | +import java.lang.annotation.RetentionPolicy; | ||
26 | +import java.lang.annotation.Target; | ||
27 | + | ||
28 | +@Retention(RetentionPolicy.RUNTIME) | ||
29 | +@Target(ElementType.METHOD) | ||
30 | +@EventListener(ContextRefreshedEvent.class) | ||
31 | +@Order | ||
32 | +public @interface AfterContextReady { | ||
33 | + @AliasFor(annotation = Order.class, attribute = "value") | ||
34 | + int order() default Integer.MAX_VALUE; | ||
35 | +} |
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.context.event.ApplicationReadyEvent; | ||
19 | +import org.springframework.context.event.EventListener; | ||
20 | +import org.springframework.core.annotation.AliasFor; | ||
21 | +import org.springframework.core.annotation.Order; | ||
22 | + | ||
23 | +import java.lang.annotation.ElementType; | ||
24 | +import java.lang.annotation.Retention; | ||
25 | +import java.lang.annotation.RetentionPolicy; | ||
26 | +import java.lang.annotation.Target; | ||
27 | + | ||
28 | +@Retention(RetentionPolicy.RUNTIME) | ||
29 | +@Target(ElementType.METHOD) | ||
30 | +@EventListener(ApplicationReadyEvent.class) | ||
31 | +@Order | ||
32 | +public @interface AfterStartUp { | ||
33 | + @AliasFor(annotation = Order.class, attribute = "value") | ||
34 | + int order() default Integer.MAX_VALUE; | ||
35 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/util/TbSnmpTransportComponent.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.ElementType; | ||
21 | +import java.lang.annotation.Retention; | ||
22 | +import java.lang.annotation.RetentionPolicy; | ||
23 | +import java.lang.annotation.Target; | ||
24 | + | ||
25 | +@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.snmp.enabled}'=='true')") | ||
26 | +@Retention(RetentionPolicy.RUNTIME) | ||
27 | +@Target({ElementType.TYPE, ElementType.METHOD}) | ||
28 | +public @interface TbSnmpTransportComponent { | ||
29 | +} |
@@ -34,6 +34,7 @@ message ServiceInfo { | @@ -34,6 +34,7 @@ message ServiceInfo { | ||
34 | int64 tenantIdMSB = 3; | 34 | int64 tenantIdMSB = 3; |
35 | int64 tenantIdLSB = 4; | 35 | int64 tenantIdLSB = 4; |
36 | repeated QueueInfo ruleEngineQueues = 5; | 36 | repeated QueueInfo ruleEngineQueues = 5; |
37 | + repeated string transports = 6; | ||
37 | } | 38 | } |
38 | 39 | ||
39 | /** | 40 | /** |
@@ -246,6 +247,36 @@ message GetEntityProfileResponseMsg { | @@ -246,6 +247,36 @@ message GetEntityProfileResponseMsg { | ||
246 | bytes apiState = 3; | 247 | bytes apiState = 3; |
247 | } | 248 | } |
248 | 249 | ||
250 | +message GetDeviceRequestMsg { | ||
251 | + int64 deviceIdMSB = 1; | ||
252 | + int64 deviceIdLSB = 2; | ||
253 | +} | ||
254 | + | ||
255 | +message GetDeviceResponseMsg { | ||
256 | + int64 deviceProfileIdMSB = 1; | ||
257 | + int64 deviceProfileIdLSB = 2; | ||
258 | + bytes deviceTransportConfiguration = 3; | ||
259 | +} | ||
260 | + | ||
261 | +message GetDeviceCredentialsRequestMsg { | ||
262 | + int64 deviceIdMSB = 1; | ||
263 | + int64 deviceIdLSB = 2; | ||
264 | +} | ||
265 | + | ||
266 | +message GetDeviceCredentialsResponseMsg { | ||
267 | + bytes deviceCredentialsData = 1; | ||
268 | +} | ||
269 | + | ||
270 | +message GetSnmpDevicesRequestMsg { | ||
271 | + int32 page = 1; | ||
272 | + int32 pageSize = 2; | ||
273 | +} | ||
274 | + | ||
275 | +message GetSnmpDevicesResponseMsg { | ||
276 | + repeated string ids = 1; | ||
277 | + bool hasNextPage = 2; | ||
278 | +} | ||
279 | + | ||
249 | message EntityUpdateMsg { | 280 | message EntityUpdateMsg { |
250 | string entityType = 1; | 281 | string entityType = 1; |
251 | bytes data = 2; | 282 | bytes data = 2; |
@@ -590,6 +621,9 @@ message TransportApiRequestMsg { | @@ -590,6 +621,9 @@ message TransportApiRequestMsg { | ||
590 | ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; | 621 | ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; |
591 | GetResourceRequestMsg resourceRequestMsg = 9; | 622 | GetResourceRequestMsg resourceRequestMsg = 9; |
592 | GetFirmwareRequestMsg firmwareRequestMsg = 10; | 623 | GetFirmwareRequestMsg firmwareRequestMsg = 10; |
624 | + GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 11; | ||
625 | + GetDeviceRequestMsg deviceRequestMsg = 12; | ||
626 | + GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 13; | ||
593 | } | 627 | } |
594 | 628 | ||
595 | /* Response from ThingsBoard Core Service to Transport Service */ | 629 | /* Response from ThingsBoard Core Service to Transport Service */ |
@@ -598,9 +632,12 @@ message TransportApiResponseMsg { | @@ -598,9 +632,12 @@ message TransportApiResponseMsg { | ||
598 | GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; | 632 | GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2; |
599 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; | 633 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; |
600 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; | 634 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; |
635 | + GetSnmpDevicesResponseMsg snmpDevicesResponseMsg = 5; | ||
601 | LwM2MResponseMsg lwM2MResponseMsg = 6; | 636 | LwM2MResponseMsg lwM2MResponseMsg = 6; |
602 | GetResourceResponseMsg resourceResponseMsg = 7; | 637 | GetResourceResponseMsg resourceResponseMsg = 7; |
603 | GetFirmwareResponseMsg firmwareResponseMsg = 8; | 638 | GetFirmwareResponseMsg firmwareResponseMsg = 8; |
639 | + GetDeviceResponseMsg deviceResponseMsg = 9; | ||
640 | + GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10; | ||
604 | } | 641 | } |
605 | 642 | ||
606 | /* Messages that are handled by ThingsBoard Core Service */ | 643 | /* Messages that are handled by ThingsBoard Core Service */ |
@@ -21,6 +21,7 @@ import org.eclipse.californium.core.CoapServer; | @@ -21,6 +21,7 @@ import org.eclipse.californium.core.CoapServer; | ||
21 | import org.springframework.beans.factory.annotation.Autowired; | 21 | import org.springframework.beans.factory.annotation.Autowired; |
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | +import org.thingsboard.server.common.data.TbTransportService; | ||
24 | import org.thingsboard.server.coapserver.CoapServerService; | 25 | import org.thingsboard.server.coapserver.CoapServerService; |
25 | import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; | 26 | import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; |
26 | 27 | ||
@@ -31,7 +32,7 @@ import java.net.UnknownHostException; | @@ -31,7 +32,7 @@ import java.net.UnknownHostException; | ||
31 | @Service("CoapTransportService") | 32 | @Service("CoapTransportService") |
32 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.coap.enabled}'=='true')") | 33 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.coap.enabled}'=='true')") |
33 | @Slf4j | 34 | @Slf4j |
34 | -public class CoapTransportService { | 35 | +public class CoapTransportService implements TbTransportService { |
35 | 36 | ||
36 | private static final String V1 = "v1"; | 37 | private static final String V1 = "v1"; |
37 | private static final String API = "api"; | 38 | private static final String API = "api"; |
@@ -65,4 +66,9 @@ public class CoapTransportService { | @@ -65,4 +66,9 @@ public class CoapTransportService { | ||
65 | public void shutdown() { | 66 | public void shutdown() { |
66 | log.info("CoAP transport stopped!"); | 67 | log.info("CoAP transport stopped!"); |
67 | } | 68 | } |
69 | + | ||
70 | + @Override | ||
71 | + public String getName() { | ||
72 | + return "COAP"; | ||
73 | + } | ||
68 | } | 74 | } |
@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
34 | import org.springframework.web.bind.annotation.RestController; | 34 | import org.springframework.web.bind.annotation.RestController; |
35 | import org.springframework.web.context.request.async.DeferredResult; | 35 | import org.springframework.web.context.request.async.DeferredResult; |
36 | import org.thingsboard.server.common.data.DeviceTransportType; | 36 | import org.thingsboard.server.common.data.DeviceTransportType; |
37 | +import org.thingsboard.server.common.data.TbTransportService; | ||
37 | import org.thingsboard.server.common.data.id.DeviceId; | 38 | import org.thingsboard.server.common.data.id.DeviceId; |
38 | import org.thingsboard.server.common.transport.SessionMsgListener; | 39 | import org.thingsboard.server.common.transport.SessionMsgListener; |
39 | import org.thingsboard.server.common.transport.TransportContext; | 40 | import org.thingsboard.server.common.transport.TransportContext; |
@@ -70,7 +71,7 @@ import java.util.function.Consumer; | @@ -70,7 +71,7 @@ import java.util.function.Consumer; | ||
70 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.http.enabled}'=='true')") | 71 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.http.enabled}'=='true')") |
71 | @RequestMapping("/api/v1") | 72 | @RequestMapping("/api/v1") |
72 | @Slf4j | 73 | @Slf4j |
73 | -public class DeviceApiController { | 74 | +public class DeviceApiController implements TbTransportService { |
74 | 75 | ||
75 | @Autowired | 76 | @Autowired |
76 | private HttpTransportContext transportContext; | 77 | private HttpTransportContext transportContext; |
@@ -407,4 +408,9 @@ public class DeviceApiController { | @@ -407,4 +408,9 @@ public class DeviceApiController { | ||
407 | } | 408 | } |
408 | } | 409 | } |
409 | 410 | ||
411 | + @Override | ||
412 | + public String getName() { | ||
413 | + return "HTTP"; | ||
414 | + } | ||
415 | + | ||
410 | } | 416 | } |
@@ -20,13 +20,14 @@ import org.eclipse.leshan.core.response.ReadResponse; | @@ -20,13 +20,14 @@ import org.eclipse.leshan.core.response.ReadResponse; | ||
20 | import org.eclipse.leshan.server.registration.Registration; | 20 | import org.eclipse.leshan.server.registration.Registration; |
21 | import org.thingsboard.server.common.data.Device; | 21 | import org.thingsboard.server.common.data.Device; |
22 | import org.thingsboard.server.common.data.DeviceProfile; | 22 | import org.thingsboard.server.common.data.DeviceProfile; |
23 | +import org.thingsboard.server.common.data.TbTransportService; | ||
23 | import org.thingsboard.server.gen.transport.TransportProtos; | 24 | import org.thingsboard.server.gen.transport.TransportProtos; |
24 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; | 25 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; |
25 | 26 | ||
26 | import java.util.Collection; | 27 | import java.util.Collection; |
27 | import java.util.Optional; | 28 | import java.util.Optional; |
28 | 29 | ||
29 | -public interface LwM2mTransportService { | 30 | +public interface LwM2mTransportService extends TbTransportService { |
30 | 31 | ||
31 | void onRegistered(Registration registration, Collection<Observation> previousObsersations); | 32 | void onRegistered(Registration registration, Collection<Observation> previousObsersations); |
32 | 33 |
@@ -40,6 +40,7 @@ import org.springframework.stereotype.Service; | @@ -40,6 +40,7 @@ import org.springframework.stereotype.Service; | ||
40 | import org.thingsboard.common.util.JacksonUtil; | 40 | import org.thingsboard.common.util.JacksonUtil; |
41 | import org.thingsboard.server.common.data.Device; | 41 | import org.thingsboard.server.common.data.Device; |
42 | import org.thingsboard.server.common.data.DeviceProfile; | 42 | import org.thingsboard.server.common.data.DeviceProfile; |
43 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
43 | import org.thingsboard.server.common.transport.TransportService; | 44 | import org.thingsboard.server.common.transport.TransportService; |
44 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 45 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
45 | import org.thingsboard.server.common.transport.service.DefaultTransportService; | 46 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
@@ -1353,4 +1354,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1353,4 +1354,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1353 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() : | 1354 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() : |
1354 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); | 1355 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); |
1355 | } | 1356 | } |
1357 | + | ||
1358 | + @Override | ||
1359 | + public String getName() { | ||
1360 | + return "LWM2M"; | ||
1361 | + } | ||
1362 | + | ||
1356 | } | 1363 | } |
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value; | @@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value; | ||
28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
29 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 29 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
30 | import org.springframework.stereotype.Service; | 30 | import org.springframework.stereotype.Service; |
31 | +import org.thingsboard.server.common.data.TbTransportService; | ||
31 | 32 | ||
32 | import javax.annotation.PostConstruct; | 33 | import javax.annotation.PostConstruct; |
33 | import javax.annotation.PreDestroy; | 34 | import javax.annotation.PreDestroy; |
@@ -38,7 +39,7 @@ import javax.annotation.PreDestroy; | @@ -38,7 +39,7 @@ import javax.annotation.PreDestroy; | ||
38 | @Service("MqttTransportService") | 39 | @Service("MqttTransportService") |
39 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.mqtt.enabled}'=='true')") | 40 | @ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.mqtt.enabled}'=='true')") |
40 | @Slf4j | 41 | @Slf4j |
41 | -public class MqttTransportService { | 42 | +public class MqttTransportService implements TbTransportService { |
42 | 43 | ||
43 | @Value("${transport.mqtt.bind_address}") | 44 | @Value("${transport.mqtt.bind_address}") |
44 | private String host; | 45 | private String host; |
@@ -90,4 +91,9 @@ public class MqttTransportService { | @@ -90,4 +91,9 @@ public class MqttTransportService { | ||
90 | } | 91 | } |
91 | log.info("MQTT transport stopped!"); | 92 | log.info("MQTT transport stopped!"); |
92 | } | 93 | } |
94 | + | ||
95 | + @Override | ||
96 | + public String getName() { | ||
97 | + return "MQTT"; | ||
98 | + } | ||
93 | } | 99 | } |
common/transport/snmp/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 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.thingsboard.common</groupId> | ||
24 | + <version>3.3.0-SNAPSHOT</version> | ||
25 | + <artifactId>transport</artifactId> | ||
26 | + </parent> | ||
27 | + | ||
28 | + <groupId>org.thingsboard.common.transport</groupId> | ||
29 | + <artifactId>snmp</artifactId> | ||
30 | + <packaging>jar</packaging> | ||
31 | + | ||
32 | + <name>Thingsboard SNMP Transport Common</name> | ||
33 | + <url>https://thingsboard.io</url> | ||
34 | + | ||
35 | + <properties> | ||
36 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
37 | + <main.dir>${basedir}/../../..</main.dir> | ||
38 | + </properties> | ||
39 | + | ||
40 | + <dependencies> | ||
41 | + <dependency> | ||
42 | + <groupId>org.thingsboard.common.transport</groupId> | ||
43 | + <artifactId>transport-api</artifactId> | ||
44 | + </dependency> | ||
45 | + <dependency> | ||
46 | + <groupId>org.springframework</groupId> | ||
47 | + <artifactId>spring-context-support</artifactId> | ||
48 | + </dependency> | ||
49 | + <dependency> | ||
50 | + <groupId>org.springframework</groupId> | ||
51 | + <artifactId>spring-context</artifactId> | ||
52 | + </dependency> | ||
53 | + <dependency> | ||
54 | + <groupId>org.slf4j</groupId> | ||
55 | + <artifactId>slf4j-api</artifactId> | ||
56 | + </dependency> | ||
57 | + <dependency> | ||
58 | + <groupId>org.snmp4j</groupId> | ||
59 | + <artifactId>snmp4j</artifactId> | ||
60 | + </dependency> | ||
61 | + <dependency> | ||
62 | + <groupId>org.snmp4j</groupId> | ||
63 | + <artifactId>snmp4j-agent</artifactId> | ||
64 | + <version>3.3.6</version> | ||
65 | + <scope>test</scope> | ||
66 | + </dependency> | ||
67 | + </dependencies> | ||
68 | +</project> |
common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpTransportContext.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.transport.snmp; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.RequiredArgsConstructor; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.springframework.context.event.EventListener; | ||
22 | +import org.springframework.stereotype.Component; | ||
23 | +import org.thingsboard.server.common.data.Device; | ||
24 | +import org.thingsboard.server.common.data.DeviceProfile; | ||
25 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
26 | +import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration; | ||
27 | +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | ||
28 | +import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; | ||
29 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
30 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
31 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
32 | +import org.thingsboard.server.common.data.security.DeviceCredentialsType; | ||
33 | +import org.thingsboard.server.common.transport.DeviceUpdatedEvent; | ||
34 | +import org.thingsboard.server.common.transport.TransportContext; | ||
35 | +import org.thingsboard.server.common.transport.TransportDeviceProfileCache; | ||
36 | +import org.thingsboard.server.common.transport.TransportService; | ||
37 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
38 | +import org.thingsboard.server.common.transport.auth.SessionInfoCreator; | ||
39 | +import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | ||
40 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
41 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | ||
42 | +import org.thingsboard.server.queue.util.AfterStartUp; | ||
43 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
44 | +import org.thingsboard.server.transport.snmp.service.ProtoTransportEntityService; | ||
45 | +import org.thingsboard.server.transport.snmp.service.SnmpAuthService; | ||
46 | +import org.thingsboard.server.transport.snmp.service.SnmpTransportBalancingService; | ||
47 | +import org.thingsboard.server.transport.snmp.service.SnmpTransportService; | ||
48 | +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; | ||
49 | + | ||
50 | +import java.util.Collection; | ||
51 | +import java.util.LinkedList; | ||
52 | +import java.util.List; | ||
53 | +import java.util.Map; | ||
54 | +import java.util.Optional; | ||
55 | +import java.util.UUID; | ||
56 | +import java.util.concurrent.ConcurrentHashMap; | ||
57 | +import java.util.concurrent.ConcurrentLinkedDeque; | ||
58 | +import java.util.stream.Collectors; | ||
59 | + | ||
60 | +@TbSnmpTransportComponent | ||
61 | +@Component | ||
62 | +@Slf4j | ||
63 | +@RequiredArgsConstructor | ||
64 | +public class SnmpTransportContext extends TransportContext { | ||
65 | + @Getter | ||
66 | + private final SnmpTransportService snmpTransportService; | ||
67 | + private final TransportDeviceProfileCache deviceProfileCache; | ||
68 | + private final TransportService transportService; | ||
69 | + private final ProtoTransportEntityService protoEntityService; | ||
70 | + private final SnmpTransportBalancingService balancingService; | ||
71 | + @Getter | ||
72 | + private final SnmpAuthService snmpAuthService; | ||
73 | + | ||
74 | + private final Map<DeviceId, DeviceSessionContext> sessions = new ConcurrentHashMap<>(); | ||
75 | + private Collection<DeviceId> allSnmpDevicesIds = new ConcurrentLinkedDeque<>(); | ||
76 | + | ||
77 | + @AfterStartUp(order = 2) | ||
78 | + public void initDevicesSessions() { | ||
79 | + log.info("Initializing SNMP devices sessions"); | ||
80 | + allSnmpDevicesIds = protoEntityService.getAllSnmpDevicesIds().stream() | ||
81 | + .map(DeviceId::new) | ||
82 | + .collect(Collectors.toList()); | ||
83 | + log.trace("Found all SNMP devices ids: {}", allSnmpDevicesIds); | ||
84 | + | ||
85 | + List<DeviceId> managedDevicesIds = allSnmpDevicesIds.stream() | ||
86 | + .filter(deviceId -> balancingService.isManagedByCurrentTransport(deviceId.getId())) | ||
87 | + .collect(Collectors.toList()); | ||
88 | + log.info("SNMP devices managed by current SNMP transport: {}", managedDevicesIds); | ||
89 | + | ||
90 | + managedDevicesIds.stream() | ||
91 | + .map(protoEntityService::getDeviceById) | ||
92 | + .collect(Collectors.toList()) | ||
93 | + .forEach(this::establishDeviceSession); | ||
94 | + } | ||
95 | + | ||
96 | + private void establishDeviceSession(Device device) { | ||
97 | + if (device == null) return; | ||
98 | + log.info("Establishing SNMP session for device {}", device.getId()); | ||
99 | + | ||
100 | + DeviceProfileId deviceProfileId = device.getDeviceProfileId(); | ||
101 | + DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId); | ||
102 | + | ||
103 | + DeviceCredentials credentials = protoEntityService.getDeviceCredentialsByDeviceId(device.getId()); | ||
104 | + if (credentials.getCredentialsType() != DeviceCredentialsType.ACCESS_TOKEN) { | ||
105 | + log.warn("[{}] Expected credentials type is {} but found {}", device.getId(), DeviceCredentialsType.ACCESS_TOKEN, credentials.getCredentialsType()); | ||
106 | + return; | ||
107 | + } | ||
108 | + | ||
109 | + SnmpDeviceProfileTransportConfiguration profileTransportConfiguration = (SnmpDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration(); | ||
110 | + SnmpDeviceTransportConfiguration deviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
111 | + | ||
112 | + DeviceSessionContext deviceSessionContext; | ||
113 | + try { | ||
114 | + deviceSessionContext = new DeviceSessionContext( | ||
115 | + device, deviceProfile, credentials.getCredentialsId(), | ||
116 | + profileTransportConfiguration, deviceTransportConfiguration, this | ||
117 | + ); | ||
118 | + registerSessionMsgListener(deviceSessionContext); | ||
119 | + } catch (Exception e) { | ||
120 | + log.error("Failed to establish session for SNMP device {}: {}", device.getId(), e.toString()); | ||
121 | + return; | ||
122 | + } | ||
123 | + sessions.put(device.getId(), deviceSessionContext); | ||
124 | + snmpTransportService.createQueryingTasks(deviceSessionContext); | ||
125 | + log.info("Established SNMP device session for device {}", device.getId()); | ||
126 | + } | ||
127 | + | ||
128 | + private void updateDeviceSession(DeviceSessionContext sessionContext, Device device, DeviceProfile deviceProfile) { | ||
129 | + log.info("Updating SNMP session for device {}", device.getId()); | ||
130 | + | ||
131 | + DeviceCredentials credentials = protoEntityService.getDeviceCredentialsByDeviceId(device.getId()); | ||
132 | + if (credentials.getCredentialsType() != DeviceCredentialsType.ACCESS_TOKEN) { | ||
133 | + log.warn("[{}] Expected credentials type is {} but found {}", device.getId(), DeviceCredentialsType.ACCESS_TOKEN, credentials.getCredentialsType()); | ||
134 | + destroyDeviceSession(sessionContext); | ||
135 | + return; | ||
136 | + } | ||
137 | + | ||
138 | + SnmpDeviceProfileTransportConfiguration newProfileTransportConfiguration = (SnmpDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration(); | ||
139 | + SnmpDeviceTransportConfiguration newDeviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
140 | + | ||
141 | + try { | ||
142 | + if (!newProfileTransportConfiguration.equals(sessionContext.getProfileTransportConfiguration())) { | ||
143 | + sessionContext.setProfileTransportConfiguration(newProfileTransportConfiguration); | ||
144 | + sessionContext.initializeTarget(newProfileTransportConfiguration, newDeviceTransportConfiguration); | ||
145 | + snmpTransportService.cancelQueryingTasks(sessionContext); | ||
146 | + snmpTransportService.createQueryingTasks(sessionContext); | ||
147 | + } else if (!newDeviceTransportConfiguration.equals(sessionContext.getDeviceTransportConfiguration())) { | ||
148 | + sessionContext.setDeviceTransportConfiguration(newDeviceTransportConfiguration); | ||
149 | + sessionContext.initializeTarget(newProfileTransportConfiguration, newDeviceTransportConfiguration); | ||
150 | + } else { | ||
151 | + log.trace("Configuration of the device {} was not updated", device); | ||
152 | + } | ||
153 | + } catch (Exception e) { | ||
154 | + log.error("Failed to update session for SNMP device {}: {}", sessionContext.getDeviceId(), e.getMessage()); | ||
155 | + destroyDeviceSession(sessionContext); | ||
156 | + } | ||
157 | + } | ||
158 | + | ||
159 | + private void destroyDeviceSession(DeviceSessionContext sessionContext) { | ||
160 | + if (sessionContext == null) return; | ||
161 | + log.info("Destroying SNMP device session for device {}", sessionContext.getDevice().getId()); | ||
162 | + sessionContext.close(); | ||
163 | + snmpAuthService.cleanUpSnmpAuthInfo(sessionContext); | ||
164 | + transportService.deregisterSession(sessionContext.getSessionInfo()); | ||
165 | + snmpTransportService.cancelQueryingTasks(sessionContext); | ||
166 | + sessions.remove(sessionContext.getDeviceId()); | ||
167 | + log.trace("Unregistered and removed session"); | ||
168 | + } | ||
169 | + | ||
170 | + private void registerSessionMsgListener(DeviceSessionContext deviceSessionContext) { | ||
171 | + transportService.process(DeviceTransportType.SNMP, | ||
172 | + TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceSessionContext.getToken()).build(), | ||
173 | + new TransportServiceCallback<>() { | ||
174 | + @Override | ||
175 | + public void onSuccess(ValidateDeviceCredentialsResponse msg) { | ||
176 | + if (msg.hasDeviceInfo()) { | ||
177 | + SessionInfoProto sessionInfo = SessionInfoCreator.create( | ||
178 | + msg, SnmpTransportContext.this, UUID.randomUUID() | ||
179 | + ); | ||
180 | + | ||
181 | + transportService.registerAsyncSession(sessionInfo, deviceSessionContext); | ||
182 | + transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), TransportServiceCallback.EMPTY); | ||
183 | + transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), TransportServiceCallback.EMPTY); | ||
184 | + | ||
185 | + deviceSessionContext.setSessionInfo(sessionInfo); | ||
186 | + deviceSessionContext.setDeviceInfo(msg.getDeviceInfo()); | ||
187 | + } else { | ||
188 | + log.warn("[{}] Failed to process device auth", deviceSessionContext.getDeviceId()); | ||
189 | + } | ||
190 | + } | ||
191 | + | ||
192 | + @Override | ||
193 | + public void onError(Throwable e) { | ||
194 | + log.warn("[{}] Failed to process device auth: {}", deviceSessionContext.getDeviceId(), e); | ||
195 | + } | ||
196 | + }); | ||
197 | + } | ||
198 | + | ||
199 | + @EventListener(DeviceUpdatedEvent.class) | ||
200 | + public void onDeviceUpdatedOrCreated(DeviceUpdatedEvent deviceUpdatedEvent) { | ||
201 | + Device device = deviceUpdatedEvent.getDevice(); | ||
202 | + log.trace("Got creating or updating device event for device {}", device); | ||
203 | + DeviceTransportType transportType = Optional.ofNullable(device.getDeviceData().getTransportConfiguration()) | ||
204 | + .map(DeviceTransportConfiguration::getType) | ||
205 | + .orElse(null); | ||
206 | + if (!allSnmpDevicesIds.contains(device.getId())) { | ||
207 | + if (transportType != DeviceTransportType.SNMP) { | ||
208 | + return; | ||
209 | + } | ||
210 | + allSnmpDevicesIds.add(device.getId()); | ||
211 | + if (balancingService.isManagedByCurrentTransport(device.getId().getId())) { | ||
212 | + establishDeviceSession(device); | ||
213 | + } | ||
214 | + } else { | ||
215 | + if (balancingService.isManagedByCurrentTransport(device.getId().getId())) { | ||
216 | + DeviceSessionContext sessionContext = sessions.get(device.getId()); | ||
217 | + if (transportType == DeviceTransportType.SNMP) { | ||
218 | + if (sessionContext != null) { | ||
219 | + updateDeviceSession(sessionContext, device, deviceProfileCache.get(device.getDeviceProfileId())); | ||
220 | + } else { | ||
221 | + establishDeviceSession(device); | ||
222 | + } | ||
223 | + } else { | ||
224 | + log.trace("Transport type was changed to {}", transportType); | ||
225 | + destroyDeviceSession(sessionContext); | ||
226 | + } | ||
227 | + } | ||
228 | + } | ||
229 | + } | ||
230 | + | ||
231 | + public void onDeviceDeleted(DeviceSessionContext sessionContext) { | ||
232 | + destroyDeviceSession(sessionContext); | ||
233 | + } | ||
234 | + | ||
235 | + public void onDeviceProfileUpdated(DeviceProfile deviceProfile, DeviceSessionContext sessionContext) { | ||
236 | + updateDeviceSession(sessionContext, sessionContext.getDevice(), deviceProfile); | ||
237 | + } | ||
238 | + | ||
239 | + public void onSnmpTransportListChanged() { | ||
240 | + log.trace("SNMP transport list changed. Updating sessions"); | ||
241 | + List<DeviceId> deleted = new LinkedList<>(); | ||
242 | + for (DeviceId deviceId : allSnmpDevicesIds) { | ||
243 | + if (balancingService.isManagedByCurrentTransport(deviceId.getId())) { | ||
244 | + if (!sessions.containsKey(deviceId)) { | ||
245 | + Device device = protoEntityService.getDeviceById(deviceId); | ||
246 | + if (device != null) { | ||
247 | + log.info("SNMP device {} is now managed by current transport node", deviceId); | ||
248 | + establishDeviceSession(device); | ||
249 | + } else { | ||
250 | + deleted.add(deviceId); | ||
251 | + } | ||
252 | + } | ||
253 | + } else { | ||
254 | + Optional.ofNullable(sessions.get(deviceId)) | ||
255 | + .ifPresent(sessionContext -> { | ||
256 | + log.info("SNMP session for device {} is not managed by current transport node anymore", deviceId); | ||
257 | + destroyDeviceSession(sessionContext); | ||
258 | + }); | ||
259 | + } | ||
260 | + } | ||
261 | + log.trace("Removing deleted SNMP devices: {}", deleted); | ||
262 | + allSnmpDevicesIds.removeAll(deleted); | ||
263 | + } | ||
264 | + | ||
265 | + | ||
266 | + public Collection<DeviceSessionContext> getSessions() { | ||
267 | + return sessions.values(); | ||
268 | + } | ||
269 | + | ||
270 | +} |
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.snmp.event; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | ||
21 | +import org.thingsboard.server.queue.discovery.event.ServiceListChangedEvent; | ||
22 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
23 | +import org.thingsboard.server.transport.snmp.service.SnmpTransportBalancingService; | ||
24 | + | ||
25 | +@TbSnmpTransportComponent | ||
26 | +@Component | ||
27 | +@RequiredArgsConstructor | ||
28 | +public class ServiceListChangedEventListener extends TbApplicationEventListener<ServiceListChangedEvent> { | ||
29 | + private final SnmpTransportBalancingService snmpTransportBalancingService; | ||
30 | + | ||
31 | + @Override | ||
32 | + protected void onTbApplicationEvent(ServiceListChangedEvent event) { | ||
33 | + snmpTransportBalancingService.onServiceListChanged(event); | ||
34 | + } | ||
35 | +} |
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.snmp.event; | ||
17 | + | ||
18 | +import org.thingsboard.server.queue.discovery.event.TbApplicationEvent; | ||
19 | + | ||
20 | +public class SnmpTransportListChangedEvent extends TbApplicationEvent { | ||
21 | + public SnmpTransportListChangedEvent() { | ||
22 | + super(new Object()); | ||
23 | + } | ||
24 | +} |
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.snmp.event; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.queue.discovery.TbApplicationEventListener; | ||
21 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
22 | +import org.thingsboard.server.transport.snmp.SnmpTransportContext; | ||
23 | + | ||
24 | +@TbSnmpTransportComponent | ||
25 | +@Component | ||
26 | +@RequiredArgsConstructor | ||
27 | +public class SnmpTransportListChangedEventListener extends TbApplicationEventListener<SnmpTransportListChangedEvent> { | ||
28 | + private final SnmpTransportContext snmpTransportContext; | ||
29 | + | ||
30 | + @Override | ||
31 | + protected void onTbApplicationEvent(SnmpTransportListChangedEvent event) { | ||
32 | + snmpTransportContext.onSnmpTransportListChanged(); | ||
33 | + } | ||
34 | +} |
common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/PduService.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.transport.snmp.service; | ||
17 | + | ||
18 | +import com.google.gson.JsonObject; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.snmp4j.PDU; | ||
21 | +import org.snmp4j.ScopedPDU; | ||
22 | +import org.snmp4j.smi.Integer32; | ||
23 | +import org.snmp4j.smi.Null; | ||
24 | +import org.snmp4j.smi.OID; | ||
25 | +import org.snmp4j.smi.OctetString; | ||
26 | +import org.snmp4j.smi.Variable; | ||
27 | +import org.snmp4j.smi.VariableBinding; | ||
28 | +import org.springframework.stereotype.Service; | ||
29 | +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | ||
30 | +import org.thingsboard.server.common.data.kv.DataType; | ||
31 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; | ||
32 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod; | ||
33 | +import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion; | ||
34 | +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig; | ||
35 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
36 | +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; | ||
37 | + | ||
38 | +import java.util.HashMap; | ||
39 | +import java.util.List; | ||
40 | +import java.util.Map; | ||
41 | +import java.util.Objects; | ||
42 | +import java.util.Optional; | ||
43 | +import java.util.stream.Collectors; | ||
44 | +import java.util.stream.IntStream; | ||
45 | + | ||
46 | +@TbSnmpTransportComponent | ||
47 | +@Service | ||
48 | +@Slf4j | ||
49 | +public class PduService { | ||
50 | + public PDU createPdu(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) { | ||
51 | + PDU pdu = setUpPdu(sessionContext); | ||
52 | + | ||
53 | + pdu.setType(communicationConfig.getMethod().getCode()); | ||
54 | + pdu.addAll(communicationConfig.getAllMappings().stream() | ||
55 | + .filter(mapping -> values.isEmpty() || values.containsKey(mapping.getKey())) | ||
56 | + .map(mapping -> Optional.ofNullable(values.get(mapping.getKey())) | ||
57 | + .map(value -> { | ||
58 | + Variable variable = toSnmpVariable(value, mapping.getDataType()); | ||
59 | + return new VariableBinding(new OID(mapping.getOid()), variable); | ||
60 | + }) | ||
61 | + .orElseGet(() -> new VariableBinding(new OID(mapping.getOid())))) | ||
62 | + .collect(Collectors.toList())); | ||
63 | + | ||
64 | + return pdu; | ||
65 | + } | ||
66 | + | ||
67 | + public PDU createSingleVariablePdu(DeviceSessionContext sessionContext, SnmpMethod snmpMethod, String oid, String value, DataType dataType) { | ||
68 | + PDU pdu = setUpPdu(sessionContext); | ||
69 | + pdu.setType(snmpMethod.getCode()); | ||
70 | + | ||
71 | + Variable variable = value == null ? Null.instance : toSnmpVariable(value, dataType); | ||
72 | + pdu.add(new VariableBinding(new OID(oid), variable)); | ||
73 | + | ||
74 | + return pdu; | ||
75 | + } | ||
76 | + | ||
77 | + private Variable toSnmpVariable(String value, DataType dataType) { | ||
78 | + dataType = dataType == null ? DataType.STRING : dataType; | ||
79 | + Variable variable; | ||
80 | + switch (dataType) { | ||
81 | + case LONG: | ||
82 | + try { | ||
83 | + variable = new Integer32(Integer.parseInt(value)); | ||
84 | + break; | ||
85 | + } catch (NumberFormatException ignored) { | ||
86 | + } | ||
87 | + case DOUBLE: | ||
88 | + case BOOLEAN: | ||
89 | + case STRING: | ||
90 | + case JSON: | ||
91 | + default: | ||
92 | + variable = new OctetString(value); | ||
93 | + } | ||
94 | + return variable; | ||
95 | + } | ||
96 | + | ||
97 | + private PDU setUpPdu(DeviceSessionContext sessionContext) { | ||
98 | + PDU pdu; | ||
99 | + SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration(); | ||
100 | + SnmpProtocolVersion snmpVersion = deviceTransportConfiguration.getProtocolVersion(); | ||
101 | + switch (snmpVersion) { | ||
102 | + case V1: | ||
103 | + case V2C: | ||
104 | + pdu = new PDU(); | ||
105 | + break; | ||
106 | + case V3: | ||
107 | + ScopedPDU scopedPdu = new ScopedPDU(); | ||
108 | + scopedPdu.setContextName(new OctetString(deviceTransportConfiguration.getContextName())); | ||
109 | + scopedPdu.setContextEngineID(new OctetString(deviceTransportConfiguration.getEngineId())); | ||
110 | + pdu = scopedPdu; | ||
111 | + break; | ||
112 | + default: | ||
113 | + throw new UnsupportedOperationException("SNMP version " + snmpVersion + " is not supported"); | ||
114 | + } | ||
115 | + return pdu; | ||
116 | + } | ||
117 | + | ||
118 | + | ||
119 | + public JsonObject processPdu(PDU pdu, List<SnmpMapping> responseMappings) { | ||
120 | + Map<OID, String> values = processPdu(pdu); | ||
121 | + | ||
122 | + Map<OID, SnmpMapping> mappings = new HashMap<>(); | ||
123 | + if (responseMappings != null) { | ||
124 | + for (SnmpMapping mapping : responseMappings) { | ||
125 | + OID oid = new OID(mapping.getOid()); | ||
126 | + mappings.put(oid, mapping); | ||
127 | + } | ||
128 | + } | ||
129 | + | ||
130 | + JsonObject data = new JsonObject(); | ||
131 | + values.forEach((oid, value) -> { | ||
132 | + log.trace("Processing variable binding: {} - {}", oid, value); | ||
133 | + | ||
134 | + SnmpMapping mapping = mappings.get(oid); | ||
135 | + if (mapping == null) { | ||
136 | + log.debug("No SNMP mapping for oid {}", oid); | ||
137 | + return; | ||
138 | + } | ||
139 | + | ||
140 | + processValue(mapping.getKey(), mapping.getDataType(), value, data); | ||
141 | + }); | ||
142 | + | ||
143 | + return data; | ||
144 | + } | ||
145 | + | ||
146 | + public Map<OID, String> processPdu(PDU pdu) { | ||
147 | + return IntStream.range(0, pdu.size()) | ||
148 | + .mapToObj(pdu::get) | ||
149 | + .filter(Objects::nonNull) | ||
150 | + .filter(variableBinding -> !(variableBinding.getVariable() instanceof Null)) | ||
151 | + .collect(Collectors.toMap(VariableBinding::getOid, VariableBinding::toValueString)); | ||
152 | + } | ||
153 | + | ||
154 | + private void processValue(String key, DataType dataType, String value, JsonObject result) { | ||
155 | + switch (dataType) { | ||
156 | + case LONG: | ||
157 | + result.addProperty(key, Long.parseLong(value)); | ||
158 | + break; | ||
159 | + case BOOLEAN: | ||
160 | + result.addProperty(key, Boolean.parseBoolean(value)); | ||
161 | + break; | ||
162 | + case DOUBLE: | ||
163 | + result.addProperty(key, Double.parseDouble(value)); | ||
164 | + break; | ||
165 | + case STRING: | ||
166 | + case JSON: | ||
167 | + default: | ||
168 | + result.addProperty(key, value); | ||
169 | + } | ||
170 | + } | ||
171 | +} |
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.snmp.service; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.springframework.stereotype.Service; | ||
20 | +import org.thingsboard.server.common.data.Device; | ||
21 | +import org.thingsboard.server.common.data.device.data.DeviceData; | ||
22 | +import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration; | ||
23 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
24 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
25 | +import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
26 | +import org.thingsboard.server.common.transport.TransportService; | ||
27 | +import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; | ||
28 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
29 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
30 | + | ||
31 | +import java.util.ArrayList; | ||
32 | +import java.util.List; | ||
33 | +import java.util.UUID; | ||
34 | +import java.util.stream.Collectors; | ||
35 | + | ||
36 | +@TbSnmpTransportComponent | ||
37 | +@Service | ||
38 | +@RequiredArgsConstructor | ||
39 | +public class ProtoTransportEntityService { | ||
40 | + private final TransportService transportService; | ||
41 | + private final DataDecodingEncodingService dataDecodingEncodingService; | ||
42 | + | ||
43 | + public Device getDeviceById(DeviceId id) { | ||
44 | + TransportProtos.GetDeviceResponseMsg deviceProto = transportService.getDevice(TransportProtos.GetDeviceRequestMsg.newBuilder() | ||
45 | + .setDeviceIdMSB(id.getId().getMostSignificantBits()) | ||
46 | + .setDeviceIdLSB(id.getId().getLeastSignificantBits()) | ||
47 | + .build()); | ||
48 | + | ||
49 | + if (deviceProto == null) { | ||
50 | + return null; | ||
51 | + } | ||
52 | + | ||
53 | + DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID( | ||
54 | + deviceProto.getDeviceProfileIdMSB(), deviceProto.getDeviceProfileIdLSB()) | ||
55 | + ); | ||
56 | + | ||
57 | + Device device = new Device(); | ||
58 | + device.setId(id); | ||
59 | + device.setDeviceProfileId(deviceProfileId); | ||
60 | + | ||
61 | + DeviceTransportConfiguration deviceTransportConfiguration = (DeviceTransportConfiguration) dataDecodingEncodingService.decode( | ||
62 | + deviceProto.getDeviceTransportConfiguration().toByteArray() | ||
63 | + ).orElseThrow(() -> new IllegalStateException("Can't find device transport configuration")); | ||
64 | + | ||
65 | + DeviceData deviceData = new DeviceData(); | ||
66 | + deviceData.setTransportConfiguration(deviceTransportConfiguration); | ||
67 | + device.setDeviceData(deviceData); | ||
68 | + | ||
69 | + return device; | ||
70 | + } | ||
71 | + | ||
72 | + public DeviceCredentials getDeviceCredentialsByDeviceId(DeviceId deviceId) { | ||
73 | + TransportProtos.GetDeviceCredentialsResponseMsg deviceCredentialsResponse = transportService.getDeviceCredentials( | ||
74 | + TransportProtos.GetDeviceCredentialsRequestMsg.newBuilder() | ||
75 | + .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) | ||
76 | + .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) | ||
77 | + .build() | ||
78 | + ); | ||
79 | + | ||
80 | + return (DeviceCredentials) dataDecodingEncodingService.decode(deviceCredentialsResponse.getDeviceCredentialsData().toByteArray()) | ||
81 | + .orElseThrow(() -> new IllegalArgumentException("Device credentials not found")); | ||
82 | + } | ||
83 | + | ||
84 | + public List<UUID> getAllSnmpDevicesIds() { | ||
85 | + List<UUID> result = new ArrayList<>(); | ||
86 | + | ||
87 | + int page = 0; | ||
88 | + int pageSize = 512; | ||
89 | + boolean hasNextPage = true; | ||
90 | + | ||
91 | + while (hasNextPage) { | ||
92 | + TransportProtos.GetSnmpDevicesResponseMsg responseMsg = requestSnmpDevicesIds(page, pageSize); | ||
93 | + result.addAll(responseMsg.getIdsList().stream() | ||
94 | + .map(UUID::fromString) | ||
95 | + .collect(Collectors.toList())); | ||
96 | + hasNextPage = responseMsg.getHasNextPage(); | ||
97 | + page++; | ||
98 | + } | ||
99 | + | ||
100 | + return result; | ||
101 | + } | ||
102 | + | ||
103 | + private TransportProtos.GetSnmpDevicesResponseMsg requestSnmpDevicesIds(int page, int pageSize) { | ||
104 | + TransportProtos.GetSnmpDevicesRequestMsg requestMsg = TransportProtos.GetSnmpDevicesRequestMsg.newBuilder() | ||
105 | + .setPage(page) | ||
106 | + .setPageSize(pageSize) | ||
107 | + .build(); | ||
108 | + return transportService.getSnmpDevicesIds(requestMsg); | ||
109 | + } | ||
110 | +} |
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.snmp.service; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.snmp4j.AbstractTarget; | ||
20 | +import org.snmp4j.CommunityTarget; | ||
21 | +import org.snmp4j.Target; | ||
22 | +import org.snmp4j.UserTarget; | ||
23 | +import org.snmp4j.security.SecurityLevel; | ||
24 | +import org.snmp4j.security.SecurityModel; | ||
25 | +import org.snmp4j.security.SecurityProtocols; | ||
26 | +import org.snmp4j.security.USM; | ||
27 | +import org.snmp4j.smi.Address; | ||
28 | +import org.snmp4j.smi.GenericAddress; | ||
29 | +import org.snmp4j.smi.OID; | ||
30 | +import org.snmp4j.smi.OctetString; | ||
31 | +import org.springframework.beans.factory.annotation.Value; | ||
32 | +import org.springframework.stereotype.Service; | ||
33 | +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | ||
34 | +import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; | ||
35 | +import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion; | ||
36 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
37 | +import org.thingsboard.server.transport.snmp.service.SnmpTransportService; | ||
38 | +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; | ||
39 | + | ||
40 | +import java.util.Optional; | ||
41 | + | ||
42 | +@Service | ||
43 | +@TbSnmpTransportComponent | ||
44 | +@RequiredArgsConstructor | ||
45 | +public class SnmpAuthService { | ||
46 | + private final SnmpTransportService snmpTransportService; | ||
47 | + | ||
48 | + @Value("${transport.snmp.underlying_protocol}") | ||
49 | + private String snmpUnderlyingProtocol; | ||
50 | + | ||
51 | + public Target setUpSnmpTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) { | ||
52 | + AbstractTarget target; | ||
53 | + | ||
54 | + SnmpProtocolVersion protocolVersion = deviceTransportConfig.getProtocolVersion(); | ||
55 | + switch (protocolVersion) { | ||
56 | + case V1: | ||
57 | + CommunityTarget communityTargetV1 = new CommunityTarget(); | ||
58 | + communityTargetV1.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv1); | ||
59 | + communityTargetV1.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV); | ||
60 | + communityTargetV1.setCommunity(new OctetString(deviceTransportConfig.getCommunity())); | ||
61 | + target = communityTargetV1; | ||
62 | + break; | ||
63 | + case V2C: | ||
64 | + CommunityTarget communityTargetV2 = new CommunityTarget(); | ||
65 | + communityTargetV2.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c); | ||
66 | + communityTargetV2.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV); | ||
67 | + communityTargetV2.setCommunity(new OctetString(deviceTransportConfig.getCommunity())); | ||
68 | + target = communityTargetV2; | ||
69 | + break; | ||
70 | + case V3: | ||
71 | + OctetString username = new OctetString(deviceTransportConfig.getUsername()); | ||
72 | + OctetString securityName = new OctetString(deviceTransportConfig.getSecurityName()); | ||
73 | + OctetString engineId = new OctetString(deviceTransportConfig.getEngineId()); | ||
74 | + | ||
75 | + OID authenticationProtocol = new OID(deviceTransportConfig.getAuthenticationProtocol().getOid()); | ||
76 | + OID privacyProtocol = new OID(deviceTransportConfig.getPrivacyProtocol().getOid()); | ||
77 | + OctetString authenticationPassphrase = new OctetString(deviceTransportConfig.getAuthenticationPassphrase()); | ||
78 | + authenticationPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, authenticationPassphrase, engineId.getValue())); | ||
79 | + OctetString privacyPassphrase = new OctetString(deviceTransportConfig.getPrivacyPassphrase()); | ||
80 | + privacyPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(privacyProtocol, authenticationProtocol, privacyPassphrase, engineId.getValue())); | ||
81 | + | ||
82 | + USM usm = snmpTransportService.getSnmp().getUSM(); | ||
83 | + if (usm.hasUser(engineId, securityName)) { | ||
84 | + usm.removeAllUsers(username, engineId); | ||
85 | + } | ||
86 | + usm.addLocalizedUser( | ||
87 | + engineId.getValue(), username, | ||
88 | + authenticationProtocol, authenticationPassphrase.getValue(), | ||
89 | + privacyProtocol, privacyPassphrase.getValue() | ||
90 | + ); | ||
91 | + | ||
92 | + UserTarget userTarget = new UserTarget(); | ||
93 | + userTarget.setSecurityName(securityName); | ||
94 | + userTarget.setAuthoritativeEngineID(engineId.getValue()); | ||
95 | + userTarget.setSecurityModel(SecurityModel.SECURITY_MODEL_USM); | ||
96 | + userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV); | ||
97 | + target = userTarget; | ||
98 | + break; | ||
99 | + default: | ||
100 | + throw new UnsupportedOperationException("SNMP protocol version " + protocolVersion + " is not supported"); | ||
101 | + } | ||
102 | + | ||
103 | + Address address = GenericAddress.parse(snmpUnderlyingProtocol + ":" + deviceTransportConfig.getHost() + "/" + deviceTransportConfig.getPort()); | ||
104 | + target.setAddress(Optional.ofNullable(address).orElseThrow(() -> new IllegalArgumentException("Address of the SNMP device is invalid"))); | ||
105 | + target.setTimeout(profileTransportConfig.getTimeoutMs()); | ||
106 | + target.setRetries(profileTransportConfig.getRetries()); | ||
107 | + target.setVersion(protocolVersion.getCode()); | ||
108 | + | ||
109 | + return target; | ||
110 | + } | ||
111 | + | ||
112 | + public void cleanUpSnmpAuthInfo(DeviceSessionContext sessionContext) { | ||
113 | + SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration(); | ||
114 | + if (deviceTransportConfiguration.getProtocolVersion() == SnmpProtocolVersion.V3) { | ||
115 | + OctetString username = new OctetString(deviceTransportConfiguration.getUsername()); | ||
116 | + OctetString engineId = new OctetString(deviceTransportConfiguration.getEngineId()); | ||
117 | + snmpTransportService.getSnmp().getUSM().removeAllUsers(username, engineId); | ||
118 | + } | ||
119 | + } | ||
120 | + | ||
121 | +} |
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.snmp.service; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.springframework.context.ApplicationEventPublisher; | ||
21 | +import org.springframework.stereotype.Service; | ||
22 | +import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; | ||
23 | +import org.thingsboard.server.queue.discovery.PartitionService; | ||
24 | +import org.thingsboard.server.queue.discovery.event.ServiceListChangedEvent; | ||
25 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
26 | +import org.thingsboard.server.transport.snmp.event.SnmpTransportListChangedEvent; | ||
27 | + | ||
28 | +import java.util.Comparator; | ||
29 | +import java.util.List; | ||
30 | +import java.util.UUID; | ||
31 | +import java.util.stream.Collectors; | ||
32 | +import java.util.stream.Stream; | ||
33 | + | ||
34 | +@TbSnmpTransportComponent | ||
35 | +@Service | ||
36 | +@RequiredArgsConstructor | ||
37 | +@Slf4j | ||
38 | +public class SnmpTransportBalancingService { | ||
39 | + private final PartitionService partitionService; | ||
40 | + private final ApplicationEventPublisher eventPublisher; | ||
41 | + private final SnmpTransportService snmpTransportService; | ||
42 | + | ||
43 | + private int snmpTransportsCount = 1; | ||
44 | + private Integer currentTransportPartitionIndex = 0; | ||
45 | + | ||
46 | + public void onServiceListChanged(ServiceListChangedEvent event) { | ||
47 | + log.trace("Got service list changed event: {}", event); | ||
48 | + recalculatePartitions(event.getOtherServices(), event.getCurrentService()); | ||
49 | + } | ||
50 | + | ||
51 | + public boolean isManagedByCurrentTransport(UUID entityId) { | ||
52 | + boolean isManaged = resolvePartitionIndexForEntity(entityId) == currentTransportPartitionIndex; | ||
53 | + if (!isManaged) { | ||
54 | + log.trace("Entity {} is not managed by current SNMP transport node", entityId); | ||
55 | + } | ||
56 | + return isManaged; | ||
57 | + } | ||
58 | + | ||
59 | + private int resolvePartitionIndexForEntity(UUID entityId) { | ||
60 | + return partitionService.resolvePartitionIndex(entityId, snmpTransportsCount); | ||
61 | + } | ||
62 | + | ||
63 | + private void recalculatePartitions(List<ServiceInfo> otherServices, ServiceInfo currentService) { | ||
64 | + log.info("Recalculating partitions for SNMP transports"); | ||
65 | + List<ServiceInfo> snmpTransports = Stream.concat(otherServices.stream(), Stream.of(currentService)) | ||
66 | + .filter(service -> service.getTransportsList().contains(snmpTransportService.getName())) | ||
67 | + .sorted(Comparator.comparing(ServiceInfo::getServiceId)) | ||
68 | + .collect(Collectors.toList()); | ||
69 | + log.trace("Found SNMP transports: {}", snmpTransports); | ||
70 | + | ||
71 | + int previousCurrentTransportPartitionIndex = currentTransportPartitionIndex; | ||
72 | + int previousSnmpTransportsCount = snmpTransportsCount; | ||
73 | + | ||
74 | + if (!snmpTransports.isEmpty()) { | ||
75 | + for (int i = 0; i < snmpTransports.size(); i++) { | ||
76 | + if (snmpTransports.get(i).equals(currentService)) { | ||
77 | + currentTransportPartitionIndex = i; | ||
78 | + break; | ||
79 | + } | ||
80 | + } | ||
81 | + snmpTransportsCount = snmpTransports.size(); | ||
82 | + } | ||
83 | + | ||
84 | + if (snmpTransportsCount != previousSnmpTransportsCount || currentTransportPartitionIndex != previousCurrentTransportPartitionIndex) { | ||
85 | + log.info("SNMP transports partitions have changed: transports count = {}, current transport partition index = {}", snmpTransportsCount, currentTransportPartitionIndex); | ||
86 | + eventPublisher.publishEvent(new SnmpTransportListChangedEvent()); | ||
87 | + } else { | ||
88 | + log.info("SNMP transports partitions have not changed"); | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
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.snmp.service; | ||
17 | + | ||
18 | +import com.google.gson.JsonElement; | ||
19 | +import com.google.gson.JsonObject; | ||
20 | +import lombok.Data; | ||
21 | +import lombok.Getter; | ||
22 | +import lombok.RequiredArgsConstructor; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
24 | +import org.snmp4j.PDU; | ||
25 | +import org.snmp4j.Snmp; | ||
26 | +import org.snmp4j.TransportMapping; | ||
27 | +import org.snmp4j.event.ResponseEvent; | ||
28 | +import org.snmp4j.mp.MPv3; | ||
29 | +import org.snmp4j.security.SecurityModels; | ||
30 | +import org.snmp4j.security.SecurityProtocols; | ||
31 | +import org.snmp4j.security.USM; | ||
32 | +import org.snmp4j.smi.OctetString; | ||
33 | +import org.snmp4j.transport.DefaultTcpTransportMapping; | ||
34 | +import org.snmp4j.transport.DefaultUdpTransportMapping; | ||
35 | +import org.springframework.beans.factory.annotation.Value; | ||
36 | +import org.springframework.stereotype.Service; | ||
37 | +import org.thingsboard.common.util.ThingsBoardThreadFactory; | ||
38 | +import org.thingsboard.server.common.data.TbTransportService; | ||
39 | +import org.thingsboard.server.common.data.kv.DataType; | ||
40 | +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; | ||
41 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; | ||
42 | +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod; | ||
43 | +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig; | ||
44 | +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig; | ||
45 | +import org.thingsboard.server.common.transport.TransportService; | ||
46 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
47 | +import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
48 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
49 | +import org.thingsboard.server.queue.util.TbSnmpTransportComponent; | ||
50 | +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; | ||
51 | + | ||
52 | +import javax.annotation.PostConstruct; | ||
53 | +import javax.annotation.PreDestroy; | ||
54 | +import java.io.IOException; | ||
55 | +import java.util.Arrays; | ||
56 | +import java.util.Collections; | ||
57 | +import java.util.EnumMap; | ||
58 | +import java.util.List; | ||
59 | +import java.util.Map; | ||
60 | +import java.util.Optional; | ||
61 | +import java.util.concurrent.ExecutorService; | ||
62 | +import java.util.concurrent.Executors; | ||
63 | +import java.util.concurrent.ScheduledExecutorService; | ||
64 | +import java.util.concurrent.ScheduledFuture; | ||
65 | +import java.util.concurrent.TimeUnit; | ||
66 | +import java.util.stream.Collectors; | ||
67 | + | ||
68 | +@TbSnmpTransportComponent | ||
69 | +@Service | ||
70 | +@Slf4j | ||
71 | +@RequiredArgsConstructor | ||
72 | +public class SnmpTransportService implements TbTransportService { | ||
73 | + private final TransportService transportService; | ||
74 | + private final PduService pduService; | ||
75 | + | ||
76 | + @Getter | ||
77 | + private Snmp snmp; | ||
78 | + private ScheduledExecutorService queryingExecutor; | ||
79 | + private ExecutorService responseProcessingExecutor; | ||
80 | + | ||
81 | + private final Map<SnmpCommunicationSpec, ResponseDataMapper> responseDataMappers = new EnumMap<>(SnmpCommunicationSpec.class); | ||
82 | + private final Map<SnmpCommunicationSpec, ResponseProcessor> responseProcessors = new EnumMap<>(SnmpCommunicationSpec.class); | ||
83 | + | ||
84 | + @Value("${transport.snmp.response_processing.parallelism_level}") | ||
85 | + private Integer responseProcessingParallelismLevel; | ||
86 | + @Value("${transport.snmp.underlying_protocol}") | ||
87 | + private String snmpUnderlyingProtocol; | ||
88 | + | ||
89 | + @PostConstruct | ||
90 | + private void init() throws IOException { | ||
91 | + queryingExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), ThingsBoardThreadFactory.forName("snmp-querying")); | ||
92 | + responseProcessingExecutor = Executors.newWorkStealingPool(responseProcessingParallelismLevel); | ||
93 | + | ||
94 | + initializeSnmp(); | ||
95 | + configureResponseDataMappers(); | ||
96 | + configureResponseProcessors(); | ||
97 | + | ||
98 | + log.info("SNMP transport service initialized"); | ||
99 | + } | ||
100 | + | ||
101 | + private void initializeSnmp() throws IOException { | ||
102 | + TransportMapping<?> transportMapping; | ||
103 | + switch (snmpUnderlyingProtocol) { | ||
104 | + case "udp": | ||
105 | + transportMapping = new DefaultUdpTransportMapping(); | ||
106 | + break; | ||
107 | + case "tcp": | ||
108 | + transportMapping = new DefaultTcpTransportMapping(); | ||
109 | + break; | ||
110 | + default: | ||
111 | + throw new IllegalArgumentException("Underlying protocol " + snmpUnderlyingProtocol + " for SNMP is not supported"); | ||
112 | + } | ||
113 | + snmp = new Snmp(transportMapping); | ||
114 | + snmp.listen(); | ||
115 | + | ||
116 | + USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); | ||
117 | + SecurityModels.getInstance().addSecurityModel(usm); | ||
118 | + } | ||
119 | + | ||
120 | + public void createQueryingTasks(DeviceSessionContext sessionContext) { | ||
121 | + List<ScheduledFuture<?>> queryingTasks = sessionContext.getProfileTransportConfiguration().getCommunicationConfigs().stream() | ||
122 | + .filter(communicationConfig -> communicationConfig instanceof RepeatingQueryingSnmpCommunicationConfig) | ||
123 | + .map(config -> { | ||
124 | + RepeatingQueryingSnmpCommunicationConfig repeatingCommunicationConfig = (RepeatingQueryingSnmpCommunicationConfig) config; | ||
125 | + Long queryingFrequency = repeatingCommunicationConfig.getQueryingFrequencyMs(); | ||
126 | + | ||
127 | + return queryingExecutor.scheduleWithFixedDelay(() -> { | ||
128 | + try { | ||
129 | + if (sessionContext.isActive()) { | ||
130 | + sendRequest(sessionContext, repeatingCommunicationConfig); | ||
131 | + } | ||
132 | + } catch (Exception e) { | ||
133 | + log.error("Failed to send SNMP request for device {}: {}", sessionContext.getDeviceId(), e.toString()); | ||
134 | + } | ||
135 | + }, queryingFrequency, queryingFrequency, TimeUnit.MILLISECONDS); | ||
136 | + }) | ||
137 | + .collect(Collectors.toList()); | ||
138 | + sessionContext.getQueryingTasks().addAll(queryingTasks); | ||
139 | + } | ||
140 | + | ||
141 | + public void cancelQueryingTasks(DeviceSessionContext sessionContext) { | ||
142 | + sessionContext.getQueryingTasks().forEach(task -> task.cancel(true)); | ||
143 | + sessionContext.getQueryingTasks().clear(); | ||
144 | + } | ||
145 | + | ||
146 | + | ||
147 | + private void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) { | ||
148 | + sendRequest(sessionContext, communicationConfig, Collections.emptyMap()); | ||
149 | + } | ||
150 | + | ||
151 | + private void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) { | ||
152 | + PDU request = pduService.createPdu(sessionContext, communicationConfig, values); | ||
153 | + RequestInfo requestInfo = new RequestInfo(communicationConfig.getSpec(), communicationConfig.getAllMappings()); | ||
154 | + sendRequest(sessionContext, request, requestInfo); | ||
155 | + } | ||
156 | + | ||
157 | + private void sendRequest(DeviceSessionContext sessionContext, PDU request, RequestInfo requestInfo) { | ||
158 | + if (request.size() > 0) { | ||
159 | + log.trace("Executing SNMP request for device {}. Variables bindings: {}", sessionContext.getDeviceId(), request.getVariableBindings()); | ||
160 | + try { | ||
161 | + snmp.send(request, sessionContext.getTarget(), requestInfo, sessionContext); | ||
162 | + } catch (IOException e) { | ||
163 | + log.error("Failed to send SNMP request to device {}: {}", sessionContext.getDeviceId(), e.toString()); | ||
164 | + } | ||
165 | + } | ||
166 | + } | ||
167 | + | ||
168 | + public void onAttributeUpdate(DeviceSessionContext sessionContext, TransportProtos.AttributeUpdateNotificationMsg attributeUpdateNotification) { | ||
169 | + sessionContext.getProfileTransportConfiguration().getCommunicationConfigs().stream() | ||
170 | + .filter(config -> config.getSpec() == SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING) | ||
171 | + .findFirst() | ||
172 | + .ifPresent(communicationConfig -> { | ||
173 | + Map<String, String> sharedAttributes = JsonConverter.toJson(attributeUpdateNotification).entrySet().stream() | ||
174 | + .collect(Collectors.toMap( | ||
175 | + Map.Entry::getKey, | ||
176 | + entry -> entry.getValue().isJsonPrimitive() ? entry.getValue().getAsString() : entry.getValue().toString() | ||
177 | + )); | ||
178 | + sendRequest(sessionContext, communicationConfig, sharedAttributes); | ||
179 | + }); | ||
180 | + } | ||
181 | + | ||
182 | + public void onToDeviceRpcRequest(DeviceSessionContext sessionContext, TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg) { | ||
183 | + SnmpMethod snmpMethod = SnmpMethod.valueOf(toDeviceRpcRequestMsg.getMethodName()); | ||
184 | + JsonObject params = JsonConverter.parse(toDeviceRpcRequestMsg.getParams()).getAsJsonObject(); | ||
185 | + | ||
186 | + String oid = Optional.ofNullable(params.get("oid")).map(JsonElement::getAsString).orElse(null); | ||
187 | + String value = Optional.ofNullable(params.get("value")).map(JsonElement::getAsString).orElse(null); | ||
188 | + DataType dataType = Optional.ofNullable(params.get("dataType")).map(e -> DataType.valueOf(e.getAsString())).orElse(DataType.STRING); | ||
189 | + | ||
190 | + if (oid == null || oid.isEmpty()) { | ||
191 | + throw new IllegalArgumentException("OID in to-device RPC request is not specified"); | ||
192 | + } | ||
193 | + if (value == null && snmpMethod == SnmpMethod.SET) { | ||
194 | + throw new IllegalArgumentException("Value must be specified for SNMP method 'SET'"); | ||
195 | + } | ||
196 | + | ||
197 | + PDU request = pduService.createSingleVariablePdu(sessionContext, snmpMethod, oid, value, dataType); | ||
198 | + sendRequest(sessionContext, request, new RequestInfo(toDeviceRpcRequestMsg.getRequestId(), SnmpCommunicationSpec.TO_DEVICE_RPC_REQUEST)); | ||
199 | + } | ||
200 | + | ||
201 | + | ||
202 | + public void processResponseEvent(DeviceSessionContext sessionContext, ResponseEvent event) { | ||
203 | + ((Snmp) event.getSource()).cancel(event.getRequest(), sessionContext); | ||
204 | + | ||
205 | + if (event.getError() != null) { | ||
206 | + log.warn("SNMP response error: {}", event.getError().toString()); | ||
207 | + return; | ||
208 | + } | ||
209 | + | ||
210 | + PDU response = event.getResponse(); | ||
211 | + if (response == null) { | ||
212 | + log.debug("No response from SNMP device {}, requestId: {}", sessionContext.getDeviceId(), event.getRequest().getRequestID()); | ||
213 | + return; | ||
214 | + } | ||
215 | + | ||
216 | + RequestInfo requestInfo = (RequestInfo) event.getUserObject(); | ||
217 | + responseProcessingExecutor.execute(() -> { | ||
218 | + processResponse(sessionContext, response, requestInfo); | ||
219 | + }); | ||
220 | + } | ||
221 | + | ||
222 | + private void processResponse(DeviceSessionContext sessionContext, PDU response, RequestInfo requestInfo) { | ||
223 | + ResponseProcessor responseProcessor = responseProcessors.get(requestInfo.getCommunicationSpec()); | ||
224 | + if (responseProcessor == null) return; | ||
225 | + | ||
226 | + JsonObject responseData = responseDataMappers.get(requestInfo.getCommunicationSpec()).map(response, requestInfo); | ||
227 | + | ||
228 | + if (responseData.entrySet().isEmpty()) { | ||
229 | + log.debug("No values is the SNMP response for device {}. Request id: {}", sessionContext.getDeviceId(), response.getRequestID()); | ||
230 | + return; | ||
231 | + } | ||
232 | + | ||
233 | + responseProcessor.process(responseData, requestInfo, sessionContext); | ||
234 | + reportActivity(sessionContext.getSessionInfo()); | ||
235 | + } | ||
236 | + | ||
237 | + private void configureResponseDataMappers() { | ||
238 | + responseDataMappers.put(SnmpCommunicationSpec.TO_DEVICE_RPC_REQUEST, (pdu, requestInfo) -> { | ||
239 | + JsonObject responseData = new JsonObject(); | ||
240 | + pduService.processPdu(pdu).forEach((oid, value) -> { | ||
241 | + responseData.addProperty(oid.toDottedString(), value); | ||
242 | + }); | ||
243 | + return responseData; | ||
244 | + }); | ||
245 | + | ||
246 | + ResponseDataMapper defaultResponseDataMapper = (pdu, requestInfo) -> { | ||
247 | + return pduService.processPdu(pdu, requestInfo.getResponseMappings()); | ||
248 | + }; | ||
249 | + Arrays.stream(SnmpCommunicationSpec.values()) | ||
250 | + .forEach(communicationSpec -> { | ||
251 | + responseDataMappers.putIfAbsent(communicationSpec, defaultResponseDataMapper); | ||
252 | + }); | ||
253 | + } | ||
254 | + | ||
255 | + private void configureResponseProcessors() { | ||
256 | + responseProcessors.put(SnmpCommunicationSpec.TELEMETRY_QUERYING, (responseData, requestInfo, sessionContext) -> { | ||
257 | + TransportProtos.PostTelemetryMsg postTelemetryMsg = JsonConverter.convertToTelemetryProto(responseData); | ||
258 | + transportService.process(sessionContext.getSessionInfo(), postTelemetryMsg, null); | ||
259 | + log.debug("Posted telemetry for SNMP device {}: {}", sessionContext.getDeviceId(), responseData); | ||
260 | + }); | ||
261 | + | ||
262 | + responseProcessors.put(SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING, (responseData, requestInfo, sessionContext) -> { | ||
263 | + TransportProtos.PostAttributeMsg postAttributesMsg = JsonConverter.convertToAttributesProto(responseData); | ||
264 | + transportService.process(sessionContext.getSessionInfo(), postAttributesMsg, null); | ||
265 | + log.debug("Posted attributes for SNMP device {}: {}", sessionContext.getDeviceId(), responseData); | ||
266 | + }); | ||
267 | + | ||
268 | + responseProcessors.put(SnmpCommunicationSpec.TO_DEVICE_RPC_REQUEST, (responseData, requestInfo, sessionContext) -> { | ||
269 | + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
270 | + .setRequestId(requestInfo.getRequestId()) | ||
271 | + .setPayload(JsonConverter.toJson(responseData)) | ||
272 | + .build(); | ||
273 | + transportService.process(sessionContext.getSessionInfo(), rpcResponseMsg, null); | ||
274 | + log.debug("Posted RPC response {} for device {}", responseData, sessionContext.getDeviceId()); | ||
275 | + }); | ||
276 | + } | ||
277 | + | ||
278 | + private void reportActivity(TransportProtos.SessionInfoProto sessionInfo) { | ||
279 | + transportService.process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder() | ||
280 | + .setAttributeSubscription(true) | ||
281 | + .setRpcSubscription(true) | ||
282 | + .setLastActivityTime(System.currentTimeMillis()) | ||
283 | + .build(), TransportServiceCallback.EMPTY); | ||
284 | + } | ||
285 | + | ||
286 | + | ||
287 | + @Override | ||
288 | + public String getName() { | ||
289 | + return "SNMP"; | ||
290 | + } | ||
291 | + | ||
292 | + @PreDestroy | ||
293 | + public void shutdown() { | ||
294 | + log.info("Stopping SNMP transport!"); | ||
295 | + if (queryingExecutor != null) { | ||
296 | + queryingExecutor.shutdownNow(); | ||
297 | + } | ||
298 | + if (responseProcessingExecutor != null) { | ||
299 | + responseProcessingExecutor.shutdownNow(); | ||
300 | + } | ||
301 | + if (snmp != null) { | ||
302 | + try { | ||
303 | + snmp.close(); | ||
304 | + } catch (IOException e) { | ||
305 | + log.error(e.getMessage(), e); | ||
306 | + } | ||
307 | + } | ||
308 | + log.info("SNMP transport stopped!"); | ||
309 | + } | ||
310 | + | ||
311 | + @Data | ||
312 | + private static class RequestInfo { | ||
313 | + private Integer requestId; | ||
314 | + private SnmpCommunicationSpec communicationSpec; | ||
315 | + private List<SnmpMapping> responseMappings; | ||
316 | + | ||
317 | + public RequestInfo(Integer requestId, SnmpCommunicationSpec communicationSpec) { | ||
318 | + this.requestId = requestId; | ||
319 | + this.communicationSpec = communicationSpec; | ||
320 | + } | ||
321 | + | ||
322 | + public RequestInfo(SnmpCommunicationSpec communicationSpec) { | ||
323 | + this.communicationSpec = communicationSpec; | ||
324 | + } | ||
325 | + | ||
326 | + public RequestInfo(SnmpCommunicationSpec communicationSpec, List<SnmpMapping> responseMappings) { | ||
327 | + this.communicationSpec = communicationSpec; | ||
328 | + this.responseMappings = responseMappings; | ||
329 | + } | ||
330 | + } | ||
331 | + | ||
332 | + private interface ResponseDataMapper { | ||
333 | + JsonObject map(PDU pdu, RequestInfo requestInfo); | ||
334 | + } | ||
335 | + | ||
336 | + private interface ResponseProcessor { | ||
337 | + void process(JsonObject responseData, RequestInfo requestInfo, DeviceSessionContext sessionContext); | ||
338 | + } | ||
339 | + | ||
340 | +} |
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.snmp.session; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.Setter; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.snmp4j.Target; | ||
22 | +import org.snmp4j.event.ResponseEvent; | ||
23 | +import org.snmp4j.event.ResponseListener; | ||
24 | +import org.thingsboard.server.common.data.Device; | ||
25 | +import org.thingsboard.server.common.data.DeviceProfile; | ||
26 | +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | ||
27 | +import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; | ||
28 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
29 | +import org.thingsboard.server.common.transport.SessionMsgListener; | ||
30 | +import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; | ||
31 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
32 | +import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | ||
33 | +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; | ||
34 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; | ||
35 | +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; | ||
36 | +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; | ||
37 | +import org.thingsboard.server.transport.snmp.SnmpTransportContext; | ||
38 | + | ||
39 | +import java.util.LinkedList; | ||
40 | +import java.util.List; | ||
41 | +import java.util.UUID; | ||
42 | +import java.util.concurrent.ScheduledFuture; | ||
43 | +import java.util.concurrent.atomic.AtomicInteger; | ||
44 | + | ||
45 | +@Slf4j | ||
46 | +public class DeviceSessionContext extends DeviceAwareSessionContext implements SessionMsgListener, ResponseListener { | ||
47 | + @Getter | ||
48 | + private Target target; | ||
49 | + private final String token; | ||
50 | + @Getter | ||
51 | + @Setter | ||
52 | + private SnmpDeviceProfileTransportConfiguration profileTransportConfiguration; | ||
53 | + @Getter | ||
54 | + @Setter | ||
55 | + private SnmpDeviceTransportConfiguration deviceTransportConfiguration; | ||
56 | + @Getter | ||
57 | + private final Device device; | ||
58 | + | ||
59 | + private final SnmpTransportContext snmpTransportContext; | ||
60 | + | ||
61 | + private final AtomicInteger msgIdSeq = new AtomicInteger(0); | ||
62 | + @Getter | ||
63 | + private boolean isActive = true; | ||
64 | + | ||
65 | + @Getter | ||
66 | + private final List<ScheduledFuture<?>> queryingTasks = new LinkedList<>(); | ||
67 | + | ||
68 | + public DeviceSessionContext(Device device, DeviceProfile deviceProfile, String token, | ||
69 | + SnmpDeviceProfileTransportConfiguration profileTransportConfiguration, | ||
70 | + SnmpDeviceTransportConfiguration deviceTransportConfiguration, | ||
71 | + SnmpTransportContext snmpTransportContext) throws Exception { | ||
72 | + super(UUID.randomUUID()); | ||
73 | + super.setDeviceId(device.getId()); | ||
74 | + super.setDeviceProfile(deviceProfile); | ||
75 | + this.device = device; | ||
76 | + | ||
77 | + this.token = token; | ||
78 | + this.snmpTransportContext = snmpTransportContext; | ||
79 | + | ||
80 | + this.profileTransportConfiguration = profileTransportConfiguration; | ||
81 | + this.deviceTransportConfiguration = deviceTransportConfiguration; | ||
82 | + | ||
83 | + initializeTarget(profileTransportConfiguration, deviceTransportConfiguration); | ||
84 | + } | ||
85 | + | ||
86 | + @Override | ||
87 | + public void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) { | ||
88 | + super.onDeviceProfileUpdate(newSessionInfo, deviceProfile); | ||
89 | + if (isActive) { | ||
90 | + snmpTransportContext.onDeviceProfileUpdated(deviceProfile, this); | ||
91 | + } | ||
92 | + } | ||
93 | + | ||
94 | + @Override | ||
95 | + public void onDeviceDeleted(DeviceId deviceId) { | ||
96 | + snmpTransportContext.onDeviceDeleted(this); | ||
97 | + } | ||
98 | + | ||
99 | + @Override | ||
100 | + public void onResponse(ResponseEvent event) { | ||
101 | + if (isActive) { | ||
102 | + snmpTransportContext.getSnmpTransportService().processResponseEvent(this, event); | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + public void initializeTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) throws Exception { | ||
107 | + log.trace("Initializing target for SNMP session of device {}", device); | ||
108 | + this.target = snmpTransportContext.getSnmpAuthService().setUpSnmpTarget(profileTransportConfig, deviceTransportConfig); | ||
109 | + log.debug("SNMP target initialized: {}", target); | ||
110 | + } | ||
111 | + | ||
112 | + public void close() { | ||
113 | + isActive = false; | ||
114 | + } | ||
115 | + | ||
116 | + public String getToken() { | ||
117 | + return token; | ||
118 | + } | ||
119 | + | ||
120 | + @Override | ||
121 | + public int nextMsgId() { | ||
122 | + return msgIdSeq.incrementAndGet(); | ||
123 | + } | ||
124 | + | ||
125 | + @Override | ||
126 | + public void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse) { | ||
127 | + } | ||
128 | + | ||
129 | + @Override | ||
130 | + public void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification) { | ||
131 | + snmpTransportContext.getSnmpTransportService().onAttributeUpdate(this, attributeUpdateNotification); | ||
132 | + } | ||
133 | + | ||
134 | + @Override | ||
135 | + public void onRemoteSessionCloseCommand(SessionCloseNotificationProto sessionCloseNotification) { | ||
136 | + } | ||
137 | + | ||
138 | + @Override | ||
139 | + public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) { | ||
140 | + snmpTransportContext.getSnmpTransportService().onToDeviceRpcRequest(this, toDeviceRequest); | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
144 | + public void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse) { | ||
145 | + } | ||
146 | +} |
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpDeviceSimulatorV2.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.transport.snmp; | ||
17 | + | ||
18 | +import org.snmp4j.CommandResponderEvent; | ||
19 | +import org.snmp4j.CommunityTarget; | ||
20 | +import org.snmp4j.PDU; | ||
21 | +import org.snmp4j.Snmp; | ||
22 | +import org.snmp4j.Target; | ||
23 | +import org.snmp4j.TransportMapping; | ||
24 | +import org.snmp4j.agent.BaseAgent; | ||
25 | +import org.snmp4j.agent.CommandProcessor; | ||
26 | +import org.snmp4j.agent.DuplicateRegistrationException; | ||
27 | +import org.snmp4j.agent.MOGroup; | ||
28 | +import org.snmp4j.agent.ManagedObject; | ||
29 | +import org.snmp4j.agent.mo.MOAccessImpl; | ||
30 | +import org.snmp4j.agent.mo.MOScalar; | ||
31 | +import org.snmp4j.agent.mo.snmp.RowStatus; | ||
32 | +import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB; | ||
33 | +import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB; | ||
34 | +import org.snmp4j.agent.mo.snmp.SnmpTargetMIB; | ||
35 | +import org.snmp4j.agent.mo.snmp.StorageType; | ||
36 | +import org.snmp4j.agent.mo.snmp.VacmMIB; | ||
37 | +import org.snmp4j.agent.security.MutableVACM; | ||
38 | +import org.snmp4j.mp.MPv3; | ||
39 | +import org.snmp4j.mp.SnmpConstants; | ||
40 | +import org.snmp4j.security.SecurityLevel; | ||
41 | +import org.snmp4j.security.SecurityModel; | ||
42 | +import org.snmp4j.security.USM; | ||
43 | +import org.snmp4j.smi.Address; | ||
44 | +import org.snmp4j.smi.GenericAddress; | ||
45 | +import org.snmp4j.smi.Integer32; | ||
46 | +import org.snmp4j.smi.OID; | ||
47 | +import org.snmp4j.smi.OctetString; | ||
48 | +import org.snmp4j.smi.UdpAddress; | ||
49 | +import org.snmp4j.smi.Variable; | ||
50 | +import org.snmp4j.smi.VariableBinding; | ||
51 | +import org.snmp4j.transport.TransportMappings; | ||
52 | + | ||
53 | +import java.io.File; | ||
54 | +import java.io.IOException; | ||
55 | +import java.util.Map; | ||
56 | +import java.util.Scanner; | ||
57 | +import java.util.function.Consumer; | ||
58 | +import java.util.stream.Collectors; | ||
59 | + | ||
60 | +public class SnmpDeviceSimulatorV2 extends BaseAgent { | ||
61 | + | ||
62 | + public static class RequestProcessor extends CommandProcessor { | ||
63 | + private final Consumer<CommandResponderEvent> processor; | ||
64 | + | ||
65 | + public RequestProcessor(Consumer<CommandResponderEvent> processor) { | ||
66 | + super(new OctetString(MPv3.createLocalEngineID())); | ||
67 | + this.processor = processor; | ||
68 | + } | ||
69 | + | ||
70 | + @Override | ||
71 | + public void processPdu(CommandResponderEvent event) { | ||
72 | + processor.accept(event); | ||
73 | + } | ||
74 | + } | ||
75 | + | ||
76 | + | ||
77 | + private final Target target; | ||
78 | + private final Address address; | ||
79 | + private Snmp snmp; | ||
80 | + | ||
81 | + private final String password; | ||
82 | + | ||
83 | + public SnmpDeviceSimulatorV2(int port, String password) throws IOException { | ||
84 | + super(new File("conf.agent"), new File("bootCounter.agent"), new RequestProcessor(event -> { | ||
85 | + System.out.println("aboba"); | ||
86 | + ((Snmp) event.getSource()).cancel(event.getPDU(), event1 -> System.out.println("canceled")); | ||
87 | + })); | ||
88 | + CommunityTarget target = new CommunityTarget(); | ||
89 | + target.setCommunity(new OctetString(password)); | ||
90 | + this.address = GenericAddress.parse("udp:0.0.0.0/" + port); | ||
91 | + target.setAddress(address); | ||
92 | + target.setRetries(2); | ||
93 | + target.setTimeout(1500); | ||
94 | + target.setVersion(SnmpConstants.version2c); | ||
95 | + this.target = target; | ||
96 | + this.password = password; | ||
97 | + } | ||
98 | + | ||
99 | + public void start() throws IOException { | ||
100 | + init(); | ||
101 | + addShutdownHook(); | ||
102 | + getServer().addContext(new OctetString("public")); | ||
103 | + finishInit(); | ||
104 | + run(); | ||
105 | + sendColdStartNotification(); | ||
106 | + snmp = new Snmp(transportMappings[0]); | ||
107 | + } | ||
108 | + | ||
109 | + public void setUpMappings(Map<String, String> oidToResponseMappings) { | ||
110 | + unregisterManagedObject(getSnmpv2MIB()); | ||
111 | + oidToResponseMappings.forEach((oid, response) -> { | ||
112 | + registerManagedObject(new MOScalar<>(new OID(oid), MOAccessImpl.ACCESS_READ_WRITE, new OctetString(response))); | ||
113 | + }); | ||
114 | + } | ||
115 | + | ||
116 | + public void sendTrap(String host, int port, Map<String, String> values) throws IOException { | ||
117 | + PDU pdu = new PDU(); | ||
118 | + pdu.addAll(values.entrySet().stream() | ||
119 | + .map(entry -> new VariableBinding(new OID(entry.getKey()), new OctetString(entry.getValue()))) | ||
120 | + .collect(Collectors.toList())); | ||
121 | + pdu.setType(PDU.TRAP); | ||
122 | + | ||
123 | + CommunityTarget remoteTarget = (CommunityTarget) getTarget().clone(); | ||
124 | + remoteTarget.setAddress(new UdpAddress(host + "/" + port)); | ||
125 | + | ||
126 | + snmp.send(pdu, remoteTarget); | ||
127 | + } | ||
128 | + | ||
129 | + @Override | ||
130 | + protected void registerManagedObjects() { | ||
131 | + } | ||
132 | + | ||
133 | + protected void registerManagedObject(ManagedObject mo) { | ||
134 | + try { | ||
135 | + server.register(mo, null); | ||
136 | + } catch (DuplicateRegistrationException ex) { | ||
137 | + throw new RuntimeException(ex); | ||
138 | + } | ||
139 | + } | ||
140 | + | ||
141 | + protected void unregisterManagedObject(MOGroup moGroup) { | ||
142 | + moGroup.unregisterMOs(server, getContext(moGroup)); | ||
143 | + } | ||
144 | + | ||
145 | + @Override | ||
146 | + protected void addNotificationTargets(SnmpTargetMIB targetMIB, | ||
147 | + SnmpNotificationMIB notificationMIB) { | ||
148 | + } | ||
149 | + | ||
150 | + @Override | ||
151 | + protected void addViews(VacmMIB vacm) { | ||
152 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c, new OctetString( | ||
153 | + "cpublic"), new OctetString("v1v2group"), | ||
154 | + StorageType.nonVolatile); | ||
155 | + | ||
156 | + vacm.addAccess(new OctetString("v1v2group"), new OctetString("public"), | ||
157 | + SecurityModel.SECURITY_MODEL_ANY, SecurityLevel.NOAUTH_NOPRIV, | ||
158 | + MutableVACM.VACM_MATCH_EXACT, new OctetString("fullReadView"), | ||
159 | + new OctetString("fullWriteView"), new OctetString( | ||
160 | + "fullNotifyView"), StorageType.nonVolatile); | ||
161 | + | ||
162 | + vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"), | ||
163 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
164 | + StorageType.nonVolatile); | ||
165 | + } | ||
166 | + | ||
167 | + protected void addUsmUser(USM usm) { | ||
168 | + } | ||
169 | + | ||
170 | + protected void initTransportMappings() { | ||
171 | + transportMappings = new TransportMapping[]{TransportMappings.getInstance().createTransportMapping(address)}; | ||
172 | + } | ||
173 | + | ||
174 | + protected void unregisterManagedObjects() { | ||
175 | + } | ||
176 | + | ||
177 | + protected void addCommunities(SnmpCommunityMIB communityMIB) { | ||
178 | + Variable[] com2sec = new Variable[]{ | ||
179 | + new OctetString("public"), | ||
180 | + new OctetString("cpublic"), | ||
181 | + getAgent().getContextEngineID(), | ||
182 | + new OctetString("public"), | ||
183 | + new OctetString(), | ||
184 | + new Integer32(StorageType.nonVolatile), | ||
185 | + new Integer32(RowStatus.active) | ||
186 | + }; | ||
187 | + SnmpCommunityMIB.SnmpCommunityEntryRow row = communityMIB.getSnmpCommunityEntry().createRow( | ||
188 | + new OctetString("public2public").toSubIndex(true), com2sec); | ||
189 | + communityMIB.getSnmpCommunityEntry().addRow(row); | ||
190 | + } | ||
191 | + | ||
192 | + public Target getTarget() { | ||
193 | + return target; | ||
194 | + } | ||
195 | + | ||
196 | +} |
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpDeviceSimulatorV3.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.transport.snmp; | ||
17 | + | ||
18 | +import org.snmp4j.MessageDispatcherImpl; | ||
19 | +import org.snmp4j.TransportMapping; | ||
20 | +import org.snmp4j.agent.BaseAgent; | ||
21 | +import org.snmp4j.agent.CommandProcessor; | ||
22 | +import org.snmp4j.agent.DuplicateRegistrationException; | ||
23 | +import org.snmp4j.agent.MOGroup; | ||
24 | +import org.snmp4j.agent.ManagedObject; | ||
25 | +import org.snmp4j.agent.mo.DefaultMOMutableRow2PC; | ||
26 | +import org.snmp4j.agent.mo.DefaultMOTable; | ||
27 | +import org.snmp4j.agent.mo.MOAccessImpl; | ||
28 | +import org.snmp4j.agent.mo.MOColumn; | ||
29 | +import org.snmp4j.agent.mo.MOMutableColumn; | ||
30 | +import org.snmp4j.agent.mo.MOMutableTableModel; | ||
31 | +import org.snmp4j.agent.mo.MOScalar; | ||
32 | +import org.snmp4j.agent.mo.MOTableIndex; | ||
33 | +import org.snmp4j.agent.mo.MOTableRow; | ||
34 | +import org.snmp4j.agent.mo.MOTableSubIndex; | ||
35 | +import org.snmp4j.agent.mo.ext.AgentppSimulationMib; | ||
36 | +import org.snmp4j.agent.mo.snmp.RowStatus; | ||
37 | +import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB; | ||
38 | +import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB; | ||
39 | +import org.snmp4j.agent.mo.snmp.SnmpTargetMIB; | ||
40 | +import org.snmp4j.agent.mo.snmp.StorageType; | ||
41 | +import org.snmp4j.agent.mo.snmp.TransportDomains; | ||
42 | +import org.snmp4j.agent.mo.snmp.VacmMIB; | ||
43 | +import org.snmp4j.agent.mo.snmp4j.example.Snmp4jHeartbeatMib; | ||
44 | +import org.snmp4j.agent.security.MutableVACM; | ||
45 | +import org.snmp4j.mp.MPv1; | ||
46 | +import org.snmp4j.mp.MPv2c; | ||
47 | +import org.snmp4j.mp.MPv3; | ||
48 | +import org.snmp4j.mp.MessageProcessingModel; | ||
49 | +import org.snmp4j.security.AuthHMAC192SHA256; | ||
50 | +import org.snmp4j.security.AuthMD5; | ||
51 | +import org.snmp4j.security.AuthSHA; | ||
52 | +import org.snmp4j.security.PrivAES128; | ||
53 | +import org.snmp4j.security.PrivAES192; | ||
54 | +import org.snmp4j.security.PrivAES256; | ||
55 | +import org.snmp4j.security.PrivDES; | ||
56 | +import org.snmp4j.security.SecurityLevel; | ||
57 | +import org.snmp4j.security.SecurityModel; | ||
58 | +import org.snmp4j.security.SecurityModels; | ||
59 | +import org.snmp4j.security.SecurityProtocols; | ||
60 | +import org.snmp4j.security.USM; | ||
61 | +import org.snmp4j.security.UsmUser; | ||
62 | +import org.snmp4j.smi.Address; | ||
63 | +import org.snmp4j.smi.Gauge32; | ||
64 | +import org.snmp4j.smi.GenericAddress; | ||
65 | +import org.snmp4j.smi.Integer32; | ||
66 | +import org.snmp4j.smi.OID; | ||
67 | +import org.snmp4j.smi.OctetString; | ||
68 | +import org.snmp4j.smi.SMIConstants; | ||
69 | +import org.snmp4j.smi.TcpAddress; | ||
70 | +import org.snmp4j.smi.TimeTicks; | ||
71 | +import org.snmp4j.smi.UdpAddress; | ||
72 | +import org.snmp4j.smi.Variable; | ||
73 | +import org.snmp4j.transport.DefaultTcpTransportMapping; | ||
74 | +import org.snmp4j.transport.TransportMappings; | ||
75 | +import org.snmp4j.util.ThreadPool; | ||
76 | + | ||
77 | +import java.io.File; | ||
78 | +import java.io.IOException; | ||
79 | +import java.util.Map; | ||
80 | + | ||
81 | +/** | ||
82 | + * The TestAgent is a sample SNMP agent implementation of all | ||
83 | + * features (MIB implementations) provided by the SNMP4J-Agent framework. | ||
84 | + * | ||
85 | + * Note, for snmp4s, this code is mostly a copy from snmp4j. | ||
86 | + * And don't remove snmp users | ||
87 | + * | ||
88 | + */ | ||
89 | +public class SnmpDeviceSimulatorV3 extends BaseAgent { | ||
90 | + protected String address; | ||
91 | + private Snmp4jHeartbeatMib heartbeatMIB; | ||
92 | + private AgentppSimulationMib agentppSimulationMIB; | ||
93 | + | ||
94 | + public SnmpDeviceSimulatorV3(CommandProcessor processor) throws IOException { | ||
95 | + super(new File("SNMP4JTestAgentBC.cfg"), new File("SNMP4JTestAgentConfig.cfg"), | ||
96 | + processor); | ||
97 | + agent.setWorkerPool(ThreadPool.create("RequestPool", 4)); | ||
98 | + } | ||
99 | + | ||
100 | + public void setUpMappings(Map<String, String> oidToResponseMappings) { | ||
101 | + unregisterManagedObject(getSnmpv2MIB()); | ||
102 | + oidToResponseMappings.forEach((oid, response) -> { | ||
103 | + registerManagedObject(new MOScalar<>(new OID(oid), MOAccessImpl.ACCESS_READ_WRITE, new OctetString(response))); | ||
104 | + }); | ||
105 | + } | ||
106 | + protected void registerManagedObject(ManagedObject mo) { | ||
107 | + try { | ||
108 | + server.register(mo, null); | ||
109 | + } catch (DuplicateRegistrationException ex) { | ||
110 | + throw new RuntimeException(ex); | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + protected void unregisterManagedObject(MOGroup moGroup) { | ||
115 | + moGroup.unregisterMOs(server, getContext(moGroup)); | ||
116 | + } | ||
117 | + | ||
118 | + protected void registerManagedObjects() { | ||
119 | + try { | ||
120 | + server.register(createStaticIfTable(), null); | ||
121 | + server.register(createStaticIfXTable(), null); | ||
122 | + agentppSimulationMIB.registerMOs(server, null); | ||
123 | + heartbeatMIB.registerMOs(server, null); | ||
124 | + } catch (DuplicateRegistrationException ex) { | ||
125 | + ex.printStackTrace(); | ||
126 | + } | ||
127 | + } | ||
128 | + | ||
129 | + protected void addNotificationTargets(SnmpTargetMIB targetMIB, | ||
130 | + SnmpNotificationMIB notificationMIB) { | ||
131 | + targetMIB.addDefaultTDomains(); | ||
132 | + | ||
133 | + targetMIB.addTargetAddress(new OctetString("notificationV2c"), | ||
134 | + TransportDomains.transportDomainUdpIpv4, | ||
135 | + new OctetString(new UdpAddress("127.0.0.1/162").getValue()), | ||
136 | + 200, 1, | ||
137 | + new OctetString("notify"), | ||
138 | + new OctetString("v2c"), | ||
139 | + StorageType.permanent); | ||
140 | + targetMIB.addTargetAddress(new OctetString("notificationV3"), | ||
141 | + TransportDomains.transportDomainUdpIpv4, | ||
142 | + new OctetString(new UdpAddress("127.0.0.1/1162").getValue()), | ||
143 | + 200, 1, | ||
144 | + new OctetString("notify"), | ||
145 | + new OctetString("v3notify"), | ||
146 | + StorageType.permanent); | ||
147 | + targetMIB.addTargetParams(new OctetString("v2c"), | ||
148 | + MessageProcessingModel.MPv2c, | ||
149 | + SecurityModel.SECURITY_MODEL_SNMPv2c, | ||
150 | + new OctetString("cpublic"), | ||
151 | + SecurityLevel.AUTH_PRIV, | ||
152 | + StorageType.permanent); | ||
153 | + targetMIB.addTargetParams(new OctetString("v3notify"), | ||
154 | + MessageProcessingModel.MPv3, | ||
155 | + SecurityModel.SECURITY_MODEL_USM, | ||
156 | + new OctetString("v3notify"), | ||
157 | + SecurityLevel.NOAUTH_NOPRIV, | ||
158 | + StorageType.permanent); | ||
159 | + notificationMIB.addNotifyEntry(new OctetString("default"), | ||
160 | + new OctetString("notify"), | ||
161 | + SnmpNotificationMIB.SnmpNotifyTypeEnum.inform, | ||
162 | + StorageType.permanent); | ||
163 | + } | ||
164 | + protected void addViews(VacmMIB vacm) { | ||
165 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv1, | ||
166 | + new OctetString("cpublic"), | ||
167 | + new OctetString("v1v2group"), | ||
168 | + StorageType.nonVolatile); | ||
169 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c, | ||
170 | + new OctetString("cpublic"), | ||
171 | + new OctetString("v1v2group"), | ||
172 | + StorageType.nonVolatile); | ||
173 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
174 | + new OctetString("SHADES"), | ||
175 | + new OctetString("v3group"), | ||
176 | + StorageType.nonVolatile); | ||
177 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
178 | + new OctetString("MD5DES"), | ||
179 | + new OctetString("v3group"), | ||
180 | + StorageType.nonVolatile); | ||
181 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
182 | + new OctetString("TEST"), | ||
183 | + new OctetString("v3test"), | ||
184 | + StorageType.nonVolatile); | ||
185 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
186 | + new OctetString("SHA"), | ||
187 | + new OctetString("v3restricted"), | ||
188 | + StorageType.nonVolatile); | ||
189 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
190 | + new OctetString("SHAAES128"), | ||
191 | + new OctetString("v3group"), | ||
192 | + StorageType.nonVolatile); | ||
193 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
194 | + new OctetString("SHAAES192"), | ||
195 | + new OctetString("v3group"), | ||
196 | + StorageType.nonVolatile); | ||
197 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
198 | + new OctetString("SHAAES256"), | ||
199 | + new OctetString("v3group"), | ||
200 | + StorageType.nonVolatile); | ||
201 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
202 | + new OctetString("MD5AES128"), | ||
203 | + new OctetString("v3group"), | ||
204 | + StorageType.nonVolatile); | ||
205 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
206 | + new OctetString("MD5AES192"), | ||
207 | + new OctetString("v3group"), | ||
208 | + StorageType.nonVolatile); | ||
209 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
210 | + new OctetString("MD5AES256"), | ||
211 | + new OctetString("v3group"), | ||
212 | + StorageType.nonVolatile); | ||
213 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
214 | + new OctetString("aboba"), | ||
215 | + new OctetString("v3group"), | ||
216 | + StorageType.nonVolatile); | ||
217 | + //============================================// | ||
218 | + // agent5-auth-priv | ||
219 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
220 | + new OctetString("agent5"), | ||
221 | + new OctetString("v3group"), | ||
222 | + StorageType.nonVolatile); | ||
223 | + //===========================================// | ||
224 | + // agent002 | ||
225 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
226 | + new OctetString("agent002"), | ||
227 | + new OctetString("v3group"), | ||
228 | + StorageType.nonVolatile); | ||
229 | + //===========================================// | ||
230 | + // user001-auth-no-priv | ||
231 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
232 | + new OctetString("user001"), | ||
233 | + new OctetString("group001"), | ||
234 | + StorageType.nonVolatile); | ||
235 | + //===========================================// | ||
236 | + | ||
237 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
238 | + new OctetString("v3notify"), | ||
239 | + new OctetString("v3group"), | ||
240 | + StorageType.nonVolatile); | ||
241 | + | ||
242 | + //===========================================// | ||
243 | + // group auth no priv | ||
244 | + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, | ||
245 | + new OctetString("v3notify-auth"), | ||
246 | + new OctetString("group001"), | ||
247 | + StorageType.nonVolatile); | ||
248 | + //===========================================// | ||
249 | + | ||
250 | + | ||
251 | + | ||
252 | + // my conf | ||
253 | + vacm.addAccess(new OctetString("group001"), new OctetString("public"), | ||
254 | + SecurityModel.SECURITY_MODEL_USM, | ||
255 | + SecurityLevel.AUTH_NOPRIV, | ||
256 | + MutableVACM.VACM_MATCH_EXACT, | ||
257 | + new OctetString("fullReadView"), | ||
258 | + new OctetString("fullWriteView"), | ||
259 | + new OctetString("fullNotifyView"), | ||
260 | + StorageType.nonVolatile); | ||
261 | + | ||
262 | + vacm.addAccess(new OctetString("v1v2group"), new OctetString("public"), | ||
263 | + SecurityModel.SECURITY_MODEL_ANY, | ||
264 | + SecurityLevel.NOAUTH_NOPRIV, | ||
265 | + MutableVACM.VACM_MATCH_EXACT, | ||
266 | + new OctetString("fullReadView"), | ||
267 | + new OctetString("fullWriteView"), | ||
268 | + new OctetString("fullNotifyView"), | ||
269 | + StorageType.nonVolatile); | ||
270 | + vacm.addAccess(new OctetString("v3group"), new OctetString(), | ||
271 | + SecurityModel.SECURITY_MODEL_USM, | ||
272 | + SecurityLevel.AUTH_PRIV, | ||
273 | + MutableVACM.VACM_MATCH_EXACT, | ||
274 | + new OctetString("fullReadView"), | ||
275 | + new OctetString("fullWriteView"), | ||
276 | + new OctetString("fullNotifyView"), | ||
277 | + StorageType.nonVolatile); | ||
278 | + vacm.addAccess(new OctetString("v3restricted"), new OctetString(), | ||
279 | + SecurityModel.SECURITY_MODEL_USM, | ||
280 | + SecurityLevel.NOAUTH_NOPRIV, | ||
281 | + MutableVACM.VACM_MATCH_EXACT, | ||
282 | + new OctetString("restrictedReadView"), | ||
283 | + new OctetString("restrictedWriteView"), | ||
284 | + new OctetString("restrictedNotifyView"), | ||
285 | + StorageType.nonVolatile); | ||
286 | + vacm.addAccess(new OctetString("v3test"), new OctetString(), | ||
287 | + SecurityModel.SECURITY_MODEL_USM, | ||
288 | + SecurityLevel.AUTH_PRIV, | ||
289 | + MutableVACM.VACM_MATCH_EXACT, | ||
290 | + new OctetString("testReadView"), | ||
291 | + new OctetString("testWriteView"), | ||
292 | + new OctetString("testNotifyView"), | ||
293 | + StorageType.nonVolatile); | ||
294 | + | ||
295 | + vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"), | ||
296 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
297 | + StorageType.nonVolatile); | ||
298 | + vacm.addViewTreeFamily(new OctetString("fullWriteView"), new OID("1.3"), | ||
299 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
300 | + StorageType.nonVolatile); | ||
301 | + vacm.addViewTreeFamily(new OctetString("fullNotifyView"), new OID("1.3"), | ||
302 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
303 | + StorageType.nonVolatile); | ||
304 | + | ||
305 | + vacm.addViewTreeFamily(new OctetString("restrictedReadView"), | ||
306 | + new OID("1.3.6.1.2"), | ||
307 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
308 | + StorageType.nonVolatile); | ||
309 | + vacm.addViewTreeFamily(new OctetString("restrictedWriteView"), | ||
310 | + new OID("1.3.6.1.2.1"), | ||
311 | + new OctetString(), | ||
312 | + VacmMIB.vacmViewIncluded, | ||
313 | + StorageType.nonVolatile); | ||
314 | + vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"), | ||
315 | + new OID("1.3.6.1.2"), | ||
316 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
317 | + StorageType.nonVolatile); | ||
318 | + vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"), | ||
319 | + new OID("1.3.6.1.6.3.1"), | ||
320 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
321 | + StorageType.nonVolatile); | ||
322 | + | ||
323 | + vacm.addViewTreeFamily(new OctetString("testReadView"), | ||
324 | + new OID("1.3.6.1.2"), | ||
325 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
326 | + StorageType.nonVolatile); | ||
327 | + vacm.addViewTreeFamily(new OctetString("testReadView"), | ||
328 | + new OID("1.3.6.1.2.1.1"), | ||
329 | + new OctetString(), VacmMIB.vacmViewExcluded, | ||
330 | + StorageType.nonVolatile); | ||
331 | + vacm.addViewTreeFamily(new OctetString("testWriteView"), | ||
332 | + new OID("1.3.6.1.2.1"), | ||
333 | + new OctetString(), | ||
334 | + VacmMIB.vacmViewIncluded, | ||
335 | + StorageType.nonVolatile); | ||
336 | + vacm.addViewTreeFamily(new OctetString("testNotifyView"), | ||
337 | + new OID("1.3.6.1.2"), | ||
338 | + new OctetString(), VacmMIB.vacmViewIncluded, | ||
339 | + StorageType.nonVolatile); | ||
340 | + | ||
341 | + } | ||
342 | + | ||
343 | + protected void addUsmUser(USM usm) { | ||
344 | + UsmUser user = new UsmUser(new OctetString("SHADES"), | ||
345 | + AuthSHA.ID, | ||
346 | + new OctetString("SHADESAuthPassword"), | ||
347 | + PrivDES.ID, | ||
348 | + new OctetString("SHADESPrivPassword")); | ||
349 | +// usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
350 | + usm.addUser(user.getSecurityName(), null, user); | ||
351 | + user = new UsmUser(new OctetString("TEST"), | ||
352 | + AuthSHA.ID, | ||
353 | + new OctetString("maplesyrup"), | ||
354 | + PrivDES.ID, | ||
355 | + new OctetString("maplesyrup")); | ||
356 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
357 | + user = new UsmUser(new OctetString("SHA"), | ||
358 | + AuthSHA.ID, | ||
359 | + new OctetString("SHAAuthPassword"), | ||
360 | + null, | ||
361 | + null); | ||
362 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
363 | + user = new UsmUser(new OctetString("SHADES"), | ||
364 | + AuthSHA.ID, | ||
365 | + new OctetString("SHADESAuthPassword"), | ||
366 | + PrivDES.ID, | ||
367 | + new OctetString("SHADESPrivPassword")); | ||
368 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
369 | + user = new UsmUser(new OctetString("MD5DES"), | ||
370 | + AuthMD5.ID, | ||
371 | + new OctetString("MD5DESAuthPassword"), | ||
372 | + PrivDES.ID, | ||
373 | + new OctetString("MD5DESPrivPassword")); | ||
374 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
375 | + user = new UsmUser(new OctetString("SHAAES128"), | ||
376 | + AuthSHA.ID, | ||
377 | + new OctetString("SHAAES128AuthPassword"), | ||
378 | + PrivAES128.ID, | ||
379 | + new OctetString("SHAAES128PrivPassword")); | ||
380 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
381 | + user = new UsmUser(new OctetString("SHAAES192"), | ||
382 | + AuthSHA.ID, | ||
383 | + new OctetString("SHAAES192AuthPassword"), | ||
384 | + PrivAES192.ID, | ||
385 | + new OctetString("SHAAES192PrivPassword")); | ||
386 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
387 | + user = new UsmUser(new OctetString("SHAAES256"), | ||
388 | + AuthSHA.ID, | ||
389 | + new OctetString("SHAAES256AuthPassword"), | ||
390 | + PrivAES256.ID, | ||
391 | + new OctetString("SHAAES256PrivPassword")); | ||
392 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
393 | + | ||
394 | + user = new UsmUser(new OctetString("MD5AES128"), | ||
395 | + AuthMD5.ID, | ||
396 | + new OctetString("MD5AES128AuthPassword"), | ||
397 | + PrivAES128.ID, | ||
398 | + new OctetString("MD5AES128PrivPassword")); | ||
399 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
400 | + user = new UsmUser(new OctetString("MD5AES192"), | ||
401 | + AuthHMAC192SHA256.ID, | ||
402 | + new OctetString("MD5AES192AuthPassword"), | ||
403 | + PrivAES192.ID, | ||
404 | + new OctetString("MD5AES192PrivPassword")); | ||
405 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
406 | + //============================================================== | ||
407 | + user = new UsmUser(new OctetString("MD5AES256"), | ||
408 | + AuthMD5.ID, | ||
409 | + new OctetString("MD5AES256AuthPassword"), | ||
410 | + PrivAES256.ID, | ||
411 | + new OctetString("MD5AES256PrivPassword")); | ||
412 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
413 | + user = new UsmUser(new OctetString("MD5AES256"), | ||
414 | + AuthMD5.ID, | ||
415 | + new OctetString("MD5AES256AuthPassword"), | ||
416 | + PrivAES256.ID, | ||
417 | + new OctetString("MD5AES256PrivPassword")); | ||
418 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
419 | + | ||
420 | + OctetString securityName = new OctetString("aboba"); | ||
421 | + OctetString authenticationPassphrase = new OctetString("abobaaboba"); | ||
422 | + OctetString privacyPassphrase = new OctetString("abobaaboba"); | ||
423 | + OID authenticationProtocol = AuthSHA.ID; | ||
424 | + OID privacyProtocol = PrivDES.ID; // FIXME: to config | ||
425 | + user = new UsmUser(securityName, authenticationProtocol, authenticationPassphrase, privacyProtocol, privacyPassphrase); | ||
426 | + usm.addUser(user); | ||
427 | + | ||
428 | + //===============================================================// | ||
429 | + user = new UsmUser(new OctetString("agent5"), | ||
430 | + AuthSHA.ID, | ||
431 | + new OctetString("authpass"), | ||
432 | + PrivDES.ID, | ||
433 | + new OctetString("privpass")); | ||
434 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
435 | + //===============================================================// | ||
436 | + // user001 | ||
437 | + user = new UsmUser(new OctetString("user001"), | ||
438 | + AuthSHA.ID, | ||
439 | + new OctetString("authpass"), | ||
440 | + null, null); | ||
441 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
442 | + //===============================================================// | ||
443 | + // user002 | ||
444 | + user = new UsmUser(new OctetString("user001"), | ||
445 | + null, | ||
446 | + null, | ||
447 | + null, null); | ||
448 | + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user); | ||
449 | + //===============================================================// | ||
450 | + | ||
451 | + user = new UsmUser(new OctetString("v3notify"), | ||
452 | + null, | ||
453 | + null, | ||
454 | + null, | ||
455 | + null); | ||
456 | + usm.addUser(user.getSecurityName(), null, user); | ||
457 | + | ||
458 | + this.usm = usm; | ||
459 | + } | ||
460 | + | ||
461 | + private static DefaultMOTable createStaticIfXTable() { | ||
462 | + MOTableSubIndex[] subIndexes = | ||
463 | + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) }; | ||
464 | + MOTableIndex indexDef = new MOTableIndex(subIndexes, false); | ||
465 | + MOColumn[] columns = new MOColumn[19]; | ||
466 | + int c = 0; | ||
467 | + columns[c++] = | ||
468 | + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING, | ||
469 | + MOAccessImpl.ACCESS_READ_ONLY); // ifName | ||
470 | + columns[c++] = | ||
471 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
472 | + MOAccessImpl.ACCESS_READ_ONLY); // ifInMulticastPkts | ||
473 | + columns[c++] = | ||
474 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
475 | + MOAccessImpl.ACCESS_READ_ONLY); // ifInBroadcastPkts | ||
476 | + columns[c++] = | ||
477 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
478 | + MOAccessImpl.ACCESS_READ_ONLY); // ifOutMulticastPkts | ||
479 | + columns[c++] = | ||
480 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
481 | + MOAccessImpl.ACCESS_READ_ONLY); // ifOutBroadcastPkts | ||
482 | + columns[c++] = | ||
483 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
484 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInOctets | ||
485 | + columns[c++] = | ||
486 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
487 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInUcastPkts | ||
488 | + columns[c++] = | ||
489 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
490 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInMulticastPkts | ||
491 | + columns[c++] = | ||
492 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
493 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInBroadcastPkts | ||
494 | + columns[c++] = | ||
495 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
496 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutOctets | ||
497 | + columns[c++] = | ||
498 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
499 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutUcastPkts | ||
500 | + columns[c++] = | ||
501 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
502 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutMulticastPkts | ||
503 | + columns[c++] = | ||
504 | + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32, | ||
505 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutBroadcastPkts | ||
506 | + columns[c++] = | ||
507 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
508 | + MOAccessImpl.ACCESS_READ_WRITE); // ifLinkUpDownTrapEnable | ||
509 | + columns[c++] = | ||
510 | + new MOColumn(c, SMIConstants.SYNTAX_GAUGE32, | ||
511 | + MOAccessImpl.ACCESS_READ_ONLY); // ifHighSpeed | ||
512 | + columns[c++] = | ||
513 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
514 | + MOAccessImpl.ACCESS_READ_WRITE); // ifPromiscuousMode | ||
515 | + columns[c++] = | ||
516 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
517 | + MOAccessImpl.ACCESS_READ_ONLY); // ifConnectorPresent | ||
518 | + columns[c++] = | ||
519 | + new MOMutableColumn(c, SMIConstants.SYNTAX_OCTET_STRING, // ifAlias | ||
520 | + MOAccessImpl.ACCESS_READ_WRITE, null); | ||
521 | + columns[c++] = | ||
522 | + new MOColumn(c, SMIConstants.SYNTAX_TIMETICKS, | ||
523 | + MOAccessImpl.ACCESS_READ_ONLY); // ifCounterDiscontinuityTime | ||
524 | + | ||
525 | + DefaultMOTable ifXTable = | ||
526 | + new DefaultMOTable(new OID("1.3.6.1.2.1.31.1.1.1"), indexDef, columns); | ||
527 | + MOMutableTableModel model = (MOMutableTableModel) ifXTable.getModel(); | ||
528 | + Variable[] rowValues1 = new Variable[] { | ||
529 | + new OctetString("Ethernet-0"), | ||
530 | + new Integer32(1), | ||
531 | + new Integer32(2), | ||
532 | + new Integer32(3), | ||
533 | + new Integer32(4), | ||
534 | + new Integer32(5), | ||
535 | + new Integer32(6), | ||
536 | + new Integer32(7), | ||
537 | + new Integer32(8), | ||
538 | + new Integer32(9), | ||
539 | + new Integer32(10), | ||
540 | + new Integer32(11), | ||
541 | + new Integer32(12), | ||
542 | + new Integer32(13), | ||
543 | + new Integer32(14), | ||
544 | + new Integer32(15), | ||
545 | + new Integer32(16), | ||
546 | + new OctetString("My eth"), | ||
547 | + new TimeTicks(1000) | ||
548 | + }; | ||
549 | + Variable[] rowValues2 = new Variable[] { | ||
550 | + new OctetString("Loopback"), | ||
551 | + new Integer32(21), | ||
552 | + new Integer32(22), | ||
553 | + new Integer32(23), | ||
554 | + new Integer32(24), | ||
555 | + new Integer32(25), | ||
556 | + new Integer32(26), | ||
557 | + new Integer32(27), | ||
558 | + new Integer32(28), | ||
559 | + new Integer32(29), | ||
560 | + new Integer32(30), | ||
561 | + new Integer32(31), | ||
562 | + new Integer32(32), | ||
563 | + new Integer32(33), | ||
564 | + new Integer32(34), | ||
565 | + new Integer32(35), | ||
566 | + new Integer32(36), | ||
567 | + new OctetString("My loop"), | ||
568 | + new TimeTicks(2000) | ||
569 | + }; | ||
570 | + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1)); | ||
571 | + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2)); | ||
572 | + ifXTable.setVolatile(true); | ||
573 | + return ifXTable; | ||
574 | + } | ||
575 | + | ||
576 | + private static DefaultMOTable createStaticIfTable() { | ||
577 | + MOTableSubIndex[] subIndexes = | ||
578 | + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) }; | ||
579 | + MOTableIndex indexDef = new MOTableIndex(subIndexes, false); | ||
580 | + MOColumn[] columns = new MOColumn[8]; | ||
581 | + int c = 0; | ||
582 | + columns[c++] = | ||
583 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
584 | + MOAccessImpl.ACCESS_READ_ONLY); // ifIndex | ||
585 | + columns[c++] = | ||
586 | + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING, | ||
587 | + MOAccessImpl.ACCESS_READ_ONLY); // ifDescr | ||
588 | + columns[c++] = | ||
589 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
590 | + MOAccessImpl.ACCESS_READ_ONLY); // ifType | ||
591 | + columns[c++] = | ||
592 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
593 | + MOAccessImpl.ACCESS_READ_ONLY); // ifMtu | ||
594 | + columns[c++] = | ||
595 | + new MOColumn(c, SMIConstants.SYNTAX_GAUGE32, | ||
596 | + MOAccessImpl.ACCESS_READ_ONLY); // ifSpeed | ||
597 | + columns[c++] = | ||
598 | + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING, | ||
599 | + MOAccessImpl.ACCESS_READ_ONLY); // ifPhysAddress | ||
600 | + columns[c++] = | ||
601 | + new MOMutableColumn(c, SMIConstants.SYNTAX_INTEGER, // ifAdminStatus | ||
602 | + MOAccessImpl.ACCESS_READ_WRITE, null); | ||
603 | + columns[c++] = | ||
604 | + new MOColumn(c, SMIConstants.SYNTAX_INTEGER, | ||
605 | + MOAccessImpl.ACCESS_READ_ONLY); // ifOperStatus | ||
606 | + | ||
607 | + DefaultMOTable ifTable = | ||
608 | + new DefaultMOTable(new OID("1.3.6.1.2.1.2.2.1"), indexDef, columns); | ||
609 | + MOMutableTableModel model = (MOMutableTableModel) ifTable.getModel(); | ||
610 | + Variable[] rowValues1 = new Variable[] { | ||
611 | + new Integer32(1), | ||
612 | + new OctetString("eth0"), | ||
613 | + new Integer32(6), | ||
614 | + new Integer32(1500), | ||
615 | + new Gauge32(100000000), | ||
616 | + new OctetString("00:00:00:00:01"), | ||
617 | + new Integer32(1), | ||
618 | + new Integer32(1) | ||
619 | + }; | ||
620 | + Variable[] rowValues2 = new Variable[] { | ||
621 | + new Integer32(2), | ||
622 | + new OctetString("loopback"), | ||
623 | + new Integer32(24), | ||
624 | + new Integer32(1500), | ||
625 | + new Gauge32(10000000), | ||
626 | + new OctetString("00:00:00:00:02"), | ||
627 | + new Integer32(1), | ||
628 | + new Integer32(1) | ||
629 | + }; | ||
630 | + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1)); | ||
631 | + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2)); | ||
632 | + ifTable.setVolatile(true); | ||
633 | + return ifTable; | ||
634 | + } | ||
635 | + | ||
636 | + private static DefaultMOTable createStaticSnmp4sTable() { | ||
637 | + MOTableSubIndex[] subIndexes = | ||
638 | + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) }; | ||
639 | + MOTableIndex indexDef = new MOTableIndex(subIndexes, false); | ||
640 | + MOColumn[] columns = new MOColumn[8]; | ||
641 | + int c = 0; | ||
642 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_NULL, MOAccessImpl.ACCESS_READ_ONLY); // testNull | ||
643 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // testBoolean | ||
644 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // ifType | ||
645 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // ifMtu | ||
646 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_GAUGE32, MOAccessImpl.ACCESS_READ_ONLY); // ifSpeed | ||
647 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING, MOAccessImpl.ACCESS_READ_ONLY); //ifPhysAddress | ||
648 | + columns[c++] = new MOMutableColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_WRITE, | ||
649 | + null); | ||
650 | + // ifAdminStatus | ||
651 | + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); | ||
652 | + // ifOperStatus | ||
653 | + | ||
654 | + DefaultMOTable ifTable = | ||
655 | + new DefaultMOTable(new OID("1.3.6.1.4.1.50000.1.1"), indexDef, columns); | ||
656 | + MOMutableTableModel model = (MOMutableTableModel) ifTable.getModel(); | ||
657 | + Variable[] rowValues1 = new Variable[] { | ||
658 | + new Integer32(1), | ||
659 | + new OctetString("eth0"), | ||
660 | + new Integer32(6), | ||
661 | + new Integer32(1500), | ||
662 | + new Gauge32(100000000), | ||
663 | + new OctetString("00:00:00:00:01"), | ||
664 | + new Integer32(1), | ||
665 | + new Integer32(1) | ||
666 | + }; | ||
667 | + Variable[] rowValues2 = new Variable[] { | ||
668 | + new Integer32(2), | ||
669 | + new OctetString("loopback"), | ||
670 | + new Integer32(24), | ||
671 | + new Integer32(1500), | ||
672 | + new Gauge32(10000000), | ||
673 | + new OctetString("00:00:00:00:02"), | ||
674 | + new Integer32(1), | ||
675 | + new Integer32(1) | ||
676 | + }; | ||
677 | + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1)); | ||
678 | + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2)); | ||
679 | + ifTable.setVolatile(true); | ||
680 | + return ifTable; | ||
681 | + } | ||
682 | + | ||
683 | + protected void initTransportMappings() throws IOException { | ||
684 | + transportMappings = new TransportMapping[2]; | ||
685 | + Address addr = GenericAddress.parse(address); | ||
686 | + TransportMapping tm = | ||
687 | + TransportMappings.getInstance().createTransportMapping(addr); | ||
688 | + transportMappings[0] = tm; | ||
689 | + transportMappings[1] = new DefaultTcpTransportMapping(new TcpAddress(address)); | ||
690 | + } | ||
691 | + | ||
692 | + public void start(String ip, String port) throws IOException { | ||
693 | + address = ip + "/" + port; | ||
694 | + //BasicConfigurator.configure(); | ||
695 | + init(); | ||
696 | + addShutdownHook(); | ||
697 | +// loadConfig(ImportModes.REPLACE_CREATE); | ||
698 | + getServer().addContext(new OctetString("public")); | ||
699 | + finishInit(); | ||
700 | + run(); | ||
701 | + sendColdStartNotification(); | ||
702 | + } | ||
703 | + | ||
704 | + protected void unregisterManagedObjects() { | ||
705 | + // here we should unregister those objects previously registered... | ||
706 | + } | ||
707 | + | ||
708 | + protected void addCommunities(SnmpCommunityMIB communityMIB) { | ||
709 | + Variable[] com2sec = new Variable[] { | ||
710 | + new OctetString("public"), // community name | ||
711 | + new OctetString("cpublic"), // security name | ||
712 | + getAgent().getContextEngineID(), // local engine ID | ||
713 | + new OctetString("public"), // default context name | ||
714 | + new OctetString(), // transport tag | ||
715 | + new Integer32(StorageType.nonVolatile), // storage type | ||
716 | + new Integer32(RowStatus.active) // row status | ||
717 | + }; | ||
718 | + MOTableRow row = | ||
719 | + communityMIB.getSnmpCommunityEntry().createRow( | ||
720 | + new OctetString("public2public").toSubIndex(true), com2sec); | ||
721 | + communityMIB.getSnmpCommunityEntry().addRow((SnmpCommunityMIB.SnmpCommunityEntryRow) row); | ||
722 | +// snmpCommunityMIB.setSourceAddressFiltering(true); | ||
723 | + } | ||
724 | + | ||
725 | + protected void registerSnmpMIBs() { | ||
726 | + heartbeatMIB = new Snmp4jHeartbeatMib(super.getNotificationOriginator(), | ||
727 | + new OctetString(), | ||
728 | + super.snmpv2MIB.getSysUpTime()); | ||
729 | + agentppSimulationMIB = new AgentppSimulationMib(); | ||
730 | + super.registerSnmpMIBs(); | ||
731 | + } | ||
732 | + | ||
733 | + protected void initMessageDispatcher() { | ||
734 | + this.dispatcher = new MessageDispatcherImpl(); | ||
735 | + this.mpv3 = new MPv3(this.agent.getContextEngineID().getValue()); | ||
736 | + this.usm = new USM(SecurityProtocols.getInstance(), this.agent.getContextEngineID(), this.updateEngineBoots()); | ||
737 | + SecurityModels.getInstance().addSecurityModel(this.usm); | ||
738 | + SecurityProtocols.getInstance().addDefaultProtocols(); | ||
739 | + this.dispatcher.addMessageProcessingModel(new MPv1()); | ||
740 | + this.dispatcher.addMessageProcessingModel(new MPv2c()); | ||
741 | + this.dispatcher.addMessageProcessingModel(this.mpv3); | ||
742 | + this.initSnmpSession(); | ||
743 | + } | ||
744 | + | ||
745 | +} |
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpTestV2.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.transport.snmp; | ||
17 | + | ||
18 | +import java.io.IOException; | ||
19 | +import java.util.Map; | ||
20 | +import java.util.Scanner; | ||
21 | + | ||
22 | +public class SnmpTestV2 { | ||
23 | + public static void main(String[] args) throws IOException { | ||
24 | + SnmpDeviceSimulatorV2 device = new SnmpDeviceSimulatorV2(1610, "public"); | ||
25 | + | ||
26 | + device.start(); | ||
27 | + device.setUpMappings(Map.of( | ||
28 | + ".1.3.6.1.2.1.1.1.50", "12", | ||
29 | + ".1.3.6.1.2.1.2.1.52", "56", | ||
30 | + ".1.3.6.1.2.1.3.1.54", "yes", | ||
31 | + ".1.3.6.1.2.1.7.1.58", "" | ||
32 | + )); | ||
33 | + | ||
34 | + | ||
35 | +// while (true) { | ||
36 | +// new Scanner(System.in).nextLine(); | ||
37 | +// device.sendTrap("127.0.0.1", 1062, Map.of(".1.3.6.1.2.87.1.56", "12")); | ||
38 | +// System.out.println("sent"); | ||
39 | +// } | ||
40 | + | ||
41 | +// Snmp snmp = new Snmp(device.transportMappings[0]); | ||
42 | +// device.snmp.addCommandResponder(event -> { | ||
43 | +// System.out.println(event); | ||
44 | +// }); | ||
45 | + | ||
46 | + new Scanner(System.in).nextLine(); | ||
47 | + } | ||
48 | + | ||
49 | +} |
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpTestV3.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.transport.snmp; | ||
17 | + | ||
18 | +import org.snmp4j.CommandResponderEvent; | ||
19 | +import org.snmp4j.agent.CommandProcessor; | ||
20 | +import org.snmp4j.mp.MPv3; | ||
21 | +import org.snmp4j.smi.OctetString; | ||
22 | + | ||
23 | +import java.io.IOException; | ||
24 | +import java.util.Map; | ||
25 | +import java.util.Scanner; | ||
26 | + | ||
27 | +public class SnmpTestV3 { | ||
28 | + public static void main(String[] args) throws IOException { | ||
29 | + SnmpDeviceSimulatorV3 device = new SnmpDeviceSimulatorV3(new CommandProcessor(new OctetString(MPv3.createLocalEngineID())) { | ||
30 | + @Override | ||
31 | + public void processPdu(CommandResponderEvent event) { | ||
32 | + System.out.println("event: " + event); | ||
33 | + } | ||
34 | + }); | ||
35 | + device.start("0.0.0.0", "1610"); | ||
36 | + | ||
37 | + device.setUpMappings(Map.of( | ||
38 | + ".1.3.6.1.2.1.1.1.50", "12", | ||
39 | + ".1.3.6.1.2.1.2.1.52", "56", | ||
40 | + ".1.3.6.1.2.1.3.1.54", "yes", | ||
41 | + ".1.3.6.1.2.1.7.1.58", "" | ||
42 | + )); | ||
43 | + | ||
44 | + new Scanner(System.in).nextLine(); | ||
45 | + } | ||
46 | +} |
1 | +{ | ||
2 | + "timeoutMs": 500, | ||
3 | + "retries": 0, | ||
4 | + "communicationConfigs": [ | ||
5 | + { | ||
6 | + "spec": "TELEMETRY_QUERYING", | ||
7 | + "queryingFrequencyMs": 3000, | ||
8 | + "mappings": [ | ||
9 | + { | ||
10 | + "oid": ".1.3.6.1.2.1.1.1.50", | ||
11 | + "key": "temperature", | ||
12 | + "dataType": "LONG" | ||
13 | + }, | ||
14 | + { | ||
15 | + "oid": ".1.3.6.1.2.1.2.1.52", | ||
16 | + "key": "humidity", | ||
17 | + "dataType": "DOUBLE" | ||
18 | + } | ||
19 | + ] | ||
20 | + }, | ||
21 | + { | ||
22 | + "spec": "CLIENT_ATTRIBUTES_QUERYING", | ||
23 | + "queryingFrequencyMs": 5000, | ||
24 | + "mappings": [ | ||
25 | + { | ||
26 | + "oid": ".1.3.6.1.2.1.3.1.54", | ||
27 | + "key": "isCool", | ||
28 | + "dataType": "STRING" | ||
29 | + } | ||
30 | + ] | ||
31 | + }, | ||
32 | + { | ||
33 | + "spec": "SHARED_ATTRIBUTES_SETTING", | ||
34 | + "mappings": [ | ||
35 | + { | ||
36 | + "oid": ".1.3.6.1.2.1.7.1.58", | ||
37 | + "key": "shared", | ||
38 | + "dataType": "STRING" | ||
39 | + } | ||
40 | + ] | ||
41 | + } | ||
42 | + ] | ||
43 | +} |
1 | +{ | ||
2 | + "address": "192.168.3.23", | ||
3 | + "port": 1610, | ||
4 | + "protocolVersion": "V3", | ||
5 | + | ||
6 | + "username": "tb-user", | ||
7 | + "engineId": "qwertyuioa", | ||
8 | + "securityName": "tb-user", | ||
9 | + "authenticationProtocol": "SHA_512", | ||
10 | + "authenticationPassphrase": "sdfghjkloifgh", | ||
11 | + "privacyProtocol": "DES", | ||
12 | + "privacyPassphrase": "rtytguijokod" | ||
13 | +} |
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.common.transport; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import org.thingsboard.server.common.data.Device; | ||
20 | + | ||
21 | +@Getter | ||
22 | +public class DeviceUpdatedEvent { | ||
23 | + private final Device device; | ||
24 | + | ||
25 | + public DeviceUpdatedEvent(Device device) { | ||
26 | + this.device = device; | ||
27 | + } | ||
28 | +} |
@@ -17,6 +17,7 @@ package org.thingsboard.server.common.transport; | @@ -17,6 +17,7 @@ package org.thingsboard.server.common.transport; | ||
17 | 17 | ||
18 | import org.thingsboard.server.common.data.Device; | 18 | import org.thingsboard.server.common.data.Device; |
19 | import org.thingsboard.server.common.data.DeviceProfile; | 19 | import org.thingsboard.server.common.data.DeviceProfile; |
20 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
20 | import org.thingsboard.server.gen.transport.TransportProtos; | 21 | import org.thingsboard.server.gen.transport.TransportProtos; |
21 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | 22 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
22 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; | 23 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; |
@@ -49,6 +50,8 @@ public interface SessionMsgListener { | @@ -49,6 +50,8 @@ public interface SessionMsgListener { | ||
49 | default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, | 50 | default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, |
50 | Optional<DeviceProfile> deviceProfileOpt) {} | 51 | Optional<DeviceProfile> deviceProfileOpt) {} |
51 | 52 | ||
53 | + default void onDeviceDeleted(DeviceId deviceId) {} | ||
54 | + | ||
52 | default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {} | 55 | default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {} |
53 | 56 | ||
54 | default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {} | 57 | default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {} |
@@ -22,6 +22,10 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes | @@ -22,6 +22,10 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes | ||
22 | import org.thingsboard.server.common.transport.service.SessionMetaData; | 22 | import org.thingsboard.server.common.transport.service.SessionMetaData; |
23 | import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; | 23 | import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; |
24 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; | 24 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; |
25 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceCredentialsRequestMsg; | ||
26 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceCredentialsResponseMsg; | ||
27 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceRequestMsg; | ||
28 | +import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceResponseMsg; | ||
25 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; | 29 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; |
26 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; | 30 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; |
27 | import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareRequestMsg; | 31 | import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareRequestMsg; |
@@ -29,6 +33,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareResponseM | @@ -29,6 +33,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareResponseM | ||
29 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; | 33 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; |
30 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg; | 34 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg; |
31 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceResponseMsg; | 35 | import org.thingsboard.server.gen.transport.TransportProtos.GetResourceResponseMsg; |
36 | +import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRequestMsg; | ||
37 | +import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesResponseMsg; | ||
32 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; | 38 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; |
33 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; | 39 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; |
34 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | 40 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
@@ -57,6 +63,12 @@ public interface TransportService { | @@ -57,6 +63,12 @@ public interface TransportService { | ||
57 | 63 | ||
58 | GetResourceResponseMsg getResource(GetResourceRequestMsg msg); | 64 | GetResourceResponseMsg getResource(GetResourceRequestMsg msg); |
59 | 65 | ||
66 | + GetSnmpDevicesResponseMsg getSnmpDevicesIds(GetSnmpDevicesRequestMsg requestMsg); | ||
67 | + | ||
68 | + GetDeviceResponseMsg getDevice(GetDeviceRequestMsg requestMsg); | ||
69 | + | ||
70 | + GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg); | ||
71 | + | ||
60 | void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, | 72 | void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, |
61 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 73 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); |
62 | 74 |
@@ -289,7 +289,7 @@ public class JsonConverter { | @@ -289,7 +289,7 @@ public class JsonConverter { | ||
289 | return result; | 289 | return result; |
290 | } | 290 | } |
291 | 291 | ||
292 | - public static JsonElement toJson(AttributeUpdateNotificationMsg payload) { | 292 | + public static JsonObject toJson(AttributeUpdateNotificationMsg payload) { |
293 | JsonObject result = new JsonObject(); | 293 | JsonObject result = new JsonObject(); |
294 | if (payload.getSharedUpdatedCount() > 0) { | 294 | if (payload.getSharedUpdatedCount() > 0) { |
295 | payload.getSharedUpdatedList().forEach(addToObjectFromProto(result)); | 295 | payload.getSharedUpdatedList().forEach(addToObjectFromProto(result)); |
@@ -558,6 +558,14 @@ public class JsonConverter { | @@ -558,6 +558,14 @@ public class JsonConverter { | ||
558 | } | 558 | } |
559 | } | 559 | } |
560 | 560 | ||
561 | + public static JsonElement parse(String json) { | ||
562 | + return JSON_PARSER.parse(json); | ||
563 | + } | ||
564 | + | ||
565 | + public static String toJson(JsonElement element) { | ||
566 | + return GSON.toJson(element); | ||
567 | + } | ||
568 | + | ||
561 | public static void setTypeCastEnabled(boolean enabled) { | 569 | public static void setTypeCastEnabled(boolean enabled) { |
562 | isTypeCastEnabled = enabled; | 570 | isTypeCastEnabled = enabled; |
563 | } | 571 | } |
@@ -599,8 +607,7 @@ public class JsonConverter { | @@ -599,8 +607,7 @@ public class JsonConverter { | ||
599 | .build(); | 607 | .build(); |
600 | } | 608 | } |
601 | 609 | ||
602 | - private static TransportProtos.ProvisionDeviceCredentialsMsg buildProvisionDeviceCredentialsMsg(String | ||
603 | - provisionKey, String provisionSecret) { | 610 | + private static TransportProtos.ProvisionDeviceCredentialsMsg buildProvisionDeviceCredentialsMsg(String provisionKey, String provisionSecret) { |
604 | return TransportProtos.ProvisionDeviceCredentialsMsg.newBuilder() | 611 | return TransportProtos.ProvisionDeviceCredentialsMsg.newBuilder() |
605 | .setProvisionDeviceKey(provisionKey) | 612 | .setProvisionDeviceKey(provisionKey) |
606 | .setProvisionDeviceSecret(provisionSecret) | 613 | .setProvisionDeviceSecret(provisionSecret) |
@@ -112,8 +112,8 @@ public class DefaultTransportDeviceProfileCache implements TransportDeviceProfil | @@ -112,8 +112,8 @@ public class DefaultTransportDeviceProfileCache implements TransportDeviceProfil | ||
112 | profile = profileOpt.get(); | 112 | profile = profileOpt.get(); |
113 | this.put(profile); | 113 | this.put(profile); |
114 | } else { | 114 | } else { |
115 | - log.warn("[{}] Can't device profile: {}", id, entityProfileMsg.getData()); | ||
116 | - throw new RuntimeException("Can't device profile!"); | 115 | + log.warn("[{}] Can't find device profile: {}", id, entityProfileMsg.getData()); |
116 | + throw new RuntimeException("Can't find device profile!"); | ||
117 | } | 117 | } |
118 | } finally { | 118 | } finally { |
119 | deviceProfileFetchLock.unlock(); | 119 | deviceProfileFetchLock.unlock(); |
@@ -23,6 +23,7 @@ import com.google.gson.JsonObject; | @@ -23,6 +23,7 @@ import com.google.gson.JsonObject; | ||
23 | import com.google.protobuf.ByteString; | 23 | import com.google.protobuf.ByteString; |
24 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
25 | import org.springframework.beans.factory.annotation.Value; | 25 | import org.springframework.beans.factory.annotation.Value; |
26 | +import org.springframework.context.ApplicationEventPublisher; | ||
26 | import org.springframework.stereotype.Service; | 27 | import org.springframework.stereotype.Service; |
27 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 28 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
28 | import org.thingsboard.server.common.data.ApiUsageRecordKey; | 29 | import org.thingsboard.server.common.data.ApiUsageRecordKey; |
@@ -50,6 +51,7 @@ import org.thingsboard.server.common.msg.tools.TbRateLimitsException; | @@ -50,6 +51,7 @@ import org.thingsboard.server.common.msg.tools.TbRateLimitsException; | ||
50 | import org.thingsboard.server.common.stats.MessagesStats; | 51 | import org.thingsboard.server.common.stats.MessagesStats; |
51 | import org.thingsboard.server.common.stats.StatsFactory; | 52 | import org.thingsboard.server.common.stats.StatsFactory; |
52 | import org.thingsboard.server.common.stats.StatsType; | 53 | import org.thingsboard.server.common.stats.StatsType; |
54 | +import org.thingsboard.server.common.transport.DeviceUpdatedEvent; | ||
53 | import org.thingsboard.server.common.transport.SessionMsgListener; | 55 | import org.thingsboard.server.common.transport.SessionMsgListener; |
54 | import org.thingsboard.server.common.transport.TransportDeviceProfileCache; | 56 | import org.thingsboard.server.common.transport.TransportDeviceProfileCache; |
55 | import org.thingsboard.server.common.transport.TransportResourceCache; | 57 | import org.thingsboard.server.common.transport.TransportResourceCache; |
@@ -134,6 +136,7 @@ public class DefaultTransportService implements TransportService { | @@ -134,6 +136,7 @@ public class DefaultTransportService implements TransportService { | ||
134 | private final TransportRateLimitService rateLimitService; | 136 | private final TransportRateLimitService rateLimitService; |
135 | private final DataDecodingEncodingService dataDecodingEncodingService; | 137 | private final DataDecodingEncodingService dataDecodingEncodingService; |
136 | private final SchedulerComponent scheduler; | 138 | private final SchedulerComponent scheduler; |
139 | + private final ApplicationEventPublisher eventPublisher; | ||
137 | private final TransportResourceCache transportResourceCache; | 140 | private final TransportResourceCache transportResourceCache; |
138 | 141 | ||
139 | protected TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> transportApiRequestTemplate; | 142 | protected TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> transportApiRequestTemplate; |
@@ -161,7 +164,8 @@ public class DefaultTransportService implements TransportService { | @@ -161,7 +164,8 @@ public class DefaultTransportService implements TransportService { | ||
161 | TransportDeviceProfileCache deviceProfileCache, | 164 | TransportDeviceProfileCache deviceProfileCache, |
162 | TransportTenantProfileCache tenantProfileCache, | 165 | TransportTenantProfileCache tenantProfileCache, |
163 | TbApiUsageClient apiUsageClient, TransportRateLimitService rateLimitService, | 166 | TbApiUsageClient apiUsageClient, TransportRateLimitService rateLimitService, |
164 | - DataDecodingEncodingService dataDecodingEncodingService, SchedulerComponent scheduler, TransportResourceCache transportResourceCache) { | 167 | + DataDecodingEncodingService dataDecodingEncodingService, SchedulerComponent scheduler, TransportResourceCache transportResourceCache, |
168 | + ApplicationEventPublisher eventPublisher) { | ||
165 | this.serviceInfoProvider = serviceInfoProvider; | 169 | this.serviceInfoProvider = serviceInfoProvider; |
166 | this.queueProvider = queueProvider; | 170 | this.queueProvider = queueProvider; |
167 | this.producerProvider = producerProvider; | 171 | this.producerProvider = producerProvider; |
@@ -174,6 +178,7 @@ public class DefaultTransportService implements TransportService { | @@ -174,6 +178,7 @@ public class DefaultTransportService implements TransportService { | ||
174 | this.dataDecodingEncodingService = dataDecodingEncodingService; | 178 | this.dataDecodingEncodingService = dataDecodingEncodingService; |
175 | this.scheduler = scheduler; | 179 | this.scheduler = scheduler; |
176 | this.transportResourceCache = transportResourceCache; | 180 | this.transportResourceCache = transportResourceCache; |
181 | + this.eventPublisher = eventPublisher; | ||
177 | } | 182 | } |
178 | 183 | ||
179 | @PostConstruct | 184 | @PostConstruct |
@@ -272,6 +277,58 @@ public class DefaultTransportService implements TransportService { | @@ -272,6 +277,58 @@ public class DefaultTransportService implements TransportService { | ||
272 | } | 277 | } |
273 | 278 | ||
274 | @Override | 279 | @Override |
280 | + public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds(TransportProtos.GetSnmpDevicesRequestMsg requestMsg) { | ||
281 | + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
282 | + UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder() | ||
283 | + .setSnmpDevicesRequestMsg(requestMsg) | ||
284 | + .build() | ||
285 | + ); | ||
286 | + | ||
287 | + try { | ||
288 | + TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
289 | + return response.getValue().getSnmpDevicesResponseMsg(); | ||
290 | + } catch (InterruptedException | ExecutionException e) { | ||
291 | + throw new RuntimeException(e); | ||
292 | + } | ||
293 | + } | ||
294 | + | ||
295 | + @Override | ||
296 | + public TransportProtos.GetDeviceResponseMsg getDevice(TransportProtos.GetDeviceRequestMsg requestMsg) { | ||
297 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
298 | + UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder() | ||
299 | + .setDeviceRequestMsg(requestMsg) | ||
300 | + .build() | ||
301 | + ); | ||
302 | + | ||
303 | + try { | ||
304 | + TransportApiResponseMsg response = transportApiRequestTemplate.send(protoMsg).get().getValue(); | ||
305 | + if (response.hasDeviceResponseMsg()) { | ||
306 | + return response.getDeviceResponseMsg(); | ||
307 | + } else { | ||
308 | + return null; | ||
309 | + } | ||
310 | + } catch (InterruptedException | ExecutionException e) { | ||
311 | + throw new RuntimeException(e); | ||
312 | + } | ||
313 | + } | ||
314 | + | ||
315 | + @Override | ||
316 | + public TransportProtos.GetDeviceCredentialsResponseMsg getDeviceCredentials(TransportProtos.GetDeviceCredentialsRequestMsg requestMsg) { | ||
317 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
318 | + UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder() | ||
319 | + .setDeviceCredentialsRequestMsg(requestMsg) | ||
320 | + .build() | ||
321 | + ); | ||
322 | + | ||
323 | + try { | ||
324 | + TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
325 | + return response.getValue().getDeviceCredentialsResponseMsg(); | ||
326 | + } catch (InterruptedException | ExecutionException e) { | ||
327 | + throw new RuntimeException(e); | ||
328 | + } | ||
329 | + } | ||
330 | + | ||
331 | + @Override | ||
275 | public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, | 332 | public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, |
276 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | 333 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { |
277 | log.trace("Processing msg: {}", msg); | 334 | log.trace("Processing msg: {}", msg); |
@@ -704,7 +761,10 @@ public class DefaultTransportService implements TransportService { | @@ -704,7 +761,10 @@ public class DefaultTransportService implements TransportService { | ||
704 | } | 761 | } |
705 | } else if (EntityType.DEVICE.equals(entityType)) { | 762 | } else if (EntityType.DEVICE.equals(entityType)) { |
706 | Optional<Device> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); | 763 | Optional<Device> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); |
707 | - deviceOpt.ifPresent(this::onDeviceUpdate); | 764 | + deviceOpt.ifPresent(device -> { |
765 | + onDeviceUpdate(device); | ||
766 | + eventPublisher.publishEvent(new DeviceUpdatedEvent(device)); | ||
767 | + }); | ||
708 | } | 768 | } |
709 | } else if (toSessionMsg.hasEntityDeleteMsg()) { | 769 | } else if (toSessionMsg.hasEntityDeleteMsg()) { |
710 | TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg(); | 770 | TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg(); |
@@ -718,6 +778,7 @@ public class DefaultTransportService implements TransportService { | @@ -718,6 +778,7 @@ public class DefaultTransportService implements TransportService { | ||
718 | rateLimitService.remove(new TenantId(entityUuid)); | 778 | rateLimitService.remove(new TenantId(entityUuid)); |
719 | } else if (EntityType.DEVICE.equals(entityType)) { | 779 | } else if (EntityType.DEVICE.equals(entityType)) { |
720 | rateLimitService.remove(new DeviceId(entityUuid)); | 780 | rateLimitService.remove(new DeviceId(entityUuid)); |
781 | + onDeviceDeleted(new DeviceId(entityUuid)); | ||
721 | } | 782 | } |
722 | } else if (toSessionMsg.hasResourceUpdateMsg()) { | 783 | } else if (toSessionMsg.hasResourceUpdateMsg()) { |
723 | TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg(); | 784 | TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg(); |
@@ -800,6 +861,17 @@ public class DefaultTransportService implements TransportService { | @@ -800,6 +861,17 @@ public class DefaultTransportService implements TransportService { | ||
800 | }); | 861 | }); |
801 | } | 862 | } |
802 | 863 | ||
864 | + private void onDeviceDeleted(DeviceId deviceId) { | ||
865 | + sessions.forEach((id, md) -> { | ||
866 | + DeviceId sessionDeviceId = new DeviceId(new UUID(md.getSessionInfo().getDeviceIdMSB(), md.getSessionInfo().getDeviceIdLSB())); | ||
867 | + if (sessionDeviceId.equals(deviceId)) { | ||
868 | + transportCallbackExecutor.submit(() -> { | ||
869 | + md.getListener().onDeviceDeleted(deviceId); | ||
870 | + }); | ||
871 | + } | ||
872 | + }); | ||
873 | + } | ||
874 | + | ||
803 | protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) { | 875 | protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) { |
804 | return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | 876 | return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); |
805 | } | 877 | } |
@@ -18,11 +18,11 @@ package org.thingsboard.server.dao.device; | @@ -18,11 +18,11 @@ package org.thingsboard.server.dao.device; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
20 | import org.thingsboard.server.common.data.DeviceInfo; | 20 | import org.thingsboard.server.common.data.DeviceInfo; |
21 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
21 | import org.thingsboard.server.common.data.EntitySubtype; | 22 | import org.thingsboard.server.common.data.EntitySubtype; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
23 | import org.thingsboard.server.common.data.page.PageData; | 24 | import org.thingsboard.server.common.data.page.PageData; |
24 | import org.thingsboard.server.common.data.page.PageLink; | 25 | import org.thingsboard.server.common.data.page.PageLink; |
25 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
26 | import org.thingsboard.server.dao.Dao; | 26 | import org.thingsboard.server.dao.Dao; |
27 | import org.thingsboard.server.dao.TenantEntityDao; | 27 | import org.thingsboard.server.dao.TenantEntityDao; |
28 | 28 | ||
@@ -219,6 +219,7 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao { | @@ -219,6 +219,7 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao { | ||
219 | */ | 219 | */ |
220 | PageData<Device> findDevicesByTenantIdAndProfileId(UUID tenantId, UUID profileId, PageLink pageLink); | 220 | PageData<Device> findDevicesByTenantIdAndProfileId(UUID tenantId, UUID profileId, PageLink pageLink); |
221 | 221 | ||
222 | + PageData<UUID> findDevicesIdsByDeviceProfileTransportType(DeviceTransportType transportType, PageLink pageLink); | ||
222 | 223 | ||
223 | /** | 224 | /** |
224 | * Find devices by tenantId, edgeId and page link. | 225 | * Find devices by tenantId, edgeId and page link. |
@@ -363,6 +363,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -363,6 +363,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
363 | } | 363 | } |
364 | 364 | ||
365 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | 365 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
366 | + transportConfiguration.validate(); | ||
366 | if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { | 367 | if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { |
367 | MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | 368 | MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; |
368 | if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { | 369 | if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { |
@@ -36,20 +36,22 @@ import org.thingsboard.server.common.data.Customer; | @@ -36,20 +36,22 @@ import org.thingsboard.server.common.data.Customer; | ||
36 | import org.thingsboard.server.common.data.Device; | 36 | import org.thingsboard.server.common.data.Device; |
37 | import org.thingsboard.server.common.data.DeviceInfo; | 37 | import org.thingsboard.server.common.data.DeviceInfo; |
38 | import org.thingsboard.server.common.data.DeviceProfile; | 38 | import org.thingsboard.server.common.data.DeviceProfile; |
39 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
39 | import org.thingsboard.server.common.data.EntitySubtype; | 40 | import org.thingsboard.server.common.data.EntitySubtype; |
40 | import org.thingsboard.server.common.data.EntityType; | 41 | import org.thingsboard.server.common.data.EntityType; |
41 | import org.thingsboard.server.common.data.EntityView; | 42 | import org.thingsboard.server.common.data.EntityView; |
42 | import org.thingsboard.server.common.data.Firmware; | 43 | import org.thingsboard.server.common.data.Firmware; |
43 | import org.thingsboard.server.common.data.Tenant; | 44 | import org.thingsboard.server.common.data.Tenant; |
44 | -import org.thingsboard.server.common.data.asset.Asset; | ||
45 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 45 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
46 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; | 46 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; |
47 | import org.thingsboard.server.common.data.device.data.CoapDeviceTransportConfiguration; | 47 | import org.thingsboard.server.common.data.device.data.CoapDeviceTransportConfiguration; |
48 | import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration; | 48 | import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration; |
49 | import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration; | 49 | import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration; |
50 | import org.thingsboard.server.common.data.device.data.DeviceData; | 50 | import org.thingsboard.server.common.data.device.data.DeviceData; |
51 | +import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration; | ||
51 | import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration; | 52 | import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration; |
52 | import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; | 53 | import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; |
54 | +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | ||
53 | import org.thingsboard.server.common.data.edge.Edge; | 55 | import org.thingsboard.server.common.data.edge.Edge; |
54 | import org.thingsboard.server.common.data.id.CustomerId; | 56 | import org.thingsboard.server.common.data.id.CustomerId; |
55 | import org.thingsboard.server.common.data.id.DeviceId; | 57 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -59,7 +61,6 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -59,7 +61,6 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
59 | import org.thingsboard.server.common.data.id.TenantId; | 61 | import org.thingsboard.server.common.data.id.TenantId; |
60 | import org.thingsboard.server.common.data.page.PageData; | 62 | import org.thingsboard.server.common.data.page.PageData; |
61 | import org.thingsboard.server.common.data.page.PageLink; | 63 | import org.thingsboard.server.common.data.page.PageLink; |
62 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
63 | import org.thingsboard.server.common.data.relation.EntityRelation; | 64 | import org.thingsboard.server.common.data.relation.EntityRelation; |
64 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 65 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
65 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 66 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
@@ -86,6 +87,7 @@ import java.util.Collections; | @@ -86,6 +87,7 @@ import java.util.Collections; | ||
86 | import java.util.Comparator; | 87 | import java.util.Comparator; |
87 | import java.util.List; | 88 | import java.util.List; |
88 | import java.util.Optional; | 89 | import java.util.Optional; |
90 | +import java.util.UUID; | ||
89 | import java.util.concurrent.ExecutionException; | 91 | import java.util.concurrent.ExecutionException; |
90 | import java.util.stream.Collectors; | 92 | import java.util.stream.Collectors; |
91 | 93 | ||
@@ -269,11 +271,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -269,11 +271,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
269 | case MQTT: | 271 | case MQTT: |
270 | deviceData.setTransportConfiguration(new MqttDeviceTransportConfiguration()); | 272 | deviceData.setTransportConfiguration(new MqttDeviceTransportConfiguration()); |
271 | break; | 273 | break; |
274 | + case COAP: | ||
275 | + deviceData.setTransportConfiguration(new CoapDeviceTransportConfiguration()); | ||
276 | + break; | ||
272 | case LWM2M: | 277 | case LWM2M: |
273 | deviceData.setTransportConfiguration(new Lwm2mDeviceTransportConfiguration()); | 278 | deviceData.setTransportConfiguration(new Lwm2mDeviceTransportConfiguration()); |
274 | break; | 279 | break; |
275 | - case COAP: | ||
276 | - deviceData.setTransportConfiguration(new CoapDeviceTransportConfiguration()); | 280 | + case SNMP: |
281 | + deviceData.setTransportConfiguration(new SnmpDeviceTransportConfiguration()); | ||
277 | break; | 282 | break; |
278 | } | 283 | } |
279 | } | 284 | } |
@@ -573,6 +578,11 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -573,6 +578,11 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
573 | } | 578 | } |
574 | 579 | ||
575 | @Override | 580 | @Override |
581 | + public PageData<UUID> findDevicesIdsByDeviceProfileTransportType(DeviceTransportType transportType, PageLink pageLink) { | ||
582 | + return deviceDao.findDevicesIdsByDeviceProfileTransportType(transportType, pageLink); | ||
583 | + } | ||
584 | + | ||
585 | + @Override | ||
576 | public Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId) { | 586 | public Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId) { |
577 | Device device = findDeviceById(tenantId, deviceId); | 587 | Device device = findDeviceById(tenantId, deviceId); |
578 | Edge edge = edgeService.findEdgeById(tenantId, edgeId); | 588 | Edge edge = edgeService.findEdgeById(tenantId, edgeId); |
@@ -677,6 +687,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -677,6 +687,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
677 | throw new DataValidationException("Can't assign device to customer from different tenant!"); | 687 | throw new DataValidationException("Can't assign device to customer from different tenant!"); |
678 | } | 688 | } |
679 | } | 689 | } |
690 | + Optional.ofNullable(device.getDeviceData()) | ||
691 | + .flatMap(deviceData -> Optional.ofNullable(deviceData.getTransportConfiguration())) | ||
692 | + .ifPresent(DeviceTransportConfiguration::validate); | ||
680 | 693 | ||
681 | if (device.getFirmwareId() != null) { | 694 | if (device.getFirmwareId() != null) { |
682 | Firmware firmware = firmwareService.findFirmwareById(tenantId, device.getFirmwareId()); | 695 | Firmware firmware = firmwareService.findFirmwareById(tenantId, device.getFirmwareId()); |
@@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable; | @@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable; | ||
20 | import org.springframework.data.jpa.repository.Query; | 20 | import org.springframework.data.jpa.repository.Query; |
21 | import org.springframework.data.repository.PagingAndSortingRepository; | 21 | import org.springframework.data.repository.PagingAndSortingRepository; |
22 | import org.springframework.data.repository.query.Param; | 22 | import org.springframework.data.repository.query.Param; |
23 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
23 | import org.thingsboard.server.dao.model.sql.DeviceEntity; | 24 | import org.thingsboard.server.dao.model.sql.DeviceEntity; |
24 | import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; | 25 | import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; |
25 | 26 | ||
@@ -210,4 +211,9 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | @@ -210,4 +211,9 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | ||
210 | * */ | 211 | * */ |
211 | @Query("SELECT count(*) FROM DeviceEntity d WHERE d.tenantId = :tenantId") | 212 | @Query("SELECT count(*) FROM DeviceEntity d WHERE d.tenantId = :tenantId") |
212 | Long countByTenantId(@Param("tenantId") UUID tenantId); | 213 | Long countByTenantId(@Param("tenantId") UUID tenantId); |
214 | + | ||
215 | + @Query("SELECT d.id FROM DeviceEntity d " + | ||
216 | + "INNER JOIN DeviceProfileEntity p ON d.deviceProfileId = p.id " + | ||
217 | + "WHERE p.transportType = :transportType") | ||
218 | + Page<UUID> findIdsByDeviceProfileTransportType(@Param("transportType") DeviceTransportType transportType, Pageable pageable); | ||
213 | } | 219 | } |
@@ -23,12 +23,12 @@ import org.springframework.stereotype.Component; | @@ -23,12 +23,12 @@ import org.springframework.stereotype.Component; | ||
23 | import org.springframework.util.StringUtils; | 23 | import org.springframework.util.StringUtils; |
24 | import org.thingsboard.server.common.data.Device; | 24 | import org.thingsboard.server.common.data.Device; |
25 | import org.thingsboard.server.common.data.DeviceInfo; | 25 | import org.thingsboard.server.common.data.DeviceInfo; |
26 | +import org.thingsboard.server.common.data.DeviceTransportType; | ||
26 | import org.thingsboard.server.common.data.EntitySubtype; | 27 | import org.thingsboard.server.common.data.EntitySubtype; |
27 | import org.thingsboard.server.common.data.EntityType; | 28 | import org.thingsboard.server.common.data.EntityType; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
29 | import org.thingsboard.server.common.data.page.PageData; | 30 | import org.thingsboard.server.common.data.page.PageData; |
30 | import org.thingsboard.server.common.data.page.PageLink; | 31 | import org.thingsboard.server.common.data.page.PageLink; |
31 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
32 | import org.thingsboard.server.dao.DaoUtil; | 32 | import org.thingsboard.server.dao.DaoUtil; |
33 | import org.thingsboard.server.dao.device.DeviceDao; | 33 | import org.thingsboard.server.dao.device.DeviceDao; |
34 | import org.thingsboard.server.dao.model.sql.DeviceEntity; | 34 | import org.thingsboard.server.dao.model.sql.DeviceEntity; |
@@ -118,6 +118,11 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | @@ -118,6 +118,11 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | ||
118 | } | 118 | } |
119 | 119 | ||
120 | @Override | 120 | @Override |
121 | + public PageData<UUID> findDevicesIdsByDeviceProfileTransportType(DeviceTransportType transportType, PageLink pageLink) { | ||
122 | + return DaoUtil.pageToPageData(deviceRepository.findIdsByDeviceProfileTransportType(transportType, DaoUtil.toPageable(pageLink))); | ||
123 | + } | ||
124 | + | ||
125 | + @Override | ||
121 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { | 126 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { |
122 | return DaoUtil.toPageData( | 127 | return DaoUtil.toPageData( |
123 | deviceRepository.findDeviceInfosByTenantIdAndCustomerId( | 128 | deviceRepository.findDeviceInfosByTenantIdAndCustomerId( |
@@ -9,6 +9,7 @@ MQTT_TRANSPORT_DOCKER_NAME=tb-mqtt-transport | @@ -9,6 +9,7 @@ MQTT_TRANSPORT_DOCKER_NAME=tb-mqtt-transport | ||
9 | HTTP_TRANSPORT_DOCKER_NAME=tb-http-transport | 9 | HTTP_TRANSPORT_DOCKER_NAME=tb-http-transport |
10 | COAP_TRANSPORT_DOCKER_NAME=tb-coap-transport | 10 | COAP_TRANSPORT_DOCKER_NAME=tb-coap-transport |
11 | LWM2M_TRANSPORT_DOCKER_NAME=tb-lwm2m-transport | 11 | LWM2M_TRANSPORT_DOCKER_NAME=tb-lwm2m-transport |
12 | +SNMP_TRANSPORT_DOCKER_NAME=tb-snmp-transport | ||
12 | 13 | ||
13 | TB_VERSION=latest | 14 | TB_VERSION=latest |
14 | 15 |
@@ -50,6 +50,9 @@ services: | @@ -50,6 +50,9 @@ services: | ||
50 | tb-mqtt-transport2: | 50 | tb-mqtt-transport2: |
51 | volumes: | 51 | volumes: |
52 | - tb-mqtt-transport-log-volume:/var/log/tb-mqtt-transport | 52 | - tb-mqtt-transport-log-volume:/var/log/tb-mqtt-transport |
53 | + tb-snmp-transport: | ||
54 | + volumes: | ||
55 | + - tb-snmp-transport-log-volume:/var/log/tb-snmp-transport | ||
53 | 56 | ||
54 | volumes: | 57 | volumes: |
55 | postgres-db-volume: | 58 | postgres-db-volume: |
@@ -70,3 +73,6 @@ volumes: | @@ -70,3 +73,6 @@ volumes: | ||
70 | tb-mqtt-transport-log-volume: | 73 | tb-mqtt-transport-log-volume: |
71 | external: true | 74 | external: true |
72 | name: ${TB_MQTT_TRANSPORT_LOG_VOLUME} | 75 | name: ${TB_MQTT_TRANSPORT_LOG_VOLUME} |
76 | + tb-snmp-transport-log-volume: | ||
77 | + external: true | ||
78 | + name: ${TB_SNMP_TRANSPORT_LOG_VOLUME} |
@@ -217,6 +217,18 @@ services: | @@ -217,6 +217,18 @@ services: | ||
217 | - ./tb-transports/lwm2m/log:/var/log/tb-lwm2m-transport | 217 | - ./tb-transports/lwm2m/log:/var/log/tb-lwm2m-transport |
218 | depends_on: | 218 | depends_on: |
219 | - zookeeper | 219 | - zookeeper |
220 | + tb-snmp-transport: | ||
221 | + restart: always | ||
222 | + image: "${DOCKER_REPO}/${SNMP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" | ||
223 | + environment: | ||
224 | + TB_SERVICE_ID: tb-snmp-transport | ||
225 | + env_file: | ||
226 | + - tb-snmp-transport.env | ||
227 | + volumes: | ||
228 | + - ./tb-transports/snmp/conf:/config | ||
229 | + - ./tb-transports/snmp/log:/var/log/tb-snmp-transport | ||
230 | + depends_on: | ||
231 | + - zookeeper | ||
220 | tb-web-ui1: | 232 | tb-web-ui1: |
221 | restart: always | 233 | restart: always |
222 | image: "${DOCKER_REPO}/${WEB_UI_DOCKER_NAME}:${TB_VERSION}" | 234 | image: "${DOCKER_REPO}/${WEB_UI_DOCKER_NAME}:${TB_VERSION}" |
@@ -24,3 +24,5 @@ mkdir -p tb-transports/lwm2m/log && sudo chown -R 799:799 tb-transports/lwm2m/lo | @@ -24,3 +24,5 @@ mkdir -p tb-transports/lwm2m/log && sudo chown -R 799:799 tb-transports/lwm2m/lo | ||
24 | mkdir -p tb-transports/http/log && sudo chown -R 799:799 tb-transports/http/log | 24 | mkdir -p tb-transports/http/log && sudo chown -R 799:799 tb-transports/http/log |
25 | 25 | ||
26 | mkdir -p tb-transports/mqtt/log && sudo chown -R 799:799 tb-transports/mqtt/log | 26 | mkdir -p tb-transports/mqtt/log && sudo chown -R 799:799 tb-transports/mqtt/log |
27 | + | ||
28 | +mkdir -p tb-transports/snmp/log && sudo chown -R 799:799 tb-transports/snmp/log |
docker/tb-snmp-transport.env
0 → 100644
docker/tb-transports/snmp/conf/logback.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
2 | +<!-- | ||
3 | + | ||
4 | + Copyright © 2016-2021 The Thingsboard Authors | ||
5 | + | ||
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + you may not use this file except in compliance with the License. | ||
8 | + You may obtain a copy of the License at | ||
9 | + | ||
10 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + | ||
12 | + Unless required by applicable law or agreed to in writing, software | ||
13 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + See the License for the specific language governing permissions and | ||
16 | + limitations under the License. | ||
17 | + | ||
18 | +--> | ||
19 | +<!DOCTYPE configuration> | ||
20 | +<configuration scan="true" scanPeriod="10 seconds"> | ||
21 | + | ||
22 | + <appender name="fileLogAppender" | ||
23 | + class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
24 | + <file>/var/log/tb-snmp-transport/${TB_SERVICE_ID}/tb-snmp-transport.log</file> | ||
25 | + <rollingPolicy | ||
26 | + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | ||
27 | + <fileNamePattern>/var/log/tb-snmp-transport/${TB_SERVICE_ID}/tb-snmp-transport.%d{yyyy-MM-dd}.%i.log</fileNamePattern> | ||
28 | + <maxFileSize>100MB</maxFileSize> | ||
29 | + <maxHistory>30</maxHistory> | ||
30 | + <totalSizeCap>3GB</totalSizeCap> | ||
31 | + </rollingPolicy> | ||
32 | + <encoder> | ||
33 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
34 | + </encoder> | ||
35 | + </appender> | ||
36 | + | ||
37 | + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
38 | + <encoder> | ||
39 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
40 | + </encoder> | ||
41 | + </appender> | ||
42 | + | ||
43 | + <logger name="org.thingsboard.server" level="INFO" /> | ||
44 | + | ||
45 | + <root level="INFO"> | ||
46 | + <appender-ref ref="fileLogAppender"/> | ||
47 | + <appender-ref ref="STDOUT"/> | ||
48 | + </root> | ||
49 | + | ||
50 | +</configuration> |
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 | + | ||
17 | +export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=/var/log/tb-snmp-transport/${TB_SERVICE_ID}-gc.log:time,uptime,level,tags:filecount=10,filesize=10M" | ||
18 | +export JAVA_OPTS="$JAVA_OPTS -XX:+IgnoreUnrecognizedVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/tb-snmp-transport/${TB_SERVICE_ID}-heapdump.bin" | ||
19 | +export JAVA_OPTS="$JAVA_OPTS -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark" | ||
20 | +export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10" | ||
21 | +export JAVA_OPTS="$JAVA_OPTS -XX:+ExitOnOutOfMemoryError" | ||
22 | +export LOG_FILENAME=tb-snmp-transport.out | ||
23 | +export LOADER_PATH=/usr/share/tb-snmp-transport/conf |
@@ -32,6 +32,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -32,6 +32,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
32 | private final static String TB_LWM2M_TRANSPORT_LOG_VOLUME = "tb-lwm2m-transport-log-test-volume"; | 32 | private final static String TB_LWM2M_TRANSPORT_LOG_VOLUME = "tb-lwm2m-transport-log-test-volume"; |
33 | private final static String TB_HTTP_TRANSPORT_LOG_VOLUME = "tb-http-transport-log-test-volume"; | 33 | private final static String TB_HTTP_TRANSPORT_LOG_VOLUME = "tb-http-transport-log-test-volume"; |
34 | private final static String TB_MQTT_TRANSPORT_LOG_VOLUME = "tb-mqtt-transport-log-test-volume"; | 34 | private final static String TB_MQTT_TRANSPORT_LOG_VOLUME = "tb-mqtt-transport-log-test-volume"; |
35 | + private final static String TB_SNMP_TRANSPORT_LOG_VOLUME = "tb-snmp-transport-log-test-volume"; | ||
35 | 36 | ||
36 | private final DockerComposeExecutor dockerCompose; | 37 | private final DockerComposeExecutor dockerCompose; |
37 | 38 | ||
@@ -41,6 +42,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -41,6 +42,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
41 | private final String tbLwm2mTransportLogVolume; | 42 | private final String tbLwm2mTransportLogVolume; |
42 | private final String tbHttpTransportLogVolume; | 43 | private final String tbHttpTransportLogVolume; |
43 | private final String tbMqttTransportLogVolume; | 44 | private final String tbMqttTransportLogVolume; |
45 | + private final String tbSnmpTransportLogVolume; | ||
44 | private final Map<String, String> env; | 46 | private final Map<String, String> env; |
45 | 47 | ||
46 | public ThingsBoardDbInstaller() { | 48 | public ThingsBoardDbInstaller() { |
@@ -57,6 +59,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -57,6 +59,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
57 | tbLwm2mTransportLogVolume = project + "_" + TB_LWM2M_TRANSPORT_LOG_VOLUME; | 59 | tbLwm2mTransportLogVolume = project + "_" + TB_LWM2M_TRANSPORT_LOG_VOLUME; |
58 | tbHttpTransportLogVolume = project + "_" + TB_HTTP_TRANSPORT_LOG_VOLUME; | 60 | tbHttpTransportLogVolume = project + "_" + TB_HTTP_TRANSPORT_LOG_VOLUME; |
59 | tbMqttTransportLogVolume = project + "_" + TB_MQTT_TRANSPORT_LOG_VOLUME; | 61 | tbMqttTransportLogVolume = project + "_" + TB_MQTT_TRANSPORT_LOG_VOLUME; |
62 | + tbSnmpTransportLogVolume = project + "_" + TB_SNMP_TRANSPORT_LOG_VOLUME; | ||
60 | 63 | ||
61 | dockerCompose = new DockerComposeExecutor(composeFiles, project); | 64 | dockerCompose = new DockerComposeExecutor(composeFiles, project); |
62 | 65 | ||
@@ -67,6 +70,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -67,6 +70,7 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
67 | env.put("TB_LWM2M_TRANSPORT_LOG_VOLUME", tbLwm2mTransportLogVolume); | 70 | env.put("TB_LWM2M_TRANSPORT_LOG_VOLUME", tbLwm2mTransportLogVolume); |
68 | env.put("TB_HTTP_TRANSPORT_LOG_VOLUME", tbHttpTransportLogVolume); | 71 | env.put("TB_HTTP_TRANSPORT_LOG_VOLUME", tbHttpTransportLogVolume); |
69 | env.put("TB_MQTT_TRANSPORT_LOG_VOLUME", tbMqttTransportLogVolume); | 72 | env.put("TB_MQTT_TRANSPORT_LOG_VOLUME", tbMqttTransportLogVolume); |
73 | + env.put("TB_SNMP_TRANSPORT_LOG_VOLUME", tbSnmpTransportLogVolume); | ||
70 | dockerCompose.withEnv(env); | 74 | dockerCompose.withEnv(env); |
71 | } | 75 | } |
72 | 76 | ||
@@ -96,6 +100,9 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -96,6 +100,9 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
96 | dockerCompose.withCommand("volume create " + tbMqttTransportLogVolume); | 100 | dockerCompose.withCommand("volume create " + tbMqttTransportLogVolume); |
97 | dockerCompose.invokeDocker(); | 101 | dockerCompose.invokeDocker(); |
98 | 102 | ||
103 | + dockerCompose.withCommand("volume create " + tbSnmpTransportLogVolume); | ||
104 | + dockerCompose.invokeDocker(); | ||
105 | + | ||
99 | dockerCompose.withCommand("up -d redis postgres"); | 106 | dockerCompose.withCommand("up -d redis postgres"); |
100 | dockerCompose.invokeCompose(); | 107 | dockerCompose.invokeCompose(); |
101 | 108 | ||
@@ -117,9 +124,11 @@ public class ThingsBoardDbInstaller extends ExternalResource { | @@ -117,9 +124,11 @@ public class ThingsBoardDbInstaller extends ExternalResource { | ||
117 | copyLogs(tbLwm2mTransportLogVolume, "./target/tb-lwm2m-transport-logs/"); | 124 | copyLogs(tbLwm2mTransportLogVolume, "./target/tb-lwm2m-transport-logs/"); |
118 | copyLogs(tbHttpTransportLogVolume, "./target/tb-http-transport-logs/"); | 125 | copyLogs(tbHttpTransportLogVolume, "./target/tb-http-transport-logs/"); |
119 | copyLogs(tbMqttTransportLogVolume, "./target/tb-mqtt-transport-logs/"); | 126 | copyLogs(tbMqttTransportLogVolume, "./target/tb-mqtt-transport-logs/"); |
127 | + copyLogs(tbSnmpTransportLogVolume, "./target/tb-snmp-transport-logs/"); | ||
120 | 128 | ||
121 | dockerCompose.withCommand("volume rm -f " + postgresDataVolume + " " + tbLogVolume + | 129 | dockerCompose.withCommand("volume rm -f " + postgresDataVolume + " " + tbLogVolume + |
122 | - " " + tbCoapTransportLogVolume + " " + tbLwm2mTransportLogVolume + " " + tbHttpTransportLogVolume + " " + tbMqttTransportLogVolume); | 130 | + " " + tbCoapTransportLogVolume + " " + tbLwm2mTransportLogVolume + " " + tbHttpTransportLogVolume + |
131 | + " " + tbMqttTransportLogVolume + " " + tbSnmpTransportLogVolume); | ||
123 | dockerCompose.invokeDocker(); | 132 | dockerCompose.invokeDocker(); |
124 | } | 133 | } |
125 | 134 |
msa/transport/snmp/docker/Dockerfile
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 | + | ||
17 | +FROM thingsboard/openjdk11 | ||
18 | + | ||
19 | +COPY start-tb-snmp-transport.sh ${pkg.name}.deb /tmp/ | ||
20 | + | ||
21 | +RUN chmod a+x /tmp/*.sh \ | ||
22 | + && mv /tmp/start-tb-snmp-transport.sh /usr/bin | ||
23 | + | ||
24 | +RUN yes | dpkg -i /tmp/${pkg.name}.deb | ||
25 | +RUN rm /tmp/${pkg.name}.deb | ||
26 | + | ||
27 | +RUN systemctl --no-reload disable --now ${pkg.name}.service > /dev/null 2>&1 || : | ||
28 | + | ||
29 | +RUN chmod 555 ${pkg.installFolder}/bin/${pkg.name}.jar | ||
30 | + | ||
31 | +USER ${pkg.user} | ||
32 | + | ||
33 | +CMD ["start-tb-snmp-transport.sh"] |
1 | +#!/bin/bash | ||
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 | +CONF_FOLDER="/config" | ||
19 | +jarfile=${pkg.installFolder}/bin/${pkg.name}.jar | ||
20 | +configfile=${pkg.name}.conf | ||
21 | + | ||
22 | +source "${CONF_FOLDER}/${configfile}" | ||
23 | + | ||
24 | +export LOADER_PATH=/config,${LOADER_PATH} | ||
25 | + | ||
26 | +echo "Starting '${project.name}' ..." | ||
27 | + | ||
28 | +cd ${pkg.installFolder}/bin | ||
29 | + | ||
30 | +exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.snmp.ThingsboardSnmpTransportApplication \ | ||
31 | + -Dspring.jpa.hibernate.ddl-auto=none \ | ||
32 | + -Dlogging.config=/config/logback.xml \ | ||
33 | + org.springframework.boot.loader.PropertiesLauncher |
msa/transport/snmp/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.msa</groupId> | ||
23 | + <artifactId>transport</artifactId> | ||
24 | + <version>3.3.0-SNAPSHOT</version> | ||
25 | + </parent> | ||
26 | + | ||
27 | + <groupId>org.thingsboard.msa.transport</groupId> | ||
28 | + <artifactId>snmp</artifactId> | ||
29 | + <packaging>pom</packaging> | ||
30 | + | ||
31 | + <name>ThingsBoard SNMP Transport Microservice</name> | ||
32 | + <url>https://thingsboard.io</url> | ||
33 | + <description>ThingsBoard SNMP Transport Microservice</description> | ||
34 | + | ||
35 | + <properties> | ||
36 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
37 | + <main.dir>${basedir}/../../..</main.dir> | ||
38 | + <pkg.name>tb-snmp-transport</pkg.name> | ||
39 | + <docker.name>tb-snmp-transport</docker.name> | ||
40 | + <pkg.logFolder>/var/log/${pkg.name}</pkg.logFolder> | ||
41 | + <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder> | ||
42 | + </properties> | ||
43 | + | ||
44 | + <dependencies> | ||
45 | + <dependency> | ||
46 | + <groupId>org.thingsboard.transport</groupId> | ||
47 | + <artifactId>snmp</artifactId> | ||
48 | + <version>${project.version}</version> | ||
49 | + <classifier>deb</classifier> | ||
50 | + <type>deb</type> | ||
51 | + <scope>provided</scope> | ||
52 | + </dependency> | ||
53 | + </dependencies> | ||
54 | + | ||
55 | + <build> | ||
56 | + <plugins> | ||
57 | + <plugin> | ||
58 | + <groupId>org.apache.maven.plugins</groupId> | ||
59 | + <artifactId>maven-dependency-plugin</artifactId> | ||
60 | + <executions> | ||
61 | + <execution> | ||
62 | + <id>copy-tb-snmp-transport-deb</id> | ||
63 | + <phase>package</phase> | ||
64 | + <goals> | ||
65 | + <goal>copy</goal> | ||
66 | + </goals> | ||
67 | + <configuration> | ||
68 | + <artifactItems> | ||
69 | + <artifactItem> | ||
70 | + <groupId>org.thingsboard.transport</groupId> | ||
71 | + <artifactId>snmp</artifactId> | ||
72 | + <classifier>deb</classifier> | ||
73 | + <type>deb</type> | ||
74 | + <destFileName>${pkg.name}.deb</destFileName> | ||
75 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
76 | + </artifactItem> | ||
77 | + </artifactItems> | ||
78 | + </configuration> | ||
79 | + </execution> | ||
80 | + </executions> | ||
81 | + </plugin> | ||
82 | + <plugin> | ||
83 | + <groupId>org.apache.maven.plugins</groupId> | ||
84 | + <artifactId>maven-resources-plugin</artifactId> | ||
85 | + <executions> | ||
86 | + <execution> | ||
87 | + <id>copy-docker-config</id> | ||
88 | + <phase>process-resources</phase> | ||
89 | + <goals> | ||
90 | + <goal>copy-resources</goal> | ||
91 | + </goals> | ||
92 | + <configuration> | ||
93 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
94 | + <resources> | ||
95 | + <resource> | ||
96 | + <directory>docker</directory> | ||
97 | + <filtering>true</filtering> | ||
98 | + </resource> | ||
99 | + </resources> | ||
100 | + </configuration> | ||
101 | + </execution> | ||
102 | + </executions> | ||
103 | + </plugin> | ||
104 | + <plugin> | ||
105 | + <groupId>com.spotify</groupId> | ||
106 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
107 | + <executions> | ||
108 | + <execution> | ||
109 | + <id>build-docker-image</id> | ||
110 | + <phase>pre-integration-test</phase> | ||
111 | + <goals> | ||
112 | + <goal>build</goal> | ||
113 | + </goals> | ||
114 | + <configuration> | ||
115 | + <skip>${dockerfile.skip}</skip> | ||
116 | + <repository>${docker.repo}/${docker.name}</repository> | ||
117 | + <verbose>true</verbose> | ||
118 | + <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled> | ||
119 | + <contextDirectory>${project.build.directory}</contextDirectory> | ||
120 | + </configuration> | ||
121 | + </execution> | ||
122 | + <execution> | ||
123 | + <id>tag-docker-image</id> | ||
124 | + <phase>pre-integration-test</phase> | ||
125 | + <goals> | ||
126 | + <goal>tag</goal> | ||
127 | + </goals> | ||
128 | + <configuration> | ||
129 | + <skip>${dockerfile.skip}</skip> | ||
130 | + <repository>${docker.repo}/${docker.name}</repository> | ||
131 | + <tag>${project.version}</tag> | ||
132 | + </configuration> | ||
133 | + </execution> | ||
134 | + </executions> | ||
135 | + </plugin> | ||
136 | + </plugins> | ||
137 | + </build> | ||
138 | + <profiles> | ||
139 | + <profile> | ||
140 | + <id>push-docker-image</id> | ||
141 | + <activation> | ||
142 | + <property> | ||
143 | + <name>push-docker-image</name> | ||
144 | + </property> | ||
145 | + </activation> | ||
146 | + <build> | ||
147 | + <plugins> | ||
148 | + <plugin> | ||
149 | + <groupId>com.spotify</groupId> | ||
150 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
151 | + <executions> | ||
152 | + <execution> | ||
153 | + <id>push-latest-docker-image</id> | ||
154 | + <phase>pre-integration-test</phase> | ||
155 | + <goals> | ||
156 | + <goal>push</goal> | ||
157 | + </goals> | ||
158 | + <configuration> | ||
159 | + <tag>latest</tag> | ||
160 | + <repository>${docker.repo}/${docker.name}</repository> | ||
161 | + </configuration> | ||
162 | + </execution> | ||
163 | + <execution> | ||
164 | + <id>push-version-docker-image</id> | ||
165 | + <phase>pre-integration-test</phase> | ||
166 | + <goals> | ||
167 | + <goal>push</goal> | ||
168 | + </goals> | ||
169 | + <configuration> | ||
170 | + <tag>${project.version}</tag> | ||
171 | + <repository>${docker.repo}/${docker.name}</repository> | ||
172 | + </configuration> | ||
173 | + </execution> | ||
174 | + </executions> | ||
175 | + </plugin> | ||
176 | + </plugins> | ||
177 | + </build> | ||
178 | + </profile> | ||
179 | + </profiles> | ||
180 | + <repositories> | ||
181 | + <repository> | ||
182 | + <id>jenkins</id> | ||
183 | + <name>Jenkins Repository</name> | ||
184 | + <url>https://repo.jenkins-ci.org/releases</url> | ||
185 | + <snapshots> | ||
186 | + <enabled>false</enabled> | ||
187 | + </snapshots> | ||
188 | + </repository> | ||
189 | + </repositories> | ||
190 | +</project> |
@@ -121,6 +121,7 @@ | @@ -121,6 +121,7 @@ | ||
121 | <javax.el.version>3.0.0</javax.el.version> | 121 | <javax.el.version>3.0.0</javax.el.version> |
122 | <javax.validation-api.version>2.0.1.Final</javax.validation-api.version> | 122 | <javax.validation-api.version>2.0.1.Final</javax.validation-api.version> |
123 | <antisamy.version>1.6.2</antisamy.version> | 123 | <antisamy.version>1.6.2</antisamy.version> |
124 | + <snmp4j.version>2.8.5</snmp4j.version> | ||
124 | </properties> | 125 | </properties> |
125 | 126 | ||
126 | <modules> | 127 | <modules> |
@@ -915,6 +916,11 @@ | @@ -915,6 +916,11 @@ | ||
915 | </dependency> | 916 | </dependency> |
916 | <dependency> | 917 | <dependency> |
917 | <groupId>org.thingsboard.common.transport</groupId> | 918 | <groupId>org.thingsboard.common.transport</groupId> |
919 | + <artifactId>snmp</artifactId> | ||
920 | + <version>${project.version}</version> | ||
921 | + </dependency> | ||
922 | + <dependency> | ||
923 | + <groupId>org.thingsboard.common.transport</groupId> | ||
918 | <artifactId>lwm2m</artifactId> | 924 | <artifactId>lwm2m</artifactId> |
919 | <version>${project.version}</version> | 925 | <version>${project.version}</version> |
920 | </dependency> | 926 | </dependency> |
@@ -1598,6 +1604,11 @@ | @@ -1598,6 +1604,11 @@ | ||
1598 | </exclusion> | 1604 | </exclusion> |
1599 | </exclusions> | 1605 | </exclusions> |
1600 | </dependency> | 1606 | </dependency> |
1607 | + <dependency> | ||
1608 | + <groupId>org.snmp4j</groupId> | ||
1609 | + <artifactId>snmp4j</artifactId> | ||
1610 | + <version>${snmp4j.version}</version> | ||
1611 | + </dependency> | ||
1601 | </dependencies> | 1612 | </dependencies> |
1602 | </dependencyManagement> | 1613 | </dependencyManagement> |
1603 | 1614 |
transport/snmp/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 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.thingsboard</groupId> | ||
24 | + <version>3.3.0-SNAPSHOT</version> | ||
25 | + <artifactId>transport</artifactId> | ||
26 | + </parent> | ||
27 | + | ||
28 | + <groupId>org.thingsboard.transport</groupId> | ||
29 | + <artifactId>snmp</artifactId> | ||
30 | + <packaging>jar</packaging> | ||
31 | + | ||
32 | + <name>Thingsboard SNMP Transport Service</name> | ||
33 | + <url>https://thingsboard.io</url> | ||
34 | + | ||
35 | + <properties> | ||
36 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
37 | + <main.dir>${basedir}/../..</main.dir> | ||
38 | + <pkg.type>java</pkg.type> | ||
39 | + <pkg.disabled>false</pkg.disabled> | ||
40 | + <pkg.process-resources.phase>process-resources</pkg.process-resources.phase> | ||
41 | + <pkg.package.phase>package</pkg.package.phase> | ||
42 | + <pkg.name>tb-snmp-transport</pkg.name> | ||
43 | + <pkg.copyInstallScripts>false</pkg.copyInstallScripts> | ||
44 | + <pkg.win.dist>${project.build.directory}/windows</pkg.win.dist> | ||
45 | + <pkg.implementationTitle>ThingsBoard SNMP Transport Service</pkg.implementationTitle> | ||
46 | + <pkg.mainClass>org.thingsboard.server.snmp.ThingsboardSnmpTransportApplication</pkg.mainClass> | ||
47 | + </properties> | ||
48 | + | ||
49 | + <dependencies> | ||
50 | + <dependency> | ||
51 | + <groupId>org.thingsboard.common.transport</groupId> | ||
52 | + <artifactId>snmp</artifactId> | ||
53 | + </dependency> | ||
54 | + <dependency> | ||
55 | + <groupId>org.thingsboard.common</groupId> | ||
56 | + <artifactId>queue</artifactId> | ||
57 | + </dependency> | ||
58 | + <dependency> | ||
59 | + <groupId>org.springframework.boot</groupId> | ||
60 | + <artifactId>spring-boot-starter-web</artifactId> | ||
61 | + </dependency> | ||
62 | + </dependencies> | ||
63 | + | ||
64 | + <build> | ||
65 | + <finalName>${pkg.name}-${project.version}</finalName> | ||
66 | + <resources> | ||
67 | + <resource> | ||
68 | + <directory>${project.basedir}/src/main/resources</directory> | ||
69 | + </resource> | ||
70 | + </resources> | ||
71 | + <plugins> | ||
72 | + <plugin> | ||
73 | + <groupId>org.apache.maven.plugins</groupId> | ||
74 | + <artifactId>maven-resources-plugin</artifactId> | ||
75 | + </plugin> | ||
76 | + <plugin> | ||
77 | + <groupId>org.apache.maven.plugins</groupId> | ||
78 | + <artifactId>maven-dependency-plugin</artifactId> | ||
79 | + </plugin> | ||
80 | + <plugin> | ||
81 | + <groupId>org.apache.maven.plugins</groupId> | ||
82 | + <artifactId>maven-jar-plugin</artifactId> | ||
83 | + </plugin> | ||
84 | + <plugin> | ||
85 | + <groupId>org.springframework.boot</groupId> | ||
86 | + <artifactId>spring-boot-maven-plugin</artifactId> | ||
87 | + </plugin> | ||
88 | + <plugin> | ||
89 | + <groupId>org.thingsboard</groupId> | ||
90 | + <artifactId>gradle-maven-plugin</artifactId> | ||
91 | + </plugin> | ||
92 | + <plugin> | ||
93 | + <groupId>org.apache.maven.plugins</groupId> | ||
94 | + <artifactId>maven-assembly-plugin</artifactId> | ||
95 | + </plugin> | ||
96 | + <plugin> | ||
97 | + <groupId>org.apache.maven.plugins</groupId> | ||
98 | + <artifactId>maven-install-plugin</artifactId> | ||
99 | + </plugin> | ||
100 | + </plugins> | ||
101 | + </build> | ||
102 | + <repositories> | ||
103 | + <repository> | ||
104 | + <id>jenkins</id> | ||
105 | + <name>Jenkins Repository</name> | ||
106 | + <url>https://repo.jenkins-ci.org/releases</url> | ||
107 | + <snapshots> | ||
108 | + <enabled>false</enabled> | ||
109 | + </snapshots> | ||
110 | + </repository> | ||
111 | + </repositories> | ||
112 | +</project> |
transport/snmp/src/main/conf/logback.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
2 | +<!-- | ||
3 | + | ||
4 | + Copyright © 2016-2021 The Thingsboard Authors | ||
5 | + | ||
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + you may not use this file except in compliance with the License. | ||
8 | + You may obtain a copy of the License at | ||
9 | + | ||
10 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + | ||
12 | + Unless required by applicable law or agreed to in writing, software | ||
13 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + See the License for the specific language governing permissions and | ||
16 | + limitations under the License. | ||
17 | + | ||
18 | +--> | ||
19 | +<!DOCTYPE configuration> | ||
20 | +<configuration> | ||
21 | + | ||
22 | + <appender name="fileLogAppender" | ||
23 | + class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
24 | + <file>${pkg.logFolder}/${pkg.name}.log</file> | ||
25 | + <rollingPolicy | ||
26 | + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | ||
27 | + <fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> | ||
28 | + <maxFileSize>100MB</maxFileSize> | ||
29 | + <maxHistory>30</maxHistory> | ||
30 | + <totalSizeCap>3GB</totalSizeCap> | ||
31 | + </rollingPolicy> | ||
32 | + <encoder> | ||
33 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
34 | + </encoder> | ||
35 | + </appender> | ||
36 | + | ||
37 | + <logger name="org.thingsboard.server" level="INFO" /> | ||
38 | + | ||
39 | + <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" /> | ||
40 | + | ||
41 | + <root level="INFO"> | ||
42 | + <appender-ref ref="fileLogAppender"/> | ||
43 | + </root> | ||
44 | + | ||
45 | +</configuration> |
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 | + | ||
17 | +export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=@pkg.logFolder@/gc.log:time,uptime,level,tags:filecount=10,filesize=10M" | ||
18 | +export JAVA_OPTS="$JAVA_OPTS -XX:+IgnoreUnrecognizedVMOptions -XX:+HeapDumpOnOutOfMemoryError" | ||
19 | +export JAVA_OPTS="$JAVA_OPTS -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark" | ||
20 | +export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10" | ||
21 | +export LOG_FILENAME=${pkg.name}.out | ||
22 | +export LOADER_PATH=${pkg.installFolder}/conf |
transport/snmp/src/main/java/org/thingsboard/server/snmp/ThingsboardSnmpTransportApplication.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.snmp; | ||
17 | + | ||
18 | +import org.springframework.boot.SpringApplication; | ||
19 | +import org.springframework.boot.SpringBootConfiguration; | ||
20 | +import org.springframework.context.annotation.ComponentScan; | ||
21 | +import org.springframework.scheduling.annotation.EnableAsync; | ||
22 | +import org.springframework.scheduling.annotation.EnableScheduling; | ||
23 | + | ||
24 | +import java.util.Arrays; | ||
25 | + | ||
26 | +@SpringBootConfiguration | ||
27 | +@EnableAsync | ||
28 | +@EnableScheduling | ||
29 | +@ComponentScan({"org.thingsboard.server.snmp", "org.thingsboard.server.common", "org.thingsboard.server.transport.snmp", "org.thingsboard.server.queue"}) | ||
30 | +public class ThingsboardSnmpTransportApplication { | ||
31 | + | ||
32 | + private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name"; | ||
33 | + private static final String DEFAULT_SPRING_CONFIG_PARAM = SPRING_CONFIG_NAME_KEY + "=" + "tb-snmp-transport"; | ||
34 | + | ||
35 | + public static void main(String[] args) { | ||
36 | + SpringApplication.run(ThingsboardSnmpTransportApplication.class, updateArguments(args)); | ||
37 | + } | ||
38 | + | ||
39 | + private static String[] updateArguments(String[] args) { | ||
40 | + if (Arrays.stream(args).noneMatch(arg -> arg.startsWith(SPRING_CONFIG_NAME_KEY))) { | ||
41 | + String[] modifiedArgs = new String[args.length + 1]; | ||
42 | + System.arraycopy(args, 0, modifiedArgs, 0, args.length); | ||
43 | + modifiedArgs[args.length] = DEFAULT_SPRING_CONFIG_PARAM; | ||
44 | + return modifiedArgs; | ||
45 | + } | ||
46 | + return args; | ||
47 | + } | ||
48 | +} |
1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
2 | +<!-- | ||
3 | + | ||
4 | + Copyright © 2016-2021 The Thingsboard Authors | ||
5 | + | ||
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + you may not use this file except in compliance with the License. | ||
8 | + You may obtain a copy of the License at | ||
9 | + | ||
10 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + | ||
12 | + Unless required by applicable law or agreed to in writing, software | ||
13 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + See the License for the specific language governing permissions and | ||
16 | + limitations under the License. | ||
17 | + | ||
18 | +--> | ||
19 | +<!DOCTYPE configuration> | ||
20 | +<configuration scan="true" scanPeriod="10 seconds"> | ||
21 | + | ||
22 | + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
23 | + <encoder> | ||
24 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
25 | + </encoder> | ||
26 | + </appender> | ||
27 | + | ||
28 | + <logger name="org.thingsboard.server" level="TRACE" /> | ||
29 | + | ||
30 | + <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" /> | ||
31 | + | ||
32 | + <root level="INFO"> | ||
33 | + <appender-ref ref="STDOUT"/> | ||
34 | + </root> | ||
35 | + | ||
36 | +</configuration> |
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 | + | ||
17 | +# Zookeeper connection parameters. Used for service discovery. | ||
18 | +zk: | ||
19 | + # Enable/disable zookeeper discovery service. | ||
20 | + enabled: "${ZOOKEEPER_ENABLED:false}" | ||
21 | + # Zookeeper connect string | ||
22 | + url: "${ZOOKEEPER_URL:localhost:2181}" | ||
23 | + # Zookeeper retry interval in milliseconds | ||
24 | + retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" | ||
25 | + # Zookeeper connection timeout in milliseconds | ||
26 | + connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" | ||
27 | + # Zookeeper session timeout in milliseconds | ||
28 | + session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" | ||
29 | + # Name of the directory in zookeeper 'filesystem' | ||
30 | + zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" | ||
31 | + | ||
32 | +transport: | ||
33 | + snmp: | ||
34 | + enabled: "${SNMP_ENABLED:true}" | ||
35 | + response_processing: | ||
36 | + # parallelism level for executor (workStealingPool) that is responsible for handling responses from SNMP devices | ||
37 | + parallelism_level: "${SNMP_RESPONSE_PROCESSING_PARALLELISM_LEVEL:20}" | ||
38 | + # to configure SNMP to work over UDP or TCP | ||
39 | + underlying_protocol: "${SNMP_UNDERLYING_PROTOCOL:udp}" | ||
40 | + sessions: | ||
41 | + inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" | ||
42 | + report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}" | ||
43 | + json: | ||
44 | + # Cast String data types to Numeric if possible when processing Telemetry/Attributes JSON | ||
45 | + type_cast_enabled: "${JSON_TYPE_CAST_ENABLED:true}" | ||
46 | + # Maximum allowed string value length when processing Telemetry/Attributes JSON (0 value disables string value length check) | ||
47 | + max_string_value_length: "${JSON_MAX_STRING_VALUE_LENGTH:0}" | ||
48 | + | ||
49 | +queue: | ||
50 | + type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) | ||
51 | + kafka: | ||
52 | + bootstrap.servers: "${TB_KAFKA_SERVERS:localhost:9092}" | ||
53 | + acks: "${TB_KAFKA_ACKS:all}" | ||
54 | + retries: "${TB_KAFKA_RETRIES:1}" | ||
55 | + batch.size: "${TB_KAFKA_BATCH_SIZE:16384}" | ||
56 | + linger.ms: "${TB_KAFKA_LINGER_MS:1}" | ||
57 | + buffer.memory: "${TB_BUFFER_MEMORY:33554432}" | ||
58 | + replication_factor: "${TB_QUEUE_KAFKA_REPLICATION_FACTOR:1}" | ||
59 | + use_confluent_cloud: "${TB_QUEUE_KAFKA_USE_CONFLUENT_CLOUD:false}" | ||
60 | + confluent: | ||
61 | + ssl.algorithm: "${TB_QUEUE_KAFKA_CONFLUENT_SSL_ALGORITHM:https}" | ||
62 | + sasl.mechanism: "${TB_QUEUE_KAFKA_CONFLUENT_SASL_MECHANISM:PLAIN}" | ||
63 | + sasl.config: "${TB_QUEUE_KAFKA_CONFLUENT_SASL_JAAS_CONFIG:org.apache.kafka.common.security.plain.PlainLoginModule required username=\"CLUSTER_API_KEY\" password=\"CLUSTER_API_SECRET\";}" | ||
64 | + security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}" | ||
65 | + other: | ||
66 | + topic-properties: | ||
67 | + rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" | ||
68 | + core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" | ||
69 | + transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" | ||
70 | + notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}" | ||
71 | + js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100;min.insync.replicas:1}" | ||
72 | + consumer-stats: | ||
73 | + enabled: "${TB_QUEUE_KAFKA_CONSUMER_STATS_ENABLED:true}" | ||
74 | + print-interval-ms: "${TB_QUEUE_KAFKA_CONSUMER_STATS_MIN_PRINT_INTERVAL_MS:60000}" | ||
75 | + kafka-response-timeout-ms: "${TB_QUEUE_KAFKA_CONSUMER_STATS_RESPONSE_TIMEOUT_MS:1000}" | ||
76 | + aws_sqs: | ||
77 | + use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}" | ||
78 | + access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}" | ||
79 | + secret_access_key: "${TB_QUEUE_AWS_SQS_SECRET_ACCESS_KEY:YOUR_SECRET}" | ||
80 | + region: "${TB_QUEUE_AWS_SQS_REGION:YOUR_REGION}" | ||
81 | + threads_per_topic: "${TB_QUEUE_AWS_SQS_THREADS_PER_TOPIC:1}" | ||
82 | + queue-properties: | ||
83 | + rule-engine: "${TB_QUEUE_AWS_SQS_RE_QUEUE_PROPERTIES:VisibilityTimeout:30;MaximumMessageSize:262144;MessageRetentionPeriod:604800}" | ||
84 | + core: "${TB_QUEUE_AWS_SQS_CORE_QUEUE_PROPERTIES:VisibilityTimeout:30;MaximumMessageSize:262144;MessageRetentionPeriod:604800}" | ||
85 | + transport-api: "${TB_QUEUE_AWS_SQS_TA_QUEUE_PROPERTIES:VisibilityTimeout:30;MaximumMessageSize:262144;MessageRetentionPeriod:604800}" | ||
86 | + notifications: "${TB_QUEUE_AWS_SQS_NOTIFICATIONS_QUEUE_PROPERTIES:VisibilityTimeout:30;MaximumMessageSize:262144;MessageRetentionPeriod:604800}" | ||
87 | + js-executor: "${TB_QUEUE_AWS_SQS_JE_QUEUE_PROPERTIES:VisibilityTimeout:30;MaximumMessageSize:262144;MessageRetentionPeriod:604800}" | ||
88 | + # VisibilityTimeout in seconds;MaximumMessageSize in bytes;MessageRetentionPeriod in seconds | ||
89 | + pubsub: | ||
90 | + project_id: "${TB_QUEUE_PUBSUB_PROJECT_ID:YOUR_PROJECT_ID}" | ||
91 | + service_account: "${TB_QUEUE_PUBSUB_SERVICE_ACCOUNT:YOUR_SERVICE_ACCOUNT}" | ||
92 | + max_msg_size: "${TB_QUEUE_PUBSUB_MAX_MSG_SIZE:1048576}" #in bytes | ||
93 | + max_messages: "${TB_QUEUE_PUBSUB_MAX_MESSAGES:1000}" | ||
94 | + queue-properties: | ||
95 | + rule-engine: "${TB_QUEUE_PUBSUB_RE_QUEUE_PROPERTIES:ackDeadlineInSec:30;messageRetentionInSec:604800}" | ||
96 | + core: "${TB_QUEUE_PUBSUB_CORE_QUEUE_PROPERTIES:ackDeadlineInSec:30;messageRetentionInSec:604800}" | ||
97 | + transport-api: "${TB_QUEUE_PUBSUB_TA_QUEUE_PROPERTIES:ackDeadlineInSec:30;messageRetentionInSec:604800}" | ||
98 | + notifications: "${TB_QUEUE_PUBSUB_NOTIFICATIONS_QUEUE_PROPERTIES:ackDeadlineInSec:30;messageRetentionInSec:604800}" | ||
99 | + js-executor: "${TB_QUEUE_PUBSUB_JE_QUEUE_PROPERTIES:ackDeadlineInSec:30;messageRetentionInSec:604800}" | ||
100 | + service_bus: | ||
101 | + namespace_name: "${TB_QUEUE_SERVICE_BUS_NAMESPACE_NAME:YOUR_NAMESPACE_NAME}" | ||
102 | + sas_key_name: "${TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME:YOUR_SAS_KEY_NAME}" | ||
103 | + sas_key: "${TB_QUEUE_SERVICE_BUS_SAS_KEY:YOUR_SAS_KEY}" | ||
104 | + max_messages: "${TB_QUEUE_SERVICE_BUS_MAX_MESSAGES:1000}" | ||
105 | + queue-properties: | ||
106 | + rule-engine: "${TB_QUEUE_SERVICE_BUS_RE_QUEUE_PROPERTIES:lockDurationInSec:30;maxSizeInMb:1024;messageTimeToLiveInSec:604800}" | ||
107 | + core: "${TB_QUEUE_SERVICE_BUS_CORE_QUEUE_PROPERTIES:lockDurationInSec:30;maxSizeInMb:1024;messageTimeToLiveInSec:604800}" | ||
108 | + transport-api: "${TB_QUEUE_SERVICE_BUS_TA_QUEUE_PROPERTIES:lockDurationInSec:30;maxSizeInMb:1024;messageTimeToLiveInSec:604800}" | ||
109 | + notifications: "${TB_QUEUE_SERVICE_BUS_NOTIFICATIONS_QUEUE_PROPERTIES:lockDurationInSec:30;maxSizeInMb:1024;messageTimeToLiveInSec:604800}" | ||
110 | + js-executor: "${TB_QUEUE_SERVICE_BUS_JE_QUEUE_PROPERTIES:lockDurationInSec:30;maxSizeInMb:1024;messageTimeToLiveInSec:604800}" | ||
111 | + rabbitmq: | ||
112 | + exchange_name: "${TB_QUEUE_RABBIT_MQ_EXCHANGE_NAME:}" | ||
113 | + host: "${TB_QUEUE_RABBIT_MQ_HOST:localhost}" | ||
114 | + port: "${TB_QUEUE_RABBIT_MQ_PORT:5672}" | ||
115 | + virtual_host: "${TB_QUEUE_RABBIT_MQ_VIRTUAL_HOST:/}" | ||
116 | + username: "${TB_QUEUE_RABBIT_MQ_USERNAME:YOUR_USERNAME}" | ||
117 | + password: "${TB_QUEUE_RABBIT_MQ_PASSWORD:YOUR_PASSWORD}" | ||
118 | + automatic_recovery_enabled: "${TB_QUEUE_RABBIT_MQ_AUTOMATIC_RECOVERY_ENABLED:false}" | ||
119 | + connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" | ||
120 | + handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" | ||
121 | + queue-properties: | ||
122 | + rule-engine: "${TB_QUEUE_RABBIT_MQ_RE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" | ||
123 | + core: "${TB_QUEUE_RABBIT_MQ_CORE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" | ||
124 | + transport-api: "${TB_QUEUE_RABBIT_MQ_TA_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" | ||
125 | + notifications: "${TB_QUEUE_RABBIT_MQ_NOTIFICATIONS_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" | ||
126 | + js-executor: "${TB_QUEUE_RABBIT_MQ_JE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" | ||
127 | + partitions: | ||
128 | + hash_function_name: "${TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" | ||
129 | + virtual_nodes_size: "${TB_QUEUE_PARTITIONS_VIRTUAL_NODES_SIZE:16}" | ||
130 | + transport_api: | ||
131 | + requests_topic: "${TB_QUEUE_TRANSPORT_API_REQUEST_TOPIC:tb_transport.api.requests}" | ||
132 | + responses_topic: "${TB_QUEUE_TRANSPORT_API_RESPONSE_TOPIC:tb_transport.api.responses}" | ||
133 | + max_pending_requests: "${TB_QUEUE_TRANSPORT_MAX_PENDING_REQUESTS:10000}" | ||
134 | + max_requests_timeout: "${TB_QUEUE_TRANSPORT_MAX_REQUEST_TIMEOUT:10000}" | ||
135 | + max_callback_threads: "${TB_QUEUE_TRANSPORT_MAX_CALLBACK_THREADS:100}" | ||
136 | + request_poll_interval: "${TB_QUEUE_TRANSPORT_REQUEST_POLL_INTERVAL_MS:25}" | ||
137 | + response_poll_interval: "${TB_QUEUE_TRANSPORT_RESPONSE_POLL_INTERVAL_MS:25}" | ||
138 | + core: | ||
139 | + topic: "${TB_QUEUE_CORE_TOPIC:tb_core}" | ||
140 | + poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" | ||
141 | + partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" | ||
142 | + pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
143 | + usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}" | ||
144 | + stats: | ||
145 | + enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" | ||
146 | + print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" | ||
147 | + js: | ||
148 | + # JS Eval request topic | ||
149 | + request_topic: "${REMOTE_JS_EVAL_REQUEST_TOPIC:js_eval.requests}" | ||
150 | + # JS Eval responses topic prefix that is combined with node id | ||
151 | + response_topic_prefix: "${REMOTE_JS_EVAL_RESPONSE_TOPIC:js_eval.responses}" | ||
152 | + # JS Eval max pending requests | ||
153 | + max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" | ||
154 | + # JS Eval max request timeout | ||
155 | + max_requests_timeout: "${REMOTE_JS_MAX_REQUEST_TIMEOUT:10000}" | ||
156 | + # JS response poll interval | ||
157 | + response_poll_interval: "${REMOTE_JS_RESPONSE_POLL_INTERVAL_MS:25}" | ||
158 | + rule-engine: | ||
159 | + topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb_rule_engine}" | ||
160 | + poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" | ||
161 | + pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
162 | + stats: | ||
163 | + enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | ||
164 | + print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" | ||
165 | + queues: | ||
166 | + - name: "${TB_QUEUE_RE_MAIN_QUEUE_NAME:Main}" | ||
167 | + topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" | ||
168 | + poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" | ||
169 | + partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" | ||
170 | + pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
171 | + submit-strategy: | ||
172 | + type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
173 | + # For BATCH only | ||
174 | + batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch | ||
175 | + processing-strategy: | ||
176 | + type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:SKIP_ALL_FAILURES}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
177 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
178 | + retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | ||
179 | + failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
180 | + pause-between-retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries; | ||
181 | + - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" | ||
182 | + topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | ||
183 | + poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | ||
184 | + partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" | ||
185 | + pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
186 | + submit-strategy: | ||
187 | + type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
188 | + # For BATCH only | ||
189 | + batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | ||
190 | + processing-strategy: | ||
191 | + type: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
192 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
193 | + retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited | ||
194 | + failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
195 | + pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | ||
196 | + - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" | ||
197 | + topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | ||
198 | + poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | ||
199 | + partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" | ||
200 | + pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
201 | + submit-strategy: | ||
202 | + type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
203 | + # For BATCH only | ||
204 | + batch-size: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | ||
205 | + processing-strategy: | ||
206 | + type: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
207 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
208 | + retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | ||
209 | + failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
210 | + pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | ||
211 | + transport: | ||
212 | + # For high priority notifications that require minimum latency and processing time | ||
213 | + notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" | ||
214 | + poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" | ||
215 | + | ||
216 | +service: | ||
217 | + type: "${TB_SERVICE_TYPE:tb-transport}" | ||
218 | + # Unique id for this service (autogenerated if empty) | ||
219 | + id: "${TB_SERVICE_ID:}" | ||
220 | + tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id. | ||
221 | + | ||
222 | +metrics: | ||
223 | + # Enable/disable actuator metrics. | ||
224 | + enabled: "${METRICS_ENABLED:false}" | ||
225 | + | ||
226 | +management: | ||
227 | + endpoints: | ||
228 | + web: | ||
229 | + exposure: | ||
230 | + # Expose metrics endpoint (use value 'prometheus' to enable prometheus metrics). | ||
231 | + include: '${METRICS_ENDPOINTS_EXPOSE:info}' |
@@ -98,6 +98,7 @@ import { DeviceProfileDialogComponent } from '@home/components/profile/device-pr | @@ -98,6 +98,7 @@ import { DeviceProfileDialogComponent } from '@home/components/profile/device-pr | ||
98 | import { DeviceProfileAutocompleteComponent } from '@home/components/profile/device-profile-autocomplete.component'; | 98 | import { DeviceProfileAutocompleteComponent } from '@home/components/profile/device-profile-autocomplete.component'; |
99 | import { MqttDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/mqtt-device-profile-transport-configuration.component'; | 99 | import { MqttDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/mqtt-device-profile-transport-configuration.component'; |
100 | import { CoapDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/coap-device-profile-transport-configuration.component'; | 100 | import { CoapDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/coap-device-profile-transport-configuration.component'; |
101 | +import { SnmpDeviceProfileTransportConfigurationComponent } from '@home/components/profile/device/snmp-device-profile-transport-configuration.component'; | ||
101 | import { DeviceProfileAlarmsComponent } from '@home/components/profile/alarm/device-profile-alarms.component'; | 102 | import { DeviceProfileAlarmsComponent } from '@home/components/profile/alarm/device-profile-alarms.component'; |
102 | import { DeviceProfileAlarmComponent } from '@home/components/profile/alarm/device-profile-alarm.component'; | 103 | import { DeviceProfileAlarmComponent } from '@home/components/profile/alarm/device-profile-alarm.component'; |
103 | import { CreateAlarmRulesComponent } from '@home/components/profile/alarm/create-alarm-rules.component'; | 104 | import { CreateAlarmRulesComponent } from '@home/components/profile/alarm/create-alarm-rules.component'; |
@@ -220,6 +221,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag | @@ -220,6 +221,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag | ||
220 | DefaultDeviceProfileTransportConfigurationComponent, | 221 | DefaultDeviceProfileTransportConfigurationComponent, |
221 | MqttDeviceProfileTransportConfigurationComponent, | 222 | MqttDeviceProfileTransportConfigurationComponent, |
222 | CoapDeviceProfileTransportConfigurationComponent, | 223 | CoapDeviceProfileTransportConfigurationComponent, |
224 | + SnmpDeviceProfileTransportConfigurationComponent, | ||
223 | DeviceProfileTransportConfigurationComponent, | 225 | DeviceProfileTransportConfigurationComponent, |
224 | CreateAlarmRulesComponent, | 226 | CreateAlarmRulesComponent, |
225 | AlarmRuleComponent, | 227 | AlarmRuleComponent, |
@@ -325,6 +327,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag | @@ -325,6 +327,7 @@ import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-pag | ||
325 | DefaultDeviceProfileTransportConfigurationComponent, | 327 | DefaultDeviceProfileTransportConfigurationComponent, |
326 | MqttDeviceProfileTransportConfigurationComponent, | 328 | MqttDeviceProfileTransportConfigurationComponent, |
327 | CoapDeviceProfileTransportConfigurationComponent, | 329 | CoapDeviceProfileTransportConfigurationComponent, |
330 | + SnmpDeviceProfileTransportConfigurationComponent, | ||
328 | DeviceProfileTransportConfigurationComponent, | 331 | DeviceProfileTransportConfigurationComponent, |
329 | CreateAlarmRulesComponent, | 332 | CreateAlarmRulesComponent, |
330 | AlarmRuleComponent, | 333 | AlarmRuleComponent, |
@@ -41,5 +41,11 @@ | @@ -41,5 +41,11 @@ | ||
41 | formControlName="configuration"> | 41 | formControlName="configuration"> |
42 | </tb-profile-lwm2m-device-transport-configuration> | 42 | </tb-profile-lwm2m-device-transport-configuration> |
43 | </ng-template> | 43 | </ng-template> |
44 | + <ng-template [ngSwitchCase]="deviceTransportType.SNMP"> | ||
45 | + <tb-snmp-device-profile-transport-configuration | ||
46 | + [required]="required" | ||
47 | + formControlName="configuration"> | ||
48 | + </tb-snmp-device-profile-transport-configuration> | ||
49 | + </ng-template> | ||
44 | </div> | 50 | </div> |
45 | </div> | 51 | </div> |
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 | +<form [formGroup]="snmpDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;"> | ||
19 | + <tb-json-object-edit | ||
20 | + required | ||
21 | + formControlName="configuration"> | ||
22 | + </tb-json-object-edit> | ||
23 | +</form> |
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 | + | ||
17 | +import {Component, forwardRef, Input, OnInit} from '@angular/core'; | ||
18 | +import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators} from '@angular/forms'; | ||
19 | +import {Store} from '@ngrx/store'; | ||
20 | +import {AppState} from '@app/core/core.state'; | ||
21 | +import {coerceBooleanProperty} from '@angular/cdk/coercion'; | ||
22 | +import { | ||
23 | + DeviceProfileTransportConfiguration, | ||
24 | + DeviceTransportType, | ||
25 | + SnmpDeviceProfileTransportConfiguration | ||
26 | +} from '@shared/models/device.models'; | ||
27 | +import {isDefinedAndNotNull} from "@core/utils"; | ||
28 | + | ||
29 | +export interface OidMappingConfiguration { | ||
30 | + isAttribute: boolean; | ||
31 | + key: string; | ||
32 | + type: string; | ||
33 | + method: string; | ||
34 | + oid: string; | ||
35 | +} | ||
36 | + | ||
37 | +@Component({ | ||
38 | + selector: 'tb-snmp-device-profile-transport-configuration', | ||
39 | + templateUrl: './snmp-device-profile-transport-configuration.component.html', | ||
40 | + styleUrls: [], | ||
41 | + providers: [{ | ||
42 | + provide: NG_VALUE_ACCESSOR, | ||
43 | + useExisting: forwardRef(() => SnmpDeviceProfileTransportConfigurationComponent), | ||
44 | + multi: true | ||
45 | + }] | ||
46 | +}) | ||
47 | +export class SnmpDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit { | ||
48 | + snmpDeviceProfileTransportConfigurationFormGroup: FormGroup; | ||
49 | + private requiredValue: boolean; | ||
50 | + private configuration = []; | ||
51 | + | ||
52 | + get required(): boolean { | ||
53 | + return this.requiredValue; | ||
54 | + } | ||
55 | + | ||
56 | + @Input() | ||
57 | + set required(value: boolean) { | ||
58 | + this.requiredValue = coerceBooleanProperty(value); | ||
59 | + } | ||
60 | + | ||
61 | + @Input() | ||
62 | + disabled: boolean; | ||
63 | + | ||
64 | + private propagateChange = (v: any) => { | ||
65 | + } | ||
66 | + | ||
67 | + constructor(private store: Store<AppState>, private fb: FormBuilder) { | ||
68 | + } | ||
69 | + | ||
70 | + ngOnInit(): void { | ||
71 | + this.snmpDeviceProfileTransportConfigurationFormGroup = this.fb.group({ | ||
72 | + configuration: [null, Validators.required] | ||
73 | + }); | ||
74 | + this.snmpDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { | ||
75 | + this.updateModel(); | ||
76 | + }); | ||
77 | + } | ||
78 | + | ||
79 | + registerOnChange(fn: any): void { | ||
80 | + this.propagateChange = fn; | ||
81 | + } | ||
82 | + | ||
83 | + registerOnTouched(fn: any): void { | ||
84 | + } | ||
85 | + | ||
86 | + writeValue(value: SnmpDeviceProfileTransportConfiguration | null): void { | ||
87 | + if (isDefinedAndNotNull(value)) { | ||
88 | + this.snmpDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
92 | + private updateModel() { | ||
93 | + let configuration: DeviceProfileTransportConfiguration = null; | ||
94 | + if (this.snmpDeviceProfileTransportConfigurationFormGroup.valid) { | ||
95 | + configuration = this.snmpDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration; | ||
96 | + configuration.type = DeviceTransportType.SNMP; | ||
97 | + } | ||
98 | + this.propagateChange(configuration); | ||
99 | + } | ||
100 | +} |
@@ -41,5 +41,11 @@ | @@ -41,5 +41,11 @@ | ||
41 | formControlName="configuration"> | 41 | formControlName="configuration"> |
42 | </tb-coap-device-transport-configuration> | 42 | </tb-coap-device-transport-configuration> |
43 | </ng-template> | 43 | </ng-template> |
44 | + <ng-template [ngSwitchCase]="deviceTransportType.SNMP"> | ||
45 | + <tb-snmp-device-transport-configuration | ||
46 | + [required]="required" | ||
47 | + formControlName="configuration"> | ||
48 | + </tb-snmp-device-transport-configuration> | ||
49 | + </ng-template> | ||
44 | </div> | 50 | </div> |
45 | </div> | 51 | </div> |
ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.html
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 | +<form [formGroup]="snmpDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;"> | ||
19 | + <tb-json-object-edit | ||
20 | + [required]="required" | ||
21 | + label="{{ 'device-profile.transport-type-snmp-hint' | translate }}" | ||
22 | + formControlName="configuration"> | ||
23 | + </tb-json-object-edit> | ||
24 | +</form> |
ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.ts
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 | + | ||
17 | +import {Component, forwardRef, Input, OnInit} from '@angular/core'; | ||
18 | +import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators} from '@angular/forms'; | ||
19 | +import {Store} from '@ngrx/store'; | ||
20 | +import {AppState} from '@app/core/core.state'; | ||
21 | +import {coerceBooleanProperty} from '@angular/cdk/coercion'; | ||
22 | +import { | ||
23 | + DeviceTransportConfiguration, | ||
24 | + DeviceTransportType, | ||
25 | + SnmpDeviceTransportConfiguration | ||
26 | +} from '@shared/models/device.models'; | ||
27 | + | ||
28 | +@Component({ | ||
29 | + selector: 'tb-snmp-device-transport-configuration', | ||
30 | + templateUrl: './snmp-device-transport-configuration.component.html', | ||
31 | + styleUrls: [], | ||
32 | + providers: [{ | ||
33 | + provide: NG_VALUE_ACCESSOR, | ||
34 | + useExisting: forwardRef(() => SnmpDeviceTransportConfigurationComponent), | ||
35 | + multi: true | ||
36 | + }] | ||
37 | +}) | ||
38 | +export class SnmpDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { | ||
39 | + | ||
40 | + snmpDeviceTransportConfigurationFormGroup: FormGroup; | ||
41 | + | ||
42 | + private requiredValue: boolean; | ||
43 | + | ||
44 | + get required(): boolean { | ||
45 | + return this.requiredValue; | ||
46 | + } | ||
47 | + | ||
48 | + @Input() | ||
49 | + set required(value: boolean) { | ||
50 | + this.requiredValue = coerceBooleanProperty(value); | ||
51 | + } | ||
52 | + | ||
53 | + @Input() | ||
54 | + disabled: boolean; | ||
55 | + | ||
56 | + private propagateChange = (v: any) => { | ||
57 | + }; | ||
58 | + | ||
59 | + constructor(private store: Store<AppState>, | ||
60 | + private fb: FormBuilder) { | ||
61 | + } | ||
62 | + | ||
63 | + registerOnChange(fn: any): void { | ||
64 | + this.propagateChange = fn; | ||
65 | + } | ||
66 | + | ||
67 | + registerOnTouched(fn: any): void { | ||
68 | + } | ||
69 | + | ||
70 | + ngOnInit() { | ||
71 | + this.snmpDeviceTransportConfigurationFormGroup = this.fb.group({ | ||
72 | + configuration: [null, Validators.required] | ||
73 | + }); | ||
74 | + this.snmpDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => { | ||
75 | + this.updateModel(); | ||
76 | + }); | ||
77 | + } | ||
78 | + | ||
79 | + setDisabledState(isDisabled: boolean): void { | ||
80 | + this.disabled = isDisabled; | ||
81 | + if (this.disabled) { | ||
82 | + this.snmpDeviceTransportConfigurationFormGroup.disable({emitEvent: false}); | ||
83 | + } else { | ||
84 | + this.snmpDeviceTransportConfigurationFormGroup.enable({emitEvent: false}); | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + writeValue(value: SnmpDeviceTransportConfiguration | null): void { | ||
89 | + this.snmpDeviceTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); | ||
90 | + } | ||
91 | + | ||
92 | + private updateModel() { | ||
93 | + let configuration: DeviceTransportConfiguration = null; | ||
94 | + if (this.snmpDeviceTransportConfigurationFormGroup.valid) { | ||
95 | + configuration = this.snmpDeviceTransportConfigurationFormGroup.getRawValue().configuration; | ||
96 | + configuration.type = DeviceTransportType.SNMP; | ||
97 | + } | ||
98 | + this.propagateChange(configuration); | ||
99 | + } | ||
100 | +} |
@@ -32,8 +32,9 @@ import { DeviceDataComponent } from './data/device-data.component'; | @@ -32,8 +32,9 @@ import { DeviceDataComponent } from './data/device-data.component'; | ||
32 | import { DefaultDeviceTransportConfigurationComponent } from './data/default-device-transport-configuration.component'; | 32 | import { DefaultDeviceTransportConfigurationComponent } from './data/default-device-transport-configuration.component'; |
33 | import { DeviceTransportConfigurationComponent } from './data/device-transport-configuration.component'; | 33 | import { DeviceTransportConfigurationComponent } from './data/device-transport-configuration.component'; |
34 | import { MqttDeviceTransportConfigurationComponent } from './data/mqtt-device-transport-configuration.component'; | 34 | import { MqttDeviceTransportConfigurationComponent } from './data/mqtt-device-transport-configuration.component'; |
35 | -import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component'; | ||
36 | import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-transport-configuration.component'; | 35 | import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-transport-configuration.component'; |
36 | +import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component'; | ||
37 | +import { SnmpDeviceTransportConfigurationComponent } from './data/snmp-device-transport-configuration.component'; | ||
37 | 38 | ||
38 | @NgModule({ | 39 | @NgModule({ |
39 | declarations: [ | 40 | declarations: [ |
@@ -41,8 +42,9 @@ import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-tr | @@ -41,8 +42,9 @@ import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-tr | ||
41 | DeviceConfigurationComponent, | 42 | DeviceConfigurationComponent, |
42 | DefaultDeviceTransportConfigurationComponent, | 43 | DefaultDeviceTransportConfigurationComponent, |
43 | MqttDeviceTransportConfigurationComponent, | 44 | MqttDeviceTransportConfigurationComponent, |
44 | - Lwm2mDeviceTransportConfigurationComponent, | ||
45 | CoapDeviceTransportConfigurationComponent, | 45 | CoapDeviceTransportConfigurationComponent, |
46 | + Lwm2mDeviceTransportConfigurationComponent, | ||
47 | + SnmpDeviceTransportConfigurationComponent, | ||
46 | DeviceTransportConfigurationComponent, | 48 | DeviceTransportConfigurationComponent, |
47 | DeviceDataComponent, | 49 | DeviceDataComponent, |
48 | DeviceComponent, | 50 | DeviceComponent, |
@@ -30,14 +30,16 @@ import { AbstractControl, ValidationErrors } from '@angular/forms'; | @@ -30,14 +30,16 @@ import { AbstractControl, ValidationErrors } from '@angular/forms'; | ||
30 | import { FirmwareId } from '@shared/models/id/firmware-id'; | 30 | import { FirmwareId } from '@shared/models/id/firmware-id'; |
31 | 31 | ||
32 | export enum DeviceProfileType { | 32 | export enum DeviceProfileType { |
33 | - DEFAULT = 'DEFAULT' | 33 | + DEFAULT = 'DEFAULT', |
34 | + SNMP = 'SNMP' | ||
34 | } | 35 | } |
35 | 36 | ||
36 | export enum DeviceTransportType { | 37 | export enum DeviceTransportType { |
37 | DEFAULT = 'DEFAULT', | 38 | DEFAULT = 'DEFAULT', |
38 | MQTT = 'MQTT', | 39 | MQTT = 'MQTT', |
39 | COAP = 'COAP', | 40 | COAP = 'COAP', |
40 | - LWM2M = 'LWM2M' | 41 | + LWM2M = 'LWM2M', |
42 | + SNMP = 'SNMP' | ||
41 | } | 43 | } |
42 | 44 | ||
43 | export enum TransportPayloadType { | 45 | export enum TransportPayloadType { |
@@ -75,6 +77,13 @@ export const deviceProfileTypeConfigurationInfoMap = new Map<DeviceProfileType, | @@ -75,6 +77,13 @@ export const deviceProfileTypeConfigurationInfoMap = new Map<DeviceProfileType, | ||
75 | hasProfileConfiguration: false, | 77 | hasProfileConfiguration: false, |
76 | hasDeviceConfiguration: false, | 78 | hasDeviceConfiguration: false, |
77 | } | 79 | } |
80 | + ], | ||
81 | + [ | ||
82 | + DeviceProfileType.SNMP, | ||
83 | + { | ||
84 | + hasProfileConfiguration: true, | ||
85 | + hasDeviceConfiguration: true, | ||
86 | + } | ||
78 | ] | 87 | ] |
79 | ] | 88 | ] |
80 | ); | 89 | ); |
@@ -84,7 +93,8 @@ export const deviceTransportTypeTranslationMap = new Map<DeviceTransportType, st | @@ -84,7 +93,8 @@ export const deviceTransportTypeTranslationMap = new Map<DeviceTransportType, st | ||
84 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default'], | 93 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default'], |
85 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt'], | 94 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt'], |
86 | [DeviceTransportType.COAP, 'device-profile.transport-type-coap'], | 95 | [DeviceTransportType.COAP, 'device-profile.transport-type-coap'], |
87 | - [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m'] | 96 | + [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m'], |
97 | + [DeviceTransportType.SNMP, 'device-profile.transport-type-snmp'] | ||
88 | ] | 98 | ] |
89 | ); | 99 | ); |
90 | 100 | ||
@@ -102,7 +112,8 @@ export const deviceTransportTypeHintMap = new Map<DeviceTransportType, string>( | @@ -102,7 +112,8 @@ export const deviceTransportTypeHintMap = new Map<DeviceTransportType, string>( | ||
102 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default-hint'], | 112 | [DeviceTransportType.DEFAULT, 'device-profile.transport-type-default-hint'], |
103 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt-hint'], | 113 | [DeviceTransportType.MQTT, 'device-profile.transport-type-mqtt-hint'], |
104 | [DeviceTransportType.COAP, 'device-profile.transport-type-coap-hint'], | 114 | [DeviceTransportType.COAP, 'device-profile.transport-type-coap-hint'], |
105 | - [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m-hint'] | 115 | + [DeviceTransportType.LWM2M, 'device-profile.transport-type-lwm2m-hint'], |
116 | + [DeviceTransportType.SNMP, 'device-profile.transport-type-snmp-hint'] | ||
106 | ] | 117 | ] |
107 | ); | 118 | ); |
108 | 119 | ||
@@ -196,6 +207,13 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy | @@ -196,6 +207,13 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy | ||
196 | hasProfileConfiguration: true, | 207 | hasProfileConfiguration: true, |
197 | hasDeviceConfiguration: false, | 208 | hasDeviceConfiguration: false, |
198 | } | 209 | } |
210 | + ], | ||
211 | + [ | ||
212 | + DeviceTransportType.SNMP, | ||
213 | + { | ||
214 | + hasProfileConfiguration: true, | ||
215 | + hasDeviceConfiguration: true | ||
216 | + } | ||
199 | ] | 217 | ] |
200 | ] | 218 | ] |
201 | ); | 219 | ); |
@@ -237,10 +255,15 @@ export interface Lwm2mDeviceProfileTransportConfiguration { | @@ -237,10 +255,15 @@ export interface Lwm2mDeviceProfileTransportConfiguration { | ||
237 | [key: string]: any; | 255 | [key: string]: any; |
238 | } | 256 | } |
239 | 257 | ||
258 | +export interface SnmpDeviceProfileTransportConfiguration { | ||
259 | + [key: string]: any; | ||
260 | +} | ||
261 | + | ||
240 | export type DeviceProfileTransportConfigurations = DefaultDeviceProfileTransportConfiguration & | 262 | export type DeviceProfileTransportConfigurations = DefaultDeviceProfileTransportConfiguration & |
241 | MqttDeviceProfileTransportConfiguration & | 263 | MqttDeviceProfileTransportConfiguration & |
242 | CoapDeviceProfileTransportConfiguration & | 264 | CoapDeviceProfileTransportConfiguration & |
243 | - Lwm2mDeviceProfileTransportConfiguration; | 265 | + Lwm2mDeviceProfileTransportConfiguration & |
266 | + SnmpDeviceProfileTransportConfiguration; | ||
244 | 267 | ||
245 | export interface DeviceProfileTransportConfiguration extends DeviceProfileTransportConfigurations { | 268 | export interface DeviceProfileTransportConfiguration extends DeviceProfileTransportConfigurations { |
246 | type: DeviceTransportType; | 269 | type: DeviceTransportType; |
@@ -307,6 +330,10 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | @@ -307,6 +330,10 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | ||
307 | const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {}; | 330 | const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {}; |
308 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; | 331 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; |
309 | break; | 332 | break; |
333 | + case DeviceTransportType.SNMP: | ||
334 | + const snmpTransportConfiguration: SnmpDeviceProfileTransportConfiguration = {}; | ||
335 | + transportConfiguration = {...snmpTransportConfiguration, type: DeviceTransportType.SNMP}; | ||
336 | + break; | ||
310 | } | 337 | } |
311 | } | 338 | } |
312 | return transportConfiguration; | 339 | return transportConfiguration; |
@@ -332,6 +359,10 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D | @@ -332,6 +359,10 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D | ||
332 | const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {}; | 359 | const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {}; |
333 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; | 360 | transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; |
334 | break; | 361 | break; |
362 | + case DeviceTransportType.SNMP: | ||
363 | + const snmpTransportConfiguration: SnmpDeviceTransportConfiguration = {}; | ||
364 | + transportConfiguration = {...snmpTransportConfiguration, type: DeviceTransportType.SNMP}; | ||
365 | + break; | ||
335 | } | 366 | } |
336 | } | 367 | } |
337 | return transportConfiguration; | 368 | return transportConfiguration; |
@@ -501,10 +532,15 @@ export interface Lwm2mDeviceTransportConfiguration { | @@ -501,10 +532,15 @@ export interface Lwm2mDeviceTransportConfiguration { | ||
501 | [key: string]: any; | 532 | [key: string]: any; |
502 | } | 533 | } |
503 | 534 | ||
535 | +export interface SnmpDeviceTransportConfiguration { | ||
536 | + [key: string]: any; | ||
537 | +} | ||
538 | + | ||
504 | export type DeviceTransportConfigurations = DefaultDeviceTransportConfiguration & | 539 | export type DeviceTransportConfigurations = DefaultDeviceTransportConfiguration & |
505 | MqttDeviceTransportConfiguration & | 540 | MqttDeviceTransportConfiguration & |
506 | CoapDeviceTransportConfiguration & | 541 | CoapDeviceTransportConfiguration & |
507 | - Lwm2mDeviceTransportConfiguration; | 542 | + Lwm2mDeviceTransportConfiguration & |
543 | + SnmpDeviceTransportConfiguration; | ||
508 | 544 | ||
509 | export interface DeviceTransportConfiguration extends DeviceTransportConfigurations { | 545 | export interface DeviceTransportConfiguration extends DeviceTransportConfigurations { |
510 | type: DeviceTransportType; | 546 | type: DeviceTransportType; |
@@ -1025,10 +1025,12 @@ | @@ -1025,10 +1025,12 @@ | ||
1025 | "transport-type-default-hint": "Supports basic MQTT, HTTP and CoAP transport", | 1025 | "transport-type-default-hint": "Supports basic MQTT, HTTP and CoAP transport", |
1026 | "transport-type-mqtt": "MQTT", | 1026 | "transport-type-mqtt": "MQTT", |
1027 | "transport-type-mqtt-hint": "Enables advanced MQTT transport settings", | 1027 | "transport-type-mqtt-hint": "Enables advanced MQTT transport settings", |
1028 | - "transport-type-lwm2m": "LWM2M", | ||
1029 | - "transport-type-lwm2m-hint": "LWM2M transport type", | ||
1030 | "transport-type-coap": "CoAP", | 1028 | "transport-type-coap": "CoAP", |
1031 | "transport-type-coap-hint": "Enables advanced CoAP transport settings", | 1029 | "transport-type-coap-hint": "Enables advanced CoAP transport settings", |
1030 | + "transport-type-lwm2m": "LWM2M", | ||
1031 | + "transport-type-lwm2m-hint": "LWM2M transport type", | ||
1032 | + "transport-type-snmp": "SNMP", | ||
1033 | + "transport-type-snmp-hint": "Specify SNMP transport configuration", | ||
1032 | "description": "Description", | 1034 | "description": "Description", |
1033 | "default": "Default", | 1035 | "default": "Default", |
1034 | "profile-configuration": "Profile configuration", | 1036 | "profile-configuration": "Profile configuration", |
@@ -1046,6 +1048,15 @@ | @@ -1046,6 +1048,15 @@ | ||
1046 | "mqtt-device-topic-filters": "MQTT device topic filters", | 1048 | "mqtt-device-topic-filters": "MQTT device topic filters", |
1047 | "mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.", | 1049 | "mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.", |
1048 | "mqtt-device-payload-type": "MQTT device payload", | 1050 | "mqtt-device-payload-type": "MQTT device payload", |
1051 | + "mqtt-device-payload-type-json": "JSON", | ||
1052 | + "mqtt-device-payload-type-proto": "Protobuf", | ||
1053 | + "snmp-add-mapping": "Add SNMP mapping", | ||
1054 | + "snmp-mapping-not-configured": "No mapping for OID to timeseries/telemetry configured", | ||
1055 | + "snmp-timseries-or-attribute-name": "Timeseries/attribute name for mapping", | ||
1056 | + "snmp-timseries-or-attribute-type": "Timeseries/attribute type for mapping", | ||
1057 | + "snmp-method-pdu-type-get-request": "GetRequest", | ||
1058 | + "snmp-method-pdu-type-get-next-request": "GetNextRequest", | ||
1059 | + "snmp-oid": "OID", | ||
1049 | "transport-device-payload-type-json": "JSON", | 1060 | "transport-device-payload-type-json": "JSON", |
1050 | "transport-device-payload-type-proto": "Protobuf", | 1061 | "transport-device-payload-type-proto": "Protobuf", |
1051 | "mqtt-payload-type-required": "Payload type is required.", | 1062 | "mqtt-payload-type-required": "Payload type is required.", |