Language: English | Español
ESPHome firmware that turns a rack into a visual assistant: addressable lighting, rack status effects, per-U alerts, rack-zone effects, and work lighting when the door opens.
The goal is for the logic to live inside the firmware: effects, selectors, brightness, timing, transitions, U mapping, and optional door override. Home Assistant is mainly used as a source of states and automations.
- Controller: QuinLED Dig-Uno ESP32.
- Data output:
GPIO3/ LED2 on the Dig-Uno. - Current strip: SK6812 RGBW, 5 V,
GRBorder, 300 addressable pixels. - Firmware: ESPHome with ESP-IDF.
rack-assistant.yaml: main ESPHome firmware.rack_assistant_helpers.h: shared curves, dithering, colors, U mapping, and transitions.secrets.example.yaml: template forsecrets.yaml.docs/calibration.md: rack height and LED/U calibration guide.docs/effects.md: effects, controls, and automation actions.docs/hardware.md: hardware and wiring notes.tools/show_block.py: lights specific LED ranges for calibration.tools/u_loop.py: visual U-by-U calibration loop.
Spanish documentation is available here:
Rack Assistant is licensed under GPL-3.0-or-later.
You can use, study, modify, and distribute it for personal or commercial projects. If you distribute modified versions or derivative firmware, you must keep them open source under the same GPL terms and include the corresponding source code.
See LICENSE for the full license text.
- Copy
secrets.example.yamltosecrets.yaml. - Edit
secrets.yamlwith your Wi-Fi, fallback AP password, optional door contact entity, and unique OTA/web credentials. - Review these values in
rack-assistant.yaml:led_pinled_countrack_unit_countchipsetrgb_orderis_rgbw
- Compile:
esphome compile rack-assistant.yaml- Upload by USB or OTA:
esphome upload rack-assistant.yaml --device rack-assistant.localBefore compiling or publishing changes, run:
python3 tools/check_project.py
esphome config rack-assistant.yamltools/check_project.py checks the expected UI options, manual LED map, security controls, and sensitive-file handling. esphome config validates the full ESPHome configuration.
This firmware is intended for an IoT or management network, not for direct internet exposure. To keep Home Assistant integration simple, the native ESPHome API is intentionally left without encryption.key.
ota.password: protects OTA firmware updates.web_server.auth: protects the local ESPHome web UI.
The OTA and web values live in secrets.yaml and should be unique per device. secrets.example.yaml only contains placeholders. If you do not need the web UI in a final installation, remove the web_server block and adapt tools/check_project.py for your fork.
Rack Assistant: main light entity.Rack mode: external preset selector.Rack zone: limits internal modes to the whole rack, side rails only, top only, or bottom only.U start: first U used by manual U alerts.U end: same U for a single position, or last U in a range.U alert: manual blinking alert applied to the selected U/range. UseNo alertto clear it.U scan time: duration of each U step in scan presets.Breathing min: shared minimum brightness for breathing effects.Breathing max: shared maximum brightness for breathing effects.Breathing cycle: full breathing cycle duration.Breathing curve:Smooth,Dynamic, orNatural.Door sensor: enables/disables the door contact override.
The firmware, exposed controls, and code comments use English names. The documentation is bilingual, with English as the default GitHub entry point.
For firmware-driven effects, the global brightness of Rack Assistant is kept internally at 100%. The visible intensity is controlled by Breathing min and Breathing max. This prevents the light entity brightness from applying a second limit on top of the effect.
Manual disables firmware effects and leaves Rack Assistant available for direct RGB/W control. The firmware keeps RGB and white separated: if RGB color is active, the white channel is forced to 0; if no RGB color is active, white effects use only the white channel.
If the Rack Assistant light is turned off and back on, the firmware restores the last active Rack mode instead of falling back to manual.
On a fresh installation, if no mode has been selected yet, the firmware starts with Blue breathing. After that, it stores that defaults have been initialized and does not overwrite the user's choice.
Main states such as breathing, internet down, error, success, U alerts, and U scans are rendered by the internal effect engine (Rack internal) so changes fade in and out instead of snapping.
Rack zone applies to internal lighting modes such as breathing and internet-down effects. U alerts keep using their selected U range, and native ESPHome addressable effects such as Rainbow, White wipe, Red wipe, and White scan still run across the whole strip.
Breathing and transitions are designed so the firmware controls the whole brightness curve. Three details matter:
gamma_correct: 1.0: prevents ESPHome from compressing low brightness levels after the firmware already calculated the curve.- Global
Rack Assistantbrightness at 100% for internal modes:Breathing minandBreathing maxdefine the real output range. - Custom curves and dithering in
rack_assistant_helpers.h: breathing curves define the temporal motion, and dithering spreads tiny brightness steps across LEDs to reduce visible stepping.
If breathing looks stepped again, first check that gamma_correct is still 1.0, the light entity is not limiting brightness, and Breathing min is not too low for your strip.
Rack height is configured with rack_unit_count. The current value is 15, but you can change it to your real rack height, for example 9, 12, 18, 22, or 42:
substitutions:
rack_unit_count: "15"The firmware distributes the LEDs on each vertical side proportionally across rack_unit_count. Taller racks usually have more LEDs per side, so you will also need to recalibrate rack_side_led_count.
The current map for my 15U rack is:
- Bottom: LEDs
0-34. - Left side: LEDs
35-77, fromU1toU15. - Top-left curve skipped: LEDs
78-79. - Top: LEDs
80-114. - Top-right curve skipped: LEDs
115-116. - Right side: LEDs
117-159, fromU15toU1.
These values are substitutions at the top of rack-assistant.yaml, not Home Assistant controls. For another rack, adjust rack_unit_count, rack_left_start, rack_side_led_count, and rack_right_start.
See docs/calibration.md for the full calibration workflow.
The visible UI keeps one manual alert so Home Assistant does not get flooded with controls. Internally there are 8 U-alert slots:
- Slot
0: reserved for the manual UI alert (U start,U end,U alert). - Slots
1-7: intended for Home Assistant automations.
Actions:
rack_u_set_preset: activates a slot with a preset effect.rack_u_set_custom: activates a slot with custom RGBW values.rack_u_clear_slot: clears one slot.rack_u_clear_all: clears all U alerts.
Example, mark a UPS in U1-U2 with a red blinking alert:
action: esphome.rack_assistant_rack_u_set_preset
data:
slot: 1
u_start: 1
u_end: 2
effect: "Red blink"Example, mark a rebooting device in U6 with white blinking:
action: esphome.rack_assistant_rack_u_set_preset
data:
slot: 2
u_start: 6
u_end: 6
effect: "White blink"Example with a custom color:
action: esphome.rack_assistant_rack_u_set_custom
data:
slot: 3
u_start: 8
u_end: 9
effect: "custom_breathing"
red: 0
green: 180
blue: 255
white: 0If two slots overlap the same U, the higher slot number wins. This allows priorities: for example, reserve slot 7 for critical alarms and lower slots for informational states.
More Home Assistant examples for changing rack mode, selecting zones, setting U ranges, clearing alerts, and showing a recovery/success animation are in docs/effects.md.
logger.baud_rate: 0is intentional becauseGPIO3shares UART RX on the ESP32.- Do not commit
secrets.yaml. - Use unique OTA and web secrets per device.
- Dimension LED strip power separately. Do not power multi-meter strips directly from the ESP32.
- For PoE, use a splitter/DC converter that provides the correct voltage and current for the strip.