Modernizing my app made it far easier to spy on my American Shorthair
My cat Tucker is a somewhat predictable animal who likes to curl up in predictable spots around the house, so he’s the perfect subject for surreptitious video surveillance and just the sort of motivating force I needed to rework a Raspberry Pi project I’d been putting off for some time.
I’d previously set up video surveillance on an Ubuntu desktop using an old USB camera and the motion-detecting app
motion to successfully catch an office prankster in the act of stealing my chair. It seemed perfect for a DIY Raspberry Pi 3 cat cam. I ported the whole thing to Raspbian and it became TuckerCam 1.0.
The rig worked pretty well, but every time I needed to change the configurations, I had to break out a spare keyboard, monitor and mouse to interact with the Raspberry Pi and Raspbian, now known as Raspberry Pi OS. When it all stopped working one day, I didn’t bother to fix it, so TuckerCam 1.0 went dark.
Time for a better approach
When my step-daughter brought home a Raspberry Pi Zero W from a STEM camp and “gifted” it to me, I decided to try again. This time, though, I wanted to overcome the hassles I encountered the first time around.
Specifically, I wanted a solution that gave me:
I was learning more about Docker, so containerizing TuckerCam 2.0 was important to help me eliminate as much overhead as possible, give the app a smaller footprint, and make it easier to replicate and deploy. This turned out to be a game-changer, and though Tucker didn’t know it, he’d inspired me to take a giant leap forward in my app development.
motion on Debian
My previous Raspberry Pi OS deployment mostly worked, but it was clunky, so this time I started by creating a Docker version based on Debian Stretch.
Motion can be installed with a simple
apt install motion so turning it into a single-container service wasn’t complicated.
The harder part was figuring out a way to dynamically set variables in the
motion.conf configuration file that suited my needs and worked with my old USB camera.
Motion has a wide variety of configuration settings, including variables that set the streaming port, the height and width of the video stream, whether to output still images, the palette to use, the frame rate, and so on.
In TuckerCam 1.0, I hard-coded these settings into the config file. This time, I wanted to store the variables as part of the container application and make them easier to edit on the fly rather than in a fixed, one-off
motion.conf file. That way I could more dynamically adjust them for different cameras and make it easier for other developers to make their own modifications.
I decided to set these values using environment variables, which turned out to be a three-step process. I had to replace the default
motion values in
/etc/motion/motion-dist.conf with shell variables, store the variable key/value pairs in a Docker
.env file, and use
envsubst in the running container to substitute the shell variable placeholders with the proper values.
Modifying the default
motion-dist.conf configuration file is a bit of an eye strain (made harder when Tucker pawed my keyboard), but it was otherwise straightforward. For example, here are three of the 14 values I replaced with shell variables:
I saved this updated file as
motion-template.conf and created a
motion.env file to hold the key/value pairs to match the shell variables:
In order to use these values in my container, they needed to be applied on the running device. I created a
start.sh bash script to run
envsubst (to do the environment variable substitution) and to start
motion with my updated configuration file. I’d previously used
sed to do variable swapping, but found
envsubst to be much simpler. It ingests my
motion-template.conf file and outputs an updated
Finalizing the Docker build
With these three files complete, I created a simple
docker-compose.yml to build my containerized application. In its most basic form, it looked like this:
I used a single directory for my build context, so I created my
Dockerfile there and added basic content to install
gettext-base, which provides
envsubst. I also used the environment variable
EXPOSE_PORT in the Dockerfile so the
motion video stream would be available externally.
With everything set, I plugged my USB camera into my workstation and ran
docker-compose up -d. The Docker build process worked flawlessly, and when I visited http://
Porting it all to my Raspberry Pi Zero with balena
With my code in good shape, I pushed it to a new GitHub repository and contemplated how best to get it running on my Raspberry Pi. Running TuckerCam 2.0 in a container on my workstation was one thing. Getting it to run on a tiny ARM-based device was quite another.
Nowadays, Docker can run on Raspberry Pi OS but, again, I wanted to avoid the manual device set-up and the overhead. I really wanted headless provisioning and management, so I used balena, which runs a Docker environment out of the box in its base balenaOS and provides a dashboard for managing everything. It’s free for the first 10 devices, plenty for scattering TuckerCams around my house.
Balena-ifying my containerized application
The original Dockerfile I used on my x86_64 workstation required a small change to the image source command in order to work properly on the Raspberry Pi Zero ARM processor, namely changing:
That worked fine if all I wanted was to run TuckerCam 2.0 on Raspberry Pi Zeros, but I preferred a more universal approach that would work with any device type I might use. To do that, I used the balenalib image repository, which offers Debian container images for multiple platforms. I changed the name of my
Dockerfile to Dockerfile.template and replaced the
FROM line with a wildcard alternative:
With this line, each device type is automatically detected and the proper image for its architecture is used. For the Raspberry Pi Zero, this automatically translates to
balenalib/raspberry-pi-debian:stretch. When I later used a Raspberry Pi 3, this automatically became
balenalib/raspberrypi3-debian:stretch. Now, I never have to edit my
Dockerfile.template or create multiple versions for different device types.
Setting environment variables
In my workstation test, I had placed all my
motion settings in a
motion.env file, which automated the process of setting the values I wanted in
motion.conf. This worked well, but the values only applied during the build process. If I made a change to some variable in
motion.env, I had to rebuild and redeploy my container.
That’s not a huge deal-breaker, but balena offers a way to apply build variables and save all the key/value pairs in the balenaCloud application itself. That lets me edit settings from the balenaCloud dashboard and apply the same variables to each new TuckerCam 2.0 device I add to my balenaCloud application. I can also override the values on a device-by-device basis without having to redeploy.
To take advantage of this capability, I created a
balena.yml file that set environment variables in much the same way as my
To use this file, I placed it in the root of my TuckerCam GitHub repo so it loads and sets all my variables using Deploy with balena without me (or users of my repo) having to retype them. Whenever I want to make a variable change, I can do it in the balenaCloud dashboard, where my changes are automatically detected and my container is restarted with the updated values.
This capability was especially useful when I was trying to tweak the video device and palette settings to get
motion to run correctly with my older USB camera.
Armed with my new
balena.yml, I removed the redundant
env_file lines from
docker-compose.yml and deleted my
One more tweak to my original Dockerfile enabled me to shrink the size of the container image, which was important given my Raspberry Pi Zero’s limited power and relatively slow WiFi.
In my original Dockerfile, I used
apt to install
gettext-base, but balena has a built-in package installer script, install_packages, which installs what I need and cleans up afterward. Using
install_packages instead of
apt reduced the size of my container by 52 MB, or about 18 percent, to just 233 MB total.
So, in my
RUN apt update && apt install -y gettext-base motion
RUN install_packages gettext-base motion
Everything else in my
start.sh stayed the same. I updated my GitHub repo with my code changes and turned to deploying my app.
Multiple ways to push code
When running Docker locally, building and deploying my
motion container was a simple matter of using the CLI to run
docker-compose up -d. Deploying to balenaCloud can also be done from the command line (after installing balenaCLI) or I could skip the CLI and just use the browser-based option with Deploy with balena.
To do that, I could either create a new balenaCloud application from scratch and manually enter my GitHub repo URL and environment variables, or I could use
Deploy with balena to wrap everything into a single step that doesn’t require manual data entry or anything to be installed on my workstation.
I took the
Deploy with balena route because it eliminated the need for me to install any image-build capability on my workstation. Instead, my images are built in the balena cloud straight from my GitHub repo code and pushed directly to my Raspberry Pi Zero or other devices.
Balena has an API endpoint to make this work, so I could either point my browser to https://dashboard.balena-cloud.com/deploy?repoUrl=https://github.com/balenalabs-incubator/balena-motion to deploy my application or add a single line of text to my GitHub repo README.md file, which wraps that link around an image “button” and makes it easy to deploy (or redeploy) directly from GitHub:
The URL to the repo isn’t necessary in the README.md because the balena endpoint automatically uses the referrer address. So, in my GitHub repo, that simple line added the
Deploy with balena button, which looks like this:
Provisioning the device
One of my key TuckerCam 2.0 goals was to avoid having to connect a keyboard and monitor to initially configure my device, so I didn’t want to burn Raspberry Pi OS to the SD card I planned to use. With balena, I could instead use a device- and application-specific base OS image.
While my container release was being built on balena’s cloud servers, I returned to the balenaCloud dashboard, clicked on my new application, and clicked the Add Device button to define and download the appropriate image for my Raspberry Pi Zero. I added my WiFi credentials, saved the .zip file to my workstation and flashed it to an SD card with balenaEtcher. This custom image was just 139 MB compared with 432 MB for Raspberry Pi OS Lite, the smallest image currently available.
Since I was able to set the WiFi credentials in the base OS image itself, I didn’t have to do anything to get the Raspberry Pi Zero online. A few minutes after I inserted the SD card and powered it up, it automatically joined my wireless network and started to download the balena OS and my container image. The device showed up in my balenaCloud dashboard, where I could see its IP address, and access the HostOS or container shell from the built-in terminal:
TuckerCam 2.0 on the Raspberry Pi Zero was up and running, and I never had to attach any peripherals to the device to provision it. In fact I didn’t have to manually log in to the Raspberry Pi or use the command line on my workstation for anything.
To test my dynamic configuration set-up, I toyed with the width and height of the image/stream and changed the
EXPOSE_PORT value to access the TuckerCam from port 8088 instead of 8081. I did this in the Environment Variables settings in the balenaCloud dashboard. My configurations applied without trouble, and the container restarted automatically with the new port setting.
I can now quickly change or redeploy TuckerCam 2.0 any time I want. I tried that by flashing another SD card with the same custom image I used before, inserting it into another Raspberry Pi Zero and powering on. Within a few minutes, the second device joined my balenaCloud application, downloaded my
motion container image, applied all the proper environment variables, and gave me two views of Tucker:
I was pleased with how it turned out and, though Tucker was none the wiser, he’d helped me accomplish my goals for TuckerCam 2.0, namely:
Working with a Raspberry Pi Zero can be especially frustrating because it’s not nearly as snappy as an RPi 3 or 4. It can take a while to reboot, download code and get started, so part of this exercise was my desire to make everything as small as possible.
In my earlier workstation test, I was a little concerned about the size of my
motion container, which stood at about 475 MB. That seemed rather large, but making a couple basic tweaks (and porting it to ARM) helped shrink the image to 233 MB, or about half the size of the original.
To shrink it even more, I created a version with Alpine that ended up at just 75 MB! Unfortunately, the Alpine folks changed their repos recently and installing the
motion package (without building from source) no longer works. Bummer.
Whether you have a cat to motivate you or not, I hope my experience with transforming my TuckerCam from a desktop app to an IoT-ready containerized version inspires you to try it with your own applications. The ability to configure my Raspberry Pi without cables or peripherals, more easily modify the application and configuration settings through the balenaCloud dashboard and GitHub workflows, easily scale it all to multiple devices, and more readily share it with
Deploy with balena made a world of difference.
Do you have an interesting project you’ve converted for use on balena? Let us know about it and share your experiences in the balenaForums!
Google Nest Hub Max Smart Home Assistant (Chalk, Refurbished, Plain Box) – EXPANSYS Japan
Best Amazon Prime Day Arlo, Nest, Ring, Blink & Smart Home Deals 2020: Top Security Camera, Video Doorbell, Floodlight, Alarm & Philips Hue Sales Presented by Deal Tomato
Prime Day smart home & security camera deals for 2020 are finally here, browse all the latest Prime Day Ring Video Doorbell, Nest Protect & Thermostat, Philips Hue smart LED bulb, Arlo Pro & Blink Mini sales listed belowPrime Day home secur…
Which Smart Home Heating Should You Choose?
Not all smart heating control systems are suited for every lifestyle and home, with some more and less beneficial than others. SMART stands for ‘Self-Monitoring Analysis & Reporting Technology’, and differs from standard heating controls by allowing you to control every aspect of your heating schedule from either a phone or tablet. Although room thermostats and timers allow you to control each room instead of your whole home, as long as you have internet access, smart home heating devices let you control your heating from your phone, no matter where you are in the world.
Today, we’re running through 7 of the best smart heating thermostats and systems, comparing features, benefits and what type of home they’re most suitable for.
– 7 day, & 5/2 day scheduling with a pre-configured schedule included
– Choice of up to 4 time periods a day
– Minimum On-Time & Cycle Rate settings ensuring compatibility with many boilers
– Table stand for ease of positioning
– Alert messages to assist fault-finding with a fail-safe mode
– Wireless technology makes upgrading easier and the installation time shorter with less wiring involved
– Homes that require high levels of automatic control that provide significant energy efficiency for a wide range of boilers and systems.
– Single Heating Zone Control
– 7 Day, 5/2 Day, or 24 Hour Control
– Programmable Room Thermostat
– Easily Programmed With The Associated App
– Homes that are just starting to take the first steps into using smart home heating
– Homes that need a single heating zone control
– Homes that have either combination or standard boiler systems
– Touch-screen interface simplifies scheduling, changing and overriding temperature
– Location-based programming (geo-fencing) adds an automated layer of control, adjusting the customer’s home heating based on their location
– Scheduling features include 7 and 5/2 day bespoke scheduling with up to 6 time periods a day
– Simple flip-up wiring bar for easy access and an easy-to-install boiler or zone valve interface
– Direct wall mounting or wall-box mounting
– Optimisation features include optimum start and stop & delayed start boiler control. Allows the thermostat and boiler to work more efficiently together
– Homes with any boiler and almost every heating system
– Homes with 230V on/off OpenTherm appliances (gas boilers, combi boilers and heat pumps)
– Ability to control water temperature and heating
– Self-learning functions to make every experience a unique one, helping it to understand your home’s needs
– Using a smart weather compensation feature and weather data, the vSMART can tell your boiler how hard it has to work to get your home to your required temperature
– You can connect multiple vSMART controllers to one app
– Homes with Valliant ecoTEC system/open vented boilers
– Households that want to be able to control water temperature from anywhere too
– A 7-day full programmer that gives great flexibility offering up to three on/off switchings per day
– LoT display, providing text feedback that gives help and programming hints
– Automatic Summer/Winter 1 hour time change
– Choice of 3 different built-in programmes
– ‘Holiday’ button
– Homes with heating and stored hot water in complete systems
– Homes with older gravity circulation stored hot water systems, where there’s no interlocking control valve
– Households with different heating needs from day-to-day
– One channel thermostat system with two radiator thermostats to start zoning your system
– Smart heating & hot water control
– Quick & simple to install using an industry-standard backplate
– Easy Zoning with the addition of extra Wiser Radiator Thermostats
– Homes with combination boilers
– Households that want to start a zoned system to control individual zones within the home
– Automatic time and temperature control of domestic heating premises
– Optimum Start, Optimum Stop and Delayed Start
– No installer links or switches on the back of the unit means no adjustment is required for combi boilers and most central heating systems
– Scheduled maintenance alert
– Automatic Summer/Winter time change
– Up to four independent time & temperature settings
– Auto, manual, holiday, override and off (frost) modes
– Domestic premises
– Most central heating systems and combi boilers
For more smart home heating controls, check out our full range today at MonsterPlumb. If you’re not interested in smart technology when it comes to controlling the heating and water temperature in your home, take a look at our selection of heating controls and valves.
IoT3 months ago
Smart Home Tech: What are the best smart thermostat options?
Home Security2 months ago
Getting Past Cybersecurity In IoT Devices And Exploring Their Performance | The Cyber Security Place
IoT2 months ago
Building Solar Energy Monitoring Systems Using IoT – floLIVE
Smart Gadgets2 months ago
VW explains how the ID.4 electric SUV gets smart about coasting
IoT2 months ago
Enerman’s Vision Is To “Provide Innovative Solutions To Save Energy And Reduce Carbon Footprint, Digitize Every PV Plant And Make It IOT Ready” In The Solar Renewable Space.
Home Security2 months ago
Boundary Launch DIY Z-Wave Smart Home Security System – Automated Home
Smart Gadgets2 months ago
China’s Tesla rival Xpeng sets sights on Europe as it delivers first batch of smart electric cars to Norway | South China Morning Post
IoT2 months ago
Purina to take guesswork out of pet nutrition with IoT ‘smart bowl’ – Smart City