Saturday 24 December 2016

Arduino + Node.js: Socket connection

Connecting the Arduino to the Node.js is fairly an easy process, and doesn't require blood and tears.

We will use Arduino Ethernet Shield.

The Arduino will send the bytes array to Node.js server, and the server will return a char string of response. I haven't found a way to parse bytes array in HTTP client in Arduino, so any help is appreciated.

I have created an example program that will send a number to Node.js server and the server will send it back. After that, Arduino will add one to the number and send it to Node.js. The process will not stop.

Node.js side:

var net = require('net');
var host = "0.0.0.0";
var port = 18997;

var sockets = [];
var nextSocketId = 0;
var server = net.createServer(function (conn) {
    var ip;
    ip = conn.remoteAddress;
    var socketId = nextSocketId++;
    sockets[socketId] = conn;

    console.log('Socket connection with #' + socketId + ' started.');
    console.log('Connected: ' + ip);

    conn.on('data', function(bytes) {
      // Retrieve the integer
      var status = (bytes[0] << 8) | bytes[1];
      // Send the return
      conn.write(status.toString());
    })

    conn.on("close", function (code, reason) {
      console.log('Closed: ' + ip);
      if (sockets[socketId]) {
        sockets[socketId].destroy();
        delete sockets[socketId];
      }
    })

    conn.on('error', function (err) {
      // don't do nothing on error
      // TODO: ACTUALLY TRAP THE ERROR
    })
}).listen(port, host);
console.log("Server has started on " + host + ":" + port + ".");

Arduino side:

#include <Ethernet.h>

// Define MAC address here
byte mac[] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02
};

// Define server IP here
IPAddress server(10, 0, 0, 21);
EthernetClient client;
int port = 18997;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  if (Ethernet.begin(mac) == 0) {
    // beep
    Serial.println("We are not getting an IP address.");
  } else {
      Serial.println("We are getting an IP address.");
    if (client.connect(server, port)) {
      Serial.println("We are now connected!");
    } else {
      // if you didn't get a connection to the server:
      Serial.println("We are not connected yet!");
    }
  }
}

void loop() {

  if (!client.connected()) {
    Serial.println("We are disconnected!");
  }

  int sendNumber = 0;
  bool sendNumberStatus = true;
  while (sendNumberStatus) {
    Serial.println("Sending number " + sendNumber);
    
    byte data[2];
    data[0] = sendNumber >> 8;
    data[1] = sendNumber & 0xFF;
    client.write(data, sizeof(data));
    
    char c = client.read();
    for (int a = 0; a < 5; a++) {
      if (c == -1) {
       delay(150);
       c = client.read();
      } else {
         // got reply. yeay
         a = 5;
         Serial.println("We got a reply! Proceed adding the number");
         sendNumber++;
      }
    }

    if (c == -1) {
      // timeout reached.
      Serial.println("Cannot send number anymore.");
      sendNumberStatus = false;
    }
  
    delay(1000);
  }

}

If there is any bug, please comment below.


4 comments: