Skip to content
/ caesium Public

NodeJS based API to control lightbulbs in Ikea's Trådfri series

License

Notifications You must be signed in to change notification settings

frklan/caesium

Repository files navigation

CAESIUM

License

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.

Using the API

Prerequisites

Make sure you have:

  • NodeJS
  • Ikea Trådfi Lightbulb
  • Ikea Trådfri Gateway
  • An SSL certificate for your domain (optional)

Installation

  1. Clone the repository $ git clone git@github.com:frklan/caesium.git

  2. Install dependencies with $ npm install

  3. 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.

  4. Run $ npm run start

Access the API on port 5000 (or set a port in the .env file: PORT=<port number>)

JWT_SECRET

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>

Generating a JWT token

A JWT token can be manually generated with the following sequence:

  1. 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
    
  2. 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.

SSL encryption

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:

  1. Get a domain name, e.g. from namecheap

  2. Install certbot,

  3. 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)

  4. Follow certbot's instruction how to verify your identity and prove that you own [YOUR-DOMAIN].

  5. 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
  6. 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.

API endpoints

POST login

$ curl https://[YOUR-DOMAIN]:5000/login -X POST -H "id: caesium_api_user" -H "otp: 349721"

Response:

{ 
    "success":true,
    "token":"eyJhbGciOiJIUz....WTlOioJg_0zIjKZnB-txLqbT4A"
}

GET api/v1/bulbs

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
            }
        },
`

GET api/v1/bulb/[bulb id]

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
            }
            }
        }
    ]
}

POST api/v1/bulb/[bulb id]/toggle

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"
}

POST api/v1/bulb/[bulb id]/[ON] || [OFF]

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"
}

TODO's

  • - [ ] Replace the JWT token with 2FA OTP? Using both JWT and OTP's seems overly complicated, perhaps a single method is enough?

Contributing

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.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

  • Fredrik Andersson - Initial work - frklan

License

This project is licensed under the MIT License - see the LICENSE file for details

About

NodeJS based API to control lightbulbs in Ikea's Trådfri series

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published