name: inverse class: center, middle, inverse layout: true
@unixbigot — Homebridge
--- layout: true
@unixbigot — Homebridge
--- class: center, middle template: inverse # Homebridge Connect your legacy devices to Apple Home with NodeJS .bottom.right[ Christopher Biggs
.blue[@unixbigot] ] ??? --- .left-column[ # Agenda ] .right-column[ #### **Homekit**: * Accessories, Bridges, Scenes, oh my #### **Homebridge**: * **Why** is Homebridge needed? * **How** do I use it? * **What** can I do with it? #### **Developing**: * Homekit plugins * Node-RED Accessories ] ??? --- .left-column[ #Intro ## Landscape ] .right-column.nopad[ ## Home automation frameworks * Various incumbents (Nine billion separate apps) * Amazon - Echo, Echo Dot and Dash (Alexa) * Google - Google Home (OK Google) * Apple - HomeKit (Hey Siri) .img-250w[] .img-250w[] .img-250w[] ] --- .left-column[ #Intro ## Landscape ## Concepts ] .right-column.nopad[ # Apple Homekit * Lights, Locks, Sensors, Alarms, Switches, Thermostats and more * Representative devices in [apple store](http://www.apple.com/shop/accessories/all-accessories/homekit) * Any developer can implement apps * Only Made-for-iPhone program members can implement accessories * MFI is not open to individuals * Accessory protocol reverse-engineeried * NDAs and DMCA takedowns ] --- .left-column[ #Intro ## Landscape ## Concepts ] .right-column.nopad[ # Terminology in Homekit * **Accessories** - things you can interact with * **Bridges** - Connect to a bunch of accessories * **Scenes** - preconfigured sets of accessory changes * Reconfigure the house in one command * **Triggers** - contextual activation of Scenes * Requires an AppleTV or iPad * Accessories can be grouped into **Rooms** * Rooms can be grouped into **Zones** ] --- .left-column[ #Intro ## Landscape ## Concepts ## Interacting ] .right-column.nopad[ # Interacting with HomeKit devices * iOS **Home** App * Status at a glance * Create scenes or triggers * iOS **Control Centre** * Quick access to favourite accessories and scenes * **Siri** Voice Assistant ] --- .left-column[ #Intro ## Landscape ## Concepts ## Interacting ] .right-column.nopad[ .img-320w[] .img-320w[] ] --- .left-column[ #Intro ## Landscape ## Concepts ## Interacting ] .right-column.nopad[ .img-320w[] .img-320w[] ] --- .left-column[ #Intro ## Landscape ## Concepts ## Interacting ] .right-column.nopad[ # Voice Interaction (Siri) * "Turn on the **lamp** in the **study**" (accessory in room) * "Turn off all the lights **downstairs**" (zones) * "Dim the **dining room lights** to 50%" * "Switch off the **pool filter**" * "Let's watch a movie" (scene activation) * "What's the temperature in **the Baby's room**?" ] --- .left-column[ # Homebridge ## Why? ] .right-column.nopad[ # So, you want to be a Supervillain? * All this is great if you have infinite money * You probably have some *Not-Completely-Dumb* Appliances already * Garage doors * Smart TVs * Security alarms and IP cameras * Remote power boards * Anything with an IR remote (fans, aircon, AV Equipment) ] --- .left-column[ # Homebridge ## Why? ## How? ] .right-column.nopad[ # Enter Homebridge ## Present non-HomeKit devices as HomeKit Accessories * NodeJS server * Implements a Bridge to Accessories (or Platforms) * Over 350 Accessory plugins * Installable on Mac, Linux (incl Pi), Windows* ] --- .left-column[ # Homebridge ## Why? ## How? ] .right-column.nopad[ # Installing Homebridge * Thorough instructions for all platforms in Wiki * For Linux: * `$ sudo npm install -g --unsafe-perm homebridge` * `$ sudo npm install -g homebridge-someplugin` * `$ vi config.json` ] --- .fullpage.small[ ```json { "bridge": { "name": "Homebridge", "pin": "031-45-154" }, "description": "Serendipity HomeBridge", "accessories": [ { "accessory": "mqttswitch", "name": "living room floor lamp", "url": "http://192.168.1.21:1883/", "caption": "floor lamp in the living room", "topics": { "statusGet": "lights/livingroom/lamp1", "statusSet": "lights/livingroom/lamp1" }, }, { "accessory": "TV", "name": "TV", "description": "Damned Television", "ip": "192.168.1.103" }, { "accessory": "mqtt-temperature", "name": "Living Room Temperature", "url": "http://192.168.1.21:1883/", "topic": "sensors/livingroom/temp/ambient" } ] } ``` ] --- .left-column[ # Homebridge ## Why? ## How? ] .right-column.nopad[ * Any existing Mac, Windows or Linux PC * Raspberry Pi, AUD$70 plus case * Orange Pi PC Plus, AUD$40 with case * Orange Pi Lite AUD$20 * Orange Pi Zero AUD$15 .img-400w[] .img-320w[] ] --- .left-column[ # Homebridge ## Why? ## How? ## What? ] .right-column.nopad[ # What can I interface to? * TVs and HiFi * Other HA platforms: **Hue** lights, **Wemo** switches, **Nest** thermostats etc. * Computers * People (presence detection) * Bluetooth switches * Anything with an infrared or RC remote * Sensors: Light, Motion, Temperature, Gas * IP Cameras ] --- .left-column[ # Homebridge ## Why? ## How? ## What? ] .right-column.nopad[ ## Start by looking for an existing plugin .img-500w[] ] --- .left-column[ # Homebridge ## Why? ## How? ## What? ] .right-column.nopad[ ## No Plugin, What now? * Generic MQTT Control (`mqttswitch` plugin) * Generic MQTT Sensors (`mqtt-temperature` plugin et.al.) * Write your own Homebridge plugins. * Implement sensors and accesories in Node-RED. ] --- .left-column[ #Development ## Concepts ] .right-column.nopad[ ## More Terminology * Services - An interface offered by an accessory * Characteristics - A mandatory or optional component of a service * metadata: format, units, min, max, step * Perms - READ, WRITE or NOTIFY * Example - Lightbulb service * Mandatory characteristic: "On" * Optional Characteristics: "Brightness", "Hue", "Saturation", "Name" ] --- .left-column[ #Development ## Concepts ## Services ] .right-column.nopad[ ## Service Types * Air Quality, CO, CO2, Smoke, Leak * Battery * Camera, Video stream, Motion sensor, Occupancy sensor, Daylight * Door, Doorbell, Lock, Garage Door Opener * Lightbulb, Fan, Speaker, Microphone * Switch, Power window, Power shutters * Security system, Contact sensor * Thermostat, Temperature, Humidity * various others ] --- .left-column[ #Development ## Concepts ## Services ## Characteristics ] .right-column.nopad[ ## Characteristics ```javascript Characteristic.Brightness = function() { Characteristic.call(this, 'Brightness', '00000008-0000-1000-8000-0026BB765291'); this.setProps({ format: Characteristic.Formats.INT, unit: Characteristic.Units.PERCENTAGE, maxValue: 100, minValue: 0, minStep: 1, perms: [Characteristic.Perms.READ, Characteristic.Perms.WRITE, Characteristic.Perms.NOTIFY] }); ``` ```javascript Characteristic.CurrentDoorState = function() { Characteristic.call(this, 'Current Door State', '0000000E-0000-1000-8000-0026BB765291'); this.setProps({ format: Characteristic.Formats.UINT8, perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY] }); // The value property of CurrentDoorState must be one of the following: Characteristic.CurrentDoorState.OPEN = 0; Characteristic.CurrentDoorState.CLOSED = 1; Characteristic.CurrentDoorState.OPENING = 2; Characteristic.CurrentDoorState.CLOSING = 3; Characteristic.CurrentDoorState.STOPPED = 4; ``` ] --- .left-column[ #Development ## Concepts ## Services ## Characteristics ## Plugins ] .right-column.nopad[ ## Implementing a plugin - Binding characteristics ```javascript module.exports = function(homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; homebridge.registerAccessory("homebridge-lockitron", "Lockitron", LockitronAccessory); } function LockitronAccessory(log, config) { this.log = log; this.name = config["name"]; this.accessToken = config["api_token"]; this.lockID = config["lock_id"]; this.service = new Service.LockMechanism(this.name); this.service .getCharacteristic(Characteristic.LockCurrentState) .on('get', this.getState.bind(this)); this.service .getCharacteristic(Characteristic.LockTargetState) .on('get', this.getState.bind(this)) .on('set', this.setState.bind(this)); } ``` ] --- .left-column[ #Development ## Concepts ## Services ## Characteristics ## Plugins ] .right-column.nopad[ ## Implementing a plugin - Characteristic callbacks ```javascript LockitronAccessory.prototype.getState = function(callback) { this.log("Getting current state..."); request.get({ url: "https://api.lockitron.com/v2/locks/"+this.lockID, qs: { access_token: this.accessToken } }, function(err, response, body) { if (!err && response.statusCode == 200) { var json = JSON.parse(body); var state = json.state; // "lock" or "unlock" this.log("Lock state is %s", state); var locked = state == "lock" callback(null, locked); // success } else { this.log("Error getting state (status code %s): %s", response.statusCode, err); callback(err); } }.bind(this)); } ``` ] --- .left-column[ #Development ## Concepts ## Services ## Characteristics ## Plugins ## Node-RED ] .right-column.nopad[ ## Building Accessories with Node-RED .img-550w[] ] --- .left-column[ #Development ## Concepts ## Services ## Characteristics ## Plugins ## Node-RED ] .right-column.nopad[ ## Projector Screen MacGyver Hack .img-800w[] ] --- .left-column[ # Recap ] .right-column.nopad[ # Recap * Apple is slightly less open, but actually available * Concepts: Accessories, Scenes and Triggers * Homebridge supports hundreds of incumbent devices * Host it on a PC or Single-Board Computer * Building a plugin: Services and Characteristics * Node-RED for MacGyver tricks ] --- .left-column[ # Recap # Q+A ] .right-column.nopad.small[ ## Resources, Questions * **Homebridge** - [github: /nfarina/homebridge](https://github.com/nfarina/homebridge) - [github: /KhaosT/HAP-NodeJS](https://github.com/KhaosT/HAP-NodeJS) - [npm: Search "homebridge-plugin"](https://www.npmjs.com/search?q=homebridge-plugin) - [npm: node-red-contrib-homekit](https://flows.nodered.org/node/node-red-contrib-homekit) - Raspberry Pi: [raspberry.piaustralia.com.au](http://raspberry.piaustralia.com.au/) - Orange Pi: [Shenzen Xunlong](https://www.aliexpress.com/store/1553371) * **Me - Christopher Biggs** - Twitter: .blue[@unixbigot] - Email: .blue[christopher@biggs.id.au] - Hire Me: http://christopher.biggs.id.au/ ]