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
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.
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).
# 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.
$ 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!