Node+JS Interactive '19 - When Porgs Scream at Webpack and Other Stories

Node+JS Interactive '19 - When Porgs Scream at Webpack and Other Stories

For many web developers the world of hardware is very intimidating. There is no easy way to go back from a broken to a working project state. You break something, you replace it — there is no Ctrl/Cmd + z. However, getting a project to work is incredibly fun and rewarding.

From an API for your coffee machine to a porg that screams every time your webpack build fails to playing games with hundreds of people at the same time, the only limit is your imagination*.

You might not leave this talk with a degree in Electrical Engineering**, but you'll learn useful basics to help you enter the wonderful world of hardware. We'll look at different ways to combine JavaScript and hardware, from APIs all the way to JS enabled microcontrollers. All tied up with some live demos. At the end you won't be able to wait to start your own hardware adventure!

*and maybe your patience
**unless you already have one

0722ad084c65f6177d80cf793cfbd013?s=128

Dominik Kundel

December 12, 2019
Tweet

Transcript

  1. 1.

    When Porgs Scream at Webpack and other stories CascadiaJS -

    Dominik Kundel d-k.im/cascadia Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs
  2. 2.

    How many of you have a microcontroller? Dominik Kundel |

    @dkundel | #nodejsinteractive | #porgjs #coffeejs
  3. 5.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs console.log(`

    Hi! I’m Dominik Kundel `); dkundel.com @dkundel dkundel@twilio.com github/dkundel Developer Evangelist !&& JavaScript Hacker
  4. 18.

    1. APIs & Protocols JavaScript 㱺 API 㱺 C/C++ 㱺

    Hardware Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs
  5. 19.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs APIs

    & Protocols Option 1 Dedicated APIs For example Particle Cloud API
  6. 21.

    What is Particle? ▶ IoT hardware manufacturer ▶ Device management

    platform ▶ Provides API to interact with deployed devices Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  7. 22.

    Particle Cloud API Example Dominik Kundel | @dkundel | #nodejsinteractive

    | #porgjs #coffeejs curl https:!//api.particle.io/v1/devices/0123456789abcdef/brew \ -d access_token=123412341234 \ -d "args=coffee" void setup() { !// register the cloud function Particle.function("brew", brewCoffee); } int brewCoffee(String command) { if(command !== "coffee") { return 1; } else return -1; }
  8. 23.

    APIs & Protocols Option 2 MQTT Lightweight machine-to-machine publish/subscribe messaging

    protocol Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs
  9. 25.

    MQTT Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    No need for IP address of a device ▶ Scales to multiple devices ▶ Cross-platform / cross-language
  10. 26.

    MQTT Example in JS Dominik Kundel | @dkundel | #nodejsinteractive

    | #porgjs #coffeejs var mqtt = require('mqtt'); var client = mqtt.connect('mqtt:!//test.mqttbroker.example'); client.on('connect', function() { client.subscribe('presence'); client.publish('presence', 'Hello mqtt'); }); client.on('message', function(topic, message) { !// message is Buffer console.log(message.toString()); client.end(); });
  11. 27.

    MQTT Example in C++ Dominik Kundel | @dkundel | #nodejsinteractive

    | #porgjs #coffeejs #include <SPI.h> #include <Ethernet.h> #include <PubSubClient.h> !// Update these with values suitable for your network. byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; IPAddress ip(172, 16, 0, 100); IPAddress server(172, 16, 0, 2); void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i=0;i<length;i!++) { Serial.print((char)payload[i]); } Serial.println(); } EthernetClient ethClient; PubSubClient mqttClient(ethClient); void reconnect() { !// Loop until we're reconnected while (!mqttClient.connected()) { Serial.print("Attempting MQTT connection!!..."); !// Attempt to connect if (mqttClient.connect("arduinoClient")) { Serial.println("connected"); !// Once connected, publish an announcement!!... mqttClient.publish("outTopic","hello world"); !// !!... and resubscribe mqttClient.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); !// Wait 5 seconds before retrying delay(5000); } } } void setup() { Serial.begin(57600); mqttClient.setServer(server, 1883); mqttClient.setCallback(callback); Ethernet.begin(mac, ip); !// Allow the hardware to sort itself out delay(1500); } void loop() { if (!mqttClient.connected()) { reconnect(); } mqttClient.loop(); }
  12. 28.

    MQTT Subscribe Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs

    #coffeejs boolean rc = mqttClient.subscribe("myTopic");
  13. 29.

    MQTT Setup Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs

    #coffeejs void setup() { Ethernet.begin(mac, ip); !// Allow the hardware to sort itself out delay(1500); mqttClient.setServer(server, 1883); if (mqttClient.connect("myClientID")) { !// connection succeeded } } void loop() { mqttClient.loop(); }
  14. 30.

    MQTT Callback Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs

    #coffeejs void callback(char* topic, byte* payload, unsigned int length) { !// Allocate the correct amount of memory for the payload copy byte* p = (byte*)malloc(length); !// Copy the payload to the new buffer memcpy(p,payload,length); !// Republish the received message mqttClient.publish("outTopic", p, length); !// Free the memory free(p); } mqttClient.setCallback(callback);
  15. 33.

    Pros ▶ Lightweight, intuitive ways to communicate between devices ▶

    Move heavy business logic off devices ▶ Programming language independent Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  16. 34.

    Cons ▶ Still have to write C++ code for the

    hardware ▶ Need to deploy/use a message broker Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  17. 35.
  18. 38.

    johnny-five ▶ Talk to microcontrollers from Node.js ▶ Use a

    familiar syntax ▶ Leverage the npm ecosystem ▶ Often tethered to a host machine Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  19. 39.

    Blink on an Arduino with C++ Dominik Kundel | @dkundel

    | #nodejsinteractive | #porgjs #coffeejs !// the setup function runs once when you press reset or power the board void setup() { !// initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } !// the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); !// turn the LED on (HIGH is the voltage level) delay(1000); !// wait for a second digitalWrite(LED_BUILTIN, LOW); !// turn the LED off by making the voltage LOW delay(1000); !// wait for a second }
  20. 40.

    Blink on an Arduino with J5 Dominik Kundel | @dkundel

    | #nodejsinteractive | #porgjs #coffeejs var five = require('johnny-five'); var board = new five.Board(); board.on('ready', function() { var led = new five.Led(13); led.blink(500); });
  21. 41.

    Button with C++ Dominik Kundel | @dkundel | #nodejsinteractive |

    #porgjs #coffeejs const int buttonPin = 2; !// the number of the pushbutton pin const int ledPin = 13; !// the number of the LED pin int buttonState = 0; !// variable for reading the pushbutton status void setup() { !// initialize the LED pin as an output: pinMode(ledPin, OUTPUT); !// initialize the pushbutton pin as an input: pinMode(buttonPin, INPUT); } void loop() { !// read the state of the pushbutton value: buttonState = digitalRead(buttonPin); !// check if the pushbutton is pressed. If it is, the buttonState is HIGH: if (buttonState !== HIGH) { !// turn LED on: digitalWrite(ledPin, HIGH); } else { !// turn LED off: digitalWrite(ledPin, LOW); } }
  22. 42.

    Button with Johnny-Five Dominik Kundel | @dkundel | #nodejsinteractive |

    #porgjs #coffeejs var five = require('johnny-five'); var board = new five.Board(); board.on('ready', function() { var led = new five.Led(13); var button = new five.Button(2); button.on('press', () !=> { led.on(); }); button.on('release', () !=> { led.off(); }); });
  23. 43.

    Example #porgjs Building your own custom peripheral Dominik Kundel |

    @dkundel | #nodejsinteractive | #porgjs #coffeejs
  24. 44.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs Build

    a custom peripheral device that reacts on events on your computer Goal of #porgjs
  25. 45.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs Build

    a custom peripheral device that reacts on events on your computer Goal of #porgjs Hack a porg toy to scream whenever your build fails!
  26. 46.

    Warning! You might see the insides of a (toy) porg

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs
  27. 56.

    Wireup ▶ Arduino ▶ Optocoupler (4N35) ▶ Resistor ▶ Green

    LED ▶ Cables Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  28. 59.

    Pros ▶ Hardware independent code with J5 ▶ Use familiar

    tools ▶ Bring your own editor/IDE ▶ Use the npm ecosystem ▶ Great website for beginners Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  29. 60.

    Cons ▶ Often tethered to a "host" ▶ Less examples

    than classic Arduino projects Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  30. 62.

    JerryScript Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs Ultra-lightweight

    JavaScript engine for the internet of things jerryscript.net Runtime: Samsung's IoT.js
  31. 63.

    JerryScript Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Lightweight ▶ Small memory footprint ▶ Not every JavaScript feature might be available ▶ Not very beginner friendly
  32. 64.

    Espruino Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs Espruino

    is a JavaScript interpreter for microcontrollers www.espruino.com
  33. 65.

    Espruino Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs Espruino

    is a JavaScript interpreter for microcontrollers www.espruino.com
  34. 66.

    Esprunio Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Can run on ESP8266 ▶ Has its own hardware versions as well ▶ Open Source Code & Hardware ▶ Comes with its own IDE ▶ Limited npm support ▶ Does not work with Johnny-Five
  35. 67.

    Neonious Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs A

    microcontroller board programmable and debuggable out of the box www.neonious.com
  36. 68.

    Neonious Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Has its own hardware. Can run on ESP32 though ▶ Comes with its own IDE ▶ Supports TypeScript out of the box ▶ Same API interface as Node.js ▶ Built-in Ethernet & WiFi
  37. 69.

    Tessel Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs Tessel

    2 is a robust IoT and robotics development platform tessel.io
  38. 70.

    Tessel Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs Tessel

    2 is a robust IoT and robotics development platform tessel.io
  39. 71.

    Tessel Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Run Node.js with (almost) the entire npm ecosystem ▶ Compatible with J5 ▶ Use your favorite toolchain & editor ▶ Open Source Code & Hardware ▶ Tessel 2 is fairly expensive
  40. 73.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs Control

    an existing device programmatically Goal of #coffeejs Build a REST API implementing IETF RFC 2324
  41. 74.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs Control

    an existing device programmatically Goal of #coffeejs Build a REST API implementing IETF RFC 2324 Build a REST API implementing HTCPCP
  42. 75.

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs Control

    an existing device programmatically Goal of #coffeejs Build a REST API implementing IETF RFC 2324 Build a REST API implementing HTCPCP Build a REST API implementing Hyper Text Coffee Pot Control Protocol www.ietf.org/rfc/rfc2324.txt
  43. 76.

    Why Tessel? Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs

    ▶ The coffee machine should work untethered ▶ Use johnny-five to easily swap microcontrollers ▶ It has to be internet connected ▶ Quick setup / easy development ▶ We need to build a server. npm packages help
  44. 88.

    How I hacked a coffee machine using JavaScript bit.ly/coffee-js github.com/dkundel/htcpcp-delonghi

    Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs #coffeejs
  45. 89.

    Pros Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Untethered systems running JavaScript ▶ Familiar programming language ▶ Use familiar tools ▶ Bring your own Editor/IDE ▶ (Potentially) use the npm ecosystem
  46. 90.

    Cons Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    Less flexible on hardware choices ▶ Missing cutting edge language features ▶ Some docs better than others
  47. 96.

    Useful things ▶ A digital multimeter (Volt, Amps, Ohm) ▶

    A breadboard ▶ Plenty of jumper wires ▶ A set of resistors ▶ A few LEDs ▶ A few Solid State Relays to emulate switches/buttons Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs
  48. 98.
  49. 100.

    Resources Dominik Kundel | @dkundel | #nodejsinteractive | #porgjs ▶

    d-k.im/cascadia ▶ bit.ly/coffeejs ▶ d-k.im/nodebots ▶ nodebots.io ▶ johnny-five.io ▶ tessel.io