Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.#*
/node_modules
/config/default.json

63 changes: 39 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,54 @@
# node-tradfri-restapi

What
---
## What

A simple REST-API implementation of [node-tradfri](https://www.npmjs.com/package/node-tradfri) with the following commands

- `/tradfri/deviceids` will provide an array of device ids
- `/tradfri/groupids` will provide an array of group ids
- `/tradfri/devices` will provide a full list of all devices including meta data
- `/tradfri/deviceids` will provide an array of device ids
- `/tradfri/groups` will provide a full list of all groups including devices and meta data
- `/tradfri/devices` will provide a full list of all devices including meta data
- `/tradfri/group/:groupid/:state` will set the state of a device (on/off). E.g. /tradfri/device/11007/off
- `/tradfri/device/:deviceid` will get the status of a device, including brightness and color
- `/tradfri/device/:deviceid/:state` will set the state of a device (on/off). E.g. /tradfri/device/17101/on
- `/tradfri/group/:groupid/:state` will set the state of a device (on/off). E.g. /tradfri/device/11007/off
- `/tradfri/device/:deviceid/on?color=:color` will set the color of a device, in hex, or 'cool', 'warm', 'normal'
- `/tradfri/device/:deviceid/on?brightness=:brightness` will set the brightness of a device, from 0 to 255
- In addition, adding `?transitionTime=30` (for example) to a `color=` or `brightness=` state change will animate the change over a number of _tenths-of-a-second_.

First release is a bit of a quick one. Exceptions needs to be managed and include toggle as an option. I did the API as I need to control my IKEA TRÅDFRI-lights with Node-RED but Node-RED does not support Node v7.x (I assume it will wait for the next LTS release) and a simple micro service is the short term solution to have it integrated and managed by Node-RED.

How
---
Setup libcoap as explained below
## How

1. Setup libcoap as explained below
2. `npm update` to install `node-tradfri` and other dependencies
3. Copy `./config/default.json-sample` as `./config/default.json` and update with the IKEA hub information
4. Run using Node >7.6, or simply use `nave`:

1. Setup libcoap as explained below
2. Rename `./config/default.json-sample` to `./config/default.json` and update with the IKEA hub information
3. Run using node >7.6
```sh
nave use 7 node index.js
```

If you use `systemd` to manage your OS, eg. recent versions of Ubuntu Linux, then you can use the supplied `tradfri-restapi.service` file to perform start-up and job management. Edit the `tradfri-restapi.service` file to match your install directory, user, group and so forth, and then:

```sh
systemctl link `pwd`/tradfri-restapi.service
systemctl start tradfri-restapi
journalctl -f tradfri-restapi
```

## Compiling libcoap

Compiling libcoap
---
Install libcoap as descibed below for Debian/Ubuntu/Raspbian:
Install libcoap as described below for Debian/Ubuntu/Raspbian:
(credits to homebridge-tradfri)

```sh
apt-get install libtool git build-essential install autoconf automake
git clone --recursive https://github.com/obgm/libcoap.git -b dtls
cd libcoap
git submodule update --init --recursive
./autogen.sh
./configure --disable-documentation --disable-shared
make
```
$ apt-get install libtool git build-essential install autoconf automake
$ git clone --recursive https://github.com/obgm/libcoap.git
$ cd libcoap
$ git checkout dtls
$ git submodule update --init --recursive
$ ./autogen.sh
$ ./configure --disable-documentation --disable-shared
$ make```

You'll find the coap-client binary in ./examples

You'll find the coap-client binary in `./examples`. This should be specified in the `config/default.json` file used above.
51 changes: 50 additions & 1 deletion api/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ exports.getDevices = function (req, res) {
});
}
}

exports.getGroupIds = function (req, res) {
try {
tradfri.getGroupIds().then(groupIds => {
Expand Down Expand Up @@ -74,6 +75,39 @@ exports.getGroups = function (req, res) {
}
}

exports.getGroup = function (req, res) {
try {
tradfri.getGroups().then(groups => {
res.json({
item: (groups.filter(group => { return group.id == req.params.groupId })).shift(),
status: "ok"
});
});

} catch (err) {
res.json({
items: [],
status: "err"
});
}
}

exports.getDevice = function (req, res) {
try {
tradfri.getDevices().then(devices => {
res.json({
item: (devices.filter(device => { return device.id == req.params.deviceId })).shift(),
status: "ok"
});
});

} catch (err) {
res.json({
items: [],
status: "err"
});
}
}

exports.setDevice = function (req, res) {
try {
Expand All @@ -82,7 +116,22 @@ exports.setDevice = function (req, res) {
};

if (req.query.brightness && !isNaN(parseInt(req.query.brightness)) && req.query.brightness <= 255)
q.brightness = req.query.brightness;
q.brightness = parseInt(req.query.brightness);

if (req.query.transitionTime && !isNaN(parseInt(req.query.transitionTime)) && req.query.transitionTime >= 0)
q.transitionTime = parseInt(req.query.transitionTime);

if (req.query.color) {
q.color = req.query.color.toLowerCase();
switch (q.color) {
case 'focus': case 'cool': q.color = 'f5faf6'; break;
case 'everyday': case 'normal': q.color = 'f1e0b5'; break;
case 'relax': case 'warm': q.color = 'efd275'; break;
default:
if ( ! req.query.color.match('/^[0-9a-fA-F]{6}$/'))
delete q.color;
}
}

tradfri.setDeviceState(req.params.deviceId, q).then(
res.json({
Expand Down
30 changes: 18 additions & 12 deletions api/routes.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
'use strict';

module.exports = function(app) {
var controller = require('./controller.js');
var controller = require('./controller.js');

// todoList Routes
app.route('/tradfri/deviceids')
.get(controller.getDeviceIds);
app.route('/tradfri/devices')
.get(controller.getDevices);
app.route('/tradfri/groupids')
.get(controller.getGroupIds);
app.route('/tradfri/groups')
.get(controller.getGroups);
// todoList Routes
app.route('/tradfri/deviceids')
.get(controller.getDeviceIds);
app.route('/tradfri/devices')
.get(controller.getDevices);
app.route('/tradfri/groupids')
.get(controller.getGroupIds);
app.route('/tradfri/groups')
.get(controller.getGroups);

app.route('/tradfri/device/:deviceId')
.get(controller.getDevice);
app.route('/tradfri/device/:deviceId/:state')
.get(controller.setDevice);
.get(controller.setDevice);

app.route('/tradfri/group/:groupId')
.get(controller.getGroup);
app.route('/tradfri/group/:groupId/:state')
.get(controller.setGroup);
.get(controller.setGroup);
};
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

require("process").title = 'node-tradfri-restapi';

var config = require("config");

var express = require("express"),
Expand Down
23 changes: 23 additions & 0 deletions tradfri-restapi.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[Unit]
Description=RESTful API for TRADFRI lighting (temporary)
Wants=network.target
Documentation=https://github.com/nidayand/node-tradfri-restapi

[Service]
Type=simple
User=node-red
Group=node-red
WorkingDirectory=/home/node-red/node-tradfri-restapi
Nice=5
Environment="NODE_OPTIONS=--max-old-space-size=128"
ExecStart=/usr/bin/env nave use 7 node $NODE_OPTIONS $NODE_RED_OPTIONS index.js
# Use SIGINT to stop
KillSignal=SIGINT
# Auto restart on crash
Restart=on-failure
# Tag things in the log
SyslogIdentifier=tradfri-restapi
#StandardOutput=syslog

[Install]
WantedBy=multi-user.target