patricklaf / SNMP

Simple Network Management Protocol library for Arduino
MIT License
10 stars 1 forks source link

Problems on Arduino UNO/Mega #2

Closed mareksoldan closed 1 year ago

mareksoldan commented 1 year ago

Hi, has anyone used this lib with classic arduino? Without stm32? I try to use but arduino restart every time when receive snmp message. Can somebody help?

patricklaf commented 1 year ago

Hi, What kind of board are you using ? Can you share your code?

mareksoldan commented 1 year ago

Hi, thanks for quick reply. I am just trying Mega 2560.

Here is code:

`

include

include

include

include

define pinDHT 2

define typeDHT DHT21

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

define UDP_TX_PACKET_MAX_SIZE 1024

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

float tep; float vlh;

DHT sensorDHT(pinDHT, typeDHT); EthernetUDP udp; SNMP::Agent snmp;

const char SYSNAME_OID = "1.3.6.1.2.1.1.5.0"; const char SYSNAME_VALUE = "Nucleo F767ZI";

// Use some SNMP classes using SNMP::OctetStringBER; using SNMP::VarBind; using SNMP::VarBindList;

void echo(String text1, String text2 = ""){ if(text2 == ""){ Serial.println(text1); } else{ Serial.print(text1); Serial.print(" | "); Serial.println(text2); } } String ipAddrToString(IPAddress address){ return String(address[0]) + "." + String(address[1]) + "." + String(address[2]) + "." + String(address[3]); }

void onMessage(const SNMP::Message message, const IPAddress remote, const uint16_t port) { // Get the variable binding list from the message. exit(0); VarBindList varbindlist = message->getVarBindList(); for (unsigned int index = 0; index < varbindlist->count(); ++index) { // Each variable binding is a sequence of 2 objects: // - First one is and ObjectIdentifierBER. It holds the OID // - Second is the value of any type VarBind varbind = (varbindlist)[index]; // There is a convenient function to get the OID as a const char const char name = varbind->getName(); if (strcmp(SYSNAME_OID, name) == 0) { // System name is requested. Need to send a response. // Create an SNMP message for response SNMP::Message response = new SNMP::Message(SNMP::VERSION2C, "public", SNMP::TYPE_GETRESPONSE); // The response must have the same request-id as the request response->setRequestID(message->getRequestID()); // SYSNAME // Create an OctetStringBER to hold the variable binding value OctetStringBER value = new OctetStringBER(SYSNAME_VALUE, strlen(SYSNAME_VALUE)); // Add the variable binding to the message response->add(SYSNAME_OID, value); // Send the response to remote IP and port snmp.send(response, remote, port); // Avoid memory leak delete response; } } }

void setup() { // put your setup code here, to run once: Serial.begin (9600); echo("Starting...");

pinMode(LED_BUILTIN, OUTPUT);

sensorDHT.begin(); echo("Sensor started...");

echo("Connecting to LAN..."); if(!Ethernet.begin(mac)){ echo("DHCP request failed!"); } else{ echo("IP address:", ipAddrToString(Ethernet.localIP())); }

snmp.begin(&udp); snmp.onMessage(onMessage); echo("SNMP ready..."); }

void loop() { // put your main code here, to run repeatedly: // tep = sensorDHT.readTemperature(); // vlh = sensorDHT.readHumidity();

// echo((String)digitalRead(LED_BUILTIN)); // if(digitalRead(LED_BUILTIN)==1) // digitalWrite(LED_BUILTIN, LOW); // else // digitalWrite(LED_BUILTIN, HIGH);

// String msg1 = "Teplota: " + String(tep) + " °C"; // String msg2 = "Vlhkost: " + String(vlh) + " %"; // echo(msg1, msg2);

snmp.loop(); }

`

patricklaf commented 1 year ago

Why exit(0) at the beginning of onMessage() handler?

mareksoldan commented 1 year ago

Sorry, its my mistake. You wrote me back so quickly and I sended some debug version. So if I try to use your example (only change ip/mac address) and if snmp packet is received, program stuck, not restarting...

`

include // Ethernet support. Replace if needed.

include

EthernetUDP udp; SNMP::Agent snmp; const char SYSNAME_OID = "1.3.6.1.2.1.1.5.0"; const char SYSNAME_VALUE = "Nucleo F767ZI";

using SNMP::OctetStringBER; using SNMP::VarBind; using SNMP::VarBindList;

// Event handler to process SNMP messages void onMessage(const SNMP::Message message, const IPAddress remote, const uint16_t port) { // Get the variable binding list from the message. VarBindList varbindlist = message->getVarBindList(); for (unsigned int index = 0; index < varbindlist->count(); ++index) { // Each variable binding is a sequence of 2 objects: // - First one is and ObjectIdentifierBER. It holds the OID // - Second is the value of any type VarBind varbind = (varbindlist)[index]; // There is a convenient function to get the OID as a const char const char name = varbind->getName(); if (strcmp(SYSNAME_OID, name) == 0) { // System name is requested. We have to send a response. // Create an SNMP message for response SNMP::Message response = new SNMP::Message(SNMP::VERSION2C, "public", SNMP::TYPE_GETRESPONSE); // The response must have the same request-id as the request response->setRequestID(message->getRequestID()); // SYSNAME // Create an OctetStringBER to hold the variable binding value OctetStringBER value = new OctetStringBER(SYSNAME_VALUE); // Add the variable binding to the message response->add(SYSNAME_OID, value); // Send the response to remote IP and port snmp.send(response, remote, port); // Avoid memory leak delete response; } } }

void setup() { Serial.begin(9600); // Ethernet byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; Ethernet.begin(mac); // SNMP snmp.begin(&udp); snmp.onMessage(onMessage); Serial.println("just started..."); }

void loop() { // Agent loop function must be called to process incoming messages snmp.loop(); } `

patricklaf commented 1 year ago

OK. What are you using as Ethernet shield and library?

mareksoldan commented 1 year ago

Ethernet shield is W5100, libs only SNMP v1.1.0 a Ethernet v2.0.2

patricklaf commented 1 year ago

Hello @mareksoldan , I just pushed some changes to support Arduino Mega. The reason why it failed is that Integers were hardcoded to int so 32 bits on STM32 as willed, but only 16 bits on AVR. Very bad idea. The example works on my setup (Mega 2560 and W5100). Can you make some test? BTW I think that this library is not usable with the UNO board as it lacks RAM. Regards, Patrick

mareksoldan commented 1 year ago

Hey, Patrick, thank you so much for your efforts and your very quick response. I just tried it and it looks much better. After Mega receives the SNMP request it actually calls the onMessage() function, responds and waits for the next request.

However, the problem I encountered is that the incoming requestID does not match the one sent in the response.

Otherwise, though, it works just fine.

Regards Marek

patricklaf commented 1 year ago

Hi @mareksoldan , I encountered the same problem. It should be fixed now hopefully with the last commits. I will let you test and if everything is OK, I will publish a new release in a few days. Regards, Patrick

mareksoldan commented 1 year ago

Hi @patricklaf , I tried it and still the same problem (different IDs in request and response). I think the problem is in the _responseID type. Probably too small. Regards, Marek

patricklaf commented 1 year ago

@mareksoldan , that's strange, it works for me, both for Arduino Mega and one of my STM32 boards. Commit #2c0559d should have solved the issue caused by the difference of sign between char and uint8_t.

mareksoldan commented 1 year ago

@patricklaf , yes, thas's strange. I captured the communication using Wireshark and I see a mismatch in the requestId. There are three different numbers, in the request packet, in the arduino and then in the captured response packet. More detailed information in the attachment. response request ide

patricklaf commented 1 year ago

Hello @mareksoldan , Thank you for the detailed report. It seems from your monitoring that the requestID is well decoded but not correctly encoded. I will try to reproduce and fix this.

patricklaf commented 1 year ago

Hello @mareksoldan , I have done some progress. This is the code I used to parse the data of the problematic request:

void test() {
    unsigned char input[43] = {
    0x30, 0x29, 0x02, 0x01, 0x01, 0x04, 0x06, 0x70, 0x75, 0x62, 0x6C, 0x69,
    0x63, 0xA0, 0x1C, 0x02, 0x04, 0x3E, 0xE3, 0x95, 0x7B, 0x02, 0x01, 0x00,
    0x02, 0x01, 0x00, 0x30, 0x0E, 0x30, 0x0C, 0x06, 0x08, 0x2B, 0x06, 0x01,
    0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00
    };

    unsigned char output[512];
    uint32_t size = 0;

    SNMP::Message *message = new SNMP::Message();
    if (message->parse(input, 43)) {
        SNMP::Message *response = new SNMP::Message(SNMP::VERSION2C, "public", SNMP::TYPE_GETRESPONSE);
        // The response must have the same request-id as the request
        response->setRequestID(message->getRequestID());
        // SYSNAME
        // Create an OctetStringBER to hold the variable binding value
        OctetStringBER* value = new OctetStringBER(SYSNAME_VALUE);
        // Add the variable binding to the message
        response->add(SYSNAME_OID, value);
        // Send the response to remote IP and port
        size = response->build(output);
    }
    Serial.println("request");
    hexa.dump(input, 43);
    Serial.println();
    Serial.println("response");
    hexa.dump(output, size);
    Serial.println();
}

And I get this:

request
00000000  30 29 02 01 01 04 06 70  75 62 6C 69 63 A0 1C 02  0 ) . . . . . p  u b l i c . . .
00000010  04 3E E3 95 7B 02 01 00  02 01 00 30 0E 30 0C 06  . > . . { . . .  . . . 0 . 0 . .
00000020  08 2B 06 01 02 01 01 05  00 05 00                 . + . . . . . .  . . . . . . . .

response
00000000  30 35 02 01 01 04 06 70  75 62 6C 69 63 A2 28 02  0 5 . . . . . p  u b l i c . ( .
00000010  04 3E E3 95 7B 02 01 00  02 01 00 30 1A 30 18 06  . > . . { . . .  . . . 0 . 0 . . 
00000020  08 2B 06 01 02 01 01 05  00 04 0C 41 72 64 75 69  . + . . . . . .  . . . A r d u i
00000030  6E 6F 20 4D 65 67 61                              n o   M e g a .  . . . . . . . .

As you can see, the request-id is the same for both 3E E3 95 7B.

Changes are committed. Can you do some testing? Regards, Patrick

mareksoldan commented 1 year ago

Hi @patricklaf , this looks ABSOLUTELY FANTASTIC. I'm testing like hell and so far it keeps returning the correct answers. I hereby consider this resolved and will keep you posted if anything pops up.

patricklaf commented 1 year ago

Hi @mareksoldan , Thanks a lot for reporting this issue and your feedback. I will shortly make a new release. Best regards, Patrick