Go Down

Topic: Cosa SNMP agent library (Read 949 times) previous topic - next topic

kowalski

The second increment of the SNMP agent support is completed. The example sketch demonstrates SNMP MIB-2 handling (system attributes) and example Arduino MIB with digital pin, analog pin and power supply voltage read.

An OID match function (SNMP::OID::match) has been introduced to make it easy to compare request PDU OIDs and dispatch GET/SET response code. Below is a snippet from the updated CosaSNMP.ino example sketch; https://github.com/mikaelpatel/Cosa/blob/master/examples/Ethernet/CosaSNMP/CosaSNMP.ino
Code: [Select]

bool system_mib(SNMP::PDU& pdu)
{
  // Match with SNMP MIB-2 System OID root
  int sys = pdu.oid.match(SNMP::MIB2_SYSTEM);
  if (sys < SNMP::sysDescr || sys > SNMP::sysServices) return (false);

  // Get system value
  if (pdu.type == SNMP::PDU_GET) {
    switch (sys) {
    case SNMP::sysDescr:
      ...
      break;
    ...
    }
  }

  // Set system value
  else if (pdu.type == SNMP::PDU_SET) {
    switch (sys) {
    case SNMP::sysContact:
      ...
      break;
    default:
      pdu.error_status = SNMP::READ_ONLY;
    }
  }
  return (true);
}

The example root OIDs (SNMP::MIB2_SYSTEM and SNMP::ARDUINO_MIB) are defined in program memory to reduce SRAM usage. Below are the definitions in SNMP.hh. Note that the root OID is a length prefixed sequnce of bytes and the access object is defined as a symbol in an enum to allows simple switch-case dispatch as above.
Code: [Select]

class SNMP {
public:
  ...
  // SNMP MIB-2 System OID(1.3.6.1.2.1.1)
  const static uint8_t MIB2_SYSTEM[] PROGMEM;
  enum {
    sysDescr = 1, // DisplayString(0..255), read-only, mandatory
    sysObjectID = 2, // OID, read-only, mandatory
    sysUpTime = 3, // TimeTicks, read-only, mandatory
    sysContact = 4, // DisplayString(0..255), read-write, mandatory
    sysName = 5, // DisplayString(0..255), read-write, mandatory
    sysLocation = 6, // DisplayString(0..255), read-write, mandatory
    sysServices = 7 // Integer(0..127), read-only, mandatory
  } __attribute__((packet));

  // Arduino MIB OID(1.3.6.1.4.1.36582)
  const static uint8_t ARDUINO_MIB[] PROGMEM;
  enum {
    ardDigitalPin = 1, // DigitalPin[0..22](0..1), read-write
    ardAnalogPin = 2, // AnalogPin[0..7](0..1023), read-only
    ardVcc = 3,         // Power supply[n](0..VCC), mV, read-only
  } __attribute__((packet));
  ...
};

Some examples of access with snmpget and snmpwalk. The options and parameters are (left-to-right); debug mode, version(1), community string(public), device network address and object identity(OID).
Code: [Select]

# Get value of digital pin 8
snmpget -d -v 1 -c public 192.168.0.22 0.1.3.6.1.4.1.36582.1.8
# Get value of analog pin 4
snmpget -d -v 1 -c public 192.168.0.22 0.1.3.6.1.4.1.36582.2.4
# Get power supply voltage (in milli-volt)
snmpget -d -v 1 -c public 192.168.0.22 0.1.3.6.1.4.1.36582.3.0
# Get system uptime
snmpget -d -v 1 -c public 192.168.0.22 0.1.3.6.1.2.1.1.3

The command snmpwalk (and snmpgetnext) can be used to iterate over the MIB and access all value; System MIB settings and status (uptime), and the Arduino Pins (Digital, Analog) and Power supply voltage. Below is a test run.
Code: [Select]

$ snmpwalk -v1 -c public 192.168.0.22 0
ccitt.1.3.6.1.2.1.1.1 = STRING: "<description>"
ccitt.1.3.6.1.2.1.1.2 = OID: ccitt.9.1.3.6.1.4.1.36582
ccitt.1.3.6.1.2.1.1.3 = 806
ccitt.1.3.6.1.2.1.1.4 = STRING: "<your name>"
ccitt.1.3.6.1.2.1.1.5 = STRING: "<device name>"
ccitt.1.3.6.1.2.1.1.6 = STRING: "<device location>"
ccitt.1.3.6.1.2.1.1.7 = INTEGER: 66
ccitt.1.3.6.1.4.1.36582.1.0 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.1 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.2 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.3 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.4 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.5 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.6 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.7 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.8 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.9 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.10 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.11 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.12 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.13 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.14 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.15 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.16 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.17 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.18 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.19 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.20 = INTEGER: 1
ccitt.1.3.6.1.4.1.36582.1.21 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.1.22 = INTEGER: 0
ccitt.1.3.6.1.4.1.36582.2.0 = INTEGER: 1023
ccitt.1.3.6.1.4.1.36582.2.1 = INTEGER: 1023
ccitt.1.3.6.1.4.1.36582.2.2 = INTEGER: 753
ccitt.1.3.6.1.4.1.36582.2.3 = INTEGER: 620
ccitt.1.3.6.1.4.1.36582.2.4 = INTEGER: 510
ccitt.1.3.6.1.4.1.36582.2.5 = INTEGER: 437
ccitt.1.3.6.1.4.1.36582.2.6 = INTEGER: 368
ccitt.1.3.6.1.4.1.36582.2.7 = INTEGER: 336
ccitt.1.3.6.1.4.1.36582.3.0 = INTEGER: 4673
End of MIB

Cheers!

Fred_Tuga

Hi all,

What about to receive SNMP Trap?
Anyone knows if there is a library to show the information of received traps?

How can I manage incoming SNMP Traps with Arduino?

Thanks and best regards,
Fred

Go Up