Pixl.js SMS Remote Monitoring

Pixl.js SMS Remote Monitoring

If you have something that you want to monitor where there's no internet connection - an allotment or shed for example - you may want to use the mobile network to send data. The obvious solution is to use internet connectivity (which you can do using the hardware in this tutorial), but you can also just use SMS text messages. Pre-pay SIM cards with just voice and text messages tend to be extremely cheap, often with no monthly fee.

In addition to this, you might have remote sensors that you don't want to connect to the main mobile phone connection. That's what we'll do here - using Pixl.js as a hub for remote devices.

This is similar to the Puck.js with SMS control except there's less wiring and we can also display the status on the Pixl's screen.

You'll Need

Wiring Up

The wiring is very simple - just plug the SIM900 Arduino shield into the back of the Pixl.js. The only thing you have to worry about is power - the SIM900 needs to draw a lot of power, and it's unlikely that the USB connector on Pixl.js will provide enough.

You can:

  • Use the external power connector on the SIM900 shield - there's a switch next to it to select the power source.
  • Solder a JST battery connector to Pixl.js and short the Pixl.js solder jumper from Vin to 5V to provide power for the SIM900.

After this, ensure the jumpers on the SIM900 board are set to Xduino, add the battery, long-press the power button on the SIM900 to turn it on and you're ready to go! (this module )

Note: The SIM900 module used here is only connected to pins D0 and D1. All the other inputs and outputs are available if you need to measure or control something directly from the Pixl.


On your remote Espruino devices, upload the following:

function updateAdvertising() {
  /* we could advertise binary data here, but let's just use JSON as
  it won't be more than a few characters */
  var data = JSON.stringify({
    manufacturer:0x590, // Espruino's Manufacturer ID
    showName: false, // don't show a name
    connectable: false, // don't allow anyone to connect
    interval:1000 // save power by advertising less often

setInterval(updateAdvertising, 30000);

function onInit() {
  // Output with as much power as we can

You may want to change the code to report different data back. You can't send many characters of advertising data, so you might want to consider encoding the data as binary.

Next, copy & paste the following code into the right-hand side of the IDE:

/* List of known device IDs and what they are.
We can get this by typing NRF.findDevices(print,10000) */
var devices = {
  "c7:59:51:ec:90:54 random" : "Garden",
  "da:34:7c:4c:5a:47 random" : "Shed",

var sms;

function onInit() {
  // Connect to serial device  
  Serial1.setup(115200, { rx: D0, tx : D1 });
  Serial1.removeAllListeners(); // in case we'd been running before
  var ATSMS = require("ATSMS");
  sms = new ATSMS(Serial1);
  //Use sms.at.debug(); here if you want debug messages

  sms.init(function(err) {
    if (err) throw err;

    sms.list("ALL", function(err,list) {
      if (err) throw err;
      if (list.length) {
        Terminal.println(list.length+" Messages");
      } else
        Terminal.println("No Messages");

// Handle any messages coming in
sms.on('message', function(msgIndex) {
  Terminal.println("New message #"+msgIndex);
  sms.get(msgIndex, function(err, msg) {
    if (err) throw err;
    // delete all messages to stop us overflowing
    // if (msg.oaddr!="+441234567890") throw "Unknown number!";
    var txt = msg.text.trim().toLowerCase();
    Terminal.println("<< ", txt);
    // do a scan and return the result
    if (txt=="scan") doScan(msg.oaddr);
    // Change output D3 on the Pixl
    if (txt=="on") D3.set();
    if (txt=="off") D3.reset();

// Actually scan for advertisements
function doScan(sendMessageToNumber) {
  NRF.findDevices(function(devs) {
    // keep only devices that match our manufacturer ID
    devs = devs.filter(x => x.manufacturer==0x590);
    // Scroll everything we had off the screen
    // What are we going to send?
    var textMessage = "";
    // Now iterate over them and display on the screen    
    devs.forEach(function(dev, idx) {
      var name = devices[dev.id];
      if (!name) {
        // ignore any devices that aren't in our list
        Terminal.println("Unknown "+dev.id);
      try {        
        var j = JSON.parse(E.toString(dev.manufacturerData));
        Terminal.println(name+" "+JSON.stringify(j));
        textMessage += name+" "+JSON.stringify(j)+", ";
      } catch (e) {
        Terminal.println(name+": bad data");
    if (!devs.length) {
      textMessage = "No devices found!";
      Terminal.println("No devices found!");
    if (sendMessageToNumber) {
      Terminal.println("Sending message");
      sms.send(sendMessageToNumber, textMessage, function() {
        Terminal.println("Message sent!");
  }, 10000 /* scan for 10 seconds */);


You'll want to change the list of known devices up the top to match your devices. Then upload!


Once powered on, you can text your Pixl.js with the following commands:

  • scan - scan for devices in the area and the send a text back with all the information received.
  • on/off- Turn pin D3 on or off.

What Next?

You can implement many more commands - for instance you could use the BLE UART library to send command directly to other Pucks (however if so, you need to remove connectable:false and increase the advertising interval on any connected devices).

You could also make Pixl.js send a text message automatically - once a day, or when some event occurs (like movement is detected by a sensor).

You might also want to make Pixl.js use the power switch pin to automatically power the SIM900 on at boot, so if there was a power failure your Pixl.js would be able to communicate using GSM. By doing this you could also leave the SIM900 powered off for the majority of the time so that you can save power.

This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.