ikea-tradfri

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

Usage no npm install needed!

<script type="module">
  import ikeaTradfri from 'https://cdn.skypack.dev/ikea-tradfri';
</script>

README

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.

  • id (integer)

    This is the internal ID used by the controller. It is not usually necessary to use this ID in this library.

  • name (string)

    This is the name of the device and is the usual way to access it in this library.

  • type (string)

    This will be one of Blind, Bulb, Plug, Remote, Repeater or Sensor.

  • alive (boolean)

    This indicates whether or not the Ikea controller believes this device to be powered on.

Device Functions

  • toString()

    This will return the device name so that the device can be used as a string.

Bulb

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

  • isOn (boolean)

    Whether this bulb is on or off

  • switchable (boolean)

    Whether this bulb can be switched on and off

  • dimmable (boolean)

    Whether this bulb can be dimmed

  • brightness (integer percentage)

    This can be from 0 to 100.

  • spectrum (white|rgb|none)

    The light spectrum of the bulb: white, rgb or none

  • colour (string | percentage | value)

    Reading the property for white bulbs will return "white", "warm" or "glow" if its value matches one of those settings (1, 62 or 97, respectively) or it will return the current numerical value.

    For RGB bulbs, it will return the RGB colour.

  • color (string | percentage)

    An alternative spelling of colour, q.v..

  • hexcolour (hex number)

    The colour of the bulb expressed as RGB.

  • hue

  • saturation

    The hue and saturation of the RGB bulbs.

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

  • switch() (boolean)

    This is the on-off switch. It should be sent true to turn the bulb on or false to turn it off. It will return a promise resolving to true if the setting was changed or false if it was not.

  • setBrightness() (integer percentage)

    This can be set from 0 to 100. It will change the brightness of the Bulb: 100 is fully bright, 0 will turn the bulb off. This will return a promise resolving to true if the setting was changed or false if it was not.

  • setColour() (white | warm | glow | integer percentage | hex number )

    For white spectrum bulbs, this can be set to:

    • "white"
    • "warm" (or "warm white")
    • "glow" (or "warm glow")

    Alternatively it can be set to a number from 1 to 100 where 1 is the coolest colour temperature and 100 is the warmest. This will return a promise resolving to true if the setting was changed or false if it was not.

  • setColor

    An alternative spelling of setColour, q.v..

Plug

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

  • isOn (boolean)

    Whether this plug is on or off

  • switchable (boolean)

    Whether this plug can be switched on and off

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

  • switch() (boolean)

    This is the on-off switch. It should be sent true to turn the plug on or false to turn it off. It will return a promise resolving to true if the setting was changed or false if it was not.

Blind

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

  • position (integer)

    This is the current position of the blind, where 100 is fully open (up) and 0 is fully closed (down).

    isOpen (boolean)

    This is true if the blind is fully open.

    isClosed (boolean)

    This is true if the blind is fully closed.

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

  • open (void)

    This will fully open the blind.

  • close (void)

    This will fully close the blind.

  • SetPosition (integer)

    This will set the blind to any position between 0 and 100.

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:

  • deleted

    This is emitted if the device has been deleted from the controller. It is passed a parameter of the Device's name.

device.on "deleted", (name) ->
  console.log "device.#{name} has just been deleted"
  • changed

    [NOTE The format for the changed event since v3.0.0 is different and incompatible with previous versions]

    This is emitted with two objects describing the change, whenever a device is changed. Each object will have a name key and one or more attribute keys:

    The first object is the new state of the device, the second object is the previous state. Only states that have changed will be in the object.

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:

  • id (integer)

    This is the internal ID used by the controller.

  • name (string)

    This is the name of the group and is the usual way to access it in this library.

  • isOn (boolean)

    This returns whether the controller believes this group to be on or off. It is unreliable.

  • level (integer percentage)

    Reading this will return the last group value applied.

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.

  • switch() (boolean)

    Calling this with on (true) will turn on all the bulbs in the group. Setting it to off (false) will turn them off.

  • setLevel() (integer percentage)

    Setting this will set all bulbs in the group to the required level.

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

  • scenes (array)

    This will return an array of scene names known by the controller.

  • scene (string: read-write)

    This will return the last scene set via this library. If written to, it will attempt to set the scene to the value passed. It will fail silently so it is probably better to use setScene(), see below.

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

Scene Method

  • setScene() (string)

    This will attempt to find the scene name passed and set that scene. It returns a promise resolving to the scene ID on success and rejects if it cannot find the scene by name.

    Currently this tries to use a transition time of 3 seconds but this appears not to work in the current version of the controller.

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.