Provide SNMP transport configuration validation; refactor
This commit is contained in:
parent
0532d22d9d
commit
afab5150b8
@ -38,4 +38,7 @@ public interface DeviceTransportConfiguration extends Serializable {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
DeviceTransportType getType();
|
DeviceTransportType getType();
|
||||||
|
|
||||||
|
default void validate() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,25 +19,30 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
|
import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SnmpDeviceTransportConfiguration implements DeviceTransportConfiguration {
|
public class SnmpDeviceTransportConfiguration implements DeviceTransportConfiguration {
|
||||||
|
|
||||||
private String address;
|
private String address;
|
||||||
private int port;
|
private int port;
|
||||||
private String community;
|
private String community;
|
||||||
private String protocolVersion;
|
private SnmpProtocolVersion protocolVersion;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceTransportType getType() {
|
public DeviceTransportType getType() {
|
||||||
return DeviceTransportType.SNMP;
|
return DeviceTransportType.SNMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate() {
|
||||||
|
if (!isValid()) {
|
||||||
|
throw new IllegalArgumentException("Transport configuration is not valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public boolean isValid() {
|
private boolean isValid() {
|
||||||
return StringUtils.isNotEmpty(this.address)
|
return StringUtils.isNotBlank(address) && port > 0 &&
|
||||||
&& this.port > 0
|
StringUtils.isNotBlank(community) && protocolVersion != null;
|
||||||
&& StringUtils.isNotEmpty(this.community)
|
|
||||||
&& StringUtils.isNotEmpty(this.protocolVersion);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|||||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@JsonTypeInfo(
|
@JsonTypeInfo(
|
||||||
@ -30,10 +31,13 @@ import org.thingsboard.server.common.data.DeviceTransportType;
|
|||||||
@JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"),
|
@JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"),
|
||||||
@JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"),
|
@JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"),
|
||||||
@JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M"),
|
@JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M"),
|
||||||
@JsonSubTypes.Type(value = SnmpProfileTransportConfiguration.class, name = "SNMP")})
|
@JsonSubTypes.Type(value = SnmpDeviceProfileTransportConfiguration.class, name = "SNMP")})
|
||||||
public interface DeviceProfileTransportConfiguration {
|
public interface DeviceProfileTransportConfiguration {
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
DeviceTransportType getType();
|
DeviceTransportType getType();
|
||||||
|
|
||||||
|
default void validate() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.device.profile;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
|
import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -25,12 +26,12 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SnmpProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
|
public class SnmpDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
|
||||||
private int pollPeriodMs;
|
private int pollPeriodMs;
|
||||||
private int timeoutMs;
|
private int timeoutMs;
|
||||||
private int retries;
|
private int retries;
|
||||||
private List<SnmpMapping> attributesMappings;
|
|
||||||
private List<SnmpMapping> telemetryMappings;
|
private List<SnmpMapping> telemetryMappings;
|
||||||
|
private List<SnmpMapping> attributesMappings;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceTransportType getType() {
|
public DeviceTransportType getType() {
|
||||||
@ -39,10 +40,25 @@ public class SnmpProfileTransportConfiguration implements DeviceProfileTransport
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public List<SnmpMapping> getAllMappings() {
|
public List<SnmpMapping> getAllMappings() {
|
||||||
if (attributesMappings != null && telemetryMappings != null) {
|
if (telemetryMappings != null && attributesMappings != null) {
|
||||||
return Stream.concat(attributesMappings.stream(), telemetryMappings.stream()).collect(Collectors.toList());
|
return Stream.concat(telemetryMappings.stream(), attributesMappings.stream()).collect(Collectors.toList());
|
||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate() {
|
||||||
|
if (!isValid()) {
|
||||||
|
throw new IllegalArgumentException("Transport configuration is not valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private boolean isValid() {
|
||||||
|
List<SnmpMapping> mappings = getAllMappings();
|
||||||
|
return pollPeriodMs > 0 && timeoutMs > 0 && retries >= 0 &&
|
||||||
|
!mappings.isEmpty() && mappings.stream().allMatch(SnmpMapping::isValid) &&
|
||||||
|
mappings.stream().map(SnmpMapping::getOid).distinct().count() == mappings.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2021 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.common.data.transport.snmp;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.thingsboard.server.common.data.kv.DataType;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SnmpMapping {
|
||||||
|
private String oid;
|
||||||
|
private SnmpMethod method;
|
||||||
|
private String key;
|
||||||
|
private DataType dataType;
|
||||||
|
|
||||||
|
private static final Pattern OID_PATTERN = Pattern.compile("^\\.?([0-2])((\\.0)|(\\.[1-9][0-9]*))*$");
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isValid() {
|
||||||
|
return StringUtils.isNotEmpty(oid) && OID_PATTERN.matcher(oid).matches() && method != null &&
|
||||||
|
StringUtils.isNotBlank(key) && dataType != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2021 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.common.data.transport.snmp;
|
||||||
|
|
||||||
|
public enum SnmpMethod {
|
||||||
|
GET(-96),
|
||||||
|
SET(-93);
|
||||||
|
|
||||||
|
// codes taken from org.snmp4j.PDU class
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
SnmpMethod(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,15 +13,20 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.common.data.device.profile;
|
package org.thingsboard.server.common.data.transport.snmp;
|
||||||
|
|
||||||
import lombok.Data;
|
public enum SnmpProtocolVersion {
|
||||||
import org.thingsboard.server.common.data.kv.DataType;
|
V1(0),
|
||||||
|
V2C(1),
|
||||||
|
V3(3);
|
||||||
|
|
||||||
@Data
|
private final int code;
|
||||||
public class SnmpMapping {
|
|
||||||
private String oid;
|
SnmpProtocolVersion(int code) {
|
||||||
private String method;
|
this.code = code;
|
||||||
private String key;
|
}
|
||||||
private DataType dataType;
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -27,12 +27,13 @@ import org.thingsboard.server.common.data.DeviceProfile;
|
|||||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.SnmpMapping;
|
import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.SnmpProfileTransportConfiguration;
|
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
|
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
|
||||||
|
import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
|
||||||
|
import org.thingsboard.server.common.data.transport.snmp.SnmpMethod;
|
||||||
import org.thingsboard.server.common.transport.DeviceUpdatedEvent;
|
import org.thingsboard.server.common.transport.DeviceUpdatedEvent;
|
||||||
import org.thingsboard.server.common.transport.TransportContext;
|
import org.thingsboard.server.common.transport.TransportContext;
|
||||||
import org.thingsboard.server.common.transport.TransportDeviceProfileCache;
|
import org.thingsboard.server.common.transport.TransportDeviceProfileCache;
|
||||||
@ -74,7 +75,7 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
private final SnmpTransportBalancingService balancingService;
|
private final SnmpTransportBalancingService balancingService;
|
||||||
|
|
||||||
private final Map<DeviceId, DeviceSessionContext> sessions = new ConcurrentHashMap<>();
|
private final Map<DeviceId, DeviceSessionContext> sessions = new ConcurrentHashMap<>();
|
||||||
private final Map<DeviceProfileId, SnmpProfileTransportConfiguration> profilesTransportConfigs = new ConcurrentHashMap<>();
|
private final Map<DeviceProfileId, SnmpDeviceProfileTransportConfiguration> profilesTransportConfigs = new ConcurrentHashMap<>();
|
||||||
private final Map<DeviceProfileId, List<PDU>> profilesPdus = new ConcurrentHashMap<>();
|
private final Map<DeviceProfileId, List<PDU>> profilesPdus = new ConcurrentHashMap<>();
|
||||||
private Collection<DeviceId> allSnmpDevicesIds = new ConcurrentLinkedDeque<>();
|
private Collection<DeviceId> allSnmpDevicesIds = new ConcurrentLinkedDeque<>();
|
||||||
|
|
||||||
@ -94,7 +95,13 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
managedDevicesIds.stream()
|
managedDevicesIds.stream()
|
||||||
.map(protoEntityService::getDeviceById)
|
.map(protoEntityService::getDeviceById)
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
.forEach(this::establishDeviceSession);
|
.forEach(device -> {
|
||||||
|
try {
|
||||||
|
establishDeviceSession(device);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to establish session for SNMP device {}: {}", device.getId(), e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void establishDeviceSession(Device device) {
|
private void establishDeviceSession(Device device) {
|
||||||
@ -110,13 +117,10 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SnmpDeviceProfileTransportConfiguration profileTransportConfiguration = (SnmpDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
||||||
SnmpDeviceTransportConfiguration deviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
SnmpDeviceTransportConfiguration deviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
||||||
if (!deviceTransportConfiguration.isValid()) {
|
|
||||||
log.warn("SNMP device transport configuration is not valid");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SnmpProfileTransportConfiguration profileTransportConfiguration = (SnmpProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
profilesTransportConfigs.put(deviceProfileId, profileTransportConfiguration);
|
||||||
profilesPdus.computeIfAbsent(deviceProfileId, id -> createPdus(profileTransportConfiguration));
|
profilesPdus.computeIfAbsent(deviceProfileId, id -> createPdus(profileTransportConfiguration));
|
||||||
|
|
||||||
DeviceSessionContext deviceSessionContext = new DeviceSessionContext(
|
DeviceSessionContext deviceSessionContext = new DeviceSessionContext(
|
||||||
@ -140,22 +144,18 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SnmpProfileTransportConfiguration profileTransportConfiguration = (SnmpProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
SnmpDeviceProfileTransportConfiguration newProfileTransportConfiguration = (SnmpDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
||||||
SnmpDeviceTransportConfiguration deviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
SnmpDeviceTransportConfiguration newDeviceTransportConfiguration = (SnmpDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
|
||||||
sessionContext.setProfileTransportConfiguration(profileTransportConfiguration);
|
|
||||||
sessionContext.setDeviceTransportConfiguration(deviceTransportConfiguration);
|
|
||||||
if (!deviceTransportConfiguration.isValid()) {
|
|
||||||
log.warn("SNMP device transport configuration is not valid");
|
|
||||||
destroyDeviceSession(sessionContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!profileTransportConfiguration.equals(profilesTransportConfigs.get(deviceProfileId))) {
|
if (!newProfileTransportConfiguration.equals(sessionContext.getProfileTransportConfiguration())) {
|
||||||
profilesPdus.put(deviceProfileId, createPdus(profileTransportConfiguration));
|
profilesPdus.put(deviceProfileId, createPdus(newProfileTransportConfiguration));
|
||||||
profilesTransportConfigs.put(deviceProfileId, profileTransportConfiguration);
|
profilesTransportConfigs.put(deviceProfileId, newProfileTransportConfiguration);
|
||||||
sessionContext.initTarget(profileTransportConfiguration, deviceTransportConfiguration);
|
|
||||||
} else if (!deviceTransportConfiguration.equals(sessionContext.getDeviceTransportConfiguration())) {
|
sessionContext.setProfileTransportConfiguration(newProfileTransportConfiguration);
|
||||||
sessionContext.initTarget(profileTransportConfiguration, deviceTransportConfiguration);
|
sessionContext.initTarget(newProfileTransportConfiguration, newDeviceTransportConfiguration);
|
||||||
|
} else if (!newDeviceTransportConfiguration.equals(sessionContext.getDeviceTransportConfiguration())) {
|
||||||
|
sessionContext.setDeviceTransportConfiguration(newDeviceTransportConfiguration);
|
||||||
|
sessionContext.initTarget(newProfileTransportConfiguration, newDeviceTransportConfiguration);
|
||||||
} else {
|
} else {
|
||||||
log.trace("Configuration of the device {} was not updated", device);
|
log.trace("Configuration of the device {} was not updated", device);
|
||||||
}
|
}
|
||||||
@ -205,8 +205,8 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PDU> createPdus(SnmpProfileTransportConfiguration deviceProfileConfig) {
|
private List<PDU> createPdus(SnmpDeviceProfileTransportConfiguration deviceProfileConfig) {
|
||||||
Map<String, List<VariableBinding>> bindingsPerMethod = new HashMap<>();
|
Map<SnmpMethod, List<VariableBinding>> bindingsPerMethod = new HashMap<>();
|
||||||
|
|
||||||
deviceProfileConfig.getAllMappings().forEach(mapping -> bindingsPerMethod
|
deviceProfileConfig.getAllMappings().forEach(mapping -> bindingsPerMethod
|
||||||
.computeIfAbsent(mapping.getMethod(), v -> new ArrayList<>())
|
.computeIfAbsent(mapping.getMethod(), v -> new ArrayList<>())
|
||||||
@ -215,7 +215,7 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
return bindingsPerMethod.keySet().stream()
|
return bindingsPerMethod.keySet().stream()
|
||||||
.map(method -> {
|
.map(method -> {
|
||||||
PDU request = new PDU();
|
PDU request = new PDU();
|
||||||
request.setType(getSnmpMethod(method));
|
request.setType(method.getCode());
|
||||||
request.addAll(bindingsPerMethod.get(method));
|
request.addAll(bindingsPerMethod.get(method));
|
||||||
return request;
|
return request;
|
||||||
})
|
})
|
||||||
@ -311,22 +311,9 @@ public class SnmpTransportContext extends TransportContext {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<SnmpMapping> getMapping(OID responseOid, List<SnmpMapping> mappings) {
|
private Optional<SnmpMapping> getMapping(OID oid, List<SnmpMapping> mappings) {
|
||||||
return mappings.stream()
|
return mappings.stream()
|
||||||
.filter(kvMapping -> new OID(kvMapping.getOid()).equals(responseOid))
|
.filter(mapping -> new OID(mapping.getOid()).equals(oid))
|
||||||
//TODO: OID shouldn't be duplicated in the config, add backend and UI verification
|
|
||||||
.findFirst();
|
.findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSnmpMethod(String configMethod) {
|
|
||||||
switch (configMethod) {
|
|
||||||
case "get":
|
|
||||||
return PDU.GET;
|
|
||||||
case "getNext":
|
|
||||||
case "response":
|
|
||||||
case "set":
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.snmp4j.PDU;
|
import org.snmp4j.PDU;
|
||||||
import org.snmp4j.Snmp;
|
import org.snmp4j.Snmp;
|
||||||
import org.snmp4j.event.ResponseEvent;
|
import org.snmp4j.event.ResponseEvent;
|
||||||
|
import org.snmp4j.smi.Null;
|
||||||
import org.snmp4j.smi.VariableBinding;
|
import org.snmp4j.smi.VariableBinding;
|
||||||
import org.snmp4j.transport.DefaultUdpTransportMapping;
|
import org.snmp4j.transport.DefaultUdpTransportMapping;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
@ -103,8 +104,8 @@ public class SnmpTransportService implements TbTransportService {
|
|||||||
try {
|
try {
|
||||||
log.debug("[{}] Sending SNMP message for device {}", pdu.getRequestID(), sessionContext.getDeviceId());
|
log.debug("[{}] Sending SNMP message for device {}", pdu.getRequestID(), sessionContext.getDeviceId());
|
||||||
snmp.send(pdu, sessionContext.getTarget(), deviceProfileId, sessionContext);
|
snmp.send(pdu, sessionContext.getTarget(), deviceProfileId, sessionContext);
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error("Failed to send SNMP request: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -123,7 +124,7 @@ public class SnmpTransportService implements TbTransportService {
|
|||||||
|
|
||||||
PDU response = event.getResponse();
|
PDU response = event.getResponse();
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
log.warn("No SNMP response, requestId: {}", event.getRequest().getRequestID());
|
log.warn("No response from SNMP device {}, requestId: {}", sessionContext.getDeviceId(), event.getRequest().getRequestID());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +139,11 @@ public class SnmpTransportService implements TbTransportService {
|
|||||||
VariableBinding variableBinding = response.get(i);
|
VariableBinding variableBinding = response.get(i);
|
||||||
log.trace("Processing variable binding {}: {}", i, variableBinding);
|
log.trace("Processing variable binding {}: {}", i, variableBinding);
|
||||||
|
|
||||||
|
if (variableBinding.getVariable() instanceof Null) {
|
||||||
|
log.debug("Response variable is empty");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
snmpTransportContext.getTelemetryMapping(deviceProfileId, variableBinding.getOid()).ifPresent(mapping -> {
|
snmpTransportContext.getTelemetryMapping(deviceProfileId, variableBinding.getOid()).ifPresent(mapping -> {
|
||||||
log.trace("Found telemetry mapping for oid {}: {}", variableBinding.getOid(), mapping);
|
log.trace("Found telemetry mapping for oid {}: {}", variableBinding.getOid(), mapping);
|
||||||
processValue(mapping.getKey(), mapping.getDataType(), variableBinding.toValueString(), telemetry);
|
processValue(mapping.getKey(), mapping.getDataType(), variableBinding.toValueString(), telemetry);
|
||||||
|
|||||||
@ -22,13 +22,12 @@ import org.snmp4j.CommunityTarget;
|
|||||||
import org.snmp4j.Target;
|
import org.snmp4j.Target;
|
||||||
import org.snmp4j.event.ResponseEvent;
|
import org.snmp4j.event.ResponseEvent;
|
||||||
import org.snmp4j.event.ResponseListener;
|
import org.snmp4j.event.ResponseListener;
|
||||||
import org.snmp4j.mp.SnmpConstants;
|
|
||||||
import org.snmp4j.smi.GenericAddress;
|
import org.snmp4j.smi.GenericAddress;
|
||||||
import org.snmp4j.smi.OctetString;
|
import org.snmp4j.smi.OctetString;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.SnmpProfileTransportConfiguration;
|
import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
import org.thingsboard.server.common.transport.SessionMsgListener;
|
import org.thingsboard.server.common.transport.SessionMsgListener;
|
||||||
import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
|
import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
|
||||||
@ -51,7 +50,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
|
|||||||
private final String token;
|
private final String token;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private SnmpProfileTransportConfiguration profileTransportConfiguration;
|
private SnmpDeviceProfileTransportConfiguration profileTransportConfiguration;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private SnmpDeviceTransportConfiguration deviceTransportConfiguration;
|
private SnmpDeviceTransportConfiguration deviceTransportConfiguration;
|
||||||
@ -79,7 +78,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
|
|||||||
this.snmpTransportContext = snmpTransportContext;
|
this.snmpTransportContext = snmpTransportContext;
|
||||||
this.snmpTransportService = snmpTransportService;
|
this.snmpTransportService = snmpTransportService;
|
||||||
|
|
||||||
this.profileTransportConfiguration = (SnmpProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
this.profileTransportConfiguration = (SnmpDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration();
|
||||||
this.deviceTransportConfiguration = deviceTransportConfiguration;
|
this.deviceTransportConfiguration = deviceTransportConfiguration;
|
||||||
|
|
||||||
initTarget(this.profileTransportConfiguration, this.deviceTransportConfiguration);
|
initTarget(this.profileTransportConfiguration, this.deviceTransportConfiguration);
|
||||||
@ -105,11 +104,11 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initTarget(SnmpProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) {
|
public void initTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) {
|
||||||
log.trace("Initializing target for SNMP session of device {}", device);
|
log.trace("Initializing target for SNMP session of device {}", device);
|
||||||
CommunityTarget communityTarget = new CommunityTarget();
|
CommunityTarget communityTarget = new CommunityTarget();
|
||||||
communityTarget.setAddress(GenericAddress.parse(GenericAddress.TYPE_UDP + ":" + deviceTransportConfig.getAddress() + "/" + deviceTransportConfig.getPort()));
|
communityTarget.setAddress(GenericAddress.parse(GenericAddress.TYPE_UDP + ":" + deviceTransportConfig.getAddress() + "/" + deviceTransportConfig.getPort()));
|
||||||
communityTarget.setVersion(getSnmpVersion(deviceTransportConfig.getProtocolVersion()));
|
communityTarget.setVersion(deviceTransportConfig.getProtocolVersion().getCode());
|
||||||
communityTarget.setCommunity(new OctetString(deviceTransportConfig.getCommunity()));
|
communityTarget.setCommunity(new OctetString(deviceTransportConfig.getCommunity()));
|
||||||
communityTarget.setTimeout(profileTransportConfig.getTimeoutMs());
|
communityTarget.setTimeout(profileTransportConfig.getTimeoutMs());
|
||||||
communityTarget.setRetries(profileTransportConfig.getRetries());
|
communityTarget.setRetries(profileTransportConfig.getRetries());
|
||||||
@ -125,20 +124,6 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: replace with enum, wtih preliminary discussion of type version in config (string or integer)
|
|
||||||
private int getSnmpVersion(String configSnmpVersion) {
|
|
||||||
switch (configSnmpVersion) {
|
|
||||||
case ("v1"):
|
|
||||||
return SnmpConstants.version1;
|
|
||||||
case ("v2c"):
|
|
||||||
return SnmpConstants.version2c;
|
|
||||||
case ("v3"):
|
|
||||||
return SnmpConstants.version3;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nextMsgId() {
|
public int nextMsgId() {
|
||||||
return msgIdSeq.incrementAndGet();
|
return msgIdSeq.incrementAndGet();
|
||||||
|
|||||||
@ -350,6 +350,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
|
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
|
||||||
|
transportConfiguration.validate();
|
||||||
if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) {
|
if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) {
|
||||||
MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
|
MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
|
||||||
if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) {
|
if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) {
|
||||||
|
|||||||
@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.device.credentials.BasicMqttCredential
|
|||||||
import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration;
|
import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.DeviceData;
|
import org.thingsboard.server.common.data.device.data.DeviceData;
|
||||||
|
import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
|
||||||
@ -604,6 +605,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
|
|||||||
throw new DataValidationException("Can't assign device to customer from different tenant!");
|
throw new DataValidationException("Can't assign device to customer from different tenant!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Optional.ofNullable(device.getDeviceData())
|
||||||
|
.flatMap(deviceData -> Optional.ofNullable(deviceData.getTransportConfiguration()))
|
||||||
|
.ifPresent(DeviceTransportConfiguration::validate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user