Commit 783b959577be49cbf020f379e09a0043dfcd95a9

Authored by Viacheslav Klimov
1 parent 415bf570

Refactor

Showing 16 changed files with 454 additions and 234 deletions
... ... @@ -17,16 +17,11 @@ package org.thingsboard.server.common.data.device.profile;
17 17
18 18 import com.fasterxml.jackson.annotation.JsonIgnore;
19 19 import lombok.Data;
20   -import org.apache.commons.lang3.ArrayUtils;
21 20 import org.thingsboard.server.common.data.DeviceTransportType;
22 21 import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
23   -import org.thingsboard.server.common.data.transport.snmp.configs.SnmpCommunicationConfig;
  22 +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
24 23
25   -import java.util.Collections;
26 24 import java.util.List;
27   -import java.util.function.Function;
28   -import java.util.stream.Collectors;
29   -import java.util.stream.Stream;
30 25
31 26 @Data
32 27 public class SnmpDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
... ... @@ -51,7 +46,7 @@ public class SnmpDeviceProfileTransportConfiguration implements DeviceProfileTra
51 46 return timeoutMs != null && timeoutMs >= 0 && retries != null && retries >= 0
52 47 && communicationConfigs != null && !communicationConfigs.isEmpty()
53 48 && communicationConfigs.stream().allMatch(config -> config != null && config.isValid())
54   - && communicationConfigs.stream().flatMap(config -> config.getMappings().stream()).map(SnmpMapping::getOid)
55   - .distinct().count() == communicationConfigs.stream().mapToInt(config -> config.getMappings().size()).sum();
  49 + && communicationConfigs.stream().flatMap(config -> config.getAllMappings().stream()).map(SnmpMapping::getOid)
  50 + .distinct().count() == communicationConfigs.stream().mapToInt(config -> config.getAllMappings().size()).sum();
56 51 }
57 52 }
... ...
... ... @@ -16,22 +16,11 @@
16 16 package org.thingsboard.server.common.data.transport.snmp;
17 17
18 18 public enum SnmpCommunicationSpec {
19   - TELEMETRY_QUERYING(true),
20   - CLIENT_ATTRIBUTES_QUERYING(true),
  19 + TELEMETRY_QUERYING,
21 20
22   - SHARED_ATTRIBUTES_SETTING;
  21 + CLIENT_ATTRIBUTES_QUERYING,
  22 + SHARED_ATTRIBUTES_SETTING,
23 23
24   - private final boolean isRepeatingQuerying;
25   -
26   - SnmpCommunicationSpec() {
27   - this.isRepeatingQuerying = false;
28   - }
29   -
30   - SnmpCommunicationSpec(boolean isRepeatingQuerying) {
31   - this.isRepeatingQuerying = isRepeatingQuerying;
32   - }
33   -
34   - public boolean isRepeatingQuerying() {
35   - return isRepeatingQuerying;
36   - }
  24 + TO_DEVICE_RPC_COMMAND_SETTING,
  25 + TO_DEVICE_RPC_RESPONSE_QUERYING
37 26 }
... ...
... ... @@ -16,13 +16,17 @@
16 16 package org.thingsboard.server.common.data.transport.snmp;
17 17
18 18 import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import lombok.AllArgsConstructor;
19 20 import lombok.Data;
  21 +import lombok.NoArgsConstructor;
20 22 import org.apache.commons.lang3.StringUtils;
21 23 import org.thingsboard.server.common.data.kv.DataType;
22 24
23 25 import java.util.regex.Pattern;
24 26
25 27 @Data
  28 +@AllArgsConstructor
  29 +@NoArgsConstructor
26 30 public class SnmpMapping {
27 31 private String oid;
28 32 private String key;
... ... @@ -32,7 +36,6 @@ public class SnmpMapping {
32 36
33 37 @JsonIgnore
34 38 public boolean isValid() {
35   - return StringUtils.isNotEmpty(oid) && OID_PATTERN.matcher(oid).matches() &&
36   - StringUtils.isNotBlank(key) && dataType != null;
  39 + return StringUtils.isNotEmpty(oid) && OID_PATTERN.matcher(oid).matches() && StringUtils.isNotBlank(key);
37 40 }
38 41 }
... ...
  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 +}
... ...
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/RepeatingQueryingSnmpCommunicationConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/RepeatingQueryingSnmpCommunicationConfig.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.transport.snmp.configs;
  16 +package org.thingsboard.server.common.data.transport.snmp.config;
17 17
18 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
... ... @@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.transport.snmp.SnmpMethod;
21 21
22 22 @EqualsAndHashCode(callSuper = true)
23 23 @Data
24   -public abstract class RepeatingQueryingSnmpCommunicationConfig extends SnmpCommunicationConfig {
  24 +public abstract class RepeatingQueryingSnmpCommunicationConfig extends MultipleMappingsSnmpCommunicationConfig {
25 25 private Long queryingFrequencyMs;
26 26
27 27 @Override
... ... @@ -31,6 +31,6 @@ public abstract class RepeatingQueryingSnmpCommunicationConfig extends SnmpCommu
31 31
32 32 @Override
33 33 public boolean isValid() {
34   - return super.isValid() && queryingFrequencyMs != null && queryingFrequencyMs > 0;
  34 + return queryingFrequencyMs != null && queryingFrequencyMs > 0 && super.isValid();
35 35 }
36 36 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/SnmpCommunicationConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/SnmpCommunicationConfig.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.transport.snmp.configs;
  16 +package org.thingsboard.server.common.data.transport.snmp.config;
17 17
18 18 import com.fasterxml.jackson.annotation.JsonIgnore;
19 19 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
... ... @@ -23,6 +23,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
23 23 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
24 24 import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
25 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;
26 29
27 30 import java.util.List;
28 31
... ... @@ -33,22 +36,19 @@ import java.util.List;
33 36 @Type(value = ClientAttributesQueryingSnmpCommunicationConfig.class, name = "CLIENT_ATTRIBUTES_QUERYING"),
34 37 @Type(value = SharedAttributesSettingSnmpCommunicationConfig.class, name = "SHARED_ATTRIBUTES_SETTING")
35 38 })
36   -public abstract class SnmpCommunicationConfig {
37   - protected List<SnmpMapping> mappings;
  39 +public interface SnmpCommunicationConfig {
38 40
39   - public List<SnmpMapping> getMappings() {
40   - return mappings;
41   - }
42   -
43   - public abstract SnmpCommunicationSpec getSpec();
  41 + SnmpCommunicationSpec getSpec();
44 42
45 43 @JsonIgnore
46   - public SnmpMethod getMethod() {
  44 + default SnmpMethod getMethod() {
47 45 return null;
48 46 }
49 47
50 48 @JsonIgnore
51   - public boolean isValid() {
52   - return mappings != null && !mappings.isEmpty() && mappings.stream().allMatch(mapping -> mapping != null && mapping.isValid());
53   - }
  49 + List<SnmpMapping> getAllMappings();
  50 +
  51 + @JsonIgnore
  52 + boolean isValid();
  53 +
54 54 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ClientAttributesQueryingSnmpCommunicationConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/ClientAttributesQueryingSnmpCommunicationConfig.java
... ... @@ -13,13 +13,16 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.transport.snmp.configs;
  16 +package org.thingsboard.server.common.data.transport.snmp.config.impl;
17 17
18 18 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
  19 +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig;
19 20
20 21 public class ClientAttributesQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig {
  22 +
21 23 @Override
22 24 public SnmpCommunicationSpec getSpec() {
23 25 return SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING;
24 26 }
  27 +
25 28 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/SharedAttributesSettingSnmpCommunicationConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/SharedAttributesSettingSnmpCommunicationConfig.java
... ... @@ -13,12 +13,14 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.transport.snmp.configs;
  16 +package org.thingsboard.server.common.data.transport.snmp.config.impl;
17 17
18 18 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
19 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 {
20 23
21   -public class SharedAttributesSettingSnmpCommunicationConfig extends SnmpCommunicationConfig {
22 24 @Override
23 25 public SnmpCommunicationSpec getSpec() {
24 26 return SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING;
... ... @@ -28,4 +30,5 @@ public class SharedAttributesSettingSnmpCommunicationConfig extends SnmpCommunic
28 30 public SnmpMethod getMethod() {
29 31 return SnmpMethod.SET;
30 32 }
  33 +
31 34 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/TelemetryQueryingSnmpCommunicationConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/TelemetryQueryingSnmpCommunicationConfig.java
... ... @@ -13,17 +13,20 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.transport.snmp.configs;
  16 +package org.thingsboard.server.common.data.transport.snmp.config.impl;
17 17
18 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20 20 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
  21 +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig;
21 22
22 23 @EqualsAndHashCode(callSuper = true)
23 24 @Data
24 25 public class TelemetryQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig {
  26 +
25 27 @Override
26 28 public SnmpCommunicationSpec getSpec() {
27 29 return SnmpCommunicationSpec.TELEMETRY_QUERYING;
28 30 }
  31 +
29 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.impl;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.kv.DataType;
  20 +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
  21 +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
  22 +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod;
  23 +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
  24 +
  25 +import java.util.Arrays;
  26 +import java.util.Collections;
  27 +import java.util.List;
  28 +
  29 +@Data
  30 +public class ToDeviceRpcCommandSettingSnmpCommunicationConfig implements SnmpCommunicationConfig {
  31 + private SnmpMapping mapping;
  32 +
  33 + @Override
  34 + public SnmpCommunicationSpec getSpec() {
  35 + return SnmpCommunicationSpec.TO_DEVICE_RPC_COMMAND_SETTING;
  36 + }
  37 +
  38 + @Override
  39 + public SnmpMethod getMethod() {
  40 + return SnmpMethod.SET;
  41 + }
  42 +
  43 + public void setMapping(SnmpMapping mapping) {
  44 + this.mapping = mapping != null ? new SnmpMapping(mapping.getOid(), RPC_COMMAND_KEY_NAME, DataType.STRING) : null;
  45 + }
  46 +
  47 + @Override
  48 + public List<SnmpMapping> getAllMappings() {
  49 + return Collections.singletonList(mapping);
  50 + }
  51 +
  52 + @Override
  53 + public boolean isValid() {
  54 + return mapping != null && mapping.isValid();
  55 + }
  56 +
  57 + public static final String RPC_COMMAND_KEY_NAME = "rpcCommand";
  58 +
  59 +}
... ...
  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.kv.DataType;
  21 +import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
  22 +import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
  23 +import org.thingsboard.server.common.data.transport.snmp.SnmpMethod;
  24 +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig;
  25 +
  26 +import java.util.Collections;
  27 +import java.util.List;
  28 +
  29 +@EqualsAndHashCode(callSuper = true)
  30 +@Data
  31 +public class ToDeviceRpcResponseQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig {
  32 + private SnmpMapping mapping;
  33 +
  34 + @Override
  35 + public SnmpCommunicationSpec getSpec() {
  36 + return SnmpCommunicationSpec.TO_DEVICE_RPC_RESPONSE_QUERYING;
  37 + }
  38 +
  39 + @Override
  40 + public SnmpMethod getMethod() {
  41 + return SnmpMethod.GET;
  42 + }
  43 +
  44 + public void setMapping(SnmpMapping mapping) {
  45 + this.mapping = mapping != null ? new SnmpMapping(mapping.getOid(), RPC_RESPONSE_KEY_NAME, DataType.STRING) : null;
  46 + }
  47 +
  48 + @Override
  49 + public List<SnmpMapping> getAllMappings() {
  50 + return Collections.singletonList(mapping);
  51 + }
  52 +
  53 + @Override
  54 + public boolean isValid() {
  55 + return true;
  56 + }
  57 +
  58 + public static final String RPC_RESPONSE_KEY_NAME = "rpcResponse";
  59 +
  60 +}
... ...
... ... @@ -42,6 +42,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
42 42 import org.thingsboard.server.queue.util.AfterStartUp;
43 43 import org.thingsboard.server.queue.util.TbSnmpTransportComponent;
44 44 import org.thingsboard.server.transport.snmp.service.ProtoTransportEntityService;
  45 +import org.thingsboard.server.transport.snmp.service.SnmpAuthService;
45 46 import org.thingsboard.server.transport.snmp.service.SnmpTransportBalancingService;
46 47 import org.thingsboard.server.transport.snmp.service.SnmpTransportService;
47 48 import org.thingsboard.server.transport.snmp.session.DeviceSessionContext;
... ... @@ -116,7 +117,7 @@ public class SnmpTransportContext extends TransportContext {
116 117 );
117 118 registerSessionMsgListener(deviceSessionContext);
118 119 } catch (Exception e) {
119   - log.error("Failed to establish session for SNMP device {}: {}", device.getId(), e.getMessage());
  120 + log.error("Failed to establish session for SNMP device {}: {}", device.getId(), e.toString());
120 121 return;
121 122 }
122 123 sessions.put(device.getId(), deviceSessionContext);
... ... @@ -177,7 +178,9 @@ public class SnmpTransportContext extends TransportContext {
177 178 );
178 179
179 180 transportService.registerAsyncSession(sessionInfo, deviceSessionContext);
180   - transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
  181 + transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), TransportServiceCallback.EMPTY);
  182 + transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), TransportServiceCallback.EMPTY);
  183 +
181 184 deviceSessionContext.setSessionInfo(sessionInfo);
182 185 deviceSessionContext.setDeviceInfo(msg.getDeviceInfo());
183 186 } else {
... ...
  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.SnmpProtocolVersion;
  33 +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
  34 +import org.thingsboard.server.queue.util.TbSnmpTransportComponent;
  35 +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext;
  36 +
  37 +import java.util.HashMap;
  38 +import java.util.List;
  39 +import java.util.Map;
  40 +import java.util.Objects;
  41 +import java.util.Optional;
  42 +import java.util.stream.Collectors;
  43 +import java.util.stream.IntStream;
  44 +
  45 +@TbSnmpTransportComponent
  46 +@Service
  47 +@Slf4j
  48 +public class PduMapper {
  49 + public PDU createPdu(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) {
  50 + PDU pdu;
  51 + SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration();
  52 + SnmpProtocolVersion snmpVersion = deviceTransportConfiguration.getProtocolVersion();
  53 + switch (snmpVersion) {
  54 + case V1:
  55 + case V2C:
  56 + pdu = new PDU();
  57 + break;
  58 + case V3:
  59 + ScopedPDU scopedPdu = new ScopedPDU();
  60 + scopedPdu.setContextName(new OctetString(deviceTransportConfiguration.getContextName()));
  61 + scopedPdu.setContextEngineID(new OctetString(deviceTransportConfiguration.getEngineId()));
  62 + pdu = scopedPdu;
  63 + break;
  64 + default:
  65 + throw new UnsupportedOperationException("SNMP version " + snmpVersion + " is not supported");
  66 + }
  67 +
  68 + pdu.setType(communicationConfig.getMethod().getCode());
  69 + pdu.addAll(communicationConfig.getAllMappings().stream()
  70 + .filter(mapping -> values.isEmpty() || values.containsKey(mapping.getKey()))
  71 + .map(mapping -> Optional.ofNullable(values.get(mapping.getKey()))
  72 + .map(value -> {
  73 + Variable variable = toSnmpVariable(mapping, value);
  74 + return new VariableBinding(new OID(mapping.getOid()), variable);
  75 + })
  76 + .orElseGet(() -> new VariableBinding(new OID(mapping.getOid()))))
  77 + .collect(Collectors.toList()));
  78 +
  79 + return pdu;
  80 + }
  81 +
  82 + private Variable toSnmpVariable(SnmpMapping mapping, String value) {
  83 + Variable variable;
  84 + switch (mapping.getDataType()) {
  85 + case LONG:
  86 + try {
  87 + variable = new Integer32(Integer.parseInt(value));
  88 + break;
  89 + } catch (NumberFormatException ignored) {
  90 + }
  91 + case DOUBLE:
  92 + case BOOLEAN:
  93 + case STRING:
  94 + case JSON:
  95 + default:
  96 + variable = new OctetString(value);
  97 + }
  98 + return variable;
  99 + }
  100 +
  101 +
  102 + public JsonObject processPdu(PDU pdu, DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) {
  103 + List<VariableBinding> variablesBindings = IntStream.range(0, pdu.size())
  104 + .mapToObj(pdu::get)
  105 + .filter(Objects::nonNull)
  106 + .filter(variableBinding -> !(variableBinding.getVariable() instanceof Null))
  107 + .collect(Collectors.toList());
  108 + JsonObject data = new JsonObject();
  109 +
  110 + Map<OID, SnmpMapping> mappings = new HashMap<>();
  111 + for (SnmpMapping mapping : communicationConfig.getAllMappings()) {
  112 + OID oid = new OID(mapping.getOid());
  113 + mappings.put(oid, mapping);
  114 + }
  115 +
  116 + variablesBindings.forEach(variableBinding -> {
  117 + log.trace("Processing variable binding: {}", variableBinding);
  118 +
  119 + OID oid = variableBinding.getOid();
  120 + SnmpMapping mapping = mappings.get(oid);
  121 + if (mapping == null) {
  122 + log.debug("No SNMP mapping for oid {}", oid);
  123 + return;
  124 + }
  125 +
  126 + processValue(mapping.getKey(), mapping.getDataType(), variableBinding.toValueString(), data);
  127 + });
  128 +
  129 + return data;
  130 + }
  131 +
  132 +
  133 + private void processValue(String key, DataType dataType, String value, JsonObject result) {
  134 + switch (dataType) {
  135 + case LONG:
  136 + result.addProperty(key, Long.parseLong(value));
  137 + break;
  138 + case BOOLEAN:
  139 + result.addProperty(key, Boolean.parseBoolean(value));
  140 + break;
  141 + case DOUBLE:
  142 + result.addProperty(key, Double.parseDouble(value));
  143 + break;
  144 + case STRING:
  145 + case JSON:
  146 + default:
  147 + result.addProperty(key, value);
  148 + }
  149 + }
  150 +}
... ...
common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpAuthService.java renamed from common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/SnmpAuthService.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.transport.snmp;
  16 +package org.thingsboard.server.transport.snmp.service;
17 17
18 18 import lombok.RequiredArgsConstructor;
19 19 import org.snmp4j.AbstractTarget;
... ... @@ -24,6 +24,7 @@ import org.snmp4j.security.SecurityLevel;
24 24 import org.snmp4j.security.SecurityModel;
25 25 import org.snmp4j.security.SecurityProtocols;
26 26 import org.snmp4j.security.USM;
  27 +import org.snmp4j.smi.Address;
27 28 import org.snmp4j.smi.GenericAddress;
28 29 import org.snmp4j.smi.OID;
29 30 import org.snmp4j.smi.OctetString;
... ... @@ -36,6 +37,8 @@ import org.thingsboard.server.queue.util.TbSnmpTransportComponent;
36 37 import org.thingsboard.server.transport.snmp.service.SnmpTransportService;
37 38 import org.thingsboard.server.transport.snmp.session.DeviceSessionContext;
38 39
  40 +import java.util.Optional;
  41 +
39 42 @Service
40 43 @TbSnmpTransportComponent
41 44 @RequiredArgsConstructor
... ... @@ -97,7 +100,8 @@ public class SnmpAuthService {
97 100 throw new UnsupportedOperationException("SNMP protocol version " + protocolVersion + " is not supported");
98 101 }
99 102
100   - target.setAddress(GenericAddress.parse(snmpUnderlyingProtocol + ":" + deviceTransportConfig.getHost() + "/" + deviceTransportConfig.getPort()));
  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")));
101 105 target.setTimeout(profileTransportConfig.getTimeoutMs());
102 106 target.setRetries(profileTransportConfig.getRetries());
103 107 target.setVersion(protocolVersion.getCode());
... ...
... ... @@ -16,11 +16,11 @@
16 16 package org.thingsboard.server.transport.snmp.service;
17 17
18 18 import com.google.gson.JsonObject;
  19 +import lombok.Data;
19 20 import lombok.Getter;
  21 +import lombok.RequiredArgsConstructor;
20 22 import lombok.extern.slf4j.Slf4j;
21   -import org.apache.commons.lang3.StringUtils;
22 23 import org.snmp4j.PDU;
23   -import org.snmp4j.ScopedPDU;
24 24 import org.snmp4j.Snmp;
25 25 import org.snmp4j.TransportMapping;
26 26 import org.snmp4j.event.ResponseEvent;
... ... @@ -28,26 +28,18 @@ import org.snmp4j.mp.MPv3;
28 28 import org.snmp4j.security.SecurityModels;
29 29 import org.snmp4j.security.SecurityProtocols;
30 30 import org.snmp4j.security.USM;
31   -import org.snmp4j.smi.Integer32;
32   -import org.snmp4j.smi.Null;
33   -import org.snmp4j.smi.OID;
34 31 import org.snmp4j.smi.OctetString;
35   -import org.snmp4j.smi.Variable;
36   -import org.snmp4j.smi.VariableBinding;
37 32 import org.snmp4j.transport.DefaultTcpTransportMapping;
38 33 import org.snmp4j.transport.DefaultUdpTransportMapping;
39 34 import org.springframework.beans.factory.annotation.Value;
40 35 import org.springframework.stereotype.Service;
41 36 import org.thingsboard.common.util.ThingsBoardThreadFactory;
42 37 import org.thingsboard.server.common.data.TbTransportService;
43   -import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
44 38 import org.thingsboard.server.common.data.id.DeviceProfileId;
45   -import org.thingsboard.server.common.data.kv.DataType;
46 39 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
47   -import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
48   -import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;
49   -import org.thingsboard.server.common.data.transport.snmp.configs.RepeatingQueryingSnmpCommunicationConfig;
50   -import org.thingsboard.server.common.data.transport.snmp.configs.SnmpCommunicationConfig;
  40 +import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryingSnmpCommunicationConfig;
  41 +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
  42 +import org.thingsboard.server.common.data.transport.snmp.config.impl.ToDeviceRpcResponseQueryingSnmpCommunicationConfig;
51 43 import org.thingsboard.server.common.transport.TransportService;
52 44 import org.thingsboard.server.common.transport.TransportServiceCallback;
53 45 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
... ... @@ -60,44 +52,37 @@ import javax.annotation.PreDestroy;
60 52 import java.io.IOException;
61 53 import java.util.Collections;
62 54 import java.util.EnumMap;
63   -import java.util.HashMap;
64 55 import java.util.List;
65 56 import java.util.Map;
66   -import java.util.Optional;
67 57 import java.util.concurrent.ExecutorService;
68 58 import java.util.concurrent.Executors;
69 59 import java.util.concurrent.ScheduledExecutorService;
70 60 import java.util.concurrent.ScheduledFuture;
71 61 import java.util.concurrent.TimeUnit;
72   -import java.util.function.BiConsumer;
73 62 import java.util.stream.Collectors;
74 63
75 64 @TbSnmpTransportComponent
76 65 @Service
77 66 @Slf4j
  67 +@RequiredArgsConstructor
78 68 public class SnmpTransportService implements TbTransportService {
79 69 private final TransportService transportService;
  70 + private final PduMapper pduMapper;
80 71
81 72 @Getter
82 73 private Snmp snmp;
83 74 private ScheduledExecutorService queryingExecutor;
84 75 private ExecutorService responseProcessingExecutor;
85 76
86   - private final Map<SnmpCommunicationSpec, BiConsumer<JsonObject, DeviceSessionContext>> responseProcessors = new EnumMap<>(SnmpCommunicationSpec.class);
  77 + private final Map<SnmpCommunicationSpec, ResponseProcessor> responseProcessors = new EnumMap<>(SnmpCommunicationSpec.class);
87 78
88 79 @Value("${transport.snmp.response_processing.parallelism_level}")
89 80 private Integer responseProcessingParallelismLevel;
90 81 @Value("${transport.snmp.underlying_protocol}")
91 82 private String snmpUnderlyingProtocol;
92 83
93   - public SnmpTransportService(TransportService transportService) {
94   - this.transportService = transportService;
95   - }
96   -
97 84 @PostConstruct
98 85 private void init() throws IOException {
99   - log.info("Initializing SNMP transport service");
100   -
101 86 queryingExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), ThingsBoardThreadFactory.forName("snmp-querying"));
102 87 responseProcessingExecutor = Executors.newWorkStealingPool(responseProcessingParallelismLevel);
103 88
... ... @@ -128,26 +113,23 @@ public class SnmpTransportService implements TbTransportService {
128 113
129 114 public void createQueryingTasks(DeviceSessionContext sessionContext) {
130 115 List<ScheduledFuture<?>> queryingTasks = sessionContext.getProfileTransportConfiguration().getCommunicationConfigs().stream()
131   - .filter(config -> config.getSpec().isRepeatingQuerying())
  116 + .filter(communicationConfig -> communicationConfig instanceof RepeatingQueryingSnmpCommunicationConfig)
132 117 .map(config -> {
133 118 RepeatingQueryingSnmpCommunicationConfig repeatingCommunicationConfig = (RepeatingQueryingSnmpCommunicationConfig) config;
134   - return createQueryingTaskForConfig(sessionContext, repeatingCommunicationConfig);
  119 + Long queryingFrequency = repeatingCommunicationConfig.getQueryingFrequencyMs();
  120 +
  121 + return queryingExecutor.scheduleWithFixedDelay(() -> {
  122 + try {
  123 + if (sessionContext.isActive()) {
  124 + sendRequest(sessionContext, repeatingCommunicationConfig);
  125 + }
  126 + } catch (Exception e) {
  127 + log.error("Failed to send SNMP request for device {}: {}", sessionContext.getDeviceId(), e.toString());
  128 + }
  129 + }, queryingFrequency, queryingFrequency, TimeUnit.MILLISECONDS);
135 130 })
136 131 .collect(Collectors.toList());
137   - sessionContext.setQueryingTasks(queryingTasks);
138   - }
139   -
140   - private ScheduledFuture<?> createQueryingTaskForConfig(DeviceSessionContext sessionContext, RepeatingQueryingSnmpCommunicationConfig communicationConfig) {
141   - Long queryingFrequency = communicationConfig.getQueryingFrequencyMs();
142   - return queryingExecutor.scheduleWithFixedDelay(() -> {
143   - try {
144   - if (sessionContext.isActive()) {
145   - sendRequest(sessionContext, communicationConfig);
146   - }
147   - } catch (Exception e) {
148   - log.error("Failed to send SNMP request for device {}: {}", sessionContext.getDeviceId(), e.toString());
149   - }
150   - }, queryingFrequency, queryingFrequency, TimeUnit.MILLISECONDS);
  132 + sessionContext.getQueryingTasks().addAll(queryingTasks);
151 133 }
152 134
153 135 public void cancelQueryingTasks(DeviceSessionContext sessionContext) {
... ... @@ -155,67 +137,23 @@ public class SnmpTransportService implements TbTransportService {
155 137 sessionContext.getQueryingTasks().clear();
156 138 }
157 139
158   - public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) throws IOException {
  140 +
  141 + public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) {
159 142 sendRequest(sessionContext, communicationConfig, Collections.emptyMap());
160 143 }
161 144
162   - public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) throws IOException {
163   - PDU request = createPdu(sessionContext, communicationConfig, values);
164   - executeRequest(sessionContext, request);
165   - }
  145 + public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) {
  146 + PDU request = pduMapper.createPdu(sessionContext, communicationConfig, values);
166 147
167   - private void executeRequest(DeviceSessionContext sessionContext, PDU request) throws IOException {
168 148 if (request.size() > 0) {
169 149 log.trace("Executing SNMP request for device {}. Variables bindings: {}", sessionContext.getDeviceId(), request.getVariableBindings());
170   - snmp.send(request, sessionContext.getTarget(), sessionContext.getDeviceProfile().getId(), sessionContext);
171   - }
172   - }
173   -
174   - private PDU createPdu(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) {
175   - PDU pdu;
176   - SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration();
177   - SnmpProtocolVersion snmpVersion = deviceTransportConfiguration.getProtocolVersion();
178   - switch (snmpVersion) {
179   - case V1:
180   - case V2C:
181   - pdu = new PDU();
182   - break;
183   - case V3:
184   - ScopedPDU scopedPdu = new ScopedPDU();
185   - scopedPdu.setContextName(new OctetString(deviceTransportConfiguration.getContextName()));
186   - scopedPdu.setContextEngineID(new OctetString(deviceTransportConfiguration.getEngineId()));
187   - pdu = scopedPdu;
188   - break;
189   - default:
190   - throw new UnsupportedOperationException("SNMP version " + snmpVersion + " is not supported");
  150 + RequestInfo requestInfo = new RequestInfo(sessionContext.getDeviceProfile().getId(), communicationConfig);
  151 + try {
  152 + snmp.send(request, sessionContext.getTarget(), requestInfo, sessionContext);
  153 + } catch (IOException e) {
  154 + log.error("Failed to send SNMP request to device {}: {}", sessionContext.getDeviceId(), e.toString());
  155 + }
191 156 }
192   -
193   - pdu.setType(communicationConfig.getMethod().getCode());
194   - pdu.addAll(communicationConfig.getMappings().stream()
195   - .filter(mapping -> values.isEmpty() || values.containsKey(mapping.getKey()))
196   - .map(mapping -> Optional.ofNullable(values.get(mapping.getKey()))
197   - .map(value -> {
198   - Variable variable;
199   - switch (mapping.getDataType()) {
200   - case LONG:
201   - try {
202   - variable = new Integer32(Integer.parseInt(value));
203   - break;
204   - } catch (NumberFormatException ignored) {
205   - }
206   - case DOUBLE:
207   - case BOOLEAN:
208   - case STRING:
209   - case JSON:
210   - default:
211   - variable = new OctetString(value);
212   - }
213   - return new VariableBinding(new OID(mapping.getOid()), variable);
214   - })
215   - .orElseGet(() -> new VariableBinding(new OID(mapping.getOid()))))
216   - .collect(Collectors.toList()));
217   -
218   - return pdu;
219 157 }
220 158
221 159
... ... @@ -223,7 +161,7 @@ public class SnmpTransportService implements TbTransportService {
223 161 ((Snmp) event.getSource()).cancel(event.getRequest(), sessionContext);
224 162
225 163 if (event.getError() != null) {
226   - log.warn("Response error: {}", event.getError().getMessage(), event.getError());
  164 + log.warn("SNMP response error: {}", event.getError().toString());
227 165 return;
228 166 }
229 167
... ... @@ -232,108 +170,65 @@ public class SnmpTransportService implements TbTransportService {
232 170 log.debug("No response from SNMP device {}, requestId: {}", sessionContext.getDeviceId(), event.getRequest().getRequestID());
233 171 return;
234 172 }
235   - DeviceProfileId deviceProfileId = (DeviceProfileId) event.getUserObject();
236   - log.debug("[{}] Processing SNMP response for device {} with device profile {}: {}",
237   - response.getRequestID(), sessionContext.getDeviceId(), deviceProfileId, response);
238 173
239   - responseProcessingExecutor.execute(() -> processResponse(sessionContext, response));
  174 + RequestInfo requestInfo = (RequestInfo) event.getUserObject();
  175 + responseProcessingExecutor.execute(() -> {
  176 + processResponse(sessionContext, response, requestInfo);
  177 + });
240 178 }
241 179
242   - private void processResponse(DeviceSessionContext sessionContext, PDU responsePdu) {
243   - Map<OID, SnmpMapping> mappings = new HashMap<>();
244   - Map<OID, SnmpCommunicationConfig> configs = new HashMap<>();
245   - Map<SnmpCommunicationSpec, JsonObject> responses = new EnumMap<>(SnmpCommunicationSpec.class);
246   -
247   - for (SnmpCommunicationConfig config : sessionContext.getProfileTransportConfiguration().getCommunicationConfigs()) {
248   - for (SnmpMapping mapping : config.getMappings()) {
249   - OID oid = new OID(mapping.getOid());
250   - mappings.put(oid, mapping);
251   - configs.put(oid, config);
252   - }
253   - responses.put(config.getSpec(), new JsonObject());
254   - }
255   -
256   - for (int i = 0; i < responsePdu.size(); i++) {
257   - VariableBinding variableBinding = responsePdu.get(i);
258   - log.trace("Processing variable binding {}: {}", i, variableBinding);
259   -
260   - if (variableBinding.getVariable() instanceof Null) {
261   - log.debug("Response variable is empty");
262   - continue;
263   - }
264   -
265   - OID oid = variableBinding.getOid();
266   - if (!mappings.containsKey(oid)) {
267   - log.debug("No SNMP mapping for oid {}", oid);
268   - continue;
269   - }
270   -
271   - SnmpCommunicationSpec spec = configs.get(oid).getSpec();
272   - if (!responseProcessors.containsKey(spec)) {
273   - log.debug("No response processor found for spec {}", spec);
274   - continue;
275   - }
276   -
277   - SnmpMapping mapping = mappings.get(oid);
278   - processValue(mapping.getKey(), mapping.getDataType(), variableBinding.toValueString(), responses.get(spec));
  180 + private void processResponse(DeviceSessionContext sessionContext, PDU response, RequestInfo requestInfo) {
  181 + ResponseProcessor responseProcessor = responseProcessors.get(requestInfo.getCommunicationConfig().getSpec());
  182 + if (responseProcessor == null) {
  183 + return;
279 184 }
280 185
281   - if (responses.values().stream().allMatch(response -> response.entrySet().isEmpty())) {
282   - log.debug("No values is the SNMP response for device {}. Request id: {}", sessionContext.getDeviceId(), responsePdu.getRequestID());
  186 + JsonObject responseData = pduMapper.processPdu(response, sessionContext, requestInfo.getCommunicationConfig());
  187 + if (responseData.entrySet().isEmpty()) {
  188 + log.debug("No values is the SNMP response for device {}. Request id: {}", sessionContext.getDeviceId(), response.getRequestID());
283 189 return;
284 190 }
285 191
286   - responses.forEach((spec, response) -> {
287   - Optional.ofNullable(responseProcessors.get(spec))
288   - .ifPresent(responseProcessor -> {
289   - if (!response.entrySet().isEmpty()) {
290   - responseProcessor.accept(response, sessionContext);
291   - }
292   - });
293   - });
294   -
  192 + responseProcessor.process(responseData, sessionContext);
295 193 reportActivity(sessionContext.getSessionInfo());
296 194 }
297 195
298 196 private void configureResponseProcessors() {
299 197 responseProcessors.put(SnmpCommunicationSpec.TELEMETRY_QUERYING, (response, sessionContext) -> {
300 198 TransportProtos.PostTelemetryMsg postTelemetryMsg = JsonConverter.convertToTelemetryProto(response);
301   - transportService.process(sessionContext.getSessionInfo(), postTelemetryMsg, TransportServiceCallback.EMPTY);
302   - log.debug("Posted telemetry for device {}: {}", sessionContext.getDeviceId(), response);
  199 + transportService.process(sessionContext.getSessionInfo(), postTelemetryMsg, null);
  200 + log.debug("Posted telemetry for SNMP device {}: {}", sessionContext.getDeviceId(), response);
303 201 });
304 202
305 203 responseProcessors.put(SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING, (response, sessionContext) -> {
306 204 TransportProtos.PostAttributeMsg postAttributesMsg = JsonConverter.convertToAttributesProto(response);
307   - transportService.process(sessionContext.getSessionInfo(), postAttributesMsg, TransportServiceCallback.EMPTY);
308   - log.debug("Posted attributes for device {}: {}", sessionContext.getDeviceId(), response);
  205 + transportService.process(sessionContext.getSessionInfo(), postAttributesMsg, null);
  206 + log.debug("Posted attributes for SNMP device {}: {}", sessionContext.getDeviceId(), response);
  207 + });
  208 +
  209 + responseProcessors.put(SnmpCommunicationSpec.TO_DEVICE_RPC_RESPONSE_QUERYING, (response, sessionContext) -> {
  210 + String rpcResponse = response.get(ToDeviceRpcResponseQueryingSnmpCommunicationConfig.RPC_RESPONSE_KEY_NAME).getAsString();
  211 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
  212 + .setPayload(rpcResponse)
  213 + .build();
  214 + transportService.process(sessionContext.getSessionInfo(), rpcResponseMsg, null);
  215 + log.debug("Processed RPC response from device {}: {}", sessionContext.getDeviceId(), rpcResponse);
309 216 });
  217 +
  218 +// responseProcessors.put(, (response, sessionContext) -> {
  219 +// TransportProtos.ClaimDeviceMsg claimDeviceMsg = JsonConverter.convertToClaimDeviceProto(sessionContext.getDeviceId(), response);
  220 +// transportService.process(sessionContext.getSessionInfo(), claimDeviceMsg, null);
  221 +// });
310 222 }
311 223
312 224 private void reportActivity(TransportProtos.SessionInfoProto sessionInfo) {
313 225 transportService.process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder()
314   - .setAttributeSubscription(false)
315   - .setRpcSubscription(false)
  226 + .setAttributeSubscription(true)
  227 + .setRpcSubscription(true)
316 228 .setLastActivityTime(System.currentTimeMillis())
317 229 .build(), TransportServiceCallback.EMPTY);
318 230 }
319 231
320   - private void processValue(String key, DataType dataType, String value, JsonObject result) {
321   - if (StringUtils.isEmpty(value)) return;
322   -
323   - switch (dataType) {
324   - case LONG:
325   - result.addProperty(key, Long.parseLong(value));
326   - break;
327   - case BOOLEAN:
328   - result.addProperty(key, Boolean.parseBoolean(value));
329   - break;
330   - case DOUBLE:
331   - result.addProperty(key, Double.parseDouble(value));
332   - break;
333   - default:
334   - result.addProperty(key, value);
335   - }
336   - }
337 232
338 233 @Override
339 234 public String getName() {
... ... @@ -358,4 +253,15 @@ public class SnmpTransportService implements TbTransportService {
358 253 }
359 254 log.info("SNMP transport stopped!");
360 255 }
  256 +
  257 + @Data
  258 + private static class RequestInfo {
  259 + private final DeviceProfileId deviceProfileId;
  260 + private final SnmpCommunicationConfig communicationConfig;
  261 + }
  262 +
  263 + private interface ResponseProcessor {
  264 + void process(JsonObject responseData, DeviceSessionContext sessionContext);
  265 + }
  266 +
361 267 }
... ...
... ... @@ -27,6 +27,8 @@ import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfigu
27 27 import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
28 28 import org.thingsboard.server.common.data.id.DeviceId;
29 29 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
  30 +import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
  31 +import org.thingsboard.server.common.data.transport.snmp.config.impl.ToDeviceRpcCommandSettingSnmpCommunicationConfig;
30 32 import org.thingsboard.server.common.transport.SessionMsgListener;
31 33 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
32 34 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
... ... @@ -36,13 +38,13 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse
36 38 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
37 39 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
38 40 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
39   -import org.thingsboard.server.transport.snmp.SnmpAuthService;
40 41 import org.thingsboard.server.transport.snmp.SnmpTransportContext;
41   -import org.thingsboard.server.transport.snmp.service.SnmpTransportService;
42 42
  43 +import java.io.IOException;
43 44 import java.util.LinkedList;
44 45 import java.util.List;
45 46 import java.util.Map;
  47 +import java.util.Optional;
46 48 import java.util.UUID;
47 49 import java.util.concurrent.ScheduledFuture;
48 50 import java.util.concurrent.atomic.AtomicInteger;
... ... @@ -64,16 +66,12 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
64 66
65 67 private final SnmpTransportContext snmpTransportContext;
66 68
67   - @Getter
68   - @Setter
69   - private long previousRequestExecutedAt = 0;
70 69 private final AtomicInteger msgIdSeq = new AtomicInteger(0);
71 70 @Getter
72 71 private boolean isActive = true;
73 72
74 73 @Getter
75   - @Setter
76   - private List<ScheduledFuture<?>> queryingTasks = new LinkedList<>();
  74 + private final List<ScheduledFuture<?>> queryingTasks = new LinkedList<>();
77 75
78 76 public DeviceSessionContext(Device device, DeviceProfile deviceProfile, String token,
79 77 SnmpDeviceProfileTransportConfiguration profileTransportConfiguration,
... ... @@ -116,7 +114,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
116 114 public void initializeTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) throws Exception {
117 115 log.trace("Initializing target for SNMP session of device {}", device);
118 116 this.target = snmpTransportContext.getSnmpAuthService().setUpSnmpTarget(profileTransportConfig, deviceTransportConfig);
119   - log.info("SNMP target initialized: {}", target);
  117 + log.debug("SNMP target initialized: {}", target);
120 118 }
121 119
122 120 public void close() {
... ... @@ -138,20 +136,14 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
138 136
139 137 @Override
140 138 public void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification) {
141   - profileTransportConfiguration.getCommunicationConfigs().stream()
142   - .filter(config -> config.getSpec() == SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING)
143   - .findFirst()
  139 + getCommunicationConfigForSpec(SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING)
144 140 .ifPresent(communicationConfig -> {
145 141 Map<String, String> sharedAttributes = JsonConverter.toJson(attributeUpdateNotification).entrySet().stream()
146 142 .collect(Collectors.toMap(
147 143 Map.Entry::getKey,
148 144 entry -> entry.getValue().isJsonPrimitive() ? entry.getValue().getAsString() : entry.getValue().toString()
149 145 ));
150   - try {
151   - snmpTransportContext.getSnmpTransportService().sendRequest(this, communicationConfig, sharedAttributes);
152   - } catch (Exception e) {
153   - log.error("Failed to send request with shared attributes to SNMP device {}: {}", getDeviceId(), e.getMessage());
154   - }
  146 + snmpTransportContext.getSnmpTransportService().sendRequest(this, communicationConfig, sharedAttributes);
155 147 });
156 148 }
157 149
... ... @@ -161,9 +153,23 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
161 153
162 154 @Override
163 155 public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) {
  156 + getCommunicationConfigForSpec(SnmpCommunicationSpec.TO_DEVICE_RPC_COMMAND_SETTING)
  157 + .ifPresent(communicationConfig -> {
  158 + String value = JsonConverter.toJson(toDeviceRequest, true).toString();
  159 + snmpTransportContext.getSnmpTransportService().sendRequest(
  160 + this, communicationConfig,
  161 + Map.of(ToDeviceRpcCommandSettingSnmpCommunicationConfig.RPC_COMMAND_KEY_NAME, value)
  162 + );
  163 + });
164 164 }
165 165
166 166 @Override
167 167 public void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse) {
168 168 }
  169 +
  170 + private Optional<SnmpCommunicationConfig> getCommunicationConfigForSpec(SnmpCommunicationSpec spec) {
  171 + return profileTransportConfiguration.getCommunicationConfigs().stream()
  172 + .filter(config -> config.getSpec() == spec)
  173 + .findFirst();
  174 + }
169 175 }
... ...