UPDATE: resin was renamed to balena. Almost all parts of this article were updated to match the new name.

I’ve decided to build a thermometer from scratch. I know, I can buy it, but it’s not fun. I found it as a perfect occasion to please my wife (she wants it) and to try new things. What new things? Mainly balena.io and balenaOS.

Goals

Here’re the main goals:

  • Measure temperature (two rooms & outside)
  • Forecast for a day (if I find a service, which offers it for free via some nice API)
  • Check if terrace doors are open / closed
  • Show all available info on some nice coloured display
  • Write it in the Rust programming language
  • Test balena.io (even with one device)

For today, we will just setup the toolchain, deployment, local development and some Rust application prototype.

Components

I’ve decided to go with following components:

Assembly

It’s easy, don’t worry. Just follow instructions in the A Raspberry Pi Thermometer you can Access Anywhere article. And if you’d like to have more than one thermometer, check the Multiple DS18B20 temperature sensors forum post.

Assembled Pi, DS18B20

balena.io and balenaOS installation

Create balena.io account and go to applications dashboard where you can create a new one. Application name is also used as a Git repository name. My application name is rust-thermometer.

Create application dialog

Select application, click on the Add device button and:

  • select your device type,
  • switch edition to Development,
  • setup networking and
  • download resinOS image.

Add device dialog

You can use Etcher (or any other tool, this one has 81MB, Electron, yay) to flash downloaded resinOS image to your SD card. Insert SD card into your Raspberry Pi device and turn it on. Wait for a couple of minutes until your device appears.

Flashed device online & listed

Works like a charm, balenaOS installed and device is up and running.

Photo of booted device with logo

Balena CLI installation

CLI stands for Command Line Interface. Follow installation instructions. Unfortunately, these instructions didn’t work for me and I had to download latest release, unzip it and install manually. Probably some npm, nvm, node, brew and macOS mess. Will investigate and report issue later.

Find your device

balenaOS is installed, device is running, visible in our balena.io application. Let’s check if we can find it with sudo balena local scan command.

Photo of booted device with logo

It’s here. Host name cae15d3.local with IP address 10.11.12.133.

1-Wire configuration

In order to make DS18B20 thermometer working, we have to add dtoverlay=w1-gpio line to /boot/config.txt (documentation). It’s not possible now (boot partition mounted as read-only). Actually, it’s possible, you can remove SD card, mount it on your computer, etc. But resin.io provides better way named Advanced boot settings. To make it short, open your fleet configuration and add RESIN_HOST_CONFIG_dtoverlay variable with w1-gpio value. Device will be automatically rebooted with new boot configuration in a few seconds.

Rust project

Found just one example resin-rust-hello-world. I took it, modified it little bit and introduced rust-thermometer. How it differs from standard Rust project? Not much, just two additional files.

resin-sync.yml it’s for local push where we just define device target architecture, build it and move the resulting binary to a common location.

Dockerfile.template template for Dockerfile where we can use variables like %%RESIN_MACHINE_NAME%%. These variables are automatically replaced when we deploy application to a device fleet.

Rest is Tim’s temperature-serve-pi rewritten to the Rust programming language.

Local development

Dockerfile.template is not supported in local push command. Create Dockerfile (copy & paste) and replace %%RESIN_MACHINE_NAME%% with raspberrypi3. List of supported devices. Then you can run sudo balena local push cae15d3.local -s . -force-build command to run your application on the device.

Printed temperatures

Or use local-push.sh script which does all these things for you.

Why -force-build? Old version was always pushed without it even if I modified Rust source code.

Fleet deployment

Every application has associated Git origin within resin.io. Mine is gh_zrzka@git.balena.io:gh_zrzka/rust-thermometer.git. Add balena origin as a first step:

git remote add resin gh_zrzka@git.balena.io:gh_zrzka/rust-thermometer.git

You have to do it just once. If you’d like to deploy application to your fleet, just push master branch to the balena origin:

git push balena master

Wait for a while and …

Pushed application

… that’s it. Open application and wait for deployment (couple of minutes). Open your device and you should see temperatures in the logs.

Logs in dashboard

Troubleshooting

I wasn’t able to deploy rust-thermometer for the first time. And that was because rustup doesn’t understand armv8l (Raspberry Pi 3 B+). Fixed it with this workaround. Not nice, but I’m happy with it now, because I have just one device for this project.

Conclusion

I like it. There’re still some bugs, but generally, it’s a very nice service and I’ll keep testing it.

Part 1 goal was achieved:

  • setup toolchain,
  • setup deployment,
  • setup local development and
  • simple temperature reader with hardcoded devices, … (released as v0.0.1, to track progress).

Next part will be about Raspberry Pi display and some Rust graphics library (didn’t choose one yet). Wish me luck, because I do not expect that it will be an easy ride like this initial setup.