Time on Espruino on ESP32

Espruino devices do not usually have a proper battery-backed RTC available, so the second easiest way to get a time is via (S)NTP. On Espruino on the ESP8266 this is super-simple ( is my NTP time server and 9 is the timezone offset):

//Wifi.setSNTP("", 9);

but that does not work on Espruino on the ESP32 as Wifi.setSNTP() does not exist here (nor anywhere else). But a module for SNTP exists. This is how to use it to set the time:

// ESP32
const sntp=require('sntp');
var options = {
    host: '',
    port: 123,
    timeout: 1000

sntp.time(options, function (err, time) {
    if (err) {
        console.log('Failed: ' + err.message);
    //console.log('Local clock is off by: ' + time.t + ' milliseconds');
    //console.log('Full NtpMessage:', time);

Way more complicated, but it's more general on Espruino.


TTGO T-Eight and Espruino

TTGO T-Eight is a small ESP32 board from here. Small OLED, left/right/select input method, microSD slot, and 4 MB PSRAM, LiPo connector, plus of course WiFi/Bluetooth is a good combination of features. The problem as usual is the lack of documentation. The situation is even worse in this particular case:

  1. The official git repo is outdated and describes only the OLED part of the old revision of the board.
  2. There's an old and new revision of the board. Luckily the silkscreen is updated, but if you copy&paste old code, you'll be possibly surprised that it won't work.
  3. There's a TTGO T8 which is similar but different. They could have called it T9, or T8a or T8D.
  4. There's no schematics so finding out what connects to what pin is somewhere between "Trust the docs" and "Detective work"

Anyway, here is what I found:

  1. SDA/SCL is Pin 21/22 as printed on the silk screen (old version: 5 and 4)
  2. microSD would then be at 5/23/18/19 as per silk screen (untested)
  3. Input is Pin 37/38/39 for right/center/left
  4. 4 blue LEDs and one red LED on the back: no idea yet. Blue could be LiPo voltage, and red one simply power

So here a small minimal Espruino program which uses the display and which can read the buttons:

// TTGO T-Eight

I2C1.setup({sda: 21, scl: 22, bitrate: 400000});

function gstart(){
 g.drawString("Hello World!",2,2);

// I2C
var g = require("SH1106").connect(I2C1, gstart, {height:64});

// g.clear(); g.drawCircle(50, 32, 30); g.flip();

// Note: pushing will trigger several times (for repeat: true)
// Need to software de-bounce

setWatch(function(e) {
}, D37, { repeat: false, edge: "falling"});

setWatch(function(e) {
}, D38, { repeat: false, edge: "falling"});

setWatch(function(e) {
}, D39, { repeat: false, edge: "falling"});

Typhoon No. 12 and Air Pressure

I was measuring air pressure during Typhoon no. 12 this year and here is a graph of the air pressure change while the typhoon was passing Tokyo. It dropped from 993 hPa to 984 hPa. While not a huge drop, it's still notable for the rate of change.

Here the path. Tokyo is where the blue dot is. It's quite far away and we had not much wind.


Espruino and InfluxDB

Espruino did unexpectedly have a module to talk to InfluxDB directly: https://github.com/espruino/EspruinoDocs/blob/master/modules/InfluxDB.js. Given that it's a simple HTTP POST request (see previous blog entry), I should not have been surprised.

That simplifies data ingestion: no need for MQTT broker, no need for an MQTT-to-InfluxDB converter. The InfluxDB instance is on the local network this way since SSL is still not doable on an ESP8266.

This is the Espruino code:

// InfluxDB configuration
 var influxDBParams = {
    influxDBHost: "",
    influxPort: 8086,
    influxDBName: "demo",
    influxUserName: "submit",  
    influxPassword: "submitpw",
    influxAgentName: "ESP32"

var influxDB = require("InfluxDB").setup(influxDBParams);

// bme() is the function to read from the BME280 sensor
let temperature=bme.readTemperature()

let data="env "+temperature+"="+temperature;

That's it. As simple as MQTT.


Data Logging and Displaying with InfluxDB and Grafana

I  was able to collect sensor data (temperature, humidy, pressure) for a while and send the data out via MQTT. What I never finished is to display the data in a nice graphical UI. Unfortunately to do this via Internet and any hosted service (e.g. Adafruit, or AWS or Google), a requirement is to use TLS (HTTPS or MQTT over TLS). Not a problem in general, but for an ESP8266 with Espruino and about 20 KByte RAM available for user programs, the TLS stack is way too large and RAM consuming. See here. ESP32 is better (512 KByte RAM ionstead of 80 KByte in total) and it could do TLS, but I have 1 ESP32 and about 10 ESP8266 modules...

Thus I am forced to use simple and unencrypted MQTT locally with a local MQTT broker. One subscriber process can get updates and send to an Internet connectable service (i.e. the many IoT related services there are). There the data is stored and displayed.

But then I thought that instead of sending the data to another hosted DB, I can instead host a small DB myself. I can run a time series DB and a graphical front-end. E.g. ELK stack or InfluxDB & Grafana. See here for a short comparison of ElasticSearch vs. InfluxDB. For the latter I found a very useful Docker Compose setup here, so InfluxDB & Grafana it was!

How to create users in InfluxDB

Grafana should only have read-only access. The submit process should only have a write-only access. Create those users:

CREATE USER submit WITH PASSWORD 'submitpw';
GRANT WRITE ON demo TO submit;
CREATE USER grafanaro WITH PASSWORD 'testro';
GRANT READ ON demo TO grafanaro;

Then there's the DB root account of course which you can find in the docker-compose.yml file.

How to submit data into InfluxDB

This simple shell script will do and quickly generate some moderately useful data:

pingAvg=`ping -c 5 router.lan | tail -1 | awk -F/ '{print $5}'`
curl -i -XPOST 'http://influxdb.lan:8086/write?db=demo' -u submit:submitpw --data-binary 'ping router='$pingAvg

Run it at least twice as Grafana won't display much if there's only one data point. Then configure a panel on a new dashboard in Grafana:

Reload the graph, set the time frame to the last 15min, and you should see something which proves that data ingestion works.

Next step

Create a small program to subscribe data updates from the MQTT broker and send it securely to InfluxDB.