From 65c64411ae87fe1656d0943ecde48188e69f2ba4 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 24 May 2026 08:35:22 +0200 Subject: [PATCH] =?UTF-8?q?fix(led-heartbeat):=20v2.1.1=20=E2=80=94=20cap?= =?UTF-8?q?=20brightness=20at=2010=20to=20keep=20IS31FL319X=20i2c=20bus=20?= =?UTF-8?q?responsive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IS31FL319X chip on the MOCHAbin's i2c-1 bus errors out with -EIO above brightness ~50. Pushing 100 or 255 saturates the bus, the chip starts NACK'ing the next register writes, the LED driver logs 'Setting an LED's brightness failed (-5)' on every retry, and the LEDs freeze at whatever value last got through. Observed live 2026-05-24 on gk2: all three RGBs stuck plain green at 218/255/255 with the bash bumper and the python heartbeat both pushing high values into a saturated chip. After dropping to brightness 10 and adding a 30 ms i2c-write delay in the python set_rgb() loop, writes succeed and the LEDs reflect the actual health state instead of a static color. Files: - usr/sbin/secubox-led BRIGHTNESS 100 -> 10 - usr/sbin/secubox-healthbump ACTIVE 100 -> 30, SLEEP 20 -> 5 - usr/sbin/secubox-led-pulse BRIGHTNESS 100 -> 10 - usr/sbin/secubox-led-heartbeat python set_rgb scales any 0-255 caller down to 0-10 in write_text, then sleeps 30 ms before the next channel — matches the bash scripts' I2C_DELAY and lets the mv64xxx_i2c controller drain between calls. - scripts/secubox-healthbump (the duplicate script kept in repo root for ad-hoc dev use) gets the same BRIGHTNESS=10 cap. The misleading 'BRIGHTNESS=100 works reliably' comment that the code contradicted is replaced with an incident note pointing at the EIO ceiling. --- .../secubox-led-heartbeat/debian/changelog | 20 +++++++++++++++++++ .../usr/sbin/secubox-healthbump | 9 ++++++--- .../usr/sbin/secubox-led | 11 +++++++--- .../usr/sbin/secubox-led-heartbeat | 15 ++++++++++++-- .../usr/sbin/secubox-led-pulse | 4 +++- scripts/secubox-healthbump | 5 +++-- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/packages/secubox-led-heartbeat/debian/changelog b/packages/secubox-led-heartbeat/debian/changelog index 33d8f48a..24db5a9e 100644 --- a/packages/secubox-led-heartbeat/debian/changelog +++ b/packages/secubox-led-heartbeat/debian/changelog @@ -1,3 +1,23 @@ +secubox-led-heartbeat (2.1.1-1~bookworm1) bookworm; urgency=medium + + * Cap LED brightness at 10 (was 100) to keep the IS31FL319X chip on + the MOCHAbin's i2c-1 bus responsive. Pushing 100 or 255 saturates + the bus, the chip starts NACK'ing register writes with -EIO, and + the LEDs freeze at whatever value last got through — observed live + 2026-05-24 with all three RGBs stuck plain green at 218/255/255. + Affected files: + - usr/sbin/secubox-led (BRIGHTNESS 100 -> 10) + - usr/sbin/secubox-healthbump (ACTIVE 100 -> 30, SLEEP 20 -> 5) + - usr/sbin/secubox-led-pulse (BRIGHTNESS 100 -> 10) + - usr/sbin/secubox-led-heartbeat (python set_rgb now scales 0-255 + callers down to 0-10 in write_text, and inserts a 30 ms sleep + between channels to give the i2c controller time to drain). + The misleading "BRIGHTNESS=100 works reliably" comment that the + code contradicted is replaced with an incident note pointing at + the EIO ceiling. + + -- Gerald Kerma Sun, 24 May 2026 08:35:00 +0200 + secubox-led-heartbeat (2.1.0-1~bookworm1) bookworm; urgency=medium * NEW: Activity-based brightness (ACTIVE=100, SLEEP=20) diff --git a/packages/secubox-led-heartbeat/usr/sbin/secubox-healthbump b/packages/secubox-led-heartbeat/usr/sbin/secubox-healthbump index cbf37e74..bce60ec1 100644 --- a/packages/secubox-led-heartbeat/usr/sbin/secubox-healthbump +++ b/packages/secubox-led-heartbeat/usr/sbin/secubox-healthbump @@ -25,9 +25,12 @@ RATE_FILE="/tmp/secubox-ban-rate" STATUS_FILE="/tmp/secubox/led-status" STATE_FILE="/tmp/secubox/prev-state" -# Brightness levels -BRIGHTNESS_ACTIVE=100 -BRIGHTNESS_SLEEP=20 +# Brightness levels. Capped at 30 active / 5 sleep — IS31FL319X on the +# MOCHAbin's i2c-1 bus errors with EIO above ~50 (the bus is shared with +# other probes that NAK on absent addresses). See secubox-led for the +# 2026-05-24 incident notes. +BRIGHTNESS_ACTIVE=30 +BRIGHTNESS_SLEEP=5 BRIGHTNESS=$BRIGHTNESS_SLEEP # Activity detection diff --git a/packages/secubox-led-heartbeat/usr/sbin/secubox-led b/packages/secubox-led-heartbeat/usr/sbin/secubox-led index 36ad83f2..cb36e8bc 100644 --- a/packages/secubox-led-heartbeat/usr/sbin/secubox-led +++ b/packages/secubox-led-heartbeat/usr/sbin/secubox-led @@ -10,12 +10,17 @@ # Layers: hw|1|bottom, svc|2|middle, sec|3|top # Status: ok|green, warn|yellow, error|red, msg|blue, off # -# Brightness value 10 is optimal for IS31FL3199 on Debian (255 causes I2C errors) +# IS31FL319X on the MOCHAbin's i2c-1 bus errors with EIO above brightness +# ~50 — pushing 100 or 255 saturates the bus, the next write fails with +# `Setting an LED's brightness failed (-5)`, and the LEDs freeze at +# whatever value last got through. Observed live 2026-05-24: green +# channels at 218/255/255, blue/red writes returning EIO, all three +# LEDs stuck plain green. Capping at 10 keeps writes reliable while +# still being clearly visible on the front panel. set -euo pipefail -# Brightness 100 works reliably with proper I2C delays -readonly BRIGHTNESS=100 +readonly BRIGHTNESS=10 readonly I2C_DELAY=0.03 led_path() { echo "/sys/class/leds/$1:led$2/brightness"; } diff --git a/packages/secubox-led-heartbeat/usr/sbin/secubox-led-heartbeat b/packages/secubox-led-heartbeat/usr/sbin/secubox-led-heartbeat index 0110a551..f377986e 100755 --- a/packages/secubox-led-heartbeat/usr/sbin/secubox-led-heartbeat +++ b/packages/secubox-led-heartbeat/usr/sbin/secubox-led-heartbeat @@ -89,7 +89,11 @@ class LEDController: log.warning("No IS31FL3199 LEDs found - running in simulation mode") def set_rgb(self, led_num: int, r: int, g: int, b: int): - """Set RGB values for a LED (0-255 each).""" + """Set RGB values for a LED. Callers pass 0-255 per the COLORS + palette; we scale down to the IS31FL319X EIO-safe ceiling + (~10) before writing. Above ~50 the chip on the MOCHAbin's + i2c-1 bus errors out with -EIO and the LEDs freeze at their + last successful value (incident 2026-05-24).""" if not 1 <= led_num <= LED_COUNT: return @@ -99,8 +103,15 @@ class LEDController: for color, value in values.items(): path = self.led_paths[led_num].get(color) if path and path.exists(): + scaled = max(0, min(10, value * 10 // 255)) try: - path.write_text(str(min(255, max(0, value)))) + path.write_text(str(scaled)) + # 30 ms between i2c writes — matches the bash + # scripts. Without this, 9 channels written + # back-to-back saturate the mv64xxx_i2c + # controller and we get -EIO sprinkled across + # random channels. + time.sleep(0.03) except PermissionError: log.warning("No write access to %s", path) diff --git a/packages/secubox-led-heartbeat/usr/sbin/secubox-led-pulse b/packages/secubox-led-heartbeat/usr/sbin/secubox-led-pulse index de8c0f52..122f0c56 100644 --- a/packages/secubox-led-heartbeat/usr/sbin/secubox-led-pulse +++ b/packages/secubox-led-heartbeat/usr/sbin/secubox-led-pulse @@ -4,7 +4,9 @@ set -euo pipefail -BRIGHTNESS=100 +# IS31FL319X EIO-safe ceiling on the MOCHAbin i2c-1 bus. See secubox-led +# for the 2026-05-24 incident notes. +BRIGHTNESS=10 I2C_DELAY=0.15 STATUS_FILE="/tmp/secubox/led-status" diff --git a/scripts/secubox-healthbump b/scripts/secubox-healthbump index c493767e..3342eced 100755 --- a/scripts/secubox-healthbump +++ b/scripts/secubox-healthbump @@ -12,8 +12,9 @@ set -euo pipefail -# Brightness 100 works reliably with proper I2C delays -readonly BRIGHTNESS=100 +# IS31FL319X EIO-safe ceiling on the MOCHAbin i2c-1 bus. +# See packages/secubox-led-heartbeat/usr/sbin/secubox-led for context. +readonly BRIGHTNESS=10 readonly I2C_DELAY=0.03 readonly RATE_FILE="/tmp/secubox-ban-rate" readonly STATUS_FILE="/tmp/secubox/led-status"