Jaron’s Blog

LivePlantCam.com now has infrared night mode

LivePlantCam.com during the day.

I’ve run LivePlantCam.com for almost a decade, and this week it got a new feature: night mode. A major weakness of the site has always been that roughly half of the time the picture it shows is black, because it is night where I live.

LivePlantCam.com at night before night mode. LivePlantCam.com at night without night mode.

Recently, I upgraded the hardware from an ordinary USB webcam connected to a computer to a PineCube, a little system-on-a-chip computer with a built-in camera. One nice feature of the PineCube is that it supports Power Over Ethernet (POE), so I can hang it from the ceiling by its ethernet cable for a top-down view.

The PineCube hanging above the plant. The PineCube hanging above the plant.

Another feature is the night mode. The PineCube has two infrared LEDs and a configurable filter that converts infrared to visible light. When the LEDs are turned on and the filter is set, the scene is apparently illuminated with an eerie purple glow.

LivePlantCam.com at night with night mode. LivePlantCam.com at night with night mode.

The LEDs and filter shouldn’t be set all the time, since they make the daytime scene look unnatural. Therefore, I need a way to enable and disable the LEDs and filter (“night mode”) automatically with the light.

LivePlantCam.com during the day with night mode. LivePlantCam.com during the day with night mode.

Everything can be done with systemd units. First, a unit turns things on, setting both LEDs and activating the GPIO-controlled filter.

/etc/systemd/system/night-mode-enable.service
[Unit]
Description=Enable PineCube camera night mode.

[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c '/usr/bin/echo 0 > /sys/class/leds/pine64:ir:led1/brightness'
ExecStart=/usr/bin/bash -c '/usr/bin/echo 0 > /sys/class/leds/pine64:ir:led2/brightness'
ExecStart=/usr/bin/gpioset gpiochip0 45=1

When activated, the filter produces a satisfying mechanical “click” from the PineCube. Next, we have a unit that does the opposite.

/etc/systemd/system/night-mode-disable.service
[Unit]
Description=Disable PineCube camera night mode.

[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c '/usr/bin/echo 1 > /sys/class/leds/pine64:ir:led1/brightness'
ExecStart=/usr/bin/bash -c '/usr/bin/echo 1 > /sys/class/leds/pine64:ir:led2/brightness'
ExecStart=/usr/bin/gpioset gpiochip0 45=0

Another mechanical “click” sounds when the filter is deactivated.

Now we have a problem: I want these units to run at twilight and dawn, respectively, so that the LEDs and filter are only active when it’s dark. These times change throughout the year, so a fixed systemd timer won’t do.

Luckily, I found a cute utility called sunwait that, given GPS coordinates, computes the date-dependant dawn and twilight times. Combined with systemd-run, which creates transient systemd timers, this made the perfect solution. This unit produces transient timers to activate the night mode enable and disable units at twilight and dawn, respectively.

/etc/systemd/system/night-mode-configure.service
[Unit]
Description=Schedule night mode for the PineCube camera.

[Service]
Type=oneshot
Environment=coords='41.9035313N 12.4561705E'
ExecStart=/usr/bin/bash -c '/usr/bin/systemd-run --on-calendar="$(date +%%F) $(/usr/bin/sunwait list civil rise ${coords})" --unit night-mode-disable.service'
ExecStart=/usr/bin/bash -c '/usr/bin/systemd-run --on-calendar="$(date +%%F) $(/usr/bin/sunwait list civil set ${coords})" --unit night-mode-enable.service'

Finally, this systemd timer ensures that the night-mode-configure unit is run every night at 2 AM, correctly setting the night mode for later. In addition, it runs the unit 60 seconds after any reboot to ensure that the transient timers (which do not survive reboots) are reset.

/etc/systemd/system/night-mode-configure.timer
[Unit]
Description=Configure night mode daily.

[Timer]
OnStartupSec=60
OnCalendar=*-*-* 2:00:00

[Install]
WantedBy=timers.target

Running systemctl enable --now night-mode-configure.timer installs and activates the timer.

Sure enough, this morning I woke up to the bright sun and a disabled night mode. Meanwhile, systemctl list-timers reveals that the night-mode-enable unit is correctly scheduled for this evening.

From here on out, night mode should work all by itself, providing exciting live plant viewing for nearly double the time.

For others with the PineCube, also feel free to borrow my Arch Linux ARM PKGBUILD for the kernel, which has been stripped down to basics in order to make the most of the PineCube’s tiny CPU and 128 MB of RAM. Building with LLVM and clang also means that cross-compilation is trivial – CARCH=armv7h makepkg should successfully build it on an x86_64 Arch Linux machine.