Internal/External temperature sensor with two ESP8266 boards and Espruino

In this article we will use two ESP8266 board to show internal and external temperature in an OLED screen using Espruino and some JavaScript code.

 

 

 

 

The internal board will:

  • read the temperature and humidity from a DHT22 sensor
  • receive the external temperature and pressure from the external ESP board
  • show all the information in the OLED screen

The external board will:

  • read the temperature and barometric pressure from a BMP085 sensor
  • send the temperature and the pressure to the internal board using a WiFi connection

In this article we will reuse the wiring and the code we wrote in the previous articles about the ESP8266 board.

Wiring

The internal board is wired to the DHT22 sensor and the OLED screen:

The external board will be connected to the BMP085 sensor:

Internal board code

The internal board gets the internal temperature using the DHT22 sensor and print it in the OLED screen. The board prints also the external board information, we keep such information in an externalData variable.

var dht = require("DHT22").connect(NodeMCU.D4);
var g;

var externalData;

function drawData(temperature, humidity) {
  g.clear();
  g.setColor(5);

  g.drawString("INT", 0, 2);
  g.drawString("T: " + temperature + " C", 0, 20);
  g.drawString("H: " + humidity + " %", 0, 40);

  g.drawString("EXT", 62, 2);

  if (externalData) {
    g.drawString("T: " + externalData.temperature.toFixed(2) + " C", 62, 20);
    var pressureInBar = externalData.pressure / 100000;
    g.drawString("P: " + pressureInBar.toFixed(2) + " bar", 62, 40);
  } else {
    g.drawString("N/A", 62, 20);
  }

  g.flip();
}

function readTemperature() {
  dht.read(function (info) {
    drawData(info.temp, info.rh);
  });
}

function setupGraphics() {
  require("Font8x12").add(Graphics);
  g.setFont8x12();
  g.drawString("Ready", 2, 2);
  g.flip();

  setInterval(readTemperature, 2000);
}

function setupOLED() {
  I2C1.setup({scl:NodeMCU.D1, sda:NodeMCU.D2});
  g = require("SSD1306").connect(I2C1, setupGraphics);
}

But how the externalData variable get updated? Through a socket server that listen for new connection on port 1234. When a connection is established the server read the sent data.
var wifi = require("Wifi");

function handleClient(socket) {
  socket.on('data', function(data) {
    console.log('external data: ', data);
    externalData = JSON.parse(data);
    socket.end();
  });
}

function setupServer() {
  var net = require("net");
  var server = net.createServer(handleClient);
  server.listen(1234);
}

function connectWiFi() {
  wifi.connect("***WIFI*SSID***", {password:"***WIFI*PASSWORD***"}, 
    setupServer
  );
}

function onInit() {
  setupOLED();
  connectWiFi();
}

save();

The complete code is available as attachment. Time to setup the external board.

External board code

The external board reads the temperature and the barometric pressure from the BMP085 sensor and send it to the internal board using a TCP connection.

var bmp;

function setupBmpSensor() {
  I2C1.setup({scl:NodeMCU.D1, sda:NodeMCU.D2});
  bmp = require("BMP085").connect(I2C1);
}

var wifi = require("Wifi");

function sendDataToServer(data) {
  var net = require("net");
  net.connect({host: "192.168.1.105", port: 1234}, function(socket){
    var json = JSON.stringify(data);
    socket.end(json);
  });
}

function getAndSendData() {
  bmp.getPressure(sendDataToServer);
}

function setupDataPolling() {
  setInterval(getAndSendData, 2000);
}

function connectWiFi() {
  wifi.connect(
    "***WIFI*SSID***", 
    {password:"***WIFI*PASSWORD***"}, 
    setupDataPolling
  );
}

function onInit() {
  setupBmpSensor();
  connectWiFi();
}

save();

The result

 

How to make two ESP8266 communicate through WiFi with Espruino and JavaScript

In this article we will make two ESP8266 communicate using the WiFi network. We will use Espruino and some JavaScript code.

Setup the WiFi

Espruino offers a WiFi module that let us to connect to a WiFi network.

The code below will connect our ESP to the WiFi network and will print the information about the obtained IP plus other network information:

var wifi = require("Wifi");
wifi.connect("***WIFI*SSID***", {password:"***WIFI*PASSWORD***"}, function(err) {
  console.log("connected? err = ", err, " info = ", wifi.getIP());
});

The result should be:
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v93 Copyright 2016 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016
>
=undefined
connected? err =  null  info =  {
  "ip": "192.168.1.106",
  "netmask": "255.255.255.0",
  "gw": "192.168.1.1",
  "mac": "5c:cf:7f:f8:53:5a"
 }

Please take note of the IP for both the devices, currently there are no other way to discover each other.

Now both the devices are connected to the WiFi network. Now we can make them talk each other. In this example we elect one board server and the other client. The client board will start a TCP communication toward the server board. Once connected they will able to exchange messages.

Setup the server

The server first setup the WiFi connection, then creates a socket server on port 1234 for receiving connection from the clients. When a connection is established it will print the messages coming from the client and will close the connection saying “I’m a server! Goodbye.”.

function handleClient(socket) {
  console.log('client connected');

  socket.on('error', console.log);

  socket.on('data', function(d) {
    console.log('client says: ', d);
    socket.end("I'm a server! Goodbye.");
  });
}

function setupServer() {
  var net = require("net");
  var server = net.createServer(handleClient);
  server.listen(1234);
}

function connectWiFi() {
  var wifi = require("Wifi");

  wifi.connect("***WIFI*SSID***", {password:"***WIFI*PASSWORD***"}, function(err) {
    console.log("connected? err = ", err, " info = ", wifi.getIP());

    setupServer();
  });
}

function onInit() {
  connectWiFi();
}

save();

Setup the client

The client, after get ready with the WiFi connection, will try to connect to the server. When the connection is established it will send a “Hello I’m a client!” message and will wait for responses from the server.

function talkToServer(socket) {
  console.log('connected to the server');

  socket.on('error', console.log);

  socket.on('data', function(d) {
    console.log('server says: ', d);
  });

  socket.on('end', function() {
    console.log('disconnected from the server');
  });

  socket.write('Hello, I\'m a client!');
}

function connectToServer() {
  var net = require("net");
  net.connect({host: "192.168.1.105", port: 1234}, talkToServer);
}

function connectWiFi() {
  var wifi = require("Wifi");

  wifi.connect("***WIFI*SSID***", {password:"***WIFI*PASSWORD***"}, function(err) {
    console.log("connected? err = ", err, " info = ", wifi.getIP());

    connectToServer();
  });
}

function onInit() {
  connectWiFi();
}

save();

The output

Here the output in the server side:

>
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v93 Copyright 2016 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016
>Erasing Flash..................
Writing.....
Compressed 25600 bytes to 2137
Checking...
DRunning onInit()...
connected? err =  null  info =  {
  "ip": "192.168.1.105",
  "netmask": "255.255.255.0",
  "gw": "192.168.1.1",
  "mac": "5c:cf:7f:0f:7a:2b"
 }
client connected
client says:  Hello, I'm a client!
>

Here the output for the client side:
>
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v93 Copyright 2016 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016
>
=undefined
Erasing Flash..................
Writing.....
Compressed 25600 bytes to 2352
Checking...
DRunning onInit()...
connected? err =  null  info =  {
  "ip": "192.168.1.104",
  "netmask": "255.255.255.0",
  "gw": "192.168.1.1",
  "mac": "5c:cf:7f:f8:53:5a"
 }
connected to the server
server says:  I'm a server! Goodbye.
disconnected from the server
>

Reading pressure and temperature from a BMP085 using an ESP8266 board and Espruino

In this short tutorial we will read the barometric pressure from the BMP085 sensor using an ESP8266 board and Espruino with some Javascript code.

Wiring

Our BMP085 sensor communicates through an I2C connection, so we need to connect the SCL pin to the corresponding D1 pin and the SDA pin to the corresponding D2 pin in the ESP board. The other two pins are dedicated to the power.

Code

To read both pressure and temperature we will use the BMP085 module of Espruino. After the I2C connection is setup we initialize the BMP085 module, then we start polling and printing the sensor information.

I2C1.setup({scl:NodeMCU.D1, sda:NodeMCU.D2});
var bmp = require("BMP085").connect(I2C1);

function readPressure() {
  bmp.getPressure(function(info) {
    console.log("Pressure: " + info.pressure + " Pa");
    console.log("Temperature: " + info.temperature + " C");
  });
}

setInterval(readPressure, 2000);

Here the result:

Showing temperature in a OLED display using Espruino and an ESP8266 board

In this short article I will show you how to read the temperature and the relative humidity from a DHT22 sensor and display it in a 128×64 OLED display using an ESP8266 board with Espruino and JavaScript running on it.

Wiring

The DHT22 has 4 pins, only three used: two for the power and one for the data. We will connect the power pins to the corresponding pins on the ESP8266 board and the data pin to one of the GPIO pin, D7 in our schema.

The display is a SSD1306 with a resolution of 128×64 pixels and I2C communication. The display has four pins, two for the power and two for the I2C. We connect the I2C pin to the corresponding D1 e D2 pins in the ESP8266 board.

Code

Espruino provides a module for reading the temperature and the relative humidity from a DHT22 sensor. We will use it to read both the values from the connected sensor.

Then we will use the I2C module combined to the SSD1306 module to show the collected information in the display.

We will poll the sensor every 2 seconds and update the display consequently.

var dht = require("DHT22").connect(NodeMCU.D7);

function drawData(temperature, humidity) {
  g.clear();
  g.drawString("T: " + temperature + " C", 2, 2);
  g.drawString("H: " + humidity, 2, 20);
  g.flip();
}

function readTemperature() {
  dht.read(function (info) {
    drawData(info.temp, info.rh);
  });
}

function setupGraphics() {
  require("Font8x16").add(Graphics);
  g.setFont8x16();
  g.drawString("Ready", 2, 2);
  g.flip();

  setInterval(readTemperature, 2000);
}

I2C1.setup({scl:NodeMCU.D1, sda:NodeMCU.D2});
var g = require("SSD1306").connect(I2C1, setupGraphics);

save();

The final result:

How to install Espruino firmware in an ESP8266 board

espruino_logo

This is an update to the installation tutorial I’ve already wrote: Run JavaScript on your ESP8266 using Espruino firmware

For this installation I’m using a D1 mini board which is a “wrapper” for the ESP8266 (ESP-12) board.

Flash the Espruino firmware

The first step is to flash the Espruino firmware into the ESP board. You can find a tutorial in the Espruino site. In this article I’m putting a short list of instructions ready to use.

Install the ESP tools with the following command:

pip install esptool

The ESP tools are a set of Python scripts necessary to flash a firmware in the ESP board.

We need now the last version of the Espruino firmware, you can get it from the download page of the Espruino site. The zip file will contain the Espruino firmware also for the ESP8266 board.

We are ready to flash our board. The following instruction are for a ESP-12 board connected to the /dev/ttyUSB0 port. Please refer to the original tutorial for a different version of the ESP board. First move to the folder where you have unzipped the firmware.

cd espruino_1v93_esp8266_4mb
esptool.py --port /dev/ttyUSB0 --baud 115200 \
  write_flash --flash_freq 80m --flash_mode qio --flash_size 32m \
  0x0000 "boot_v1.5.bin" 0x1000 espruino_esp8266_user1.bin \
  0x3FC000 esp_init_data_default.bin 0x3FE000 blank.bin

The blue led in the board will start blinking and you will see the following output in console:
WARNING: Flash size arguments in megabits like '32m' are deprecated.
Please use the equivalent size '4MB'.
Megabit arguments may be removed in a future release.
esptool.py v2.0.1
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash params set to 0x004f
Compressed 3856 bytes to 2763...
Wrote 3856 bytes (2763 compressed) at 0x00000000 in 0.2 seconds (effective 124.0 kbit/s)...
Hash of data verified.
Compressed 479796 bytes to 336471...
Wrote 479796 bytes (336471 compressed) at 0x00001000 in 29.7 seconds (effective 129.3 kbit/s)...
Hash of data verified.
Compressed 128 bytes to 75...
Wrote 128 bytes (75 compressed) at 0x003fc000 in 0.0 seconds (effective 86.3 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x003fe000 in 0.0 seconds (effective 4737.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...

If you’re having problems finding the correct device path in Linux:

  • first check that you’re using an USB data cable. The first time I’ve tried I was getting crazy because I was using a simple power USB cable.
  • second try this console command to print the system events when the USB cable is plugged:
    watch -n 0.1 "dmesg | tail -n $((LINES-6))"

    When you plug the cable you will get something like this:
    [ 5597.132098] usb 6-1: new full-speed USB device number 11 using uhci_hcd
    [ 5597.298148] usb 6-1: New USB device found, idVendor=10c4, idProduct=ea60
    [ 5597.298156] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [ 5597.298160] usb 6-1: Product: CP2102 USB to UART Bridge Controller
    [ 5597.298163] usb 6-1: Manufacturer: Silicon Labs
    [ 5597.298165] usb 6-1: SerialNumber: 0001
    [ 5597.304121] cp210x 6-1:1.0: cp210x converter detected
    [ 5597.306173] usb 6-1: cp210x converter now attached to ttyUSB0

Ready to run

After the flash operation the board is ready to receive your JavaScript commands!

To send the commands you need to connect to the board using a serial connection (through the USB port). Under linux you can use the screen program:

screen /dev/ttyUSB0 115200

Now you can send JavaScript commands that will be interpreted and the output provided as response.

For example writing:

1+1

you will get:
=2

You can call functions, for example:
reset();

it will reset the board and print a boot message:
 _____                 _ 
|   __|___ ___ ___ _ _|_|___ ___ 
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v93 Copyright 2016 G.Williams

Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016

If you want to exit from Screen press CTRL-A and then \.

Now you’re ready to write your JavaScript code and run it in a ESP8266 board, for example using the Espruino Web IDE.

 

Run JavaScript on your ESP8266 using Espruino firmware

espruino_logo

Espruino is a board that comes with a pre-installed firmware capable of running JavaScript code. You can buy one of the official board or you can flash a list of “not officially supported” boards. The list contains also the ESP8266 board, so let’s try to run our JavaScript code on it.

For this article I’m using a NodeMCU Amica board which lets us play with the ESP8266 (ESP-12) without the burden of connecting it to the computer and also powering it to the right voltage all from a micro USB port.

All the programs in the article are run from a Linux Mint 17 operative system.

Flash the firmware on ESP8266

First step is to flash the Espruino firmware into the ESP board. You can find a tutorial in the Espruino site. In this article I’m putting a short list of instructions ready to use.

Create a working folder and download there the ESP tools.

mkdir espruino
cd espruino
wget https://github.com/themadinventor/esptool/archive/master.zip
unzip master.zip

The ESP tools are a set of Python scripts necessary to flash a firmware in the ESP board.

We need now a ESP8266 dedicate version of the Espruino firmware. You can find the latest version in this forum post. Here the instructions to download the last version available today (26/06/2016):

wget http://s3.voneicken.com/espruino/espruino_1v85.tve_master_124390c_esp8266.tgz
tar -xvf espruino_1v85.tve_master_124390c_esp8266.tgz 

We are ready to flash our board. The following instruction are for a ESP-12 board connected to the /dev/ttyUSB0 port. Please refer to the original tutorial for a different version of the ESP board.
cd espruino_1v85.tve_master_124390c_esp8266
../esptool-master/esptool.py --port /dev/ttyUSB0 --baud 115200 \
  write_flash --flash_freq 80m --flash_mode qio --flash_size 32m \
  0x0000 "boot_v1.5.bin" 0x1000 espruino_esp8266_user1.bin \
  0x3FC000 esp_init_data_default.bin 0x3FE000 blank.bin

The blue led in the board will start blinking and you will see the following output in console:
esptool.py v1.2-dev
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x004f
Writing 4096 @ 0x0... 4096 (100 %)
Wrote 4096 bytes at 0x0 in 0.4 seconds (90.2 kbit/s)...
Writing 462848 @ 0x1000... 462848 (100 %)
Wrote 462848 bytes at 0x1000 in 40.1 seconds (92.4 kbit/s)...
Writing 4096 @ 0x3fc000... 4096 (100 %)
Wrote 4096 bytes at 0x3fc000 in 0.4 seconds (90.2 kbit/s)...
Writing 4096 @ 0x3fe000... 4096 (100 %)
Wrote 4096 bytes at 0x3fe000 in 0.4 seconds (90.5 kbit/s)...
Leaving...

(Did you noticed the “Running Cesanta flasher stub…” print? Looks familiar?)

If you’re having problems finding the correct device path in Linux:

  • first check that you’re using an USB data cable. The first time I’ve tried I was getting crazy because I was using a simple power USB cable.
  • second try this console command to print the system events when the USB cable is plugged:
    watch -n 0.1 "dmesg | tail -n $((LINES-6))"

    When you plug the cable you will get something like this:
    [ 5597.132098] usb 6-1: new full-speed USB device number 11 using uhci_hcd
    [ 5597.298148] usb 6-1: New USB device found, idVendor=10c4, idProduct=ea60
    [ 5597.298156] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [ 5597.298160] usb 6-1: Product: CP2102 USB to UART Bridge Controller
    [ 5597.298163] usb 6-1: Manufacturer: Silicon Labs
    [ 5597.298165] usb 6-1: SerialNumber: 0001
    [ 5597.304121] cp210x 6-1:1.0: cp210x converter detected
    [ 5597.306173] usb 6-1: cp210x converter now attached to ttyUSB0

After the flash operation the board is ready to receive your JavaScript commands!

To send the commands you need to connect to the board using a serial connection (through the USB port). Under linux you can use the screen program:

screen /dev/ttyUSB0 115200

Now you can send JavaScript commands that will be interpreted and the output provided as response.

For example writing:

1+1

you will get:
=2

You can call functions, for example:
reset();

it will reset the board and print a boot message:
=undefi
 _____                 _ 
|   __|___ ___ ___ _ _|_|___ ___ 
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v85.tve_master_124390c Copyright 2016 G.Williams

Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016

Time to use the Espruino Web IDE.

Espruino Web IDE

The Espruino project provides a Web IDE for editing and uploading your JavaScript code to your board. The IDE also manages the modules that can be used in your code in order to extend the basic functionalities offered by the SDK, for example to use the Wi-Fi device or external sensors like the DHT-22.

The Web IDE can be installed as Chrome application or as NodeJS package.

Espruino Web IDE

After the IDE has been installed we have to configure the baud rate in order to have the communication with the board working fine. Click on the gear icon on the top right, select the COMMUNICATIONS tab, then set the “Baud Rate” to 115200.

espruino_web_ide_settings

Now everything is ready to play. Click the connect button on the top left, select the USB port to use and the IDE will connect to the board.

On the left side you can write commands directly to the board and get the response live.

espruino_web_ide_console

On the right side you can write your code and then upload it to the board using the upload button on the center.

espruino_web_ide_editor

Now we ready to write our first JavaScript program to run on our ESP8266 board!

Run JavaScript in your ESP8266 device

In the previous article we saw how to build the Smart.js framework and flash the firmware in the ESP8266 device. Now is time to play a little more with it.

In this article I will show how to read the temperature and the humidity from a DHT11 sensor connected to the ESP8266 device and how to send those values to a public site using an HTTP GET request, all using JavaScript code.

How to add new files to the firmware

To add a new file to the firmware add it in the smart.js/platforms/esp8266/fs folder. All the files in the fs folder are added to the file system of the firmware during the build process. Those file will be accessible using the File API.

Lets try it creating a file myfirst.js with the following code:

//print the Hello World message
function sayHello() {
   print('Hello World');
};

//print my external IP
function getMyIp() {
 Http.get("http://jsonip.com", function(data, error) { 
   if (error) { 
     print("error ", error); 
   } else { 
     print("my ip is ", JSON.parse(data).ip); 
   } 
 });
};

Now save the file and run the firmware build process:
sh make.sh

Connect the ESP device as explained before and flash the new firmware.

In the console we can now load and evaluate our JavaScript file using the eval function from the File API:

File.eval('myFirst.js');

The code in the file is evaluated and the functions that we have defined can now be called:
smartjs 29592/2268$ sayHello();
Hello World
undefined

The sayHello method prints the “Hello World” message visible in the output area. Instead the “undefined” value is the value returned by the function and printed by default.
Let’s try the other function getMyIp:
smartjs 29408/2160$ getMyIp();
undefined
smartjs 26728/1956$ error cannot resolve

The execution terminates with an error message, this happens because the WiFi is not configured. We can configure it using the Wifi API:
Wifi.setup('yourssid', 'yourpassword');

The setup function will make the ESP device scan for the specified network and connect to it. If everything go fine the method return the true value.

The Wifi API offers also a method to check the current Wifi status:

smartjs 29384/2160$ Wifi.status()
got ip

Now that the Wifi is configured we can try the getMyIpFunction:
smartjs 28752/1860$ getMyIp();
undefined
smartjs 25656/1860$ my ip is 86.12.19.195

The printed IP is our external IP, the one of our modem. If, instead, we want the internal IP, the one assigned by our access point, simply call Wifi.ip().
Now we are able to write our program and execute it. Time to read values from a DHT11 sensor.

Wiring the DHT11

To read the sensor values we will use the only available pin in the ESP device the GPIO_02.
First connect the VCC and GND pins of the sensor to the respective VCC and GND on the USB adapter. Then connect the DATA pin to the ESP GPIO_02 pin. Note that the GPIO_0 is NOT connected to the GND.

Now connect the USB adapter to the computer and click the “connect” button on the Flash’n’Chips tool. I don’t know why but sometime I have to disconnect the sensor DATA pin before turn on the ESP device otherwise the ESP console don’t reply.

The framework comes with the support for the DHT11 sensor, a global object DHT11 is defined with a read function. The function takes an integer as input, the sensor port, in our case is the number 2.

We can use the DHT11 object simply calling his read method:

smartjs 29584/2268$ DHT11.read(2);
{"rh":61,"temp":22}

The returned value is an object with temperature and relative humidity. Time to publish the sensor values.

Publish the sensor values

We will publish the sensor values in a site that accepts a GET request with the values as url parameters, something like http://mysite.com/publish.php?temperature=22.0&humidity=55.0

Create a sensor.js file in the fs folder with the following code:

function readSensor() {

  //read the sensor data
  var data = DHT11.read(2);

  //compose the GET url
  var url = "http://mysite.com/publish.php?temperature="+data.temp+"&humidity="+data.rh;

  //do the GET
  Http.get(url, function(data, error) {
    if (error) {
      print("error ", error);
    } else {
      print("data published");
    }
  });
};

Build the firmware with the new file. Before flash the device re-connect the GPIO_0 to the GND and disconnect the sensor DATA pin. After the flash is complete disconnect the adapter e disconnect the GPIO_0 from the GND.

Connect the adapter to the computer, then click the “connect” button in the Flash’n’Chips tool. After the console is connected re-connect the DATA pin.

First, setup the WiFi:

Wifi.setup('yourssid', 'yourpassword');

Then load and evaluate the sensor code:
File.eval('sensor.js');

We can now run our method readSensor. It will read the values from the sensor and publish them to a site using the HTTP API. Here the console output:
readSensor();
undefined
smartjs 25656/1860$ data published


And a chart built using the published values:

chart

So our little ESP device is able to read values from a sensor and publish them in a site using the Wi-Fi network.

Continuous and automatic publication

What if we want a continuous publication of sensor values?
Here the solution:

function streamSensorData() {
  readSensor();
  setTimeout(streamSensorData, 5000);
};

This method will publish the sensor data every 5 seconds.

What if we want to start the publication automatically without the need to run it from a console?
Here the solution.

First append those lines to the sensor.js code:

if (Wifi.status() === "idle") Wifi.setup('yourssid', 'yourpassword');
streamSensorData();

The first line checks if the WiFi is active otherwise setups it. The second line starts the data streaming.

In order to make our sensor.js file evaluated at boot time we need to modify the user.js file under smart.js/src/js folder appending this line:

File.eval('sensor.js');

Build and flash the firmware. After rebooting the device it will start to publish the sensor values.

Conclusions

We saw how to run our JavaScript code in our ESP device thanks to the great work from Cesanta. The framework is still under development so the APIs or the tools can change in any moment.

I think there will be for sure a lot of news in the coming months. One thing will be the integration of the web server Mongoose in the Smart.js framework, that means connecting directly to the device using the browser!
Another thing, as I can understand from the Smart.js online dashboard, is that we will be able to upload our JavaScript code directly from our browser so we don’t need to flash the firmware every time we update the code!!!

Build the Smart.js framework

Cesanta has developed a JavaScript engine, capable of run JavaScript code in the ESP8266 device and in other embedded devices. The JavaScript engine is provided with the Smart.js framework. The framework offers a set of APIs for files management, networking and WiFi management, SPI and I2C communication, GPIOs and Cloud services. The framework is distributed ready to flash under Windows and Mac. Here you can find a short guide.

In this article I will show how to build the framework under the Ubuntu’s like OS and flash your ESP8266-01 device with the latest Smart.js framework version.

Framework build

In order to build the Smart.js framework we need first to install Docker. A complete and updated set of instructions on how to install Docker can be found here. To make it short you can simply run this command in the console:

wget -qO- https://get.docker.com/ | sh

After the Docker installation is complete we checkout the framework code:
git clone https://github.com/cesanta/Smart.js.git

To build the framework move to the esp platform directory:
cd Smart.js/platforms/esp8266

and run the build process:
sh make.sh

The first time it will require a little bit because the tool has to download the docker images. Next builds will be really fast.

The three binary files composing our ESP firmware will be generated under the firmware folder. Now we need the tool to flash the ESP device.

Flash’n’Chips build

The Smart.js framework is provided with a tool for flashing our devices: Flash’n’Chips.

fnc

To build the tool first we need to install the required dependencies: Qt 5 and libftdi.

To install Qt 5 you can use the installer distributed by Qt here. It will install all the Qt tools under the specified folder. In the folder you will find the binary required to compile Flash’n’Chips. I suggest to add the bin folder to your PATH variable:

export PATH=Qt5.5.0/5.5/gcc_64/bin:$PATH

To install the libftdi library run:
sudo apt-get install libftdi-dev

Now we are ready to compile the Flash’n’Chips tool. Move to the source folder:
cd smart.js/flashnchips

And run first:
qmake

then:
make

In a bit the tool will be ready to be executed. Time to connect the ESP device to your computer.

Wiring

To connect my ESP 8266-01 I’m using a FT232 adapter. If you are using it remember to set it to 3v3.

ft232

We connect the respective VCC and GND pins, same for RX and TX pins but inverting them. We need also to connect the ESP CH_PD to the VCC and, only for the flashing process, the ESP GPIO_0 to the GND.

ft232 esp8266_bb

We are now ready to flash the previously built firmware into the ESP device.

Flash the ESP

Connect the USB adapter and run the Flash’n’Chips tool using this command from the flashnchips folder (I had to use this parameters for some issues with my ESP board):

./flashnchips --overwrite-flash-fs --esp8266-flash-params 0x0000 --gui

The tool should show the “Flash firmware” button active.

fnc ready

If not press the “Detect devices” button and see if the adapter is recognized.

Press the “Flash firmware” button and the flash process will start. You can see the progress bar running and the current operation explained under it.

fnc flash

When the process is completed the communication console will be activated under the progress bar area. You will see some messages from the device.

fnc console

Now we are ready to run some JavaScript commands in our ESP device.

Play with console

The Flash’n’Chips console has two areas, the first shows the device output, the second let us write commands to send to the device. The commands are snippets of JavaScript code that are executed on the device.

We can start writing a simple expression:

2+2

The device will calculate it and reply with the result:
smartjs 29176/2256$ 2+2
4

We can also use the framework’s APIs, for example we can list the files present on the device:
File.list('.');

It should output something like:
smartjs 29536/2268$ File.list('.')

["cloud.js","demo.js","clubby.js","MC24FC_test.js","MPL115A1.js","I2C.js","MC24FC.js","smart.js","user.js","sys_rts.js","MCP9808.js","MCP9808_test.js","gpio.js","sys_config.json"]

These are some of the JavaScript functions that our device can run. In the next article we will see how to run a simple program that reads values from a DHT11 sensor and publish them in a site.

How to translate a search query into a JavaScript filtering function

In a project I had to translate a search query into a filtering function to apply to a stream of JavaScript objects. The query language was very simple, boolean expressions of property constraints, for example “name:john AND age:52” where the search should return all the objects with property “name” equals to “john” and property “age” equals to 52.

The first step was to parse the search query with a parser. You can write a parser by hand or your can use a parser generator like PEG.js. I prefered the second one.

With the online editor I’ve wrote the language grammar:

start = andExpression

andExpression = orExpression (and andExpression)?

orExpression = expression (or andExpression)?

expression = string ':' string

string = char*

char = [a-zA-Z0-9]

and = ws 'AND'i ws

or = ws 'OR'i ws

ws = [ \t\n\r]*

The generated parser takes as input the text to parse and returns the parsed elements:
Output
[
   [
      [
         [
            "n",
            "a",
            "m",
            "e"
         ],
         ":",
         [
            "j",
            "o",
            "h",
            "n"
         ]
      ],
      null
   ],
   [
      [
         [
            " "
         ],
         "AND",
         [
            " "
         ]
      ],
      [
         [
            [
               [
                  "a",
                  "g",
                  "e"
               ],
               ":",
               [
                  "5",
                  "2"
               ]
            ],
            null
         ],
         null
      ]
   ]
]

The grammar can be changed to make the parser method return a boolean expression:
{
  function combine(left, right) {

    if (right === null) return left;
   
    return left + " " + right[0] + " " +right[1];
  }
}

start = ex:andExpression 
        {return 'return '+ex+';';}

andExpression = left:orExpression right:(and andExpression)? 
                {return combine(left,right);}

orExpression = left:expression right:(or andExpression)?  
               {return combine(left,right);}

expression = name:string ':' value:string
             {return 'LangParser.hasKeyValue(obj,\''+name+'\', \''+value+'\')';}

string = chars:char* 
         { return chars.join(""); }

char = [a-zA-Z0-9]

and = ws 'AND'i ws 
      {return '&&';}

or = ws 'OR'i ws 
     {return '||';}

ws = [ \t\n\r]*

The parser for a query like “name:john AND age:52” generates the following expression:
return LangParser.hasKeyValue(obj,'name', 'john') 
        && LangParser.hasKeyValue(obj,'age', '52');

In the generated expression I’ve used an utility method that checks if the specified couple of name and value exists as property for the specified object:
/**
 * Checks if the passed Object has the specified couple of key and value as property.
 * @param obj the object to check.
 * @param key the key.
 * @param value the value-
 * @returns {Boolean} <code>true</code> if the couple is found, <code>false</code> otherwise.
 */
LangParser.hasKeyValue = function (obj, key, value) {
    return obj.hasOwnProperty(key) && value === obj[key];
};

The expression can be then passed as parameter in the function constructor:
var expression = parser.parse(query);
var filterFunction = new Function("obj", expression);

Now you can use the new function as filter, for example with stream.js streams:
var filtered = new Stream.filter(filterFunction).toArray();

The grammar can be expanded with more operators and capabilities.