diff --git a/CLAUDE.md b/CLAUDE.md index 7bc3b90..7b5b533 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,18 +4,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What this repository is -Firmware for the UiMetrix shop-floor RFID tag-reader stations: an M5Stack CoreS3 with an RFID Unit and an RGB light bar, running MicroPython on the UIFlow 2.0 firmware (`M5`, `m5ui`, `unit`, `hardware`, `umqtt.simple`, `esp32.NVS` APIs). The whole program is the single file `M5-Stack Code for Uimetrix.txt`; on the device it is `/flash/main.py` (the `.txt` extension is just how it was exported; CRLF line endings). +Firmware for the UiMetrix shop-floor RFID tag-reader stations: an M5Stack CoreS3 with an RFID Unit and an RGB light bar, running MicroPython on the UIFlow 2.0 firmware (`M5`, `m5ui`, `unit`, `hardware`, `umqtt.simple`, `esp32.NVS` APIs). The whole program is the single file `main.py`, served to the devices exactly as committed (the repo stores LF; the Windows checkout shows CRLF through `core.autocrlf`). It was `M5-Stack Code for Uimetrix.txt` until 2026-09-15; `git log --follow main.py` crosses the rename. -The repository is hosted on the company Gitea at `https://git.utopiadeals.com/UIND/UiMetrix-M5-Firmware` (branch `main`); pushing there does not reach any device, since devices pull from the GitHub repo described under "Releasing to devices". There is no PC-side toolchain: nothing to build, lint or run here, and there are no tests. Changes can only be verified on a device; debug output is `print()` over the USB serial port. +The repository is hosted on the company Gitea at `https://git.utopiadeals.com/UIND/UiMetrix-M5-Firmware` (branch `main`), and **that is what the devices update from** (see "Releasing to devices"): a push to `main` that also bumps `version.txt` goes live on every box at its next boot, so keep unfinished work off `main` or leave `version.txt` alone until it is ready. There is no PC-side toolchain: nothing to build, lint or run here, and there are no tests. Changes can only be verified on a device; debug output is `print()` over the USB serial port. The server that talks to this device is the UiMetrix ASP.NET Core app in `D:\Projects\UiMetrix` (`Services/MqttService.cs`; its own `CLAUDE.md` documents the server side). `D:\Projects\MqttWorkerService` is an older standalone worker that speaks the same protocol, and its `tools/rfid_enrol.py` numbers cards from this device's MQTT messages. ## Releasing to devices (OTA) -Devices update themselves at boot from the GitHub repo `husbananjum/m5core-s3-UIMETRIX-Z87` (`main` branch): `check_for_update()` fetches `version.txt`, compares it as a float against the `fw_version` string in NVS namespace `storage` (default `"1.0"`), and if newer downloads that repo's `main.py` and hands it to `install_update()`. The download must be HTTP 200, at least 1000 bytes, contain `def setup` and `def loop`, and compile; otherwise it is rejected. Installation writes it to `/flash/main_ota_temp.py`, renames the running program to `/flash/main_prev.py` (a rollback copy for manual recovery over USB), renames the download to `/flash/main.py`, and only then stores the new version in NVS and resets. A rejected download or a failed swap leaves the old program and the old version in place, so the next boot retries. A release is therefore: push the new `main.py` and bump `version.txt`. Things to keep in mind: +Devices update themselves at boot from this repo's `main` branch on Gitea, over its anonymous raw-file URLs (`.../raw/branch/main/version.txt` and `.../raw/branch/main/main.py`; the host resolves to a public address, so any box with internet reaches it). `check_for_update()` fetches `version.txt`, compares it as a float against the `fw_version` string in NVS namespace `storage` (default `"1.0"`), and if newer downloads `main.py` and hands it to `install_update()`. The download must be HTTP 200, at least 1000 bytes, contain `def setup` and `def loop`, and compile; otherwise it is rejected. Installation writes it to `/flash/main_ota_temp.py`, renames the running program to `/flash/main_prev.py` (a rollback copy for manual recovery over USB), renames the download to `/flash/main.py`, and only then stores the new version in NVS and resets. A rejected download or a failed swap leaves the old program and the old version in place, so the next boot retries. A release is therefore: push the new `main.py` and bump `version.txt`. Things to keep in mind: - Versions compare as floats, so `1.10` is older than `1.9`. - Builds before 2026-09-11 downloaded the file but never installed it, while still stamping the new version into NVS. Devices running such a build never pick up an OTA release: they need one manual USB copy of the fixed `main.py` first, and because their NVS may already claim a version they never ran, the next `version.txt` must be higher than any number published so far. +- Until 2026-09-15 the update location was the personal GitHub repo `husbananjum/m5core-s3-UIMETRIX-Z87`, which now returns 404 for both files, so every box on that build has been failing its boot-time check (harmlessly) since. Those boxes, and any box running a build without OTA code at all (the ones with the broker at `192.168.2.174` hardcoded and no `V…` label on screen), need one manual USB copy of the current `main.py` to start following Gitea. `version.txt` was reset to `2.0` at the move; nobody knows the highest number ever published on GitHub, so if a box shows a higher `V…` on its screen, bump `version.txt` above it. +- A box freshly copied over USB still carries its old NVS version (or the default `1.0`), so on its first boot it downloads and installs the identical `main.py` from Gitea once and resets; that is expected, not a loop. ## How the program works diff --git a/M5-Stack Code for Uimetrix.txt b/main.py similarity index 98% rename from M5-Stack Code for Uimetrix.txt rename to main.py index 26809ca..c00012f 100644 --- a/M5-Stack Code for Uimetrix.txt +++ b/main.py @@ -149,15 +149,16 @@ def check_for_update(): print("Update check failed:", e) -UPDATE_VERSION_URL = "https://raw.githubusercontent.com/husbananjum/m5core-s3-UIMETRIX-Z87/refs/heads/main/version.txt" -UPDATE_FILE_URL = "https://raw.githubusercontent.com/husbananjum/m5core-s3-UIMETRIX-Z87/refs/heads/main/main.py" +UPDATE_VERSION_URL = "https://git.utopiadeals.com/UIND/UiMetrix-M5-Firmware/raw/branch/main/version.txt" +UPDATE_FILE_URL = "https://git.utopiadeals.com/UIND/UiMetrix-M5-Firmware/raw/branch/main/main.py" OTA_MAIN_PATH = "/flash/main.py" # the program the device runs at boot OTA_TEMP_PATH = "/flash/main_ota_temp.py" # a download lands here first OTA_BACKUP_PATH = "/flash/main_prev.py" # the previous program, kept for manual rollback MQTT_CLIENT_ID = serial -MQTT_BROKER = '192.168.87.11' +MQTT_BROKER = '192.168.2.174' +#MQTT_BROKER = '192.168.87.11' #MQTT_BROKER = 'scada.utopia.pk' MQTT_PORT = 1883 MQTT_USER = 'utopia' diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..cd5ac03 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +2.0