PHP – Arduino Communication through socket

In this tutorial a demo project will be explained, communication is established between PHP and Arduino using a simple intermediate C program which runs as a Linux daemon.

The concept used here is Unix local Sockets, a fast and effective way to perform IPC (or Inter-Process Communication) on Unix based systems.

The communication occurs as follows:

PHP sends some data over the Unix Socket > our C daemon receives the data > it sends it to our Arduino using a serial connection > Arduino replies through the serial port > C receives the response > our C daemon sends the response through the local socket again and PHP reads it!

Cool, but hey. I’ve just used some sort of library and I got PHP working with the serial port, I’m done with this tutorial!

Wait! I forgot, this method allows you to also:

– Cache the response from the serial port and access it from different programs (and programming languages)

– The communication can be asynchronous if you prefer

– You don’t have to give PHP permission to access your /dev (s)

– Many other advantages I really can’t remember now…

Let’s start!

We’ll refer to some files during this tutorial, they are:

socket.php > This is the PHP script that communicates with the socket.

– socket_sketch.ino > This is the program running on our Arduino, it replies OK whenever it receives “SEND” through the serial connection.

– echosocket.c (when compiled: echosocket) It’s our C daemon which relays data between PHP and Arduino.

First, we have to create the PHP script (name it: socket.php and copy it to your web folder), it needs to get some sort of user input and sends it to our socket, this is the code I wrote:

<?php

echo ” — PHP communication with C daemon over Linux/Unix socket —<br><br>”;

$fp = fsockopen(“unix:///tmp/socket.sock”, -1, $errno, $errstr, 2);

if ($fp != false) {

echo “Socket initialization sequence completed!<br>”;

$send = “MESSAGE\r\n”; // This is the message we send!
fwrite($fp, $send);

echo “Sent: Ciao over Linux/Unix Socket<br>”;
echo “Waiting for response…<br>”;

echo “Response: “.fgets($fp).”<br>”;

fclose($fp);

echo “Socket closed.<br>”;

} else {
echo “Can’t connect to Linux Daemon.\r\n”;
}

?>

It reads a local socket at /tmp/socket.sock and sends “MESSAGE” through it.

Now let’s create the C deamon which handles the communication, You can download the source code from: here, just save it somewhere.

Brief explanation: It initializes the serial port portname at 9600 8N1 for communication with our Arduino, then it listens on the local socket.

What matters is down here:

if (n > 0) {
printf(“Received: %s”, socketBuffer);

if (strstr(socketBuffer, “MESSAGE”) != NULL) {

write(fd, “SEND\n”, 5);

usleep (5 * 100); //Wait 100uS * 5

int n = read(fd, serialBuffer, sizeof buf);

if (n>0) {
if (send(s2, serialBuffer, strlen(serialBuffer), 0) < 0) {
perror(“send”);
}
}
}

}

If something is received, it checks whether it’s equal to MESSAGE (remember, the same MESSAGE we sent earlier with PHP), then it sends SEND to the Arduino, waits for a response and then sends everything back to PHP.

On the Arduino side, we run something like (create a sketch called: socket_sketch.ino):

char buf[10];
int lastIndex = 0;
int in = 0;

void setup() {
Serial.begin(9600);
}

void loop() {

while (Serial.available()) {
buf[lastIndex] = Serial.read();
lastIndex++;
in = 1;
delay(10);
}
if (in == 1) {
lastIndex = 0; //Reset

if (strstr(buf, “SEND”) != NULL) {
Serial.println(“OK”);
}
in = 0;
}
}

Whenever SEND is received, OK is sent back as a response.

That’s all! Now let’s run it!

First of all we have to compile the C program so that it runs on our machine, go to the same folder as the source code and run:

gcc -o echosocket echosocket.c

The C daemon should always be running, we can start it manually by typing ./echosocket while in the same folder as root.

Automatic Execution

You can also set it up for automatic execution at boot time, I’ll provide instructions for ArchLinux as this is the system I actually use.

Note: It’s assumed you are logged it as root at this time

Go to /usr/lib/systemd/system/ and create a new unit file:

touch echosocket.service

Now you can edit its content:

nano echosocket.service

Paste in: (change path with your path to echosocket)

[Unit]
Description=C Socket

[Service]
Type=simple
ExecStart=/PATH/echosocket
Restart=always

[Install]

WantedBy=multi-user.target

Now you can start/stop/enable the C daemon just like any other service:

systemctl start echosocket

systemctl stop echosocket

systemctl enable echosocket <– Enables the unit at boot time

If you haven’t already, you can now flash your Arduino with the sketch above… you are all set!

We’re done! A basic communication should now be possible! Make sure the C daemon is running and visit the PHP page, you should receive OK from the Arduino!

Troubleshooting:

– PHP says “Can’t connect to Linux Daemon.”, What should I do?

Check you’ve gone through all steps! If so, read below:

  • Check the C daemon is running
  • Make sure the file /tmp/socket.sock exists! (It’s created automatically)
  • Check /tmp/socket.sock file permissions, are they 777?
  • Make sure /tmp is added to PHP open_basedir or that open_basedir is disabled!
  • Make sure you are running echosocket as root

Special note to Arch Users:

If you use Apache2 and you can’t get this tutorial to work, please note that PHP access to /tmp may be restricted; check that PrivateTmp in /usr/lib/systemd/system/httpd.service is false.

Amedeo,

See ya!