Hi MarsWarrior,
its a Mega, so there is plenty of mem - more than 7300 bytes.
this is my loop :
// Service SNMP requests with given MIB handlers
server.request();
SNMP::PDU pdu;
if (snmp.request(pdu) < 0) return;
#if defined(PRINT_PDU)
// Print available memory and resulting protocol data unit
TRACE(free_memory());
trace << pdu << endl;
#endif
when I comment out the server.request the snmp works fine, the same goes the other way.
When i Leave both in place, I can get the page to load once or twice - then there is no response.
I've put some debug info to the webservers on_request and it seems that function is not even called when it hangs.
I am too tired to think straight, but it seems to me that something is blocking either the ethernet (as an object) or the stream library, it might be because i mixed the two examples together the bad way.
this is the entire source code, to doublecheck.
/**
#include "Cosa/Memory.h"
#include "Cosa/InputPin.hh"
#include "Cosa/AnalogPin.hh"
#include "Cosa/Trace.hh"
#include "Cosa/Watchdog.hh"
#include "Cosa/INET/SNMP.hh"
#include "Cosa/Socket/Driver/W5100.hh"
#include "Cosa/IOStream/Driver/UART.hh"
#include "Cosa/INET.hh"
#include "Cosa/INET/HTTP.hh"
#include "Cosa/IOStream.hh"
/**
* Arduino MIB OID(1.3.6.1.4.1.36582)
*/
class ARDUINO_MIB : public SNMP::MIB {
private:
enum {
ardDigitalPin = 1, // Digital pin[0..22](0..1), read-only
ardAnalogPin = 2, // Analog pin[0..7](0..1023), read-only
ardVcc = 3, // Power supply[0](0..VCC), mV, read-only
} __attribute__((packed));
public:
/**
* @override SNMP::MIB
* Return object identity root for Arduino MIB.
*/
virtual const uint8_t* get_oid()
{
return (SNMP::ARDUINO_MIB_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);
};
bool
ARDUINO_MIB::is_request(SNMP::PDU& pdu)
{
// Match with Arduino MIB OID root
int pos = pdu.oid.match(get_oid(), false);
if (pos < 0 || pdu.oid.length != 11) return (false);
// Access pin type and number
uint8_t sys = pdu.oid.name[pos];
uint8_t pin = pdu.oid.name[pos + 1];
// Get next value; adjust pin referens
if (pdu.type == SNMP::PDU_GET_NEXT) {
switch (sys) {
case 0:
sys = ardDigitalPin;
pin = 0;
break;
case ardDigitalPin:
if (pin < 22)
pin += 1;
else {
pin = 0;
sys = ardAnalogPin;
}
break;
case ardAnalogPin:
if (pin < 7)
pin += 1;
else {
pin = 0;
sys = ardVcc;
}
break;
case ardVcc:
return (false);
}
pdu.oid.name[pos] = sys;
pdu.oid.name[pos + 1] = pin;
pdu.type = SNMP::PDU_GET;
}
// Check request type
if (sys < 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 (pin > 22)
pdu.error_status = SNMP::NO_SUCH_NAME;
else
pdu.value.encode(SNMP::SYNTAX_INT, (int16_t) InputPin::read(pin));
break;
case ardAnalogPin:
if (pin > 7)
pdu.error_status = SNMP::NO_SUCH_NAME;
else
pdu.value.encode(SNMP::SYNTAX_INT, (int16_t) AnalogPin::sample(pin));
break;
case ardVcc:
if (pin > 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);
}
// HTML end of line
#define CRLF "\r\n"
// Example WebServer that responds with HTTP page with state of pins
class WebServer : public HTTP::Server {
public:
// Construct WebServer and initiate sequence counter
WebServer() : m_nr(0) {}
// Response member function
virtual void on_request(char* http);
private:
// Request sequence number
uint16_t m_nr;
};
void
WebServer::on_request(char* http)
{
// Uptime in seconds
uint32_t uptime = Watchdog::millis() / 1000;
uint16_t h = uptime / 3600;
uint8_t m = (uptime / 60) % 60;
uint8_t s = uptime % 60;
// Bind the socket to an iostream
IOStream page(m_sock);
INET::addr_t addr;
// Get client connection information; MAC, IP address and port
m_sock->get_src(addr);
// Reply page; header and footer are static, contents dynamic
static const char header[] __PROGMEM =
"HTTP/1.1 200 OK" CRLF
"Content-Type: text/html" CRLF
"Connection: close" CRLF
"Refresh: 5" CRLF CRLF
"<!DOCTYPE HTML>" CRLF
"<HTML>" CRLF
"<HEAD><TITLE>CosaWebServer</TITLE></HEAD>" CRLF
"<BODY>" CRLF;
static const char footer[] __PROGMEM =
"</BODY>" CRLF
"</HTML>";
static const char BR[] __PROGMEM =
"
" CRLF;
// Construct the page; header-contents-footer
page << header;
for (uint8_t i = 0; i < 14; i++)
page << PSTR("D") << i << PSTR(": ") << InputPin::read(i) << BR;
for (uint8_t i = 0; i < 4; i++)
page << PSTR("A") << i << PSTR(": ") << AnalogPin::sample(i) << BR;
page << PSTR("Vcc (mV): ") << AnalogPin::bandgap() << BR;
page << PSTR("Memory (byte): ") << free_memory() << BR;
page << PSTR("Uptime (h:m:s): ") << h << ':' << m << ':' << s << BR;
page << PSTR("Request(") << ++m_nr << PSTR("): ") << http << BR;
page << PSTR("MAC: "); INET::print_mac(page, addr.mac); page << BR;
page << PSTR("IP: "); INET::print_addr(page, addr.ip, addr.port); page << BR;
page << footer;
}
// Network configuration
#define IP 192,168,2,129
#define SUBNET 255,255,255,0
#define GATEWAY 192,168,2,254
#define PORTIK 80
static const uint8_t mac[6] __PROGMEM = { 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed };
// SNMP MIB-2 System configuration
static const char descr[] __PROGMEM = "<service description>";
static const char contact[] __PROGMEM = "<contact information>";
static const char name[] __PROGMEM = "<device name>";
static const char location[] __PROGMEM = "<device location>";
W5100 ethernet(mac);
SNMP::MIB2_SYSTEM mib2(descr, contact, name, location);
ARDUINO_MIB arduino;
SNMP snmp;
WebServer server;
void setup()
{
uint8_t ip[4] = { IP };
uint8_t subnet[4] = { SUBNET };
// Start watchdog and uart. Use uart for trace output
uart.begin(9600);
trace.begin(&uart, PSTR("CosaSNMP: started"));
Watchdog::begin();
// Start ethernet controller and request network address for hostname
ASSERT(ethernet.begin_P(PSTR("CosaSNMPAgent")));
// Alternative give network address and subnet mask
// ASSERT(ethernet.begin(ip, subnet));
// Print the given or default network address
ethernet.get_addr(ip, subnet);
trace << PSTR("IP = ");
INET::print_addr(trace, ip);
trace << 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(server.begin(ethernet.socket(Socket::TCP, 80)));
ASSERT(snmp.begin(ethernet.socket(Socket::UDP, SNMP::PORT), &mib2, &arduino));
}
void loop()
{
// Service SNMP requests with given MIB handlers
server.request();
SNMP::PDU pdu;
if (snmp.request(pdu) < 0) return;
#if defined(PRINT_PDU)
// Print available memory and resulting protocol data unit
TRACE(free_memory());
// trace << pdu << endl;
#endif
}
thanks for any inputs on this.