Tuesday, March 10, 2015

Home Water System Pt 2 - Get and Set SNMP

With PowerShell, there's a couple of great options to purchase SNMP libraries to perform SNMP get and set. I had some success with OlePrn.OleSNMP class as UsPeoples, over at tomorrow.uspeoples.org, wrote about, but my success was short lived. It only supports SNMPv1 and attempting to do any of the Methods from three of my Windows 7 computers returns:

Exception calling "Get" with "1" argument(s): "WinSNMP API Error: For internal/undefined errors"
At line:1 char:10
+ $SNMP.Get <<<< (".1.3.6.1.2.1.1.5.0")
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

Alternatively, I've been using a command-line (CLI) tool with PowerShell and capturing the output. Since there are a few old CLI tools for SNMP that are free, like snmpget.exe and snmpset.exe by snmpsoft (dot) com. I've been using this for my SNMP get and set routines to control my home brewed SCADA system for nearly a year now with no issue.

So, where do we get started?

You can capture any output from a CLI tool fairly easily. Just run the program inside of a PowerShell variable value, as such:

$output = mycli.exe

That seems simple enough. Next, you need to ensure that you capture all of your CLI tool's output - or at least I prefer to - including any errors which sometimes sneak by. about_Redirection describes that 2>&1 at the end of your CLI tool will capture your success output along with any error output. You can also include all output with *>&1 - to each their own, but I prefer just errors and success output.

$output = mycli.exe 2>&1

Wrap it all tight in a few functions and you just saved some dollars... on SNMP get and set funcitons.

PowerShell get-snmp function
  <#  
 .SYNOPSIS  
  Function to capture output from snmpget exe CLI tool.  
    
 .DESCRIPTION   
  Based on the parameters sent, the CLI tool will be triggered and the output will be returned based on the output.  
    
 .NOTES   
  Author   : Justin Bennett   
  Date     : 2015-03-10  
  Contact  : http://www.allthingstechie.net
  Revision : v1.01
  Changes  : v1.01 - Changed Write-Error to Throw  
   
 .PARAMETER ip  
  IP Address or Hostname  
   
 .PARAMETER ver  
  SNMP Version  
   
 .PARAMETER community  
  SNMP Community String to read the OID  
   
 .PARAMETER OID  
  SNMP OID to read  
   
 .PARAMETER returntype  
  Specify the preferred return type - gauge32, integer, string (Default), timeticks, or todate   
    
 .EXAMPLE  
  C:\PS> get-snmp -ip "192.168.0.10" -ver "1" -community "public" -oid "1.3.6.1.2.1.1.5.0"  
  sysLocation-Example  
    
 .EXAMPLE  
  C:\PS> #Get SNMP Contact Info  
  C:\PS> $oid = "1.3.6.1.2.1.1.4.0", "1.3.6.1.2.1.1.5.0", "1.3.6.1.2.1.1.6.0"  
  C:\PS> $oid | % { get-snmp -ip "192.168.0.10" -ver "1" -community "public" -oid $_ }  
  sysName-Example  
  sysLocation-Example  
  sysServices-Example  
 #>  
 function get-snmp {  
      [CmdletBinding()]  
      param (  
           [parameter(Mandatory = $true)] [string]$ip,  
           [parameter(Mandatory = $true)] [string]$ver,  
           [parameter(Mandatory = $true)] [string]$community,  
           [parameter(Mandatory = $true)] [string]$oid,  
           [parameter(Mandatory = $false)] [ValidateSet("timeticks","integer","gauge32","string","todate")] [string]$returntype = "string"  
      )  
        
      #location of the snmpget program  
      $snmpdir = ".\"  
   
      $output = (. $snmpdir\snmpget.exe -v:$ver -c:"$community" -r:$ip -o:$oid 2>&1) | select -skip 3  
      $outputsplit = $output -split "="  
        
      if ($outputsplit[0].tolower() -ne "oid") {  
           #one more try  
           $output = (. $snmpdir\snmpget.exe -v:$ver -c:"$community" -r:$ip -o:$oid 2>&1) | select -skip 3  
           $outputsplit = $output -split "="  
      }  
        
      switch ($outputsplit[0].tolower()) {  
       "oid" {  
           if($returntype -eq $null) { $returntype = $outputsplit[3] }  
           switch ($returntype.tolower()) {  
                 "timeticks" {  
                     $time = ($outputsplit[5]) -replace "\.", ":" -split ":"  
                     return New-TimeSpan -hour $time[0] -min $time[1]  
                     }  
                 "integer" {  
                     return [int]$outputsplit[5]  
                     }  
                 "gauge32" {  
                     return [int]$outputsplit[5]  
                     }  
                 "string" {  
                     return [string]$outputsplit[5]  
                     }  
                 "todate" {  
                     return [datetime](get-date (($outputsplit[5]) -replace "`"",""))  
                     }  
                 default{  
                     return $outputsplit[5]  
                }  
           }  
    }  
       default {  
             throw $output  
           }  
      }  
 }    
Formatted for web with http://codeformatter.blogspot.com/ 

Example Output

Cheers. Even more pieces to the puzzle coming soon.


No comments: