Agentuino - A lightweight SNMP Agent

I've been away. It does check the lengths of a data type when parsed.

If anyone would like to contribute please send their e-mail in a private message.


Please excuse the thread intrerruption and the newbie question: Can i use the SNMP agent code to make the arduino a SNMP host? I want to read some values from a router and output a PWM signal from the arduino based on them.

Hi, I have recently started a project using the Agentuino library. The project is a weather station with several sensors. The values of the sensors can be requested via SNMP and logged/graphed in Cacti (or similar).

I got this all more or less working but have now run into some issues.

First, Cacti seems to send some default SNMP requests to the agent that are not directly related to the requested value/OID. When the Arduino receives a packet that is not covered in the pduReceived() function, the packet seems to get stuck somewhere. The whole else if construction in the sample sketch (plus my own OIDs added) falls through because no OID matches. Then the pdu is freed. However, the next time I call Agentuino.listen() the same packet seems to be there still. So that creates an endless loop and no further SNMP GET requests will be processed.

So in other words, if I send a GET request that is handled in my sketch, all is fine. But if an unknown packet is being sent to the Arduino, there is an issue.

I've tried to work around it by doing the following:

if ( (pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GET_NEXT || pdu.type == SNMP_PDU_SET) && pdu.error == SNMP_ERR_NO_ERROR && api_status == SNMP_API_STAT_SUCCESS ) { // handle OID requests as in sample sketch } else { pdu.type = SNMP_PDU_RESPONSE; pdu.error = SNMP_ERR_GEN_ERROR; Agentuino.responsePdu(&pdu); }

That has stopped the endless loop but now the Arduino resets shortly after receiving an unknown packet.

The other issue is that Cacti seems to think that my room is 80 million degrees hot. :o When I use Presser SNMP Tester to send test GET requests, I get a normal temperature reading of, say, 24 degrees. In Cacti it is being graphed as 80 million. There seems to be a data format issue that I haven't figured out yet.

This is what I do if I get a GET request for the Object Temperature:

// response packet from get-request - v_ObjTemp status = pdu.VALUE.encode(SNMP_SYNTAX_INT32, v_ObjTemp); pdu.type = SNMP_PDU_RESPONSE; pdu.error = status;

I see in SNMP Tester and in Wireshark that the response has a value of 24 (for example) and is 4 bytes long.

I'll work on these 2 today and report back but I think I might need a little help with this. So if anyone has any ideas, they would be more than welcome.

I just thought of something. Does the Agentuino lib check if a received packet is indeed an SNMP packet and only then pass it to the sketch? Or would it be possible that any other UDP packet could be reported in pduReceived() ? Would I need to handle that in the sketch?

OK, I think I figured both out.

The Agentuino lib does NOT like receiving another GET request before it has responded to the previous one. The workaround was to increase the time-out value to 1500ms in Cacti. This causes Cacti to wait 1.5 sec for a response (instead of the default 500ms) before re-transmitting the request. Since the Arduino does reply within 1.5 sec, Cacti does not need to re-transmit the request. With my current code the Arduino takes just under 1 sec to reply.

It would be nice if the lib could handle this a bit better. But I guess with 2kB of RAM, you can't buffer more than one packet?

The problem with the values being in the millions was solved by specifying "GAUGE" as the data type in Cacti. Before I used ABSOLUTE, which seems to interpret the data differently. So that was not an issue with the Agentuino lib.


You mentioned that you are using SNMP to read data from your arduino weather station. Are the sensors read using non-blocking calls? Simple test is to place a timer variable at the beginning of your loop and see how long it take to cycle without making an SNMP call. This may explain why there is latency between SNMP requests.

I am using a Sensirion SHT?? (Temp/RH) and Intersema BP sensor both over serial or bit bang (together and plan on adding a second BP sensor)) and I don't have a latency problem. Keep mind that both libraries I have written for these sensors have non-blocking capabilities.

And yes the library does detect non-snmp packets, although there is always room to improve on the implemented method.


Myself and John D. have been busy (work pays and this doesn't he he) since we started the project and orbitalair is hardware stricken till he can get a new ethernet sheild or port an ethernet lib. Although it seems that the wiznet and other chipsets have become the arduino standard. Anyway hopefully Santa comes through for orbitalair and drops off a new ethernet shield :)

I do intend on spending more time on this project in the new year as it ties into another project I am working on.

As per the project's web site (; this is an Alpha library and were looking for others to contribute.

Alcor wrote; Please excuse the thread intrerruption and the newbie question: Can i use the SNMP agent code to make the arduino a SNMP host? I want to read some values from a router and output a PWM signal from the arduino based on them.

Yes, you could use code from agentuino to talk to a host. Instead of listening, your requesting and waiting for a response. In theory the PDU can be used interchangeably.

If you decide to cut code and get it working please share your findings with us.



LAVco, I use blocking calls when reading the sensors. But I don't read them when an SNMP request comes in. I read the Melexis temperature sensor continuously once per loop(). I've added a SHT15 last night and that is being read at least 10 seconds after the previous read (to stop it from getting warm and mess up my readings). The values are stored in global variables. When the SNMP request comes in, it just replies with the value from the variable.

I have put everything back outside now collecting data. So I can't change code right now (I wish there was a way to update the sketch via the Eth shield instead of USB). Will try it as soon as I bring it in for "maintenance" again or as soon as my 2nd Arduino arrives (which ever is sooner).

I'm really glad you made this library. I'd like to contribute but I'm not a good programmer. I do know some C / C++ and have written small MFC apps on Windows. So the Arduino API feels a bit familiar. But I'm not sure what I could contribute. Maybe some testing?

I still think there is some sort of issue in agentuino when a non-SNMP packet is received. When I call Agentuino.listen() and there was a packet received, I HAVE to send a response packet back, otherwise it will end up in an endless loop trying to process the previous packet.

Another question:

Can you think of any way of supporting a float data type in agentuino? I'd like to send my temperature data with one or 2 decimal places. Currently you only seem to have some integers and strings.

yesyes wrote; Can you think of any way of supporting a float data type in agentuino? I'd like to send my temperature data with one or 2 decimal places. Currently you only seem to have some integers and strings.

SNMP doesn't support floating points. Strings are possible as per included example e.g. sysName and sysDescr but read the limitations section on our main project page.

Now back to floating point values, as the saying goes, there is more than one way to skin a cat! Use multipliers and divisors.

Know what your measuring; based on the sensor and parameter being measured there is always a max/min range and resolution that it can measure. So let's use Temperature and RH as an example. Say the sensor measures temperature from 70 deg C to -40 deg C and RH from 0 to 100 %.

INT is 65535 (unsigned 16bit int) but it can handle signed values as well -32000 to 32000 (approximation but a 16bit float)

Temperature: 70.00 (upper range) = 7000 (x100) -40.00 (lower range) = 4000 (x100)

To normalize this further for other types of sensors (some can measure down to -50 deg C etc.) we could simply use 10,000 (max upper range) and -10,000 (min lower range) having an error value of 10,001. So if the system detects an out of bound measurement (out of range of the sensor's parameter being measured) you can flag it as an error. So if you receive an SNMP value of 2345, simply divide by 100 to get 23.45 deg C.

RH (floating point with RH is rarely used due to the type of measurement - it's relative :) ) 0 (lower range) = 0 100 (upper range) = 100

RH is always 0 to 100 (%) and again you could use 101 to reflect an error.

Resolution; if the sensor's parameter's resolution is only 0.1, your not adding accuracy by offering a resolution of 0.01.

The error codes aren't required and are used as basic QA/QC (meteorological QA/QC is a whole other subject).

On the string side, are you sure you need strings e.g. you can use enumerators in SNMP which consume an INT value versus a string (in the MCU wold that's needless memory consumption). For example, Precipitation Situation; 1-Light Rain, 2-Moderate Rain, 3-Heavy Rain.

I read the Melexis temperature sensor continuously once per loop

You don't need to sample that frequently for meteorological related applications. As per WMO/NWS standards it is recommended to sample air temperature at either 3 or 5 second intervals and is averaged over 1-minute. Soil temperature is sampled every minute due to the slow rate of change.

Hope this shed's some light on measurements using SNMP. The above examples are methodologies used in existing meteorological standards that I have been involved with.



Thanks for that. I did think of that way of doing it. But (at least for now) for me the only purpose of using SNMP is to graph (and store) the data with Cacti. And that doesn't seem to have an option to divide received data by 10 or 100. At least none that I could find. I'll have a poke around. Maybe a Cacti script could help.

I only mentioned the strings because you already support them. I won't use them other than for the standard system name and so on. They are hard to graph .. :P

In the end this weather station will go in my observatory (a roll-off roof shed with a telescope inside), record weather data and warn me when there's cloud and rain. And eventually close the roof when it starts raining. But that's not even built yet... ;)

yesyes I took a quick look at Cacti (seems like a pretty cool tool) and it's based on the RRDTool. The RRDTool round-robin database does support divisors.

If you haven't done so yet, I would subscribe to their forum and ask.

Sounds like a pretty neat project your undertaking. Good luck.

Also, I am waiting for TangoAlpha to upload his updates so I can add some updates that I've done as well.



Correction; RRDTool graphing portion supports divisors.

Hi, just wanted to report back with success... ;-) I have asked on the Cacti forum after failing to find anything in the Cacti documentation. Got an answer from a developer that pointed me in the right direction. While you can't modify data before being written to the database, you can apply math to the data before being graphed. So I now send (float_value * 100) converted to an int32 from the Arduino and when generating a graph it automatically divides everything by 100 again. Nice.

Thanks to you, LAVco, for pointing me in the right direction....

Hi All,

An updated library was uploaded to Google Code

  • decode functions were corrected (byte array, uint, int, etc)
  • all malloc calls were removed

We would like to thank TangoAlpha for detecting and correcting decoding bugs.

More to come and keep us posted should you find a bug.



Thanks for the new version. Any chance of more details on the fixed bugs? Is there a changelog? ;) There was an issue when a new SNMP request comes in before the current one had been fully processed and replied to. Has this been fixed by any chance? :)

Example graphs from my web server created using Cacti...

Hardware: Arduino Uno, I2C pressure/temperature sensor, LDR, ethernet shield v2

Software: Agentuino SNMP library, (extended) I2C library

Interesting TangoAlpha. Your project is very similar to mine… :wink:

yesyes wrote: There was an issue when a new SNMP request comes in before the current one had been fully processed and replied to. Has this been fixed by any chance?

This problem can be resolved by using an RTOS :) The problem lies in two areas; your sketch and the Ethernet chipset. If your sketch has blocking calls you are going to run into latency and race condition issues. The Ethernet chipset buffers incoming requests and the atmel MCU will process when interrupted if it can. If the MCU is blocked by a blocking call it can't do anything else till it's done.

AlphaTango What are the units on the light graph? Lux,etc.?


What are the units on the light graph? Lux,etc.?

The sensor is a light dependent resistor. The data is inverted and scaled roughly so that the brightest sunshine should be around 1024 and darkness is 0.

The Arduino will eventually become an outdoor weather station once I have a PoE ethernet shield.

The weather station data will be used in two ways...

  1. Logged as simple weather data
  2. As input into a bespoke heating controller (a work in progress), in order to create a more efficient central heating system

For 2, I only really need the light data to further qualify the temperature reading (whether the sun will effect it or not) so the actual value (Lux or otherwise) is not important to me.