{"id":16806145,"url":"https://github.com/pkgw/rc-stickynote","last_synced_at":"2025-03-17T07:49:52.842Z","repository":{"id":138164915,"uuid":"240535407","full_name":"pkgw/rc-stickynote","owner":"pkgw","description":"A project to add a radio-controlled sticky note to my office door using a Raspberry Pi and a Waveshare e-Paper Display.","archived":false,"fork":false,"pushed_at":"2022-06-22T15:44:53.000Z","size":203,"stargazers_count":0,"open_issues_count":9,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-23T17:19:23.701Z","etag":null,"topics":["raspberry-pi","rust","waveshare-eink"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pkgw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-14T15:10:34.000Z","updated_at":"2020-03-05T22:26:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"ecf6f8f8-8791-4b0a-b537-e0d3b3b57b4e","html_url":"https://github.com/pkgw/rc-stickynote","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkgw%2Frc-stickynote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkgw%2Frc-stickynote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkgw%2Frc-stickynote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkgw%2Frc-stickynote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pkgw","download_url":"https://codeload.github.com/pkgw/rc-stickynote/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243997041,"owners_count":20380980,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["raspberry-pi","rust","waveshare-eink"],"created_at":"2024-10-13T09:50:12.418Z","updated_at":"2025-03-17T07:49:52.822Z","avatar_url":"https://github.com/pkgw.png","language":"Rust","readme":"# Raspberry Pi Radio-Controlled Sticky Note\n\nThis repository contains the software component of a project to show custom\nmessages on a Raspberry Pi (RPi) hooked up to an e-Print display (EPD),\nintended to act as a radio-controlled (RC) sticky note on an office door.\n\nAn important aspect of this project is that it is a testbed for using the\n[blobman][blobman] framework to construct the necessary software in as\nreproducible a fashion as can be managed.\n\n[blobman]: https://github.com/pkgw/blobman/\n\n\n## Hardware\n\nThis project is currently executed on a\n[Raspberry Pi 4 Model B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/),\nwhich turns out to be way overpowered for this application.\n\nThe EPD is a 680×374 pixel, 7.5\", black-and-white display from\n[Waveshare](https://www.waveshare.com/product/displays/e-paper.htm) (SKU\n13187). This particular model, the \"V1\" seems not to be available anymore —\ninstead there are options with the same resolution but three colors, or still\nmonochrome but at higher resolution (the \"V2\").\n\n\n## Software\n\nThere are two software components: a “hub” that runs on a persistent server,\nand a “display client” that runs on the RPi. Both are written in\n[Rust](https://rust-lang.org/). The Pi needs to be able to SSH into the hub\nserver.\n\n\n## Step 1: Set up builder VM\n\nIn order for this project to work, we need to create a custom Raspberry Pi OS\nimage that will be flashed onto an SD card. Creating this image requires some\nlow-level custom Linux-y work, so we do the operations inside a Vagrant\nvirtual machine (“box”) for reproducibility.\n\nThe basis for the builder box is the 20200116.1 version of the\n`ubuntu/bionic64` Vagrant box. This can be initialized reproducibly with:\n\n```\nblobman provide bionic-server-cloudimg-amd64-vagrant.box\nvagrant box add --name ubuntu_bionic64_20200116.1 bionic-server-cloudimg-amd64-vagrant.box\n```\n\nRunning `vagrant up` will initialize and provision the builder box. **TODO**:\nthe provisioning uses Apt commands and therefore touches the network! The goal\nis to get blobman infrastructure such that we can provision the box even when\nrunning fully offline, but we're not there yet.\n\n\n## Step 2: Configuration\n\nVarious configuration files need to be set up in the directory `local/`.\n\n1. Create an SSH keypair that has no protective passphrase. This will be used\n   by the Pi to connect to the Hub. Run:\n   ```\n   ssh-keygen -t ed25519 -f local/stickynote_ed25519_key\n   ```\n2. Configure the client to talk to the hub. Copy\n   `local/client-config.example.toml` to `local/client-config.toml` and\n   customize as appropriate for your hub setup, as described in comments in\n   that file.\n3. Configure the Raspberry Pi OS image build. Copy\n   `local/pi-gen-config.example` to `local/pi-gen-config` and customize as\n   desired, as described in comments in that file.\n\n\n## Step 3: Building the Software\n\nBuilding the software requires a Rust toolchain and the Rust\n[cross](https://github.com/rust-embedded/cross) tool.\n\nTo build the hub, run:\n\n```\ncargo build --bin rc_stickynote_hub --release\n```\n\nIf your server runs an OS that's not fully compatible with your build machine\n(e.g., it runs an older version of glibc), you can cross-compile it if you'd\nlike:\n\n```\ncross build --target x86_64-unknown-linux-musl --release\n```\n\nTo cross-compile the display client for the RPi, run:\n\n```\ncross build --target armv7-unknown-linux-gnueabihf --release\n```\n\n\n## Step 4: Build the RPi OS image\n\nWe build the Raspberry Pi OS image using scripts derived from the\n[pi-gen][pi-gen] tool used for the official RPi images. The forked scripts\nlive in the `semi-pi-gen/` directory.\n\n[pi-gen]: https://github.com/RPi-Distro/pi-gen\n\nTo build the image, run:\n\n```\nvagrant ssh -c \"cd /vagrant/semi-pi-gen \u0026\u0026 sudo STAGE_LIST='stage0 stage1 stage2' ./build.sh\"\n```\n\nThis will output the image file in\n`semi-pi-gen/deploy/YYYY-MM-DD-rc-stickynote.img`, where the `YYYY-MM-DD`\ncorresponds to today’s date. This command does not automatically rebuild the\ncustom software, so make sure to recompile beforehand if needed. The\nfrom-scratch build process takes about 20 minutes on my machine.\n\nTo rebuild a new image with updated configuration or stickynote executables, you\ncan modify the `STAGE_LIST` in the above command to contain just `stage2`. Note,\nhowever, that this will reuse the existing filesystem tree, so operations should\nbe idempotent. To avoid this, add `CLEAN=1\nPREV_ROOTFS_DIR=/pigenwork/stage1/rootfs` to the `build.sh` environment, where\n`PREV_ROOTFS_DIR` specifies the `rootfs` directory of the previous stage (e.g.,\n`stage1` if you're just rerunning `stage2`).\n\nTo write the image to an SD card, first insert the card into your machine. If it\nalready contained an OS image, your computer might mount the partitions, which\nwe definitely don't want! Ummount anything like `/run/$USER/media/boot` or\n`/run/$USER/media/rootfs` that appears.\n\nOnce that's done, the obvious GUI method didn't work for me and I don't feel\nlike futzing around with this too much, so here's the command-line method to\nflash the disk. **Make sure you specify the right device otherwise you might\nmake your machine unbootable**, etc., because we're writing data straight to a\nblock device node!\n\n```\nsudo dd bs=4M if=semi-pi-gen/deploy/*-rc-stickynote.img of=/dev/mmcblk0 conv=fsync\n```\n\nIf the `dd` seems to exit instantly in a suspicious fashion, you may have a\nstale `/dev/mmcblk0` device. Try removing the SD card, deleting that device\nnode, and re-inserting.\n\n\n## Testing: Simulator Client\n\nTo run a “simulator” version of the client that uses\n[SDL](https://www.libsdl.org/) to draw graphics to a window rather than the\nEPD, run:\n\n```\ncd displayer \u0026\u0026 cargo run --no-default-features --features=simulator -- client\n```\n\nThis program will require a client configuration file, which should be placed\nin `~/.config/rc-stickynote-client/rc-stickynote-client.toml`. This is the\nsame file format as used in `local/client-config.toml`.\n\n\n## Testing: Checking the RPi OS image\n\nTo mount the RPi OS image on your (Linux) machine and poke around its\nfilesystem, you can mount it with a loopback device. The only tricky part is\nthat the image file is a partitioned disk image, not just a single filesystem\npartition, so you need to be able to tell the mount program the right offset\ninto the disk image to find the filesystem.\n\nThe `pi-gen` build process outputs this information while creating the image. It\nwill emit some output that looks like this:\n\n```\n[19:26:46] Begin /vagrant/semi-pi-gen/export-image/prerun.sh\n/boot: offset 4194304, length 268435456\n/:     offset 272629760, length 1635778560\n```\n\nIn the above, the number 272629760 is the offset we want to know.\n\nAlternatively, you can use `fdisk`. If you run `fdisk -lu /path/to/stickynote.img`, the\noutput will look something like:\n\n```\nDisk stickynote.img: 1.8 GiB, 1908408320 bytes, 3727360 sectors\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: dos\nDisk identifier: 0x8319fb68\n\nDevice          Boot  Start     End Sectors  Size Id Type\nstickynote.img1        8192  532479  524288  256M  c W95 FAT32 (LBA)\nstickynote.img2      532480 3727359 3194880  1.5G 83 Linux\n```\n\nIn this example, the blocksize is the 512 in the `Units:` line, and the offset\nin blocks is the \"start\" value, 532480, in the final output line. The offset\nin bytes is the product of these two numbers, `512 * 532480 = 272629760`.\n\nOnce you have the offset, mounting the image is as simple as:\n\n```\nsudo mount -o loop,offset=$OFFSET /path/to/stickynote.img /tmp/img\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkgw%2Frc-stickynote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpkgw%2Frc-stickynote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkgw%2Frc-stickynote/lists"}