1

I have developed an application with a SunFounder Mega2560 with a W5100 Ethernet shield that acts as a server and successfully parses TCP message packets from a client sending in updates. I am now trying to add HTTP GETs into the mix by sending off my data to update an XAMPP server, which I am treating as a client in my code.

For some reason, I can't seem to connect to the XAMPP's Apache service on my machine for it to receive the HTTP message to update the MariaDB table through a PHP script I created. The Apache service seems to be listening on port 80, which I am attempting to initiate the connection on.

You can mostly just pay attention to the postData() command below, but I'm including everything for completeness.

#include <stdlib.h>
#include <string.h>
#include <SPI.h>
#include <Ethernet.h>

#define MAX_CLIENTS 1
#define MAX_LINE_LEN 100 
char inputs[MAX_CLIENTS][MAX_LINE_LEN] = {0}; // Instantiate 2D array of client/received data
int msg_array[] = {0,0,0,0};

EthernetServer server(1174);                  // Create server object on port of server, which will be used to respond to commands
EthernetClient *client = NULL;                // Create client objects limited to size of MAX_CLIENTS
EthernetClient db;                            // Create a client object just for posting HTTP commands to the database

byte mac[] = {0x24,0x0A,0xC4,0xAC,0xC1,0x78}; // Arduino's physical MAC
byte ip[] = {192,168,1,23};                   // IP of this controller 
byte gateway[] = {192,168,1,77};              // Router address (internet)
byte myDns[] = {192,168,1,77};                // Router dns
byte subnet[] = {255,255,0,0};                // Subnet mask
byte dbserver[] = {192,168,1,77};             // IP address of SQL server 

unsigned long wd_Dside, wd_Cside;             // Gather current Arduino pgm ms timestamp
unsigned long wd_Delap, wd_Celap = 0;         // Create an elapsed time counter 
int dside_prev, cside_prev = 0;       // Create a previous state for each AV to determine code execution 
char rId[3] = {0}; 
int avSide = 0; 

// --------------------------------------------------------------------------------------------------------


void setup(){

// initialize the ethernet device
//  Ethernet.begin(mac, ip, myDns, gateway, subnet);
  Ethernet.begin(mac, ip); 

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
  ; // wait for serial port to connect. Needed for native USB port only
  }

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware.");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
        }
  }

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  pinMode(22, OUTPUT);                          // pin selected to control AV D SIDE
  pinMode(23, OUTPUT);                          // pin selected to control AV C SIDE

  // wait 5 seconds for connection:

  delay(5000);
  server.begin();                                // Start server
  Serial.print("Server started on ");
  Serial.println(Ethernet.localIP()); 
  delay(1000);

  wd_Dside, wd_Cside = millis(); 

}

// --------------------------------------------------------------------------------------------------------

void loop() {

  delay(100); 
  int i=0; 

  EthernetClient newClient = server.available(); 
  if (newClient) {
    if (client==NULL){
    client = new EthernetClient(newClient); 
  }
  }

  if (client != NULL && client->available()){                     // If the data isn't garbage and the data is available..
    Serial.print("Client's IP address: ");
    Serial.println(client->remoteIP());
    Serial.print("Client sent: ");
    char newChar = client->read();                                // Read the data  
    Serial.println(newChar); 

    if (newChar == '\0') {                                        // Check for a termination character for separation
      Serial.println("Client terminated message.");
      char delimiters[] = ",";                                    // Use a string parser in order to get command parameterization
      char* valIndex;
      valIndex = strtok(inputs[i], delimiters);
      for (int j=0; j<4; j++){                                    // Expand later to largest anticipated character count
        msg_array[j] = atoi(valIndex); 
        //Serial.print(msg_array[j]);
        valIndex = strtok(NULL, delimiters);
      }

      switch(msg_array[0]) {                                      // Determine type of message received via Ethernet (Character 0 parsed as Message Type) 

        case 3:                                                   // Examine string for instructions to turn AVs on or off. 

        char cstr[16];
        strcat(rId, itoa(msg_array[2],cstr,10));              // Build rId string prior to any potential HTTP post (which refs rId)
        strcat(rId, itoa(msg_array[3],cstr,10));
        Serial.print("R ID: ");
        Serial.println(rId); 

        if(msg_array[1] == 1)                                     // Msg type 3, Instruction 1: Turn D side AV ON
          {
            avSide = 0; 
            if (dside_prev != msg_array[1]){
              Serial.println("Dside AV is OPEN.");
              digitalWrite(22, HIGH);                             // Set pin 4 low
              postData();                                         // Call the HTTP POST function
            }

            dside_prev = msg_array[1];
            wd_Delap = 0;                                         // Reset elapsed time watchdog time value for D side. 
            wd_Dside = millis();                                  // Last good heartbeat received from client device on D side. 
          }
        if(msg_array[1] == 2)                                     // Msg type 3, Instruction 2: Turn Dside AV OFF
          {
            avSide = 0; 
            if (dside_prev != msg_array[1]){
              Serial.println("Dside AV is CLOSED.");
              digitalWrite(22, LOW);                              // Set pin 4 low
              //postData();                                         // Call the HTTP POST function
            }

            dside_prev = msg_array[1];
            wd_Delap = 0;                                         // Reset elapsed time watchdog time value for D side. 
            wd_Dside = millis();                                  // Last good heartbeat received from client device on D side. 
          } 
        if(msg_array[1] == 3)                                     // Msg type 3, Instruction 3: Turn Cside AV ON
          {
            avSide = 1; 
            if (cside_prev != msg_array[1]){
              Serial.println("Cside AV is OPEN.");
              digitalWrite(23, HIGH);                             // Set pin 5 high
              //postData();                                         // Call the HTTP POST function
            }

            cside_prev = msg_array[1];
            wd_Celap = 0;                                         // Reset elapsed time watchdog time value for C side. 
            wd_Cside = millis();                                  // Last good heartbeat received from client device on C side. 
          }
        if(msg_array[1] == 4)                                     // Msg type 3, Instruction 4: Turn Cside AV OFF
          {
            avSide = 1;
            if (cside_prev != msg_array[1]){
              Serial.println("Cside AV is CLOSED.");
              digitalWrite(23, LOW);                              // Set pin 5 high
              //postData();                                         // Call the HTTP POST function
            }

            cside_prev = msg_array[1];
            wd_Celap = 0;                                         // Reset elapsed time watchdog time value for C side. 
            wd_Cside = millis();                                  // Last good heartbeat received from client device on C side. 
          }

        rId[0]='\0';                                          // Clear the array 
        break;

        case 6:
                                                                  // Examine string for EA status messages 
        break; 

        default: 
          Serial.println("Default break encountered. Received gibberish.");
        break;

      }

    inputs[0][0] = '\0';                                      // Clear out this array element for the next message
    //client->stop();                                         // By default, kill the client session and just wait for a new TCP open
    //delete client;                                          // Remove client element's data
    //client = NULL;                                          // Reset to NULL 
    Serial.println(inputs[0]); 

    }

    else {

       if (strlen(inputs[i]) > MAX_LINE_LEN) {                     // Append it to the message content string, but first check for size compliance
        Serial.println("Max line length exceeded from client.");
        inputs[0][0] = '\0';                                       // Clear out this array element for the next message
       }
       else {
        size_t l = strlen(inputs[0]);  
        inputs[0][l] = newChar;    
        inputs[0][l + 1] = 0;
        // strcat(inputs[i], newChar);                             // Add character to the received string
       }

      Serial.print("inputs[0]: ");
      Serial.println(inputs[0]);

    }
  }

/* Update watchdog timers

wd_Delap = (millis()-wd_Dside);
wd_Celap = (millis()-wd_Cside); 

if (wd_Delap>=60000)
      {
        Serial.print("Elapsed time on watchdog, D side: ");
        Serial.println(wd_Delap);
        Serial.print("Last message recieved: ");
        Serial.println(wd_Dside);
        digitalWrite(4, LOW);    // set pin 4 low
        Serial.println("Dside AV didn't hear from anyone in 60s; defaulting to OFF.");
      } 

if (wd_Celap>=60000)
      {
        Serial.print("Elapsed time on watchdog, C side: ");
        Serial.println(wd_Celap);
        Serial.print("Last message recieved: ");
        Serial.println(wd_Cside);
        digitalWrite(5, LOW);    // set pin 5 low
        Serial.println("Cside AV didn't hear from anyone in 60s; defaulting to OFF.");
      } 
  */   
}

// Section to update database via HTTP 
void postData() {
  Serial.println("Hit postData");
  client->stop();

  delay(250);
  Serial.println("Stopping and reconnecting."); 

  if (db.connect(dbserver, 80)) {
    Serial.println("Connected to DB host machine."); 
    db.print("GET /write_data.php?");

    db.print("RID=");
    db.print(rId); 
    db.print("&");

    db.print("side=");
    db.print(avSide); 
    db.print("&");

    db.print("state=");
    db.print("1");

    db.println(" HTTP/1.1");
    db.println("Host: localhost");
    db.println("User-Agent: Arduino/1.0");
    db.println("Connection: close");
    db.println();
    db.println();
    db.stop(); 

  } 
  else {
  Serial.println("Connection failed to DB host machine.");
  }

  delay(5000);
}

This is the output:

Client's IP address: 192.168.1.77
Client sent: ,
inputs[0]: ,
Client's IP address: 192.168.1.77
Client sent: 3
inputs[0]: ,3
Client's IP address: 192.168.1.77
Client sent: ,
inputs[0]: ,3,
Client's IP address: 192.168.1.77
Client sent: 1
inputs[0]: ,3,1
Client's IP address: 192.168.1.77
Client sent: ,
inputs[0]: ,3,1,
Client's IP address: 192.168.1.77
Client sent: 3
inputs[0]: ,3,1,3
Client's IP address: 192.168.1.77
Client sent: ,
inputs[0]: ,3,1,3,
Client's IP address: 192.168.1.77
Client sent: 7
inputs[0]: ,3,1,3,7
Client's IP address: 192.168.1.77
Client sent:
Client terminated message.
R ID: 37
Dside AV is OPEN.
Hit postData
Connecting...
Connection failed to DB host machine.

Am I maybe initializing something incorrectly, or am I becoming a victim to one of the commonly references issues with the Ethernet library not being able to handle multiple connections on the Arduino?

Thanks!

EDIT: Well with some troubleshooting of the HTTP methods and formats to address the URI, I didn't turn up much; But I did by chance notice that changing my semicolons to ampersands for the value fields are what did the trick! I have achieved communication to my MariaDB! The issue I'm having now is that the client disconnects after dumping the information to the database, and does not re-enter the normal loop to wait on another message.

My postData() routine above has been edited to show what I am doing. The main loop is looping, but does not show that the server() receives anything like it would previously.

7
  • Ethernet.begin(mac, ip); for IP 192.168.1.77 assumes gateway and DNS at 192.168.1.1. use "Host: 192.168.1.77". Is the port 80 open on firewall of the PC? Commented Aug 29, 2019 at 4:36
  • Can you reach port 80/send a POST from another machine on your network? Commented Aug 29, 2019 at 6:10
  • db.print("R ID="); there is a space inside your url. Urls shouldn't contain spaces. Commented Aug 29, 2019 at 9:40
  • @Juraj Are you referring to a specific function that the Ethernet() library implements? I don't see a Host parameter. Commented Aug 29, 2019 at 19:03
  • @MarkusDeibel you and Juraj's suggestions are good ones, as I couldn't access the web page without adding a rule for all port 80, 443 and 3306 traffic; however, the code is now stepping in and attempting to connect but locks up and restarts everything. Commented Aug 29, 2019 at 19:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.