A library to access the Ikea Trådfri lighting system without needing to call a separate binary
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}"
- Rationale
- Installation
- Changes in Version 5
- Connecting to the Trådfri Controller
- Devices
- Groups
- Scenes
- Other Methods and Properties
- Issues
- Licence
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.
npm install ikea-tradfri
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.
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 await
ing 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.
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.
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.
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.
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.
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.
-
toString()
This will return the device name so that the device can be used as a string.
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 orfalse
to turn it off. It will return a promise resolving totrue
if the setting was changed orfalse
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 orfalse
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 orfalse
if it was not. -
setColor
An alternative spelling of setColour, q.v..
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 orfalse
to turn it off. It will return a promise resolving totrue
if the setting was changed orfalse
if it was not.
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.
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.
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.
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.
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}"
The global scenes can now only be read and
set via the tradfri
object.
-
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'
-
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}"
tradfri.reset()
This can be used to reset the connection.
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 = tradfri.devices
This will return an array of all the devices that have been detected.
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.
Please report all issues via the Github issues page.
This library is currently offered under version 3 of the GNU Lesser General Public Licence. If you need a different licence, please contact me.