/// <summary> /// Queries the given OIDs and returns the value as string or null if the OID is not available. /// </summary> /// <param name="lowerLayer">The lower layer engine to extend.</param> /// <param name="oid">The OID to query.</param> /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param> /// <param name="encoding">If not null, will try to detect whether the string is a hex string and then use the given encoding to decode it.</param> /// <returns>The OID's value as string or null if the OID is not available.</returns> public static string QueryAsString(this ISnmpLowerLayer lowerLayer, Oid oid, string what, Encoding encoding = null) { VbCollection result = lowerLayer.Query(oid); var retVal = result[oid]?.Value?.ToString(); if (retVal == null) { log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as string returned null"); } if ((encoding != null) && (retVal.Length > 0)) { bool couldBeHexString = true; for (int i = 2; i < retVal.Length; i += 3) { if (retVal[i] != ' ') { couldBeHexString = false; break; } } if (couldBeHexString) { retVal = encoding.GetString(retVal.HexStringToByteArray(' ')); } } return(retVal); }
/// <summary> /// Queries the given OIDs and returns the value as OID or null if the OID is not available. /// </summary> /// <param name="lowerLayer">The lower layer engine to extend.</param> /// <param name="oid">The OID to query.</param> /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param> /// <returns>The OID's value as OID or null if the OID is not available.</returns> public static Oid QueryAsOid(this ISnmpLowerLayer lowerLayer, Oid oid, string what) { VbCollection result = lowerLayer.Query(oid); var retVal = result[oid]?.Value as Oid; if (retVal == null) { log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as OID returned null"); } return(retVal); }
/// <summary> /// Queries the given OIDs and returns the value as string or null if the OID is not available. /// </summary> /// <param name="lowerLayer">The lower layer engine to extend.</param> /// <param name="oid">The OID to query.</param> /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param> /// <returns>The OID's value as int or <see cref="int.MinValue" /> if the OID is not available.</returns> public static int QueryAsInt(this ISnmpLowerLayer lowerLayer, Oid oid, string what) { VbCollection result = lowerLayer.Query(oid); int retVal = int.MinValue; if (!(result[oid]?.Value?.TryToInt(out retVal) ?? false)) { log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as string returned null"); } return(retVal); }
/// <summary> /// Queries the given OIDs and returns the value as <see cref="TimeSpan" /> or null if the OID is not available. /// </summary> /// <param name="lowerLayer">The lower layer engine to extend.</param> /// <param name="oid">The OID to query.</param> /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param> /// <returns>The OID's value as <see cref="TimeSpan" /> or null if the OID is not available or cannot be parsed as <see cref="TimeSpan" />.</returns> public static TimeSpan?QueryAsTimeSpan(this ISnmpLowerLayer lowerLayer, Oid oid, string what) { VbCollection result = lowerLayer.Query(oid); var retVal = result[oid]?.Value as TimeTicks; if (retVal == null) { log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as TimeTicks returned null"); return(null); } return(TimeSpan.FromMilliseconds(retVal.Milliseconds)); }
/// <summary> /// Queries the given OIDs and returns the value as string or null if the OID is not available. /// </summary> /// <param name="lowerLayer">The lower layer engine to extend.</param> /// <param name="oids">The OIDs list to query.</param> /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param> /// <returns>The OID's value as int or or <see cref="int.MinValue" /> if the OID is not available.</returns> public static Dictionary <Oid, int> QueryAsInt(this ISnmpLowerLayer lowerLayer, IEnumerable <Oid> oids, string what) { if (oids == null) { throw new ArgumentNullException(nameof(oids), "The array of oids to query is null"); } VbCollection queryResult = lowerLayer.Query(oids); return(queryResult.ToDictionary(qr => qr.Oid, qr => { int retVal = int.MinValue; if (!(qr.Value?.TryToInt(out retVal) ?? false)) { log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as Dictionary<Oid, int>: Conversion to int returned null for response '{qr}'"); } return retVal; })); }
/// <inheritdoc /> public override IDeviceHandler CreateHandler(ISnmpLowerLayer lowerLayer, IQuerierOptions options) { if (!this.detectionId.HasValue) { var ex = new InvalidOperationException("Cannot perform CreateHandler() without previous and successful call to IsApplicable"); this.CollectException("UbntSnmp: CreateHandler(ISnmpLowerLayer, IQuerierOptions)", ex); throw ex; } try { List <Oid> queryList = new List <Oid>(); Oid osVersionOid = null; if (string.IsNullOrWhiteSpace(this.osDetectedVersion)) { osVersionOid = OsVersionRootOid + new Oid(new uint[] { this.detectionId.Value }); queryList.Add(osVersionOid); } Oid modelOid = null; if (string.IsNullOrWhiteSpace(this.detectedModel)) { modelOid = ModelRootOid + new Oid(new uint[] { this.detectionId.Value }); queryList.Add(modelOid); } VbCollection osVersionCollection = null; if (queryList.Count > 0) { osVersionCollection = lowerLayer.Query(queryList); } string osVersionString = (osVersionOid != null) ? osVersionCollection[osVersionOid].Value.ToString() : this.osDetectedVersion; Match match = OsVersionExtractionRegex.Match(osVersionString); SemanticVersion osVersion = match.Success ? match.Groups[1].Value.ToSemanticVersion() : null; string model = (modelOid != null) ? osVersionCollection[modelOid].Value.ToString() : this.detectedModel; if (string.IsNullOrWhiteSpace(model)) { var info = $"Model (retrieved using OID '{modelOid}') is null, empty or white-space-only"; log.Warn(info); var ex = new HamnetSnmpException(info, lowerLayer?.Address?.ToString()); this.CollectException("UbntSnmp: No model", ex); throw ex; } log.Info($"Detected device '{lowerLayer.Address}' as Ubiquiti '{model}' v '{osVersion}'"); DeviceVersion deviceVersion; IDeviceSpecificOidLookup oidTable = this.ObtainOidTable(model.Trim(), osVersion, out deviceVersion, lowerLayer?.Address); if (string.IsNullOrWhiteSpace(deviceVersion.HandlerClassName)) { return((model == AirFiberFakeModelString) ? new UbiquitiAirFiberDeviceHandler(lowerLayer, oidTable, osVersion, model, options) as IDeviceHandler : new UbiquitiAirOsAbove56DeviceHandler(lowerLayer, oidTable, osVersion, model, options) as IDeviceHandler); } else { return(this.GetHandlerViaReflection(deviceVersion.HandlerClassName, lowerLayer, oidTable, osVersion, model, options)); } } catch (Exception ex) { this.CollectException("UbntSnmp: Model detection and OID lookup", ex); // we want to catch and nest the exception here as the APIs involved are not able to append the infomration for which // device (i.e. IP address) the exception is for throw new HamnetSnmpException($"Failed to create handler for Ubiquiti device '{lowerLayer.Address}': {ex.Message}", ex, lowerLayer?.Address?.ToString()); } }