Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making Robots (PHP Unicorn Conf)

Making Robots (PHP Unicorn Conf)

I bet you're the kind of person who's too busy working to build robots, with PHP. Well, you're missing out!

Over the last few years, I've built all sorts of useful robots (Internet of Things machines); to connect to virtual environments, automate my surroundings, or generally make my life easier.

And I found all of these could be built using little more than the familiar PHP code I was using in my 9-to-5. Join me as I show you some of the cool things you can do, with an Arduino, some useful PHP libraries, and a lot of imagination.

Christopher Pitt

May 04, 2017
Tweet

More Decks by Christopher Pitt

Other Decks in Programming

Transcript

  1. namespace Notifier\Service; use Notifier\Service; use Endroid\Twitter\Twitter as Client; class Twitter

    implements Service { private $client; private $new = false; private $since = null; public function __construct($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret) { $this->client = new Client( $consumerKey, $consumerSecret, $accessToken, $accessTokenSecret ); } }
  2. public function query() { if ($this->new) return true; $parameters =

    ["count" => 1]; if ($this->since) { $parameters["since_id"] = $this->since; } $response = $this->client->query( "statuses/mentions_timeline", "GET", "json", $parameters ); $tweets = json_decode($response->getContent()); if (count($tweets) > 0) { $this->new = true; $this->since = (int) $tweets[0]->id; } return $this->new; }
  3. public function dismiss() { $this->new = false; } public function

    name() { return "twitter"; } public function colors() { return [1 - 0.11, 1 - 0.62, 1 - 0.94]; }
  4. namespace Notifier\Service; use Notifier\Service; class Gmail implements Service { private

    $new = false; private $emails = []; private $username; private $password; public function __construct($username, $password) { $this->username = $username; $this->password = $password; } }
  5. public function query() { if ($this->new) return true; $inbox =

    imap_open( "{imap.gmail.com:993/imap/ssl}INBOX", $this->username, $this->password ); if (!inbox) { return false; } // ...
  6. $emails = imap_search($inbox, "ALL", SE_UID); if ($emails) { foreach ($emails

    as $email) { if (!in_array($email, $this->emails)) { $this->new = true; break; } } $this->emails = array_values($emails); } return $this->new; }
  7. public function dismiss() { $this->new = false; } public function

    name() { return "gmail"; } public function colors() { return [1 - 0.89, 1 - 0.15, 1 - 0.15]; }
  8. use Carica\Io; use Carica\Firmata; $loop = Io\Event\Loop\Factory::get(); $board = new

    Firmata\Board( Io\Stream\Serial\Factory::create( "/dev/cu.usbmodem14111", 57600 ) ); $board ->activate() ->done(function () use ($loop, $board) { // ...connect to services }); $loop->run();
  9. // diode pins $board->pins[10]->mode = Firmata\Pin::MODE_PWM; $board->pins[10]->analog = 1; $board->pins[11]->mode

    = Firmata\Pin::MODE_PWM; $board->pins[11]->analog = 1; $board->pins[9]->mode = Firmata\Pin::MODE_PWM; $board->pins[9]->analog = 1; // sensor pins $board->pins[12]->mode = Firmata\Pin::MODE_OUTPUT; $board->pins[12]->digital = 1; $board->pins[14]->mode = Firmata\Pin::MODE_ANALOG;
  10. $services = new SplQueue(); $services->enqueue([ new Notifier\Service\Twitter( getenv("SERVICE_TWITTER_CONSUMER_KEY"), getenv("SERVICE_TWITTER_CONSUMER_SECRET"), getenv("SERVICE_TWITTER_ACCESS_TOKEN"),

    getenv("SERVICE_TWITTER_ACCESS_TOKEN_SECRET") ), false ]); $services->enqueue([ new Notifier\Service\Gmail( getenv("SERVICE_GMAIL_USERNAME"), getenv("SERVICE_GMAIL_PASSWORD") ), false ]);
  11. $loop->setInterval(function () use (&$services) { $remaining = count($services); while ($remaining--)

    { $next = $services->dequeue(); $next[1] = $next[0]->query(); $services->enqueue($next); } }, 1000 * 5);
  12. $service = null; $next = function () use ($loop, $board,

    &$next, &$services, &$service) { $remaining = count($services); while ($remaining--) { $next = $services->dequeue(); $services->enqueue($next); if ($next[1]) { $service = $next; break; } } // ...no notifications if (!$service) return; // ...
  13. $colors = $service[0]->colors(); $board->pins[10]->analog = $colors[0]; $board->pins[11]->analog = $colors[1]; $board->pins[9]->analog

    = $colors[2]; $loop->setTimeout(function () use ($board, &$service) { $board->pins[10]->analog = 1; $board->pins[11]->analog = 1; $board->pins[9]->analog = 1; $service = null; }, 1000 * 1.5); }; $loop->setInterval($next, 1000 * 4);
  14. $loop->setInterval(function() use ($board, &$services, &$service) { if ($service !== null

    && $board->pins[14]->analog < 0.1) { $remaining = count($services); while ($remaining--) { $next = $services->dequeue(); // dismissing notification... if ($next[0]->name() === $service[0]->name()) { $service = null; $next[0]->dismiss(); $next[1] = false; } $services->enqueue($next); } } }, 50);