Ethernet library server.available() problem

Status
Not open for further replies.

GeppettoLab

Active member
Hi, I'm sorry for this huge post but I need to explain it clearly.
I'm working on the realization of an Escape Room.
I would use Teensy as controller of each game, connected via Ethernet to a PC.
After the first trial I found some problem with the communication with the software due by the server.available() function.

This is my configuration:
From the modem of my office (and later from the one of the escape room) I connect a Router (netgear R6220). From the router I connect my pc and a switch (TL-SG1024D (1Gbit)).
I use the router as a DHCP server reserving all the IP that I need (with the correspondent MAC address).
Then I use a Teensy 3.2 and a Teensy 3.5 with the WIZ820io Adaptor and the WIZ820io Module, and an Arduino Mega with an Ethernet shield based on W5100.
These three board are connected to the switch and are uploaded with the following code (with the right configuration of IPs and MAC addresses)

Code:
/*
   A prop with a button that sends a signal to ERM & can also trigger a relay
*/

#include <Ethernet.h>

#define BUTTON_PIN 5
//A14 per teensy, 5 per Mega
#define RELAY_PIN 6


bool useDHCP = false;

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:

byte mac[] = {0x04, 0xE9, 0xE5, 0x06, 0xE1, 0x2B}; //Dipende da ogni dispositivo, da trovare con T3_readmac.ino (Teensy) o generare (Arduino)
IPAddress ip(10, 0, 0, 103);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// Track the room game state
bool relayTriggered = false;  // has the button in the room been pressed?




void setup() {
  //start serial connection (debugging)
  Serial.begin(9600);

  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);    // begin reset the WIZ820io
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);  // de-select WIZ820io
  digitalWrite(9, HIGH);   // end reset pulseo

  // NOTE: pin 1 & 2 are used for Serial
  // 4 & 10 - 13 are used for ethernet

  pinMode(BUTTON_PIN, INPUT_PULLUP);   // Game btn
  pinMode(RELAY_PIN, OUTPUT);   // Control mag lock or lights

  // start the Ethernet connection and the server:
  if (useDHCP) {
    Serial.println("Using DHCP");
    Ethernet.begin(mac); // Use DHCP instead of ip
  }
  else {
    Serial.println("Not using DHCP");
    Ethernet.begin(mac, ip);
  }
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());


  // Initial game state
  relayTriggered = false;
}



void loop() {
  //read the pushbutton value into a variable
  int gameBtnVal = digitalRead(BUTTON_PIN);

  //print out the value of the pushbutton
  //Serial.println(gameBtnVal);

  // Keep in mind the pullup means the pushbutton's
  // logic is inverted. It goes HIGH when it's open,
  // and LOW when it's pressed
  if (gameBtnVal == LOW) {
    trigger();
  } else reset();

  // listen for incoming Ethernet connections:
  listenForEthernetClients();

  // Maintain DHCP lease
  if (useDHCP) {
    Ethernet.maintain();
  }


  // Use serial for debugging to bypass web server
  if (Serial.available()) {
    //read serial as a character
    char ser = Serial.read();

    switch (ser) {
      case 'r': // reset prop
        reset();
        break;

      case 'b': // button press
        trigger();
        break;
    }
  }
}


/*
   Game states
*/


// actions after button has been pressed
void trigger() {
  // While the code below is safe to run multiple times
  // it's best not to re-run it in case an expensive operation
  // is later added
  if (relayTriggered) {
    return;
  }

  relayTriggered = true;
  digitalWrite(RELAY_PIN, HIGH);
  Serial.println("solved");
}

// Reset the prop
void reset() {
  relayTriggered = false;
  digitalWrite(RELAY_PIN, LOW);
}


/*
   URL routing for prop commands and polling
*/

// This function dictates what text is returned when the prop is polled over the network
String statusString() {
  return relayTriggered ? "solved" : "not solved";
}

// Actual request handler
void processRequest(EthernetClient& client, String requestStr) {
  Serial.println(requestStr);
  // Send back different response based on request string
  if (requestStr.startsWith("GET /status")) {
    Serial.println("polled for status!");
    writeClientResponse(client, statusString());
  } else if (requestStr.startsWith("GET /reset")) {
    Serial.println("Room reset");
    reset();
    writeClientResponse(client, "ok");
  } else if (requestStr.startsWith("GET /trigger")) {
    Serial.println("Network prop trigger");
    trigger();
    writeClientResponse(client, "ok");
  } else {
    writeClientResponseNotFound(client);
  }
}


/*
   HTTP helper functions
*/

void listenForEthernetClients() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("Got a client");
    // Grab the first HTTP header (GET /status HTTP/1.1)
    String requestStr;
    boolean firstLine = true;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          processRequest(client, requestStr);
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
          firstLine = false;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;

          if (firstLine) {
            requestStr.concat(c);
          }
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}


void writeClientResponse(EthernetClient& client, String bodyStr) {
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/plain");
  client.println("Access-Control-Allow-Origin: *");  // ERM will not be able to connect without this header!
  client.println();
  client.print(bodyStr);
  Serial.println(bodyStr);
}


void writeClientResponseNotFound(EthernetClient& client) {
  // send a standard http response header
  client.println("HTTP/1.1 404 Not Found");
  client.println("Access-Control-Allow-Origin: *");  // ERM will not be able to connect without this header!
  client.println();
}

This code is given by the Escape room software developer to connect an Arduino to his browser based software (Escape Room Master.com).
I set the room for a test and all the connection works in the test mode. The teensy answer to requests (using the /reset and /trigger stirngs) from the software in the right way.
test.PNGpuzzle trigger.PNGserial monitor.PNG
But when I launch the room (open the webpage of the live view of my room) if the Teensy are running, the sketches return false as output of server.available() and the board cannot communicate with the software.
Returning from there in the test mode the server.available() continue to return false (but the sketch is running).
If I restart the Teensy when the live view of my room is open, they begin to communicate correctly with the software.

This does not happen with the Arduino board...

There is an alert on the manual that say "Please make sure you are using the w5500 adapters, and NOT using the w5100 adapters as they do not conform to current hardware and network specifications." can the w5100 on the arduino board generate a connection problem for the Teensy?

How can I resolve without power on the boards after the software is started?

Thanks
Luca
 
Hi I made some other test studiying the ethernet protocol but without results.
Someane have some suggestions?
It will be very helpful!
Thanks
Luca
 
Sorry but I need to solve this problem and I cannot find a solution myself.
There is someone that can help me?
Thanks
Luca
 
I've put this one on my list of bugs to investigate. Will likely look into it early next week.

I see your code seems to listen for HTTP requests. When I run your code on a board here, what should I run in my browser to test it?
 
I ran your server sketch on a T3.2 (IDE 1.8.5 1.40) with my local IP and mac address. Server seems to be working. I accessed from browser with http://192.168.1.15/reset and http://192.168.1.15/trigger and got back ok. I also ping'd the server and did a
telnet 192.168.1.15 80
get


and all that seemed to work just fine. I tested with both a WIZ820io and WIZ850io.

When your tests are failing, can you ping the T3.2 or T3.5 from a console window? can you try telnet to port 80 on T3.5 and T3.2 when things seem broken?

you might turn on an LED in the while(client.connected() ) loop and turn it off before the client.stop() -- then you can see if the server is hung assembling a line.
 
Last edited:
I do not understand how I am supposed to use that public site to communicate with a Teensy board on my desk, using a IP number assigned by my private network.
 
I do not understand how I am supposed to use that public site to communicate with a Teensy board on my desk, using a IP number assigned by my private network.
You are right, sorry.
In the Room Management page you can create an event (or use the one that I had created) specifing the IP.
If you give me the right IP I set it for you.

Thanks
Luca
 
This isn't going to work. The IP number is assigned by my router (using NAT routing) for the internal network. It is not reachable directly from the outside world.

I also know nothing about how your site is supposed to work. The page I saw is complex with no apparent instructions. I need a relatively simple way to test which can run here on my network, where the IP number of the Teensy+Wiznet is accessible.
 
i connect PC and Teensy on a switch connected to my router where I assign the private static IP's.

Unfortunately is not my site and the user manual is not so good. It is the first voice of the menu. I understand that it's not so easy to make some tests, I hoped there was some known problem I was not aware of about HTTP's requests on Teensy.
 
Status
Not open for further replies.
Back
Top