CliffS / ikea-tradfri

A library to access the IKEA Trådfri lighting system without needing to call a separate binary
GNU Lesser General Public License v3.0
12 stars 6 forks source link

ikea-tradfri

A library to access the Ikea Trådfri lighting system without needing to call a separate binary

Example

Currently the examples are in Coffeescript. I may add Javascript examples later. Coffeescript is not necessary to be able to use this library, it will work with any language that transpiles to Javascript.

Tradfri  = require 'ikea-tradfri'
Identity = require './Identity'     # Identity.json is private credentials

tradfri = new Tradfri 'device.example.com', Identity
tradfri.connect()
.then (credentials) ->
  # store the credentials if necessary
  group4 = tradfri.group 'TRADFRI group 4'  # find a group
  group4.switch on                          # switch it on
  group4.setBrightness 50                   # set it to 50%
  bulb = tradfri.device 'Standard Lamp'     # Find a bulb
  bulb.colour = 'white'                     # Set the cool colour
  bulb.level  = 50                          # Set half brightness
  tradfri.scene = 'My Global Scene'         # Set up a global scene
.catch (err) ->
  console.error "Failed to connect: #{err}"

Table of Contents

Rationale

This library is designed to abstract away the complexities of both CoAP and the excellent underlying libraries, node-tradfri-client and node-coap-client, both by the amazing AlCalzone.

Currently it assumes that your Trådfri controller is set up using another tool, probably the Ikea app for Android or iPhone.

Installation

npm install ikea-tradfri

Changes in Version 5

With no warning, Ikea implemented major changes to groups and scenes. Previously, each group had a set of scenes that could be applied. This was changed so that all scenes became global and could work across groups.

The effect of this is that setting scenes on groups no longer works. Scenes need to be set on the tradfri object. Scenes can be created with the mobile app and can be called from this library.

Connecting to the Trådfri Controller

There are two ways to connect. The first time, you should use the security code printed on the base of the controller. You should then save the returned credentials and always use these credentials when connecting in the future.

NB: If you continue to use the security code, the controller will gradually forget about any other connected apps and these will need to reauthenticate.

The host can be a domain name such as device.example.com or a dotted IP address such as 192.168.1.20.

tradfri.connect() returns a Promise. You should wait for the promise to resolve before continuing. This can be done with a .then() or by awaiting the result. Either way you should catch any error. On success, the promise will resolve to the credentials object.

It is safe to call tradfri.connect() multiple times on the same instance. The first call will perform the actual connect; subsequent calls will resolve when the connect is completed.

You should not create multiple tradfri instances for the same controller.

First time

The first time you connect, you should use the code from the bottom of the controller:

Identity = 'mOPupErDolDw5gDf'
tradfri = new Tradfri 'device.example.com', Identity
tradfri.connect()
.then (credentials) ->
  # Save the credentials
.catch (err) ->
  console.error err
  process.exit 1

credentials will be an object containing two keys, identity and psk. This object should be stored, perhaps as a JSON file, for future use.

Subsequent connect calls

Subsequently the call could look like this:

Identity = require './identity'  # stored in identity.json
tradfri = new Tradfri 'device.example.com', Identity
try
  await tradfri.connect()
catch err
  console.error err
  process.exit 1

There are two more parameters to new Tradfri. This is so that you may pass in a custom logger. Unless you pass in a function here, the debug module will be used with the key ikea-tradfri. If you pass in a function as the third parameter, it should itself expect two parameters: a message and a level. If the fourth parameter to new tradfri is true, the custom logging function will also be passed down to the node-tradfri-client library.

All example code below assumes you have the tradfri variable described above.

Devices

There are currently seven types of device:

Bulb
A lightbulb, panel etc.
Plug
A switchable wall plug
Blind
A roller blind
Remote
A remote control device
SlaveRemote
A remote control device, slaved to another
Sensor
A movement sensor
Repeater
A signal repeater

For this library to work correctly, each device and group should be distinctly named as the library works exclusively from those names.

The Trådfri controller only permits Bulbs, Plugs and Blinds to be tracked. There seems to be no way to know when a Remote has been activated, other than by tracking a connected device.

Getting a Device

Using the tradfri variable created above, you call tradfi.device(name) where name is the name of the device you are looking for. It will return the approriate class for name or undefined if it is not found.

name can also be an array of device names. In this case, trafri.device(array) will return an array of all the devices matched or an empty array if none are found. Currently there is no provision for wildcards.

Device Properties

These are the properties that are common to all devices. All these properties should be considered read-only. Changing them will currently not be fed back to the controller.

Device Functions

Bulb

These are the bulb-specific properties (read-only):

The following are the methods to change settings on a bulb:

Plug

These are the plug-specific properties (read-only):

The following is the method to change settings on a plug:

Blind

These are the blind-specific properties (read-only):

The following are the methods to change positions on a blind:

Remote and Sensor

Currently these only have the common properties described above. It is not currently possible to detect changes when a remote is pressed or a sensor triggered owing to a lack of reporting by the Trådfri controller.

Events

All device types are event emitters although Remotes and Sensors do not seem to emit events when they are triggered.

Currently only two events are emitted:

device.on "deleted", (name) ->
  console.log "device.#{name} has just been deleted"
bulb.on changed, (current, previous) ->
  console.log "bulb.#{current.name} has changed:"
  for key, val of current when key isnt 'name'
    console.log "  #{key} was #{previous[key]}, now #{current[key]}"

Note that blinds emit changes continually as they move. You can test that a blind has stopped moving when the current.position is equal to the requested position.

Groups

Getting a Group

Getting a group is similar to getting a device. Using the tradfri variable, you call tradfri.group(name) where name is the name of the group you are looking for. It will return undefined if not found.

Group Properties

The read-only properties for a group are:

The methods are as follows. Each of these methods returns a promise that resolves to a boolean. If true, the change was made, if false nothing was changed.

group = tradfri.group 'Hallway'
console.log "#{group.name} is currently at level #{group.level}"
group.level 50
console.log "#{group.name} is now at level #{group.level}"

Scenes

The global scenes can now only be read and set via the tradfri object.

Scene Properties

currentScene = tradfri.scene
tradfri.scene = 'Evening Lights'

Scene Method

tradfri.setScene 'Evening Lights'
.then (id) ->
  console.log "Scene ID is now #{id} and named #{tradfri.scene}"

Other Methods and Properties

reset()

tradfri.reset()

This can be used to reset the connection.

close()

tradfri.close()

This should be called before ending the program so that the gateway can clean up its resources and so that the program will close its connections. Note that it may nevertheless take a few seconds for the program to end as there may be timers still running.

devices

devices = tradfri.devices

This will return an array of all the devices that have been detected.

Acknowlegements

Many thanks to AlCalzone for his excellent libraries, without which this library would have been infinitely harder to write.

I have no affiliation to Ikea and this library is not approved or endorsed in any way by Ikea.

Issues

Please report all issues via the Github issues page.

Licence

This library is currently offered under version 3 of the GNU Lesser General Public Licence. If you need a different licence, please contact me.