N.B. Very much in Alpha mode -- beware of bugs and unexpected behaviour.
A Rest API to control Ikea Trådfri Lightbulbs. Pretty basic and probably unsecure. Make sure you understand the risks exposing the API to the world.
Make sure you have:
- NodeJS
- Ikea Trådfi Lightbulb
- Ikea Trådfri Gateway
- An SSL certificate for your domain (optional)
-
Clone the repository
$ git clone git@github.com:frklan/caesium.git
-
Install dependencies with
$ npm install
-
Create an .env file in the root of the project containing:
GW_PASSWORD=<Password as printed on your Tråfri gateway> JWT_SECRET=<jwt secret> OTP_SECRET=<otp secret>
Please refer to below instructions how to generate the JWT_SECRET and OTP_SECRET
Alternatively you can set the corresponding environment variables using your preferred method.
-
Run
$ npm run start
Access the API on port 5000 (or set a port in the .env file: PORT=<port number>
)
The JWT_SECRET can be generated by any means, it should be a 32 character cryptographically strong random string, store it either in:
a. the .env file in the root of the project as
JWT_SECRET=<secret string>
b. the $JWT_SECRET environment variable, e.g.:
$ export JWT_SECRET=<secret string>
A JWT token can be manually generated with the following sequence:
-
run
$ src/util/generateJwtToken
, the output will be similar to:src/util/generateJwtToken ID: caesium_api_user TTL: 3600 Extra data: <not set> JWT token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A
-
Set the header field
token
to the JWT token displayed when using the API endpoint, e.g.:$ curl https://[YOUR-DOMAIN]:5000/api/v1/bulbs -H "token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
Note that the JWT token will default expire in 3600 seconds. A longer (or shorter) expiration time can be set with the option --ttl, refer to $ src/util/generateJwtToken --help
for details. There is no way of invalidating JWT tokens unless it expires automatically, hence it is important to treat them as secrets.
If the API is served openly on the internet it is recommended to encrypt all traffic with SSL. It's pretty easy to generate an SSL certificate with letsencrypt and it costs 0€! Yo do, however, need access to a domain or a public webserver. My preferred way of generating the SSL certificate is these easy steps:
-
Get a domain name, e.g. from namecheap
-
Install certbot,
-
Generate the certificate with
$certbot certonly --config-dir ./conf --work-dir ./ --logs-dir ./ --preferred-challenges dns -d [YOUR-DOMAIN] --manual
(replace [YOUR-DOMAIN] with your actuall domain) -
Follow certbot's instruction how to verify your identity and prove that you own [YOUR-DOMAIN].
-
Set the following environment variables
SSL_CERT_FILE=../conf/live/[YOUR-DOMAIN]/fullchain.pem SSL_KEY_FILE=../conf/live/[YOUR-DOMAIN]/privkey.pem USE_SSL=TRUE
-
Run the server as normal and access the the API at https://.....
Note. if you'd like to get an official certificate but not expose the API to the internet, you can generate the certificate for a 'non existing' domain, e.g. dev.example.com and then route dev.example.com to a local ip address by changing your hosts file.
Note. Do NOT show, transmit or otherwise expose the private key associated with your SSL certificate.
$ curl https://[YOUR-DOMAIN]:5000/login -X POST -H "id: caesium_api_user" -H "otp: 349721"
Response:
{
"success":true,
"token":"eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
}
Lists current known bulbs and states
Example:
$ curl https://[YOUR-DOMAIN]:5000/api/v1/bulbs -X GET -H "token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
Response:
{
"gateway": {
"status": "online",
"name": "gw-xxxxxxxxxxxx",
"host": "TRADFRI-Gateway-xxxxxxxxxxxx.local"
},
"lightbulbs": [
{
"name": "Table",
"id": 65537,
"lastSeen": 1533745439,
"light": {
"onOff": false,
"dimmer": 22.8,
"color": "f1e0b5",
"colorTemperature": 0,
"colorX": 0,
"colorY": 0,
"transitionTime": 0.5
}
},
{
"name": "Window",
"id": 65539,
"lastSeen": 1533667468,
"light": {
"onOff": false,
"dimmer": 0,
"color": "0",
"colorTemperature": 0,
"colorX": 0,
"colorY": 0,
"transitionTime": 0.5
}
},
`
Report state on a single bulb
Example:
$ curl https://[YOUR-DOMAIN]:5000/api/v1/bulb/65530 -X GET -H "token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
Response:
{
"gateway": {
"status": "online",
"name": "gw-xxxxxxxxxxxx",
"host": "TRADFRI-Gateway-xxxxxxxxxxxx.local"
},
"lightbulbs": [
{
"name": "Window",
"id": 65539,
"lastSeen": 1533667468,
"light": {
"onOff": false,
"dimmer": 0,
"color": "0",
"colorTemperature": 0,
"colorX": 0,
"colorY": 0,
"transitionTime": 0.5
}
}
}
]
}
Toggles a bulb on or off
Example:
$ curl https://[YOUR-DOMAIN]:5000/api/v1/bulb/65530/toggle -X POST -H "token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
Response:
{
"gateway": {
"status": "online",
"name": "gw-xxxxxxxxxxxx",
"host": "TRADFRI-Gateway-xxxxxxxxxxxx.local"
},
"status": "done"
}
Switches a bulb on or off.
Example:
$ curl https://[YOUR-DOMAIN]:5000/api/v1/bulb/65530/ON -X POST -H "token: eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
Response:
{
"gateway": {
"status": "online",
"name": "gw-xxxxxxxxxxxx",
"host": "TRADFRI-Gateway-xxxxxxxxxxxx.local"
},
"status": "done"
}
- - [ ] Replace the JWT token with 2FA OTP? Using both JWT and OTP's seems overly complicated, perhaps a single method is enough?
Contributions are always welcome!
When contributing to this repository, please first discuss the change you wish to make via the issue tracker, email, or any other method with the owner of this repository before making a change.
Please note that we have a code of conduct, you are required to follow it in all your interactions with the project.
We use SemVer for versioning. For the versions available, see the tags on this repository.
- Fredrik Andersson - Initial work - frklan
This project is licensed under the MIT License - see the LICENSE file for details