---
title: "Cosa-SNMP"
url: "https://maker.wiznet.io/teddy/projects/cosa-snmp/"
markdown_url: "https://maker.wiznet.io/teddy/projects/cosa-snmp/md"
type: "UCC: User Created Content"
author: "Cosa-SNMP"
author_url: "https://github.com/mikaelpatel/Cosa-SNMP"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "Cosa-SNMP"
original_url: "https://github.com/mikaelpatel/Cosa-SNMP"
published: "2022-11-28"
language: "en"
likes: 2
views: 640
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# Cosa-SNMP

> Cosa-SNMP

Original author: Cosa-SNMP (source: https://github.com/mikaelpatel/Cosa-SNMP)

## Documents and links

- [cosa_snmp](https://github.com/mikaelpatel/Cosa-SNMP.git) (code)

## Article

/**
* @file CosaSNMP.ino
* @version 1.0
*
* @section License
* Copyright (C) 2014-2015, Mikael Patel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* @section Description
* W5100 Ethernet Controller device driver example code; SNMP agent
* with support for GET/GETNEXT/SET for MIB-2 SYSTEM and Arduino MIB.
*
* @section Circuit
* This sketch is designed for the Ethernet Shield.
* @code
* W5100/ethernet
* +--------------+
* (D10)--------------29-|CSN |
* (D11)--------------28-|MOSI |
* (D12)--------------27-|MISO |
* (D13)--------------30-|SCK |
* (D2)-----[ ]-------56-|IRQ |
* +---------------+
* @endcode
*
* @section Testing
* Test with Linux snmp commands:
* 1. Access the MIB-2 SYSTEM (sysDescr)
* snmpget -v1 -c public {W5100_IP} 1.3.6.1.2.1.1.1
* 2. Access the Arduino MIB (ardDigitalPin.0)
* snmpget -v1 -c public {W5100_IP} 1.3.6.1.4.1.36582.1.0
* 3. Walk all available OID tree
* snmpwalk -v1 -c public {W5100_IP} 1
*
* This file is part of the Arduino Che Cosa project.
*/

#include &lt;DHCP.h>
#include &lt;DNS.h>
#include &lt;SNMP.h>
#include &lt;W5X00.h>
#include &lt;W5100.h>
// #include &lt;W5200.h>

#include "Cosa/Memory.h"
#include "Cosa/InputPin.hh"
#include "Cosa/AnalogPin.hh"
#include "Cosa/Trace.hh"
#include "Cosa/Watchdog.hh"
#include "Cosa/UART.hh"

// Comment this out to remove some tracing and reduce memory usage
#define PRINT_PDU

// Network configuration
// If WS5100 board has a MAC sticker then use here instead of this default
static const uint8_t mac[6] __PROGMEM = { 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed };
// If no DHCP on network set these
// #define USE_FIXED_IP 192,168,1,100
// #define SUBNET 255,255,255,0

// Disable SD on Ethernet Shield
#define USE_ETHERNET_SHIELD
#if defined(USE_ETHERNET_SHIELD)
#include "Cosa/OutputPin.hh"
OutputPin sd(Board::D4, 1);
#endif

W5100 ethernet(mac);
// W5200 ethernet(mac);

/**
* Arduino MIB OID(1.3.6.1.4.1.36582)
*/
class ARDUINO_MIB : public SNMP::MIB {
private:
enum {
ardDigitalPin = 1, // Digital pin[0..19](0..1), read-only
ardAnalogPin = 2, // Analog pin[0..5](0..1023), read-only
ardVcc = 3, // Power supply[0](0..VCC), mV, read-only
} __attribute__((packed));

public:
static const uint8_t OID[] PROGMEM;
/**
* @override SNMP::MIB
* Return object identity root for Arduino MIB.
*/
virtual const uint8_t* oid()
{
return (OID);
}

/**
* @override SNMP::MIB
* Handle Arduino MIB objects SNMP requests. Returns true and
* value for SNMP::GET in given protocol data unit, otherwise false.
* @param[in,out] pdu protocol data unit.
* @return bool
*/
virtual bool is_request(SNMP::PDU& pdu);
};
// Arduino MIB OID(1.3.6.1.4.1.36582)
const uint8_t ARDUINO_MIB::OID[] __PROGMEM = { 8,0x2b,6,1,4,1,130,157,102 };

// SNMP MIB-2 System configuration
static const char descr[] __PROGMEM = "&lt;service description>";
static const char contact[] __PROGMEM = "&lt;contact information>";
static const char name[] __PROGMEM = "&lt;device name>";
static const char location[] __PROGMEM = "&lt;device location>";
SNMP::MIB2_SYSTEM mib2(descr, contact, name, location, ARDUINO_MIB::OID);
SNMP snmp;

bool
ARDUINO_MIB::is_request(SNMP::PDU& pdu)
{
uint8_t mib_baselen = pgm_read_byte(OID);
if(pdu.oid.length > (mib_baselen + 2)) return (false);

// Match with Arduino MIB OID root
int sys = pdu.oid.match(oid());
if (sys &lt; -1) return (false); // MIB is greater than what we deal with
int index = ((pdu.oid.length == (mib_baselen + 2)) ? pdu.oid.name[mib_baselen+1] : -1);
// Get next value request; adjust sys and index references to next
if (pdu.type == SNMP::PDU_GET_NEXT) {
if (sys &lt;= 0) {
memcpy_P(&pdu.oid, OID, mib_baselen + 1);
sys = ardDigitalPin;
}
switch (sys) {
case ardDigitalPin:
if (index &lt; 19)
index += 1;
else {
index = 0;
sys = ardAnalogPin;
}
break;
case ardAnalogPin:
if (index &lt; 5)
index += 1;
else {
index = 0;
sys = ardVcc;
}
break;
case ardVcc:
return (false);
}
pdu.oid.name[mib_baselen] = sys;
pdu.oid.name[mib_baselen + 1] = index;
pdu.oid.length = mib_baselen + 2;
pdu.type = SNMP::PDU_GET;
}

// Check request type
if ((index &lt; 0) || (sys &lt; ardDigitalPin) || (sys > ardVcc)) return (false);

// Get value for digital or analog pin, or power supply voltage
if (pdu.type == SNMP::PDU_GET) {
switch (sys) {
case ardDigitalPin:
if (index > 19)
pdu.error_status = SNMP::NO_SUCH_NAME;
else {
Board::DigitalPin pin;
pin = (Board::DigitalPin) pgm_read_byte(&digital_pin_map[index]);
pdu.value.encode(SNMP::SYNTAX_INT, (int16_t) InputPin::read(pin));
}
break;
case ardAnalogPin:
if (index > 5)
pdu.error_status = SNMP::NO_SUCH_NAME;
else {
Board::AnalogPin pin;
pin = (Board::AnalogPin) pgm_read_byte(&analog_pin_map[index]);
pdu.value.encode(SNMP::SYNTAX_INT, (int16_t) AnalogPin::sample(pin));
}
break;
case ardVcc:
if (index > 0)
pdu.error_status = SNMP::NO_SUCH_NAME;
else
pdu.value.encode(SNMP::SYNTAX_INT, (int16_t) AnalogPin::bandgap());
break;
}
}

// Set value is not allowed (yet)
else if (pdu.type == SNMP::PDU_SET) {
pdu.error_status = SNMP::READ_ONLY;
}
return (true);
}

ARDUINO_MIB arduino;

void setup()
{
uint8_t ip[4]
#if defined(USE_FIXED_IP)
= { USE_FIXED_IP };
#else
;
#endif
uint8_t subnet[4]
#if defined(SUBNET)
= { SUBNET };
#else
;
#endif

// Start watchdog and uart. Use uart for trace output
uart.begin(9600);
trace.begin(&uart, PSTR("CosaSNMP: started"));
Watchdog::begin();
AnalogPin::powerup();

// Start ethernet controller and request network address for hostname
#if defined(USE_FIXED_IP)
ASSERT(ethernet.begin(ip, subnet);
#else
ASSERT(ethernet.begin_P(PSTR("CosaSNMPAgent")));
#endif

// Print the given or default network address
ethernet.addr(ip, subnet);
trace &lt;&lt; PSTR("IP = ");
INET::print_addr(trace, ip);
trace &lt;&lt; endl;

// Print some memory statistics
TRACE(free_memory());
TRACE(sizeof(W5100));
TRACE(sizeof(SNMP));
TRACE(sizeof(SNMP::OID));
TRACE(sizeof(SNMP::VALUE));
TRACE(sizeof(SNMP::PDU));
TRACE(sizeof(SNMP::MIB2_SYSTEM));
TRACE(sizeof(ARDUINO_MIB));

// Start the SNMP manager with a connection-less socket
ASSERT(snmp.begin(ethernet.socket(Socket::UDP, SNMP::PORT), &mib2, &arduino));
}

void loop()
{
// Service SNMP requests with given MIB handlers
SNMP::PDU pdu;
if (snmp.request(pdu) &lt; 0) return;

#if defined(PRINT_PDU)
// Print available memory and resulting protocol data unit
TRACE(free_memory());
trace &lt;&lt; pdu &lt;&lt; endl;
#endif
}

---

Source: https://maker.wiznet.io/teddy/projects/cosa-snmp/
