Go Down

Topic: Agentuino - A lightweight SNMP Agent (Read 21 times) previous topic - next topic

Steve1337

Code: [Select]
#include <Agentuino.h>

#include <Agentuino.h>

/**
* Agentuino SNMP Agent Library Prototyping...
*
* Copyright 2010 Eric C. Gionet <lavco_eg@hotmail.com>
*
*/
#include <Streaming.h>         // Include the Streaming library
#include <Ethernet.h>          // Include the Ethernet library
#include <MemoryFree.h>
#include <Agentuino.h>
#include <avr/pgmspace.h>
//
static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
static byte ip[] = { 192, 168, 2, 64 };
static byte gateway[] = { 192, 168, 1, 190 };
static byte subnet[] = { 255, 255, 255, 0 };
//
//
// RFC1213-MIB OIDs
static char sysDescr[] PROGMEM      = "1.3.6.1.2.1.1.1.0";  // read-only  DisplayString
static char sysObjectID[] PROGMEM   = "1.3.6.1.2.1.1.2.0";  // read-only  (ObjectIdentifier)
static char sysUpTime[] PROGMEM     = "1.3.6.1.2.1.1.3.0";  // read-only  (TimeTicks)
static char sysContact[] PROGMEM    = "1.3.6.1.2.1.1.4.0";  // read-write (DisplayString)
static char sysName[] PROGMEM       = "1.3.6.1.2.1.1.5.0";  // read-write (DisplayString)
static char sysLocation[] PROGMEM   = "1.3.6.1.2.1.1.6.0";  // read-write (DisplayString)
static char sysServices[] PROGMEM   = "1.3.6.1.2.1.1.7.0";  // read-only  (Integer)
//
//
/* RFC1213 local values */
static char locDescr[] PROGMEM      = { "Agentuino, a light-weight SNMP Agent." };  // read-only (static)
static char locObjectID[] PROGMEM   = "1.3.6.1.3.2009.0";                       // read-only (static)
static long locUpTime               = 0;                                        // RTC is needed for this unless the NTP Time library is used
static char locContact[20]          = "Eric Gionet";
static char locName[20]             = "Agentuino";
static char locLocation[20]         = "Nova Scotia, CA";
static short locServices PROGMEM    = 7;                                        // read-only (static)

AgentuinoClass agent = Agentuino();

SNMP_SESSION session;


void pduReceived()
{
  char oidString[SNMP_MAX_OID_LEN];
  SNMP_PDU pdu;
  //
  Serial << "UDP Packet Received Start.." << " RAM:" << freeMemory() << endl;
  //
  agent.requestPdu(&pdu);
  //
  pdu.OID.toString(oidString);
  //
  Serial << "OID: " << oidString << endl;
  //
  if ( pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GET_NEXT ) {
    //
    if ( strcmp_P(oidString, sysName) == 0 ) {
      //
      // response packet - locName
      pdu.type = SNMP_PDU_RESPONSE;
      pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locName);
      //
      Serial << "sysName..." << locName << " " << pdu.VALUE.size << endl;
      //
      agent.responsePdu(&pdu);
    } else {
      // oid does not exist
      //
      // response packet - object not found
    }
  }
  //
  agent.freePdu(&pdu);
}

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  //
  session.getCommName = "public";
  session.setCommName = "private";
  session.port = 161;
  //
  agent.initSession(&session);
  agent.onPduReceive(pduReceived);
  //
  delay(10);
  //
  Serial.println("Initalized...");
}

void loop()
{
  agent.listen();
}

LAVco

Please take a look at the library's class constructor to see how to use the session struct.  Based on your posted code your missing some parameters.

Code: [Select]
// set community name set/get sizes

session->setSize = strlen(session->setCommName);

session->getSize = strlen(session->getCommName);

//

// validate get/set community name sizes

if ( session->setSize > SNMP_MAX_NAME_LEN || session->getSize > SNMP_MAX_NAME_LEN ) {

return SNMP_API_STAT_NAME_TOO_BIG;

}

//

// set session property

_session = session;

//

// validate session port number

if ( session->port == NULL || session->port == 0 ) session->port = SNMP_DEFAULT_PORT;

//

// init UDP socket

_socket.initUDP(session->port);

//

return SNMP_API_STAT_SUCCESS;
Common sense is not so common...

yesyes

I'm afraid I need a little more help with the SNMP library and possibly the underlying Ethernet library...

It's been a while but I've now come back to troubleshooting / debugging my weather station sketch. The problem is that occasionally a received packet gets stuck and is being processes over and over again. I'm not sure what that packet is but it's definitely not an SNMP packet.

What I have done is I added lots and lost of serial port output to the sketch and I keep a machine running to log that output to a file. I have attached both the sketch and the part of the log file that shows the sketch running into the problem.

The problem starts at line 2170 in the log.txt. What is happening is that (for some reason) the Arduino receives an unknown packet from the same IP that usually sends the SNMP GET requests. Since it is not a valid SNMP packet, the following if statement is not true (from line 200 in the sketch):

Code: [Select]
  // check if valid packet
  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 )
    {


So the sketch jumps to the following else statement (line 505)

Code: [Select]
  else
  // packet not valid, send GENERAL_ERROR response. Required, otherwise the invalid packet
  // will get stuck in the buffer and processed over and over again
 
  {
    Serial << "Unknown Packet!!" << endl;
    Serial << "PDU Type: " << pdu.type << " PDU Error: " << pdu.error << " API status: "<< api_status << endl;
    Serial << "from IP: " << Agentuino.g_dstIP(0) << "." << Agentuino.g_dstIP(1) << "." << Agentuino.g_dstIP(2) << "." << Agentuino.g_dstIP(3) << endl;   
    pdu.type = SNMP_PDU_RESPONSE;
    pdu.error = SNMP_ERR_GEN_ERROR;
//    Agentuino.responsePdu(&pdu);
    Serial << "Sent 'GENERAL_ERROR' response" << endl;
  }


So far so good. However, the next time and all subsequent times I call Agentuino.listen() that same packet is still in the buffer. No further received packets are being processed.

The question is, why does this packet stay in the buffer? Is there a way to flush the buffer from my sketch (or from Agentuino) if an unknown packet is being received? I've been through all the components of the Ethernet library (Udp, Ethernet, W5100, socket) and also the Agentuino library to figure out where and how the packet buffer is released but I couldn't find it.

BTW, the method Agentuino.g_dstIP() is one I added to the Agentuino library in order to get the IP address where the packet came from in an attempt to determine what the nature of the offending packets is.
Chris

Location: Berkshire, UK
My Astro and DIY projects website: http://yesyes.info/

yesyes

Hmmm, nobody? I was hoping LAVco would read this... ;-)
Chris

Location: Berkshire, UK
My Astro and DIY projects website: http://yesyes.info/

bborncr

#14
Dec 09, 2011, 01:41 pm Last Edit: Dec 09, 2011, 02:45 pm by bborncr Reason: 1
Yesyes,

I been using your Weather Station code as a basis to create a simple test using a TMP36 temperature sensor connected to analog0.  For the most part everything works well.  However, there are two problems:
1. The device does not respond if I connect the power (wall wart or usb).  Only after pressing reset does everything start working.
2. After a few hours the device hangs up and the SNMP stops responding.  I can still ping the device but no SNMP until I do a reset.

By comparing the first Weather Station code that I found initially in a previous post and the code in the post above I saw that you added a watchdog timer to the setup routine.  I don't know what a watchdog timer is but I added it and will be testing for stability.  Any tips would be greatly appreciated.

Also, I noticed that this line is commented out //    Agentuino.responsePdu(&pdu);


Have had any luck troubleshooting your issues?

The Agentuino library seems to be such a useful tool if it could be polished just a little more.  I wonder if anyone would work on it for a bounty?

Go Up