diff --git a/bundles/org.openhab.binding.snmp/README.md b/bundles/org.openhab.binding.snmp/README.md index e2cd61acb4a..725d27f9459 100644 --- a/bundles/org.openhab.binding.snmp/README.md +++ b/bundles/org.openhab.binding.snmp/README.md @@ -77,13 +77,8 @@ The default is `v1`. ### `target3` -The `target3` thing has additional mandatory parameters: `engineId` and `user`. - -The `engineId` must be given in hexadecimal notation (case-insensitive) without separators (e.g. `80000009035c710dbcd9e6`). -The allowed length is 11 to 32 bytes (22 to 64 hex characters). -If you encounter problems, please check if your agent prefixes the set engine id (e.g. Mikrotik uses `80003a8c04` and appends the set value to that). - -The `user` parameter is named "securityName" or "userName" in most agents. +The `target3` thing has an additional mandatory parameter: `user`. +This value of this parameter is named "securityName" or "userName" in most agents. Optional configuration parameters are: `securityModel`, `authProtocol`, `authPassphrase`, `privProtocol` and `privPassphrase`. @@ -99,7 +94,7 @@ If authentication encryption is required, at least `authPassphrase` needs to be Other possible values for `authProtocol` are `SHA`, `HMAC128SHA224`, `HMAC192SHA256`, `HMAC256SHA384` and `HMAC384SHA512`. If encryption of transmitted data (privacy encryption) is required, at least `privPassphrase` needs to be set, while `privProtocol` defaults to `DES`. -Other possible values for `privProtocol` are `AES128`, `AES192` and `AES256`. +Other possible values for `privProtocol` are `DES3`, `AES128`, `AES192` and `AES256`. ## Channels diff --git a/bundles/org.openhab.binding.snmp/pom.xml b/bundles/org.openhab.binding.snmp/pom.xml index a53a670b5db..89182919dbe 100644 --- a/bundles/org.openhab.binding.snmp/pom.xml +++ b/bundles/org.openhab.binding.snmp/pom.xml @@ -18,7 +18,13 @@ org.snmp4j snmp4j - 2.8.6 + 3.8.2 + compile + + + org.snmp4j + snmp4j-unix-transport + 1.1.0 compile diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpService.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpService.java index 58b42791004..80f51eacc70 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpService.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpService.java @@ -16,12 +16,13 @@ import java.io.IOException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.snmp.internal.types.SnmpAuthProtocol; -import org.openhab.binding.snmp.internal.types.SnmpPrivProtocol; import org.snmp4j.CommandResponder; import org.snmp4j.PDU; import org.snmp4j.Target; import org.snmp4j.event.ResponseListener; +import org.snmp4j.security.UsmUser; +import org.snmp4j.smi.Address; +import org.snmp4j.smi.OctetString; /** * The {@link SnmpService} is responsible for SNMP communication @@ -33,12 +34,53 @@ import org.snmp4j.event.ResponseListener; @NonNullByDefault public interface SnmpService { + /** + * Add a listener for received PDUs to the service + * + * @param listener the listener + */ void addCommandResponder(CommandResponder listener); + /** + * Remove a listener for received PDUs from the service + * + * @param listener the listener + */ void removeCommandResponder(CommandResponder listener); - void send(PDU pdu, Target target, @Nullable Object userHandle, ResponseListener listener) throws IOException; + /** + * Send a PDU to the given target + * + * @param pdu the PDU + * @param target the target + * @param userHandle an optional user-handle to identify the request + * @param listener the listener for the response (always called, even in case of timeout) + * @throws IOException when an error occurs + */ + void send(PDU pdu, Target target, @Nullable Object userHandle, ResponseListener listener) throws IOException; - void addUser(String userName, SnmpAuthProtocol snmpAuthProtocol, @Nullable String authPassphrase, - SnmpPrivProtocol snmpPrivProtocol, @Nullable String privPassphrase, byte[] engineId); + /** + * Add a user to the service for a given engine id (v3 only) + * + * @param user the {@link UsmUser} that should be added + * @param engineId the engine id + */ + void addUser(UsmUser user, OctetString engineId); + + /** + * Remove a user from the service and clear the context engine id for this address (v3 only) + * + * @param address the remote address + * @param user the user + * @param engineId the engine id + */ + void removeUser(Address address, UsmUser user, OctetString engineId); + + /** + * Get the engine id of a remote system for a given address (v3 only) + * + * @param address the address of the remote system + * @return the engine id or {@code null} when engine id could not be determined + */ + byte @Nullable [] getEngineId(Address address); } diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpServiceImpl.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpServiceImpl.java index 86e223feb38..5182e7093af 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpServiceImpl.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpServiceImpl.java @@ -22,8 +22,6 @@ import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.snmp.internal.config.SnmpServiceConfiguration; -import org.openhab.binding.snmp.internal.types.SnmpAuthProtocol; -import org.openhab.binding.snmp.internal.types.SnmpPrivProtocol; import org.openhab.core.config.core.Configuration; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -37,11 +35,22 @@ import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.MPv3; +import org.snmp4j.security.AuthHMAC128SHA224; +import org.snmp4j.security.AuthHMAC192SHA256; +import org.snmp4j.security.AuthHMAC256SHA384; +import org.snmp4j.security.AuthHMAC384SHA512; +import org.snmp4j.security.AuthMD5; +import org.snmp4j.security.AuthSHA; import org.snmp4j.security.Priv3DES; +import org.snmp4j.security.PrivAES128; +import org.snmp4j.security.PrivAES192; +import org.snmp4j.security.PrivAES256; +import org.snmp4j.security.PrivDES; import org.snmp4j.security.SecurityModels; import org.snmp4j.security.SecurityProtocols; import org.snmp4j.security.USM; import org.snmp4j.security.UsmUser; +import org.snmp4j.smi.Address; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; import org.snmp4j.transport.DefaultUdpTransportMapping; @@ -58,7 +67,6 @@ import org.snmp4j.transport.DefaultUdpTransportMapping; public class SnmpServiceImpl implements SnmpService { private final Logger logger = LoggerFactory.getLogger(SnmpServiceImpl.class); - private @NonNullByDefault({}) SnmpServiceConfiguration config; private @Nullable Snmp snmp; private @Nullable DefaultUdpTransportMapping transport; @@ -67,9 +75,7 @@ public class SnmpServiceImpl implements SnmpService { @Activate public SnmpServiceImpl(Map config) { - SecurityProtocols.getInstance().addDefaultProtocols(); - SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES()); - + addProtocols(); OctetString localEngineId = new OctetString(MPv3.createLocalEngineID()); USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0); SecurityModels.getInstance().addSecurityModel(usm); @@ -79,34 +85,33 @@ public class SnmpServiceImpl implements SnmpService { @Modified protected void modified(Map config) { - this.config = new Configuration(config).as(SnmpServiceConfiguration.class); + SnmpServiceConfiguration snmpCfg = new Configuration(config).as(SnmpServiceConfiguration.class); try { shutdownSnmp(); final DefaultUdpTransportMapping transport; - if (this.config.port > 0) { - transport = new DefaultUdpTransportMapping(new UdpAddress(this.config.port), true); + if (snmpCfg.port > 0) { + transport = new DefaultUdpTransportMapping(new UdpAddress(snmpCfg.port), true); } else { transport = new DefaultUdpTransportMapping(); } - SecurityProtocols.getInstance().addDefaultProtocols(); - SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES()); + addProtocols(); final Snmp snmp = new Snmp(transport); listeners.forEach(snmp::addCommandResponder); snmp.listen(); // re-add user entries - userEntries.forEach(u -> addUser(snmp, u)); + userEntries.forEach(u -> snmp.getUSM().addUser(u.user, u.engineId)); this.snmp = snmp; this.transport = transport; logger.debug("initialized SNMP at {}", transport.getAddress()); } catch (IOException e) { - logger.warn("could not open SNMP instance on port {}: {}", this.config.port, e.getMessage()); + logger.warn("could not open SNMP instance on port {}: {}", snmpCfg.port, e.getMessage()); } } @@ -120,6 +125,21 @@ public class SnmpServiceImpl implements SnmpService { } } + private void addProtocols() { + SecurityProtocols secProtocols = SecurityProtocols.getInstance(); + secProtocols.addAuthenticationProtocol(new AuthMD5()); + secProtocols.addAuthenticationProtocol(new AuthSHA()); + secProtocols.addAuthenticationProtocol(new AuthHMAC128SHA224()); + secProtocols.addAuthenticationProtocol(new AuthHMAC192SHA256()); + secProtocols.addAuthenticationProtocol(new AuthHMAC256SHA384()); + secProtocols.addAuthenticationProtocol(new AuthHMAC384SHA512()); + secProtocols.addPrivacyProtocol(new PrivDES()); + secProtocols.addPrivacyProtocol(new Priv3DES()); + secProtocols.addPrivacyProtocol(new PrivAES128()); + secProtocols.addPrivacyProtocol(new PrivAES192()); + secProtocols.addPrivacyProtocol(new PrivAES256()); + } + private void shutdownSnmp() throws IOException { DefaultUdpTransportMapping transport = this.transport; if (transport != null) { @@ -152,7 +172,7 @@ public class SnmpServiceImpl implements SnmpService { } @Override - public void send(PDU pdu, Target target, @Nullable Object userHandle, ResponseListener listener) + public void send(PDU pdu, Target target, @Nullable Object userHandle, ResponseListener listener) throws IOException { Snmp snmp = this.snmp; if (snmp != null) { @@ -164,35 +184,40 @@ public class SnmpServiceImpl implements SnmpService { } @Override - public void addUser(String userName, SnmpAuthProtocol snmpAuthProtocol, @Nullable String authPassphrase, - SnmpPrivProtocol snmpPrivProtocol, @Nullable String privPassphrase, byte[] engineId) { - UsmUser usmUser = new UsmUser(new OctetString(userName), - authPassphrase != null ? snmpAuthProtocol.getOid() : null, - authPassphrase != null ? new OctetString(authPassphrase) : null, - privPassphrase != null ? snmpPrivProtocol.getOid() : null, - privPassphrase != null ? new OctetString(privPassphrase) : null); - OctetString securityNameOctets = new OctetString(userName); - - UserEntry userEntry = new UserEntry(securityNameOctets, new OctetString(engineId), usmUser); + public void addUser(UsmUser user, OctetString engineId) { + UserEntry userEntry = new UserEntry(user, engineId); userEntries.add(userEntry); Snmp snmp = this.snmp; if (snmp != null) { - addUser(snmp, userEntry); + snmp.getUSM().addUser(user, engineId); } } - private static void addUser(Snmp snmp, UserEntry userEntry) { - snmp.getUSM().addUser(userEntry.securityName, userEntry.engineId, userEntry.user); + @Override + public void removeUser(Address address, UsmUser user, OctetString engineId) { + Snmp snmp = this.snmp; + if (snmp != null) { + snmp.getUSM().removeAllUsers(user.getSecurityName(), engineId); + snmp.removeCachedContextEngineId(address); + } + userEntries.removeIf(e -> e.engineId.equals(engineId) && e.user.equals(user)); + } + + @Override + public byte @Nullable [] getEngineId(Address address) { + Snmp snmp = this.snmp; + if (snmp != null) { + return snmp.discoverAuthoritativeEngineID(address, 15000); + } + return null; } private static class UserEntry { - public OctetString securityName; public OctetString engineId; public UsmUser user; - public UserEntry(OctetString securityName, OctetString engineId, UsmUser user) { - this.securityName = securityName; + public UserEntry(UsmUser user, OctetString engineId) { this.engineId = engineId; this.user = user; } diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java index 5b3c8bd72c3..7890e50112a 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java @@ -17,7 +17,6 @@ import static org.openhab.binding.snmp.internal.SnmpBindingConstants.*; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Collections; import java.util.Objects; import java.util.Set; import java.util.concurrent.ScheduledFuture; @@ -53,7 +52,6 @@ import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; import org.openhab.core.types.util.UnitUtils; -import org.openhab.core.util.HexUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.snmp4j.AbstractTarget; @@ -68,6 +66,8 @@ import org.snmp4j.UserTarget; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.security.UsmUser; +import org.snmp4j.smi.Address; import org.snmp4j.smi.Counter64; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.IpAddress; @@ -87,8 +87,8 @@ import org.snmp4j.smi.VariableBinding; */ @NonNullByDefault public class SnmpTargetHandler extends BaseThingHandler implements ResponseListener, CommandResponder { - private static final Pattern HEXSTRING_VALIDITY = Pattern.compile("([a-f0-9]{2}[ :-]?)+"); - private static final Pattern HEXSTRING_EXTRACTOR = Pattern.compile("[^a-f0-9]"); + private static final Pattern HEX_STRING_VALIDITY = Pattern.compile("([A-Fa-f0-9]{2}[ :-]?)+"); + private static final Pattern HEX_STRING_EXTRACTOR = Pattern.compile("[^A-Fa-f0-9]"); private final Logger logger = LoggerFactory.getLogger(SnmpTargetHandler.class); @@ -97,13 +97,17 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe private @Nullable ScheduledFuture refresh; private int timeoutCounter = 0; - private @NonNullByDefault({}) AbstractTarget target; + private @NonNullByDefault({}) AbstractTarget target; private @NonNullByDefault({}) String targetAddressString; private @NonNullByDefault({}) Set readChannelSet; private @NonNullByDefault({}) Set writeChannelSet; private @NonNullByDefault({}) Set trapChannelSet; + // SNMP v3 + private @Nullable UsmUser usmUser; + private @Nullable OctetString engineId; + public SnmpTargetHandler(Thing thing, SnmpService snmpService) { super(thing); this.snmpService = snmpService; @@ -139,7 +143,7 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe } } else { Command rawValue = command; - if (command instanceof QuantityType quantityCommand) { + if (command instanceof QuantityType quantityCommand) { Unit channelUnit = channel.unit; if (channelUnit == null) { rawValue = new DecimalType(quantityCommand.toBigDecimal()); @@ -180,7 +184,7 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe try { if (config.protocol.toInteger() == SnmpConstants.version1 || config.protocol.toInteger() == SnmpConstants.version2c) { - CommunityTarget target = new CommunityTarget(); + CommunityTarget target = new CommunityTarget<>(); target.setCommunity(new OctetString(config.community)); this.target = target; } else if (config.protocol.toInteger() == SnmpConstants.version3) { @@ -189,31 +193,31 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "user not set"); return; } - String engineIdHexString = config.engineId; - if (engineIdHexString == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "engineId not set"); - return; - } String authPassphrase = config.authPassphrase; - if ((config.securityModel == SnmpSecurityModel.AUTH_PRIV - || config.securityModel == SnmpSecurityModel.AUTH_NO_PRIV) - && (authPassphrase == null || authPassphrase.isEmpty())) { + if (config.securityModel != SnmpSecurityModel.NO_AUTH_NO_PRIV + && (authPassphrase == null || authPassphrase.isBlank())) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Authentication passphrase not configured"); return; } String privPassphrase = config.privPassphrase; if (config.securityModel == SnmpSecurityModel.AUTH_PRIV - && (privPassphrase == null || privPassphrase.isEmpty())) { + && (privPassphrase == null || privPassphrase.isBlank())) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Privacy passphrase not configured"); return; } - byte[] engineId = HexUtils.hexToBytes(engineIdHexString); - snmpService.addUser(userName, config.authProtocol, authPassphrase, config.privProtocol, privPassphrase, - engineId); - UserTarget target = new UserTarget(); - target.setAuthoritativeEngineID(engineId); + usmUser = new UsmUser(new OctetString(userName), + config.securityModel != SnmpSecurityModel.NO_AUTH_NO_PRIV ? config.authProtocol.getOid() : null, + config.securityModel != SnmpSecurityModel.NO_AUTH_NO_PRIV && authPassphrase != null + ? new OctetString(authPassphrase) + : null, + config.securityModel == SnmpSecurityModel.AUTH_PRIV ? config.privProtocol.getOid() : null, + config.securityModel == SnmpSecurityModel.AUTH_PRIV && privPassphrase != null + ? new OctetString(privPassphrase) + : null); + + UserTarget target = new UserTarget<>(); target.setSecurityName(new OctetString(config.user)); target.setSecurityLevel(config.securityModel.getSecurityLevel()); this.target = target; @@ -248,6 +252,16 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe r.cancel(true); } snmpService.removeCommandResponder(this); + + UsmUser user = usmUser; + OctetString engineId = this.engineId; + Address address = target.getAddress(); + if (user != null && engineId != null && address != null) { + snmpService.removeUser(address, user, engineId); + } + + usmUser = null; + this.engineId = null; } @Override @@ -260,7 +274,7 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe // Always cancel async request when response has been received // otherwise a memory leak is created! Not canceling a request // immediately can be useful when sending a request to a broadcast - // address (Comment is taken from the snmp4j API doc). + // address (Comment is taken from the SNMP4J API doc). ((Snmp) event.getSource()).cancel(event.getRequest(), this); } @@ -350,7 +364,7 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe if (configUnit != null) { unit = UnitUtils.parseUnit(configUnit); if (unit == null) { - logger.warn("Failed to parse unit from '{}'for channel '{}'", unit, channel.getUID()); + logger.warn("Failed to parse unit from '{}'for channel '{}'", configUnit, channel.getUID()); } } } else if (CHANNEL_TYPE_UID_STRING.equals(channel.getChannelTypeUID())) { @@ -394,8 +408,9 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe } private void generateChannelConfigs() { - Set channelConfigs = Collections.unmodifiableSet(thing.getChannels().stream() - .map(this::getChannelConfigFromChannel).filter(Objects::nonNull).collect(Collectors.toSet())); + Set channelConfigs = thing.getChannels().stream() + .map(this::getChannelConfigFromChannel).filter(Objects::nonNull).map(Objects::requireNonNull) + .collect(Collectors.toUnmodifiableSet()); this.readChannelSet = channelConfigs.stream() .filter(c -> c.mode == SnmpChannelMode.READ || c.mode == SnmpChannelMode.READ_WRITE) .collect(Collectors.toSet()); @@ -520,9 +535,9 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe case HEXSTRING -> { if (command instanceof StringType stringCommand) { String commandString = stringCommand.toString().toLowerCase(); - Matcher commandMatcher = HEXSTRING_VALIDITY.matcher(commandString); + Matcher commandMatcher = HEX_STRING_VALIDITY.matcher(commandString); if (commandMatcher.matches()) { - commandString = HEXSTRING_EXTRACTOR.matcher(commandString).replaceAll(""); + commandString = HEX_STRING_EXTRACTOR.matcher(commandString).replaceAll(""); return OctetString.fromHexStringPairs(commandString); } } @@ -541,7 +556,25 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe private boolean renewTargetAddress() { try { target.setAddress(new UdpAddress(InetAddress.getByName(config.hostname), config.port)); - targetAddressString = ((UdpAddress) target.getAddress()).getInetAddress().getHostAddress(); + targetAddressString = target.getAddress().getInetAddress().getHostAddress(); + logger.trace("Determined {} as address for {} (thing {})", target.getAddress(), config.hostname, + this.thing.getUID()); + UsmUser user = usmUser; + if (user != null && target instanceof UserTarget userTarget) { + byte[] engineIdBytes = snmpService.getEngineId(target.getAddress()); + if (engineIdBytes != null) { + OctetString engineIdOctets = new OctetString(engineIdBytes); + this.engineId = engineIdOctets; + logger.trace("Determined {} as engineId for {}", engineIdOctets, target.getAddress()); + snmpService.addUser(user, engineIdOctets); + userTarget.setAuthoritativeEngineID(engineIdBytes); + } else { + target.setAddress(null); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Cannot determine engineId"); + return false; + } + } return true; } catch (UnknownHostException e) { target.setAddress(null); diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/config/SnmpTargetConfiguration.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/config/SnmpTargetConfiguration.java index 218a48e6e8c..8f3a0068ac0 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/config/SnmpTargetConfiguration.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/config/SnmpTargetConfiguration.java @@ -41,7 +41,6 @@ public class SnmpTargetConfiguration { // v3 only public SnmpSecurityModel securityModel = SnmpSecurityModel.NO_AUTH_NO_PRIV; public @Nullable String user; - public @Nullable String engineId; public SnmpAuthProtocol authProtocol = SnmpAuthProtocol.MD5; public @Nullable String authPassphrase; public SnmpPrivProtocol privProtocol = SnmpPrivProtocol.DES; diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/types/SnmpPrivProtocol.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/types/SnmpPrivProtocol.java index 91148048818..9efee83a8de 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/types/SnmpPrivProtocol.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/types/SnmpPrivProtocol.java @@ -13,6 +13,7 @@ package org.openhab.binding.snmp.internal.types; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.snmp4j.security.Priv3DES; import org.snmp4j.security.PrivAES128; import org.snmp4j.security.PrivAES192; import org.snmp4j.security.PrivAES256; @@ -29,7 +30,8 @@ public enum SnmpPrivProtocol { AES128(PrivAES128.ID), AES192(PrivAES192.ID), AES256(PrivAES256.ID), - DES(PrivDES.ID); + DES(PrivDES.ID), + DES3(Priv3DES.ID); private final OID oid; diff --git a/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/i18n/snmp.properties b/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/i18n/snmp.properties index ee531d1c769..322261c92e5 100644 --- a/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/i18n/snmp.properties +++ b/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/i18n/snmp.properties @@ -47,6 +47,7 @@ thing-type.config.snmp.target3.privProtocol.option.AES128 = AES128 thing-type.config.snmp.target3.privProtocol.option.AES192 = AES192 thing-type.config.snmp.target3.privProtocol.option.AES256 = AES256 thing-type.config.snmp.target3.privProtocol.option.DES = DES +thing-type.config.snmp.target3.privProtocol.option.DES3 = 3DES thing-type.config.snmp.target3.refresh.label = Refresh Time thing-type.config.snmp.target3.refresh.description = Refresh time in s (default 60s) thing-type.config.snmp.target3.retries.label = Retries @@ -85,8 +86,8 @@ channel-type.config.snmp.number.mode.option.READ_WRITE = Read/Write channel-type.config.snmp.number.mode.option.TRAP = Trap channel-type.config.snmp.number.oid.label = OID channel-type.config.snmp.number.oid.description = OID in dotted format (eg. .1.3.6.1.4.1.6574.3.1.1.3.0) -channel-type.config.snmp.number.unit.label = Unit Of Measurement -channel-type.config.snmp.number.unit.description = Unit of measurement (optional). The unit is used for representing the value in the GUI as well as for converting incoming values (like from '°F' to '°C'). Examples: "°C", "°F" +channel-type.config.snmp.number.unit.label = Unit +channel-type.config.snmp.number.unit.description = The unit of this value. channel-type.config.snmp.string.datatype.label = Datatype channel-type.config.snmp.string.datatype.description = Content data type channel-type.config.snmp.string.datatype.option.STRING = String diff --git a/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/thing/thing-types.xml index 782d70d6fe0..82ffc2d8985 100644 --- a/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.snmp/src/main/resources/OH-INF/thing/thing-types.xml @@ -64,10 +64,6 @@ Hostname or IP address of target host network-address - - - The authorization engine ID of this target in hexadecimal notation (22-64 characters) - @@ -106,6 +102,7 @@ + true DES diff --git a/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/AbstractSnmpTargetHandlerTest.java b/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/AbstractSnmpTargetHandlerTest.java index 2ad98869c54..570f3faba57 100644 --- a/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/AbstractSnmpTargetHandlerTest.java +++ b/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/AbstractSnmpTargetHandlerTest.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -156,9 +155,8 @@ public abstract class AbstractSnmpTargetHandlerTest extends JavaTest { if (refresh) { ArgumentCaptor pduCaptor = ArgumentCaptor.forClass(PDU.class); verify(snmpService, timeout(500).atLeast(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler)); - Vector variables = pduCaptor.getValue().getVariableBindings(); - assertTrue(variables.stream().filter(v -> v.getOid().toDottedString().equals(TEST_OID)).findFirst() - .isPresent()); + List variables = pduCaptor.getValue().getVariableBindings(); + assertTrue(variables.stream().anyMatch(v -> v.getOid().toDottedString().equals(TEST_OID))); } else { verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler)); }