name: inverse class: center, middle, inverse layout: true
@unixbigot — IoT for Slackers
--- layout: true
@unixbigot — IoT for Slackers
--- class: center, middle template: inverse # IoT for Slackers How to bring IoT into your workplace simply and safely,
using .blue[NodeMCU] and .blue[Slack]. .bottom.right[ Christopher Biggs
.blue[@unixbigot] ] --- .left-column[ # Agenda ] .right-column[ ### **Introduction**: About .blue[Me] and my take on IoT ### **Hardware**: The .blue[ESP8266] Micro-controller ### **Software**: The .blue[NodeMCU] Lua environment ### **People**: The .blue[Slack] messaging platform ### **Things**: Some .blue[Ideas] to start you off ] --- template: inverse # About Me --- .left-column[ ## Intro ### About Me] .right-column[ * If I was a kid today, I'd be arrested. .img-600w[![Pyro](pyro.jpg)] .right[disclaimer:
not me
] ] --- .left-column[ ## Intro ### About Me] .right-column.small[ * Worked on the first generation of web-configurable routers. * Most recently directed a team of 60+ app and web coders. .img-320w[![Herding cats](herding_cats_comic.gif)] .right.flyspeck[Image:
Glen Knight
] ] --- .left-column[ ## Intro ### About Me] .right-column.small[ * Thinking about ways to inspire creativity in teams. * This presentation originated as my plan for team hackathon. .img-600w[![Creativity](creativity.jpg)] .right.flyspeck[Image:
Nicolas Raymond
] ] --- .left-column[ ## Intro ### About Me ### IoT Philosophy] .right-column.small[ ## My IoT Philosophy * Low power, low complexity .img-400w[![IBM 360](ibm.jpg)] ] --- .left-column[ ## Intro ### About Me ### IoT Philosophy] .right-column[ * .grey[Low power, low complexity] * Do one job efficiently and simply .img-400w[![Wall mounted Unix server](unix_wall.jpg)] ] --- .left-column[ ## Intro ### About Me ### IoT Philosophy] .right-column[ * .grey[Low power, low complexity] * .grey[Do one job efficiently and simply] * High level languages for rapid prototyping and development ```Lua -- a simple HTTP server srv = net.createServer(net.TCP) srv:listen(80, function(conn) conn:on("receive", function(sck, payload) print(payload) sck:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n
Hello, NodeMCU.
") end) conn:on("sent", function(sck) sck:close() end) end) ``` ] --- template: inverse # Hardware --- .left-column[ ## Hardware ### Prehistory ] .right-column.small[ ## The IoT hardware space * Before the mid '90s, things were primitive and expensive * Vendors considered compilers and development kits a profit source .img-400w[![1980s PLC](1980s_plc.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ] .right-column[ * Specs and data were essentially secret * Hobbyists were locked out .img-320w[![TTL Databook](ttl_databook.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ] .right-column[ * 1990s: MIT Media lab and Lego * It still cost hundreds of dollars to get started .img-250w[![MIT Handyboard](handyboard.jpg)] .img-250w[![Lego Mindstorms](rcx.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ### Arduino ] .right-column[ * 2005: Arduino arrived for $50 - Tools were free, portable, and open source .img-500w[![Arduino NG](arduino_ng.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ### Arduino ### Raspberry Pi ] .right-column.small[ * 2012: Raspberry Pi, $35. - Pros: Full Linux system. - Cons: Full Linux system. * WiFi was an extra cost add-on for both Arduino and Pi. .img-400w[![Raspberry Pi](raspberry_pi.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ### Arduino ### Raspberry Pi ### ESP ] .right-column.small[ * 2014: Espressif ESP8266 - initially sold as a cheap WiFi Modem peripheral * Rapid diversification of hardware modules .img-500w[![ESP 8266](esp8266.jpg)] ] --- .left-column[ ## Hardware ### Prehistory ### Arduino ### Raspberry Pi ### ESP ] .right-column.small[ ### The ESP8266 System-on-a-Chip .smaller[ * 80MHz 32-bit CPU * 64kB of on-board RAM * External flash ROM up to 16MB * On-board WiFi * 16 General-purpose Input/Output pins * SPI, I2C and Asynchronous serial communications * Proprietary real-time operating system * Packaged in a number of different hardware modules with between 2 and 22 IO pins ] ] --- .left-column[ ## Hardware ### Prehistory ### Arduino ### Raspberry Pi ### ESP ### Cheap as in Chips ] .right-column.small[ * All this for as little as two dollars * ...in unit quantity .img-500w[![NodeMCU Dev Kit](nodemcu_devkit.jpg)] ] --- template: inverse # Software --- .left-column[ ## Software ### Release ] .right-column[ ### ESP becomes a platform * 2013: (Dec) Espressif ESP8266 WiFi System-on-a-Chip (SOC), with "AT" firmware ``` AT+CWJAP="ExampleCorp WiFi", "swordfish" OK AT+CIFSR 192.168.1.100 OK AT+CIPSTART="TCP", "www.example.com", 80 OK AT+CIPSEND=16 GET / HTTP/1.0 OK +IPD, 16: HTTP/1.0 200 Ok ``` ] --- .left-column[ ## Software ### Release ] .right-column[ ### ESP becomes a platform * 2013: .grey[(Dec) Espressif ESP8266 WiFi System-on-a-Chip (SOC), with "AT" firmware] * 2014: (Aug) Espressif releases SDK * 2014: (Nov) Open-source SDK using **gcc** and friends ] --- .left-column[ ## Software ### Release ### Explosion ] .right-column[ ### Explosion of Diversity * 2014: (Oct) NodeMCU project creates a Lua programming environment * 2014: (Nov) Arduino runtime ported to ESP8266 * 2014: (Nov) MicroPython ported to ESP8266 ] --- .left-column[ ## Software ### Release ### Explosion ] .right-column.small[ * 2014: (Nov) Open source NodeMCU Dev Kit design is published. * Boards cost under $5 .img-500w[![NodeMCU Pins](nodemcu_pins.png)] ] --- .left-column[ ## Software ### Release ### Explosion ] .right-column.small[ * 2016: (May) AWS IoT button on sale in USA (only) for $20 .img-320w[![AWS IoT button](aws_iot.jpg)] .img-320w[![AWS IoT in use](aws_tide.jpg)] ] --- .left-column[ ## Software ### Release ### Explosion ### NodeMCU ] .right-column.small[ ### The NodeMCU Lua Environment * Uses the lightweight "Lua" scripting language * Event-loop model inspired by NodeJS (but not actually Javascript) .img-640w[![NodeMCU rationale](nodemcu_why.png)] ] --- .left-column[ ## Software ### Release ### Explosion ### NodeMCU ] .right-column.small[ * Construct a firmware (OS image) consisting of the RTOS core plus Lua interpreter .img-500w[![NodeMCU build](nodemcu_build.png)] ] --- .left-column[ ## Software ### Release ### Explosion ### NodeMCU ] .right-column.small[ * Lua functionality broken into modules, to preserve on-chip resources .img-500w[![NodeMCU modules](nodemcu_modules.png)] * Dev tools from github, or docker, or cloud build service ] --- .left-column[ ## Software ### Release ### Explosion ### NodeMCU ] .right-column.small[ * IDE .blue[esp8266.ru/esplorer] * CLI .blue[github.com/kmpm/nodemcu-uploader] .img-640w[![ESPlorer](esplorer.png)] ] --- .left-column[ ## Software ### Release ### Explosion ### NodeMCU ] .right-column.small[ * Comprehensive doco .blue[nodemcu.readthedocs.io] .img-640w[![NodeMCU documentation](nodemcu_doco.png)] ] --- template: inverse # People --- .left-column[ ## People ### Slack ] .right-column[ * Slack is a cloud hosted team collaboration platform (chatserver) * Mobile, Desktop, Browser * Easy to use APIs .img-500w[![Slack homepage](slack_homepage.png)] ] --- .left-column[ ## People ### Slack ### Sending ] .right-column[ ### Device to Slack - .blue[Incoming Webhooks]s .img-400h[![Slack admin](slack_admin.png)] .img-320w[![Slack webhooks](slack_webhooks.png)] ] --- .left-column[ ## People ### Slack ### Sending ] .right-column.small[ * .grey[To send to slack, create an **Incoming Webhook**] * Testing your webhook ```bash curl -X POST --data-urlencode 'payload={"channel": "#demo", "username": "interruptingcow", "text": "MOOOO!.", "icon_emoji": ":cow:"}' https://hooks.slack.com/services/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 ``` .img-500w[![Webhook example](slack_inbound_test.png)] ] --- .left-column[ ## People ### Slack ### Sending ] .right-column.small[ * .grey[To send to slack, create an **Incoming Webhook**] * .grey[Testing your webhook] * Doing HTTP from .blue[NodeMCU] ```Lua function slack_send(msg) local post_headers= 'Content-Type: application/json\r\n' local post_body = '{ "channel": "#demo", "username": "interruptingcow", "icon_emoji": ":cow:", "text": "'..msg..'", "mrkdwn":true}' http.post(slack_url, post_headers, post_body, function(code, data) if (code < 0) then print("HTTP request failed: code "..code) else print("Slack response: ", code, data) end end ) end ``` ] --- .left-column[ ## People ### Slack ### Sending ] .right-column.small[ * .grey[Doing HTTP from NodeMCU] * ...the easy way (.blue[github.com/unixbigot/manfred]) ```json // config.json { "application_name": "button", "button_message": "Everybody PANIC!!" } ``` ```json // credentials.json { "wifi_passwords" : { "ExampleCorp Wifi": "swordfish" }, "slack_webhook_url" :"https://hooks.slack.com/services/T1MV1421H/B2B01B5GV/thereisafroginmybidet" } ``` ```lua -- button.lua function button_start() register_button(config.pin_button, "down", button_event) end function button_event(level) slack(config.button_message); end ``` ] --- .left-column[ ## People ### Slack ### Sending ### Receiving ] .right-column.small[ ### Slack to Device - .blue[Outgoing webhooks] * Listen for keywords on a channel * .blue[POST] details to a URL .img-500w[![Outgoing setup](slack_outgoing_setup.png)] ] --- .left-column[ ## People ### Slack ### Sending ### Receiving ] .right-column[ * Receiving .blue[POST]s in the cloud .img-500w[![IoT Broker](iot_broker.png)] ] --- .left-column[ ## People ### Slack ### Sending ### Receiving ] .right-column.small[ * Siting your .blue[middleware]: * Any old web server you already have * Red Hat OpenShift (prototyped, three free servers per account) * Amazon Lambda (prototyped, X free calls per month) * Amazon EC2 (this is what I'll demo) * localtunnel.me (a public endpoint for your internal servers) * Your favourite cloud service * Run your own MQTT broker, or try .blue[test.mosquitto.org] ] --- .left-column[ ## People ### Slack ### Sending ### Receiving ] .right-column.small[ * Using .blue[nodered.org] as your middleware - Visual wiring system for the IoT - Make HTTP APIs, pubish and subscribe with MQTT - **hundreds** of plugins for all sorts of systems - eg. route your BI metrics to a custom phone app in an hour .img-640w[![Node Red Flows](nodered_hooks.png)] ] --- .fullpage[ ## A closer look at the .red[Node-RED] flows .img-800w[![Node Red Flows](nodered_hooks.png)] ] 1. Someone (or thing) slacks "Status for Project Icarus is green" 1. Node-red publishes `projects/icarus/status <= green` 1. A Thing subscribed to this topic receives the message --- .left-column[ ## People ### Slack ### Sending ### Receiving ### Networks ] .right-column.small[ ## Getting your Things on the Internet * Use your guest wifi * Use a personal hotspot * Use your office lan with caution ```json // credentials.json { "wifi_passwords" : { "Guest WiFi": "guest", "Alice's Phone": "margarita", "Bob's Phone": "daiquiri", "ExampleCorp Wifi": "swordfish" }, "mqtt_server": "nodered.unixbigot.id.au", "mqtt_user": "iot", "mqtt_pass": "userabetterpassword", "slack_topic" :"slack/inject" } ``` ] --- template: inverse # Things --- .left-column[ ## Things ### Electronics ] .right-column.small[ ### Electronics for Noobs * Don't panic, read [blog.unixbigot.id.au](http://blog.unixbigot.id.au/2016/09/iot-for-absolute-beginners.html) * Ones and zeros are volts and no volts * It's pretty much Lego bricks with wires .img-400w[![Electronics for dogs](electronics_for_dogs.gif)] .right.flyspeck[Image:
Out There Films
] ] --- .left-column[ ## Things ### Electronics ] .right-column[ ### Starter kit * Costs about $12 .img-400w[![IOT Starter Kit](iot_starter_kit.jpg)] ] --- .left-column[ ## Things ### Electronics ] .right-column[ ### Module extension kit * Sample bag of IO modules - $10 .img-400w[![IOT module Kit](iot_modules.jpg)] ] --- .left-column[ ## Things ### Electronics ] .right-column.small[ * Powering your things * USB power points or power-boards * Phone chargers (or nearest PC) * Lithium power banks .img-250w[![USB power point](usb_power_point.png)] .img-250w[![USB wall wart](usb_wall_wart.jpg)] ] --- .left-column[ ## Things ### Electronics ] .right-column.small[ * Boxing your things * Search "project enclosure" on aliexpress.com * Supermarket storage containers * CNC cut plastic .img-500w[![Enclosures](enclosures.jpg)] ] --- .left-column[ ## Things ### Electronics ### Big Red Button ] .right-column.small[ ## The Big Red Button ```lua function button_start() register_button(config.pin_button, "down", button_event) end function button_event(level) slack("Everybody Panic!!"); end ``` .img-250w[![Panic Button](panic_button.png)] ] --- .left-column[ ## Things ### Electronics ### Big Red Button ] .right-column.nopad.small[ ### Team meeting alerts ```lua function meeting_start() register_button(config.pin_button, "down", meeting_button) mqtt_subscribe("teams/excalibur/meeting", 0, meeting_receive) end function meeting_button(level) if (meeting_state == 'idle') then slack("Standup meeting time!") mqtt_publish("teams/excalibur/meeting", "1") meeting_state='called'; flash_led(500) else slack("Meeting Ack!") if meeting_state == 'called' then mqtt_publish("teams/excalibur/meeting", "0") end meeting_state='idle'; stop_led() end end function meeting_receive(conn, topic, data) if (data == "1") then meeting_state = 'invited'; flash_led(500) else meeting_state='idle'; stop_led() end end ``` ] --- .left-column[ ## Things ### Electronics ### Big Red Button ### Traffic Light ] .right-column.nopad.small[ ### Project status "Traffic Lights" ```lua function traffic_start() mqtt_subscribe("projects/icarus/status", 0, traffic_receive) end function traffic_receive(conn, topic, data) if data=="red" or data=="danger" then ws2812.write(string.char(0,0,0,0,0,0,0,255,0)) elseif data=="amber" or data == "yellow" or data=="warning" then ws2812.write(string.char(0,0,0,126,255,0,0,0,0)) elseif data=="green" or data=="good" then ws2812.write(string.char(255,0,0,0,0,0,0,0,0)) end end ``` .img-250w[![Traffic Lights](traffic_lights.jpg)] ] --- .left-column[ ## Things ### Electronics ### Big Red Button ### Traffic Light ] .right-column.nopad.center[ .img-320w[![Traffic Lights](traffic_light.gif)] ] --- .left-column[ ## Things ### Electronics ### Big Red Button ### Traffic Light ### Slacker Toast ] .right-column.nopad.small[ ## Slacker toast .img-640w[![Slacker toast](slacker_toast.jpg)] ] --- template: inverse # Conclusion --- .left-column[ ## Intro ## Hardware ## Software ## People ## Devices ## Conclusion ] .right-column[ ## Summary * Low-cost special purpose devices * Really easy software framework * Use the systems you already have * Glue misaligned parts with .red[Node-RED] ] --- .left-column[ ## Intro ## Hardware ## Software ## People ## Devices ## Conclusion ] .right-column[ ## Future * SSL client authentication * Integrate with AWS IoT message broker * Serverless middleware * Over-the-air updates * Voice control * Clinical testing on "reference noobs" ] --- .right-column[ ## Resources, Questions * Code: http://github.com/unixbigot/manfred * Tutorials: http://blog.unixbigot.id.au/ * Get in Touch: - Twitter: .blue[@unixbigot] - Email: .blue[christopher@biggs.id.au] * Hire Me: http://christopher.biggs.id.au/ ] --- .right-column.small[ ## Suppliers * China (cheap but slow) - [AliExpress.com](http://aliexpress.com) - See the shopping lists on [my blog](http://blog.unixbigot.id.au/2016/09/iot-for-absolute-beginners.html) * Australia - [Little Bird Electronics](http://littlebirdelectronics.com.au) - [Tronixlabs](http://tronixlabs.com.au) * USA - [Adafruit](http://adafruit.com) - [FriedCircuits](https://www.tindie.com/products/FriedCircuits/nodemcu/) ]