Programming a LIFX Lightbulb
It’s Christmas and at the end of every year, I do a few things — revisiting goals, learning, relaxing, seeing family and friends and making something fun.
For this year, I’ve chosen to dive into an IoT project, to program my LIFX lightbulb. I’ve been eyeing the smart light for many months, and decided to use this project as an excuse to experiment.
The Idea
I find that I often fall asleep reading, so I wanted to automatically switch off my light at a particular time everyday.
I’ll be using Python to code a simple example and deploy the solution to Heroku.
In a nutshell, this is how I wanted the light to behave:
- At 10PM: switch on the light at a specific brightness level
- At 12PM: dim the lightbulb
- At 1AM: switch off the light
Setup
The first thing you will need to do, is setup the lightbulb with the App.
Once you’ve set up, you can adjust settings of your lightbulb, for example the colour and brightness, as well as switching the device on and off.
Understanding the API
You will need to log in to LIFX and generate a token to be used with the API.
Head over to https://cloud.lifx.com/settings to create a token.
Try It Out
The API https://api.developer.lifx.com/ lists the API requests available to test the lightbulb
Example:
- List lights you have: https://api.developer.lifx.com/docs/list-lights
- Setting light states: https://api.developer.lifx.com/docs/set-states
- Toggling the device on and off: https://api.developer.lifx.com/docs/toggle-power
You can test out the API on the page or via the example cURL/code that is provided
Step 1: Finding the light ID
First thing we need to is find the light id so we can target the light
API to use: https://api.developer.lifx.com/docs/list-lights
Let’s make a cURL request to find the device id.
In the docs, the id
field in the response is the device id to reference.
Step 2: Request the current state of the device
Let’s add some code.
Create a project e.g. light
and add a file called main.py
import enum
import json
import requests
import osclass State(enum.Enum):
Off = 'off'
On = 'on'def updateState():
print ("Running cron job") token = os.getenv('LIFX_TOKEN')
lightId = os.getenv('LIGHT_ID')
headers = {
"Authorization": "Bearer %s" % token,
} response = requests.get('https://api.lifx.com/v1/lights/' + lightId, headers=headers)
lights = json.loads(response.text)
currentState = lights[0]['power']
currentBrightness= lights[0]['brightness'] print ("Current state and brightness: [" + str(currentState) + ", " + str(currentBrightness) + "]")updateState()
Next, set environment variables for LIFX_TOKEN
and LIGHT_ID
export LIFX_TOKEN=XXX
export LIGHT_ID=YYY
Install the required dependencies (using pip
or pip3
)
pip install requests
Then run the code:
python main.py
(if you are running Python3, you may need to run this via python3 main.py)
This will print something like
$ Current state and brightness: [on, 0.3]
Step 3: Check the time
The next part of the logic is to check the time so the light can switch on, dim and switch off at the right time.
Time is usually in UTC, but if you wanted to, you can also convert the time to your timezone.
First, add the following imports
import time
from datetime import datetime
import pytz
Then install required dependencies using pip
or pip3
Next, under the code that printed the current state of the device, convert the time to your timezone, example:
tz = pytz.timezone('Europe/Vienna')
now = datetime.now(tz)
print ("Current hour: " + str(now.hour))
Now run the code python main.py
, you should get something like:
$ Current hour: 11
$ Current state and brightness: [on, 0.3]
Next, let’s check the time. For brevity, I’ll demonstrate with a couple of conditions
if now.hour == 22:
power = State.On.value
brightness = 0.7
elif now.hour == 0:
power = State.On.value
brightness = 0.3
else:
power = State.Off.value
brightness = 0.1
Then add payload information for the request.
payload = {
"power": power,
"brightness": brightness
}print ("Updating state to: " + power)
response = requests.put('https://api.lifx.com/v1/lights/d073d5627d36/state', data=payload, headers=headers)
Putting that together, this looks like
For testing purposes, you can update the “hour” in the conditions to turn the light off and on.
Step 4: Setting up Scheduling
We next want to schedule the code to run in certain hours of the day
Add another file called toggle.py
.
For this example, I’ve set this to run every hour, but you can set this to run at specific times (check https://crontab.guru/ for examples).
from main import toggle
from apscheduler.schedulers.blocking import BlockingSchedulerprint("Running scheduler")
scheduler = BlockingScheduler()
scheduler.add_job(updateState, 'cron', day_of_week = '*', hour='*', minute='0')
scheduler.start()
Next, remove the last line updateState()
in main.py
I’ve chosen to deploy the project to Heroku, so we need to setup other files
In the same project, create requirements.txt
and add
requests
pytz
apscheduler
Then create Procfile
with the following contents
clock: python toggle.py
Lastly, create runtime.txt
to set the python version. In my example, the file contents:
python-3.9.0
Step 5: Push your code to Github
In the project, initialise the project
git init
Then add and commit your files
git add .
git commit -m "Adding project"
In Github, create your repository (see: https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/create-a-repo)
After you’re done, add the remote to your project on the command line
git remote add origin <git repo url>
Then push the code to the repository
git push origin master
Step 6: Heroku Setup
- Set up the Heroku CLI
See: https://devcenter.heroku.com/articles/heroku-cli
2. Create an app and pipeline
Go to: https://dashboard.heroku.com/ to add the project in the UI and connect to your Github repository.
To create a pipeline, refer to this page on how- https://devcenter.heroku.com/articles/pipelines
Example pipeline I have set up (only production for now):
Then add the environment variables under project settings (go to project name > Settings
)
Then enable automatic deploys for your project (i.e. every time you add code, this will automatically deploy)
You should see this section from the Deploy tab: your project > Deploy
3. Add a Scheduler
See this guide as a reference: https://devcenter.heroku.com/articles/clock-processes-python
On the command line, type and run
heroku addons:create scheduler:standard
Then add a dyno
heroku ps:scale clock=1 --app <your app name>
Check the resources tab your project > Resources
, you should see something like the following
Step 7: Check Logs
You should be setup now. To check if the app is running as expected:
heroku logs -t -a your-app
Here is an example run:
2020-12-30T11:00:00.836778+00:00 app[clock.1]: Current hour: 22
2020-12-30T11:00:00.836804+00:00 app[clock.1]: Current state and brightness: [off, 0.1]
2020-12-30T12:00:00.721686+00:00 app[clock.1]: Updating state to: on
2020-12-30T13:00:00.007372+00:00 app[clock.1]: Running cron job
2020-12-30T13:00:00.603605+00:00 app[clock.1]: Current hour: 0
2020-12-30T13:00:00.603733+00:00 app[clock.1]: Current state and brightness: [on, 0.5]
2020-12-30T13:00:00.603833+00:00 app[clock.1]: Updating state to: on
2020-12-30T14:00:00.007353+00:00 app[clock.1]: Running cron job
2020-12-30T14:00:00.789883+00:00 app[clock.1]: Current hour: 1
2020-12-30T14:00:00.790068+00:00 app[clock.1]: Current state and brightness: [on, 0.3]
2020-12-30T14:00:00.790171+00:00 app[clock.1]: Updating state to: off
That’s it. Happy coding, enjoy your LIFX light!