Trouble sending data from Arduino WiFi rev2 to XAMP localhost using POST

I can usually figure out most Arduino issues but this has me beat. I am new to websites, HTML/PHP etc. My project (for now) is simply a test bed to send data from the Arduino to the localhost server on my PC,so no circuitry is involved. A lot of my code is working fine:

  • Arduino connects to my WiFi network and stays connected.
  • Arduino connects to my localhost server
  • my PHP code runs and successfully writes a variable composed of a time marker and the received data from the Arduino to an html file which displays the variable.

The problem is than no data passes from the Arduino to $_POST[] in the PHP script, so no value gets written to the html file. The time marker successfully updates when I refresh the PHP scrip and html, so I know that is running OK. I suspect that something is wrong in this section of code:

void loop() {
postData = "Here are the data";

if (client.connect(server, 80)) {

Serial.println("Connected to Server");
client.println("POST /http://localhost/Firstphp/first.php HTTP/1.1");
client.println("Host: 192.168.1.4");
client.println("Content-Type: text/php");
client.print("Content-Length: ");
client.println(postData.length());
client.println();
client.print(postData);
Serial.println ("Still connected");
delay(3000);
}

}
When this code runs the if loop executes continuously, but just does not send anything to the PHP script.
Other relevant info:

  • my PHP scrip is in a file called first.php which is in htdocs/Firstphp.
  • I checked that the IP of my localhost is indeed 192.168.1.4
  • I copied this code from elsewhere, but the original was designed to POST to a website on the internet, so some of the code was different. Probably the changes I made to address localhost instead are not valid? Any help GREATLY appreciated. Full code below:

Arduino Code:
//#include <SPI.h>
#include <WiFiNINA.h>

char ssid[] = "abcdef";
char pass[] = "ghijkl";

int count=0;
int status = WL_IDLE_STATUS;

char server[] ="192.168.1.4";

String postData;

WiFiClient client;

void setup() {

Serial.begin(9600);

while (status !=WL_CONNECTED){

Serial.print("Status: ");
Serial.println (WiFi.status());
Serial.println(ssid);
status = WiFi.begin(ssid, pass);

delay(1000);
}

Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
IPAddress gateway = WiFi.gatewayIP();
Serial.print("IP Address: ");
Serial.println(ip);

}

void loop() {
postData = "Here are the data";

if (client.connect(server, 80)) {

Serial.println("Connected to Server");
client.println("POST /http://localhost/Firstphp/first.php HTTP/1.1");
client.println("Host: 192.168.1.4");
client.println("Content-Type: text/php");
client.print("Content-Length: ");
client.println(postData.length());
client.println();
client.print(postData);
Serial.println ("Still connected");
delay(3000);
}

}

PHP Script:

<?php $time = time(); echo $time; $temp = $_POST['temp']; $file = 'temp.html'; $data = $temp." . ".$time; file_put_contents($file, $data); ?>

Edit your post and insert code tags!

client.println("POST /http://localhost/Firstphp/first.php HTTP/1.1");

This line probably should read:

client.println("POST /Firstphp/first.php HTTP/1.1");

and this line:

 client.println("Content-Type: text/php");

probably is

 client.println("Content-Type: application/x-www-form-urlencoded");

although you have to adapt your post data too:

postData = "temp=Here+are+the+data";

You either should add a "Connection" header or change the HTTP version to 1.0.

Thanks for your response. I guess I'm showing how much I need to learn. I will certainly follow up on your instructions, but I have no clue what it means - especially your last comment. I'll do some research on Connection headers.
I guess it would really help if someone could describe in words what happens when the arduino POST code runs. What handshakes with what? How does it fit together. Where does the data go and how can it be retrieved?
I've been all over Google and Youtube without finding an explanation.

You still didn't edit your post to insert code tags!

I've been all over Google and Youtube without finding an explanation.

Here you find a description of the HTTP/1.1 protocol. This is a complete description of what happens.

I realize that I didn't do a go job with my post last time - apologies for that. I'll try and do better this time!
I still cannot get the arduino to send data to my localhost webpage using php POST. This is despite changing my approach. I went back to basics and used the example sketch WiFiWebClientRepeating as my start point. I did this because a) I know it works, and b) it provides debugging to see what is going on with the http request. I did not change this code except to provide my own IP addresses. I did change the key function "httpRequest()" to serve as a POST request based on numerous searches on this forum and Google. The full code is given below. I also copied a php script to handle the POST request from another article:

<?php header("Content-type: text/html"); header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past if(strlen($_POST["data"]) > 0 ) { echo "YES!!"; // if it displays this it worked }else{ echo "NO, It didn't work";//displays this if it didn't work } ?>

This file is in htdocs/Firstphp/first.php
When I run the arduino script I successfully connect to my WiFi network AND the localhost server, as can be seen by the serial port printout:

Please upgrade the firmware (Note: my firmware is 1.3.0 - I could not update to a later version)
Attempting to connect to SSID: ianjenniewireless1
SSID: XXXXXXXXXXXXXX
IP Address: 192.168.1.19
signal strength (RSSI):-70 dBm
connecting...
HTTP/1.1 200 OK
Date: Fri, 16 Oct 2020 15:18:19 GMT
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1g PHP/7.4.10
X-Powered-By: PHP/7.4.10
Cache-Control: no-cache, must-revalidate
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Content-Length: 131
Connection: close
Content-Type: text/html;charset=UTF-8

Notice: Undefined index: data in C:\xampp\htdocs\Firstphp\first.php on line 6

NO, It didn't work

Clearly I am connecting to the server and the php script runs, but nothing is passed to $_POST as seen by the last 2 lines of the serial port printout, This corresponds exactly to what I see when I refresh the webpage Localhost/Firstphp/first.php
Everything seems to be working, but no data transfers. I just can't figure this out, but suspect I may be making some dumb error. Any help will be hugely appreciated!!
Full sketch code follows:

Repeating Wifi Web Client

  This sketch connects to a a web server and makes a request
  using a WiFi equipped Arduino board.

  created 23 April 2012
  modified 31 May 2012
  by Tom Igoe
  modified 13 Jan 2014
  by Federico Vanzati

  http://www.arduino.cc/en/Tutorial/WifiWebClientRepeating
  This code is in the public domain.
*/

#include <SPI.h>
#include <WiFiNINA.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

// Initialize the Wifi client library
WiFiClient client;

// server address:
//char server[] = "example.org";
IPAddress server(192, 168, 1, 4);

unsigned long lastConnectionTime = 0;            // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds

void setup() {
  //Initialize serial 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 the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  // you're connected now, so print out the status:
  printWifiStatus();
}

void loop() {

  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:

  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
  // if ten seconds have passed since your last connection,
  // then connect again and send data:
  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();
  }

}

// this method makes a HTTP connection to the server:
void httpRequest() {
  String data;
  data = "A";

  // close any connection before send a new request.
  // This will free the socket on the Nina module
  client.stop();

  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.println("POST /Firstphp/first.php HTTP/1.1");
    client.println("Host: 192.168.1.4");
    client.println("Content-Type:application/x-www-form-urlencoded ");   
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);


    //client.println("Connection: close");
    //client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  } else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Clearly I am connecting to the server and the php script runs, but nothing is passed to $_POST as seen by the last 2 lines of the serial port printout, This corresponds exactly to what I see when I refresh the webpage Localhost/Firstphp/first.php

Sure, because your telling the server you're sending the content as application/x-www-form-urlencoded but actually you're sending bare data (better: one single character). Take a look at my answer #1, it shows how the data should look like to get a better result on the server.

Hi pylon, Thanks for your reply. Your help is REALLY appreciated. Obviously, I'm getting close to where I want to be. At least I know that the arduino client is connecting to the server and the target php script also runs OK
Based on your latest reply I assume the problem is in this section of code:

if (client.connect(server, 80)) {
    // if connected:
    Serial.println("Connected to server");
    // make a HTTP request:
    // send HTTP header
    client.println("POST /Firstphp/first.php HTTP/1.1");
    client.println("Host: localhost");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);

In view of your comment I presume the problem is in client.println("Content-Type: application/x-www-form-urlencoded");
However, if this is inappropriate for the data I'm trying to send, how should this line be written? Does it depend on the type of data (string, int etc.) or does it refer to "Firstphp/first.php? I tried just sending "A" to keep it simple, but it made no difference. I also tried changing the content-type to text/plain, but again with no change.

I followed up with the link you provided (very useful) regarding the HTTP protocol and connection headers, so I have a better understanding, but I still don't know which Connection header to use?
Thanks again!

Based on your latest reply I assume the problem is in this section of code:

No, it's in this line:

  data = "A";

Have you tried to set the data variable to the value I proposed in answer #1?