Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rise of the Machines: PHP and IoT - php[world] 2016

1,105 views

Published on

The Internet of Things (IoT) is fundamentally changing how we interact with the digital world. In this talk, we’ll explore the implementation of live examples which bridge the gap between the physical and digital world using PHP: asking Alexa for information on php[world] conference sessions; displaying API data on an Arduino-powered display; using PHP to control LEDs on a Raspberry Pi to monitor application uptime; and connecting IR sensors to Slack to see whether a conference room is in use.

Published in: Software

Rise of the Machines: PHP and IoT - php[world] 2016

  1. 1. Rise of the Machines: PHP & IoT php[world] 2016 @colinodell - joind.in/talk/18676
  2. 2. Colin O’Dell • Lead Web Developer at Unleashed Technologies • PHP League Member  league/commonmark  league/html-to-markdown • PHP 7 Upgrade Guide e-book • Arduino / RasPi / 3D printing Enthusiast @colinodell - joind.in/talk/18676
  3. 3. Internet of Things The Internet of Things is the internetworking of physical devices, vehicles, buildings and other items—embedded with electronics, software, sensors, actuators, and network connectivity that enable these objects to collect and exchange data. - https://en.wikipedia.org/wiki/Internet_of_things @colinodell - joind.in/talk/18676
  4. 4. Internet of Things The Internet of Things is the internetworking of physical devices, vehicles, buildings and other items—embedded with electronics, software, sensors, actuators, and network connectivity that enable these objects to collect and exchange data. - https://en.wikipedia.org/wiki/Internet_of_things @colinodell - joind.in/talk/18676
  5. 5. @colinodell - joind.in/talk/18676
  6. 6. Connectivity • Ethernet / WiFi • NFC / RFID • Bluetooth LE • Zigbee / Z-Wave • Cellular (LTE / CDMA / GSM) • And many others @colinodell - joind.in/talk/18676
  7. 7. 0 10 20 30 40 50 60 2003 2010 2015 2020 (Billions) Population vs Connected Devices People Connected Devices @colinodell - joind.in/talk/18676Source: https://www.cisco.com/c/dam/en_us/about/ac79/docs/innov/IoT_IBSG_0411FINAL.pdf
  8. 8. @colinodell - joind.in/talk/18676
  9. 9. Today’s Agenda • Device overview • Four examples of combining IoT with PHP  Project Goals  Hardware & Platform Choice  Building the device  Demo • Q&A @colinodell - joind.in/talk/18676
  10. 10. DIY IoT Devices For the software or hardware enthusiast @colinodell - joind.in/talk/18676
  11. 11. @colinodell - joind.in/talk/18676
  12. 12. How to choose? • Identify required features • Ideal programming language • Consider power requirements • Size / footprint @colinodell - joind.in/talk/18676
  13. 13. Four Examples Using PHP @colinodell - joind.in/talk/18676
  14. 14. Uptime Monitor Use Raspberry Pi to monitor if site is up; change LED color accordingly
  15. 15. Why Raspberry Pi? • Runs Linux (Raspian – a derivative of Debian) • Has GPIO pins • PHP easily installed • Raspberry Pi Zero only $5 • Handles HTTPs out-of-the-box • Why not? @colinodell - joind.in/talk/18676
  16. 16. Hardware @colinodell - joind.in/talk/18676 • Raspberry Pi (any variant) • Micro USB cable (power) • USB WiFi dongle • RGB LED • Two resistors • Wires
  17. 17. RGB LEDs @colinodell - joind.in/talk/18676
  18. 18. Wiring @colinodell - joind.in/talk/18676
  19. 19. @colinodell - joind.in/talk/18676 $ composer require piphp/gpio
  20. 20. @colinodell - joind.in/talk/18676 <?php const URL = 'https://www.colinodell.com'; const GPIO_PIN_GREEN = 12; const GPIO_PIN_RED = 16; require_once 'vendor/autoload.php'; $gpio = new PiPHPGPIOGPIO(); $greenLed = $gpio->getOutputPin(GPIO_PIN_GREEN); $redLed = $gpio->getOutputPin(GPIO_PIN_RED); $httpClient = new GuzzleHttpClient(); while (true) { try { $response = $httpClient->head(URL, [ 'connect_timeout' => 3, 'timeout' => 3, ]); echo URL . " is onlinen"; $greenLed->setValue(1); $redLed->setValue(0); } catch (RuntimeException $ex) { echo URL . " is OFFLINE!n"; $greenLed->setValue(0); $redLed->setValue(1); } sleep(3); }
  21. 21. Recap • PHP on a Raspberry Pi • PHP checks if site is up • PiPHP/GPIO library used to control output pins (LEDs) Other uses for output pins: • Control motors/servos • Control relays (turn higher-voltage things on/off) • Drive digital displays (LCD screens, LED number displays, etc.) @colinodell - joind.in/talk/18676
  22. 22. Conference Room Occupancy Sensor Raspberry Pi detects movement in room; sends room status to Slack @colinodell - joind.in/talk/18676
  23. 23. Why Raspberry Pi? • Runs Linux (Raspian – a derivative of Debian) • Has GPIO pins • PHP easily installed • Raspberry Pi Zero only $5 • Handles HTTPs out-of-the-box • Why not? @colinodell - joind.in/talk/18676 TL;DR: Same reasons as before!
  24. 24. Hardware @colinodell - joind.in/talk/18676 • Raspberry Pi (any variant) • Micro USB cable (power) • USB WiFi dongle • PIR Sensor • Wires
  25. 25. PIR Sensors @colinodell - joind.in/talk/18676Images from https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/overview
  26. 26. Wiring @colinodell - joind.in/talk/18676
  27. 27. @colinodell - joind.in/talk/18676
  28. 28. Signal @colinodell - joind.in/talk/18676 Motion Detected Occupied Vacant Occupied
  29. 29. @colinodell - joind.in/talk/18676 <?php namespace ColinODellPHPIoTExamplesPHPPIRSensor; class Room { /** * @var bool */ private $occupied = false; /** * @var int */ private $lastMovement; /** * @var callable */ private $onRoomStateChange; /** * @var int */ private $roomEmptyTimeout; /**
  30. 30. @colinodell - joind.in/talk/18676 <?php // Configuration: const GPIO_PIN = 17; const DECLARE_ROOM_EMPTY_AFTER = 60*5; // 5 minutes const SLACK_INCOMING_WEBHOOK_URL = 'https://hooks.slack.com/services/xxxx/xxxx/xxxx'; // End configuration require_once 'vendor/autoload.php'; use ColinODellPHPIoTExamplesPHPPIRSensorRoom; use PiPHPGPIOGPIO; use PiPHPGPIOPinInputPinInterface; // HTTP client for communicating with Slack $http = new GuzzleHttpClient(); // Instantiate a new room object to keep track of its state $room = new Room(); $room->setRoomEmptyTimeout(DECLARE_ROOM_EMPTY_AFTER); $room->setOnRoomChangeCallback(function($isOccupied) use ($http) { $message = 'The conference room is now ' . ($isOccupied ? 'occupied.' : 'vacant.'); $http->postAsync(SLACK_INCOMING_WEBHOOK_URL, [
  31. 31. @colinodell - joind.in/talk/18676
  32. 32. Recap • PHP on a Raspberry Pi • PiPHP/GPIO library monitors GPIO pin for signal changes • PHP tracks duration between rising edges (low-to-high signal changes) • Notifications pushed to Slack via webhook Other uses for input pins: • Switches & buttons • Sensors (temperature, humidity, motion, accelerometer, GPS) • Receiving data from other devices @colinodell - joind.in/talk/18676
  33. 33. Alexa Custom Skill Use PHP + Laravel to handle request for php[world] session information @colinodell - joind.in/talk/18676
  34. 34. Why Alexa / Amazon Echo? • Amazon handles voice recognition • Parsed request passed from Amazon to our API endpoint • We handle accordingly; send formatted response for Alexa to read aloud • Published skills easily installable @colinodell - joind.in/talk/18676
  35. 35. User Interaction Flow @colinodell - joind.in/talk/18676Diagram from https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/overviews/understanding-custom-skills
  36. 36. Invoking Custom Skills • Ask [skill name] [action] Ask PHP World which sessions are next • Tell [skill name] [action] Tell PHP World this talk is great • [action] using [skill name] Rate this talk 5 stars using PHP World @colinodell - joind.in/talk/18676
  37. 37. Actions • What sessions are next? • What session is next in {room}? • What sessions are at {time} in {room}? • Who is speaking in {room} {day} at {time}? @colinodell - joind.in/talk/18676
  38. 38. Defining Actions GetSessions what sessions are next GetSessions what talks are next GetSessions who is talking next GetSessions who is speaking next GetSessions which sessions are next GetSessions which talks are next GetSessions what session is next in {room} GetSessions what talk is next in {room} GetSessions who is talking next in {room} GetSessions who is speaking next in {room} GetSessions which session is next in {room} GetSessions which talk is next in {room} GetSessions what sessions are at {time} GetSessions what talks are at {time} GetSessions who is talking at {time} GetSessions who is speaking at {time} GetSessions which sessions are at {time} GetSessions which talks are at {time} GetSessions what sessions are at {time} {day} GetSessions what talks are at {time} {day} GetSessions who is talking at {time} {day} GetSessions who is speaking at {time} {day} GetSessions which sessions are at {time} {day} GetSessions which talks are at {time} {day} GetSessions what session is in {room} at {time} GetSessions what talk is in {room} at {time} GetSessions who is talking in {room} at {time} GetSessions who is speaking in {room} at {time} GetSessions which session is in {room} at {time} GetSessions which talk is in {room} at {time} GetSessions what session is in {room} at {time} {day} GetSessions what talk is in {room} at {time} {day} GetSessions who is talking in {room} at {time} {day} GetSessions who is speaking in {room} at {time} {day} GetSessions which session is in {room} at {time} {day} GetSessions which talk is in {room} at {time} {day} GetSessions what session is {day} in {room} at {time} GetSessions what talk is {day} in {room} at {time} GetSessions who is talking {day} in {room} at {time} GetSessions who is speaking {day} in {room} at {time} GetSessions which session {day} is in {room} at {time} GetSessions which talk {day} is in {room} at {time} @colinodell - joind.in/talk/18676
  39. 39. Intent Schema @colinodell - joind.in/talk/18676 { "intents": [ { "intent": "GetSessions", "slots": [ { "name": "day", "type": "AMAZON.DATE" }, { "name": "time", "type": "AMAZON.TIME" }, { "name": "room", "type": "ROOM" } ] }, { "intent": "AMAZON.HelpIntent" } ] } Fairfax Great Falls Potomac Ash Grove A Ash Grove B Ash Grove C
  40. 40. @colinodell - joind.in/talk/18676 $ composer require develpr/alexa-app AlexaRoute::intent('/alexa-end-point', 'GetDeveloperJoke', function(){ Alexa::say("A SQL query goes into a bar, walks up to two tables and asks, "Can I join you?""); });
  41. 41. @colinodell - joind.in/talk/18676 <?php namespace AppConsoleCommands; use CarbonCarbon; use IlluminateSupportFacadesDB; use GuzzleHttpClient; use IlluminateConsoleCommand; class ImportScheduleCommand extends Command { protected $signature = 'import:schedule'; protected $description = 'Imports the php[world] schedule from the conference website.'; public function handle() { // Manually scraped from the site by viewing the AJAX requests for each day $timestamps = [1479081600, 1479168000, 1479254400, 1479340800, 1479427200]; foreach ($timestamps as $timestamp) { $this->importSchedule($timestamp); } } private function importSchedule($timestamp) { $client = new Client([ 'base_uri' => '', 'timeout' => 10, ]); $response = $client->post('https://world.phparch.com/wp-admin/admin-ajax.php', [ 'form_params' => [ 'action' => 'get_schedule', 'data-timestamp' => $timestamp, 'data-location' => 0, 'data-track' => 0,
  42. 42. @colinodell - joind.in/talk/18676 <?php namespace AppHttpControllers; use CarbonCarbon; use DevelprAlexaAppFacadesAlexa; use DevelprAlexaAppRequestAlexaRequest; use IlluminateDatabaseQueryBuilder; use IlluminateSupportFacadesDB; class SessionController extends Controller { public function getSessions(AlexaRequest $request) { $request->getIntent(); $time = $request->slot('time') ?: Carbon::now()->format('G:i'); $day = $request->slot('day') ?: Carbon::now()->format('Y-m-d'); $room = $request->slot('room'); try { $sessions = $this->findSessions($time, $day, $room); if (count($sessions) === 0) { // No sessions found return Alexa::say('Sorry, I couldn't find any sessions on ' . $day . ' at ' . $time)->endSession(); } elseif (count($sessions) === 1) { return Alexa::say($this->getSessionText(reset($sessions)))->endSession();; } else { $text = 'I found ' . count($sessions) . ' sessions. '; foreach ($sessions as $session) {
  43. 43. @colinodell - joind.in/talk/18676 <?php // app/Http/routes.php AlexaRoute::intent('/alexa', 'GetSessions', 'AppHttpControllersSessionController@getSessions');
  44. 44. Recap • Alexa parses voice request; passes to PHP • Laravel application handles requests; returns response • Alexa renders responses as voice and/or cards Other uses for Alexa: • Querying for information • Interactive sessions (online ordering, games, etc.) • Home automation @colinodell - joind.in/talk/18676
  45. 45. Packagist Download Counter Displaying downloads counts from the Packagist API with Particle Photon
  46. 46. Particle Photon @colinodell - joind.in/talk/18676 • WiFi built in • Small footprint • Can be powered via MicroUSB • Enough digital GPIO pins • Programmable via web-based IDE • OTA flashing • Built-in webhook support
  47. 47. Hardware @colinodell - joind.in/talk/18676 • Particle Photon • MAX7219 8-Digit Red LED Display Module • Micro USB cable (power) • Wires
  48. 48. MAX7219 8-Digit Red LED Display Module @colinodell - joind.in/talk/18676Images from https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/overview
  49. 49. Wiring @colinodell - joind.in/talk/18676
  50. 50. @colinodell - joind.in/talk/18676
  51. 51. @colinodell - joind.in/talk/18676
  52. 52. @colinodell - joind.in/talk/18676
  53. 53. Problem! • JSON document is 32.5 KB • Photon webhook responses are 512-byte chunks spaced 250ms apart @colinodell - joind.in/talk/18676
  54. 54. Problem! • JSON document is 32.5 KB • Photon webhook responses are 512-byte chunks spaced 250ms apart @colinodell - joind.in/talk/18676 Solution! • Use Yahoo YQL to reduce response size
  55. 55. Problem! • JSON document is 32.5 KB • Photon webhook responses are 512-byte chunks spaced 250ms apart @colinodell - joind.in/talk/18676 Solution! • Use Yahoo YQL to reduce response size • Use PHP to parse JSON, return just one number
  56. 56. packagist-counter.php @colinodell - joind.in/talk/18676 <?php const URL = 'https://packagist.org/packages/league/commonmark.json'; $json = json_decode(file_get_contents(URL), true); header('Content-Type: text/plain'); echo $json['package']['downloads']['total'];
  57. 57. @colinodell - joind.in/talk/18676
  58. 58. @colinodell - joind.in/talk/18676
  59. 59. @colinodell - joind.in/talk/18676
  60. 60. @colinodell - joind.in/talk/18676
  61. 61. Recap • Particle Photon + 8 digit LED display • Particle webhook fetches data from packagist-counter.php • packagist-counter.php fetches from packagist.org; trims out the fat @colinodell - joind.in/talk/18676
  62. 62. Summary @colinodell - joind.in/talk/18676
  63. 63. Summary • IoT is everywhere! • PHP can bridge the gap • Run PHP:  On the device (RasPi examples)  In “the cloud” (Alexa; Particle Photon)  Or both! • Anyone can build web-connected devices @colinodell - joind.in/talk/18676
  64. 64. Questions? @colinodell - joind.in/talk/18676
  65. 65. Thanks! Slides/Feedback: http://joind.in/talk/18676 Project Source Code / Documentation: https://github.com/colinodell/php-iot-examples @colinodell - joind.in/talk/18676

×