More Clever Night Light
FleetingThe night light of my kid has:
- a clock that diverges quite fast
- 1 minute per week,
- no memory of the program
- I need to enter the program again after a power outage (and no battery backup),
- no way to program several hours
- for school days and holidays,
an annoying UX :
Let’s use its casing to build something that does not have those disadvantages.
I want to have a device that is in general disconnected from the wifi, but that connects for a few minutes to:
- fetch the current time,
- fetch the next wake hour,
As it happens, I have an unused raspberry pi 1B that could do the trick. I could later use a smaller devices, like a ESP8266 based board in the future, but that is a story for another time.
First idea -> using the gpio to power a few leds. That will result in a lot of wires, and I’m an not sure that I will have enough brightness.
Second idea -> use a extra neopixel from my IOT heart project.
It looks like it is quite simple according to https://learn.adafruit.com/neopixels-on-raspberry-pi/overview
On the raspberry pi 1B, it seems like there is only one pin to deal with pwm, the 18. Hence I need to follow the advice of disabling the sound.
Sound must be disabled to use GPIO18. This can be done in /boot/config.txt by changing “dtparam=audio=on” to “dtparam=audio=off” and rebooting. Failing to do so can result in a segmentation fault.
— https://learn.adafruit.com/neopixels-on-raspberry-pi/python-usage
ssh bayberry sudo sed -i 's/dtparam=audio=on/dtparam=audio=off/' /boot/config.txt
To debug:
The line below still does not work
docker run --device /dev/mem --device /dev/gpiomem --device /dev/vcio --rm -ti konubinix/neopixel /app/venv/bin/ipython
Until I fix the line above, let’s simply use the privileged mode.
docker run --privileged --rm -ti konubinix/neopixel /app/venv/bin/ipython
This is the code that is in the lighton.py program
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import board
import neopixel
import requests
from datetime import datetime
def main():
pixels = neopixel.NeoPixel(board.D18, 1)
pixels[0] = (255, 255, 255)
print("On")
requests.post("http://192.168.1.46:9705/nightlight", headers={"Title": "nightlight"}, data=f"{datetime.now()}: On")
if __name__ == "__main__":
main()
And, of course the code of the lightoff program.
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import board
import neopixel
import requests
from datetime import datetime
def main():
pixels = neopixel.NeoPixel(board.D18, 1)
pixels[0] = (0, 0, 0)
print("Off")
requests.post("http://192.168.1.46:9705/nightlight", headers={"Title": "nightlight"}, data=f"{datetime.now()}: Off")
if __name__ == "__main__":
main()
To say to my kid that it is almost time:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import board
import neopixel
import requests
from datetime import datetime
def main():
pixels = neopixel.NeoPixel(board.D18, 1)
pixels[0] = (0, 30, 40)
print("Almost")
requests.post("http://192.168.1.46:9705/nightlight", headers={"Title": "nightlight"}, data=f"{datetime.now()}: Almost")
if __name__ == "__main__":
main()
To be able to stop and start again the wifi from the container, I need to use run this command at least once on the host.
ssh bayberry mkdir -p /home/sam/cronlog
ssh bayberry docker run --pull always --detach --name nightlight --network host --restart always --privileged --volume /home/sam/cronlog/:/var/log/cronlog/ -ti konubinix/nightlight crond -f -L /var/log/cronlog/cron.log -l 6
And, to kill and remove the development version
To fetch the logs of cron, simply run
ssh bayberry cat cronlog/cron.log
To light on, I can simply do
ssh bayberry docker exec nightlight /app/venv/bin/python /app/lighton.py
And to change the program, I can simply restart the machine to get back the wifi and then run the following command (to change the start time to ten past noon for instance).
ssh bayberry docker exec nightlight /app/changestarttime.sh 12 10
To restore the wlan at startup, I needed to add a command in the host
cat<<EOF | ssh bayberry sudo tee /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
rfkill unblock wlan
exit 0
EOF
To get an interactive shell, it is as simple as
ssh -t bayberry docker exec -ti nightlight ipython
Simply drilling a hole into the back of the device
Insert the led strip. And that’s all.
Now, reinstall it
And the magic happens
Change the scheduling with:
ssh -t bayberry docker exec -ti nightlight crontab -e