Go Down

Topic: Ethernet lib client.flush() Bug? (Read 1 time) previous topic - next topic

stahlstift

Hello there,

I currently try to write a little IRC Bot with the Arduino and the Ethernet Shield. I ran into a problem and I think that it is maybe a bug in the Ethernet lib. I am not a really good C/C++ coder and also absolutly new to hardware and micros.

The code isn´t very well designed (not optimized) at the moment, because it´s just a prototype I wrote in about 3h.

Sketch:
Code: [Select]

#include <MsTimer2.h>
#include <Ethernet.h>
#include <Client.h>

// Network
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 111 };
byte ircserver[] = { 207, 182, 240, 74 };

// IRC
char hostname[] = "irc.freenode.net";
char nickname[] = "stahlArduinoBot";
char ident[] = "arduinoBot";
char channel[] = "#stahlstift";

// Don´t touch anything!
Client client(ircserver, 6667);
const int bufferSize = 1024;
char buffer[bufferSize]; // Buffer für die Timerfunktion
int pingDelay = 100; // Wird für einen sicheren Anmeldeprozess benötigt!



// NTC
int tempPin = 0;
float voltbit = 0.0048828125f;


boolean authIRC() {
 int buffSize = 512;
 char authBuffer[buffSize]; // lokaler Buffer, da dieser nur einmal benötigt wird
 int i = 0;
 boolean initData = false;
 boolean authInfoSended = false;
 long authTimeout = 60000; // 60 Sekunden
 long startTime = millis();
 
 while(!initData) { // Ich muss sicher sein, das Daten eingetroffen sind    
   if(client.available()) {
     initData = true; // Hier weiß ich nun das Daten vorhanden sind und kann die WhileSchleife später beenden
     
     while (client.available()) {        
       char c = client.read();
       if (c == 13) {
         authBuffer[i] = 0;
         i = 0;          
         if (authInfoSended) {          
           // TODO: Registrierter Benutzername
           if (strstr(authBuffer, "Welcome to the freenode IRC Network") != NULL) {
             return true;
           }
           
           // Timeout damit wir uns nicht in einer Endlosschleife befinden, falls mit der Anmeldung was schief ging
           if ((millis() - startTime) > authTimeout) {
             Serial.println("Timeout!");
             return false;
           }
         } else {
           // Anmelden
           client.print("NICK ");
           client.println(nickname);
           
           client.print("USER ");
           client.print(ident);
           client.print(" ");
           client.print(hostname);
           client.println(" bla :arduino");
           
           authInfoSended = true;
           startTime = millis(); // Ab hier beginnt die Timeoutzählung
         }
       } else {
         authBuffer[i] = c;
         i++;
       }
       delay(pingDelay);
     }
   }
 }
 return false;
}

void checkMsg() {
 int i = 0;
 
 // DEBUG 1 Check
 if(client.available()) {
   Serial.println("not empty!");
 } else {
   Serial.println("empty!"); // it will print empty
 }
 
 // DEBUG 2 Check
 if(client.available()) {
   Serial.println("not empty!"); // it will print not empty!
 } else {
   Serial.println("empty!");
 }
 
 // DEBUG 3 Check
 if(client.available()) {
   Serial.println("not empty!"); // it will print not empty!
 } else {
   Serial.println("empty!");
 }
 
 // DEBUG 4 Check
 if(client.available()) {
   Serial.println("not empty!"); // it will print not empty!
 } else {
   Serial.println("empty!");
 }
 
 while(client.available()) {
   char c = client.read();
   if (c == 13) {
     buffer[i] = 0;
     i = 0;
     
     // Auf Server PING antworten
     if (strstr(buffer, "PING ") != NULL) {
       if (buffer[0] == 'P' && buffer[1] == 'I' && buffer[2] == 'N' && buffer[3] == 'G') {
         client.println("PONG");
       }
     }

     // Nachricht aus dem aktuellen Channel?
     if (strstr(buffer, channel) != NULL) {
       // Auf !roomtemp im aktuellen Channel reagieren
       if (strstr(buffer, "!roomtemp")) {
         // NTC
         float tmp = analogRead(tempPin) * voltbit;
         int r1 = (5 * 1000 / (5-tmp)) - 1000;
 
         client.print("PRIVMSG ");
         client.print(channel);
         client.print(" :In stahlstift´s room is currently ");
         client.print(r1);
         client.println(" (NTC ohm - translation table will be there in a feature version). Thanks for your interest! (simpleIRC v0.1 by stahlstift on Arduino Duemilanove)");
       }
     }
     
     Serial.print("checkMsg(): ");
     Serial.println(buffer);
   } else {
     buffer[i] = c;
     i++;
   }
 }
}

void joinRoom() {
 client.print("JOIN ");
 client.println(channel);
}

void setup() {
 Ethernet.begin(mac, ip);
 Serial.begin(9600);
 delay(2000); // EthernetShield etwas Zeit lassen
 if (client.connect()) {
   if(!authIRC()) {
     Serial.println("Authentifizierung fehlgeschlagen!");
   } else {
     Serial.println("Authentifizierung erfolgreich");
         
     joinRoom();
         
     client.flush(); // Message of the Day, Raumliste etc, den ganzen Mist löschen, den wollen wir nicht einlesen :)
         
     delay(1000); // Noch ne Sekunde warten bevor es los geht :)
   
     // Der Timer ruft jede Sekunde "checkMsg" auf welche Kommandos entgegen nimmt
     MsTimer2::set(1000, checkMsg);
     MsTimer2::start();
   }
 } else {
   Serial.println("Verbindung fehlgeschlagen!");
 }
}

void loop() {
 if (!client.connected()) {
   Serial.println("Verbindung verloren");
   client.flush();
   client.stop();
   
   while(true); // Damit Verbindung verloren nicht gespammed wird!
 }
}


The problem is in "void checkMsg() {".
Because freenode spams me with motd and channel list I want to do client.flush() and so I do. But client.available() is in the first statment empty, in the second not and in the while-loop also not.

Maybe it´s a failure from me, so...

I am using the Arduino 2009 and Arduino 0017.

Greetings!

stahlstift

By the way,
I startet a project on googlecode for the IRC Client.
http://code.google.com/p/arduinoirc/

There is nothing there at the moment, after fixing the bug I got described above, I try to start a lib for easy using.

The code above is GPL3! So be nice!

stahlstift

#2
Aug 26, 2009, 02:29 pm Last Edit: Aug 26, 2009, 02:30 pm by stahlstift Reason: 1
I completely redesigned the Code.

Now it doesn´t depend any more on client.flush() and it is a bit more "event driven" and now also able to join multiple Channels and listen in them.

+ ~700bytes smaller :)

Code will follow the next days on the google project site.

Spinlock

stahlstift -

I have used flush() and it works as advertised.  It isn't guaranteed to work in your case because the data may not be in the buffer yet for the function to flush.

You may need to design a more suitable function like "ignoreIRCStuffIDontWantToDealWith" to accomplish what you are aiming for.  

Go Up