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.


Servers: Getting current public IP address

This is a simple trick on getting public IP address in system if you are behind some NATs or something.

curl -s http://whatismijnip.nl/?f |cut -d " " -f 5


What to expect:

<public ip address>

Mikrotik: Use multiple public IP in single WAN interface

In some cases, there are more than one public IPs given by ISP for users. For example, business packages that are very pricey.

How to configure for each device/interface to get the specific public IP?

Of course, in stock routers given by ISP, they teach us to use Unnumbered IP, which for some reasons are not as easy as using NAT in Mikrotik.

Network Address Translation (NAT).

First, you need to determine that the address are already added inside the IP > Address in Mikrotik. If not, you should do so.

/ip address add address=<public ip here> interface=<wan/pppoe client interface here>

After making sure it is available, go ahead to IP > Firewall > NAT. Add the src-nat and dst-nat translation to your specific network address/interface.

/ip firewall nat
add chain=dst-nat action=dst-nat dst-address=<public ip here> to-address=<local server address>

add chain=src-nat action=src-nat src-address=<local server address> to-address=<public ip here> out-interface=<wan/pppoe client interface here>

If public IP on the server returning wrong/same public IP please check if you already have a masquerade rule that applies to all interface and address. If you do so, add a new rule at the end of ruleset and disable the masquerade rule. This will allow you to select the public IP that is default in the network.

/ip firewall natadd chain=src-nat action=src-nat to-address=<public ip here> out-interface=<wan/pppoe client interface here>

Wednesday 13 August 2014

EasyMaths Camp @ SMK Bandar Rinching

6 & 7 August.

A seminar by Easymaths Centre organized by Shinobi's Solution was held at SMK Bandar Rinching, to help SPM candidates with their well-known weakness, Additional Mathematics.

Actually I've already been to the same seminar last year at USIM, but since I was attending Kem Pembangunan Remaja Kreatif 2014, I can't attend the same one this year. But luckily with Puan Noraini as Head of Additional Mathematics initiative to held the same seminar at the school, it can probably help a lot of students too.

The teacher who is assigned to this camp is Encik Azahari, which I remember well for his "kambing" joke. I like his explaination and Easymaths formula, especially, which is very easy to be remembered regardless my short-term memory.

Since there is no pictures of me they uploaded to Facebook, I don't want to attach any pictures here.

:v