Konubinix' opinionated web of thoughts

More Clever Night Light

Fleeting

The 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:

  1. fetch the current time,
  2. 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

Notes linking here