• v0.2.0-rc.3 41e652ee27

    v0.2.0-rc.3
    Some checks failed
    CI / Lint, type-check, test (library, 3.11) (push) Successful in 27s
    CI / Lint, type-check, test (library, 3.14) (push) Successful in 33s
    Publish / Publish to PyPI (push) Successful in 29s
    CI / Type-check + test the integration (push) Successful in 2m12s
    Publish / Create releases + Linux binary (Forgejo, NAS, GitHub) (push) Has been cancelled
    Publish / Bridge the macOS .pkg → NAS (push) Has been cancelled
    Pre-release

    Cody Bryant released this 2026-08-09 23:23:19 -07:00 | 170 commits to main since this release

    Most of this release came from a field install by
    @CryingPecan, who ran a Litter-Robot 4 with a
    LitterHopper on ESP 1.4.4 for two weeks of MQTT capture. Protocol detail for all
    of the below lives in docs/devices/litter-robot-4/.

    Added

    • The clean cycle is back, and reset with it. Both work by synthesising a
      panel button press — the code the robot already emits when you press it —
      proven on ESP 1.1.75 and independently confirmed on 1.4.4. This reverses the
      0.1.2 removal, which pulled a clean-cycle button built on a byte that never was
      the cycle.
    • Pet weight actually works, and reports the whole cat. It is carried only in
      the activity stream, which was previously used as a poll trigger and thrown
      away — and the raw-to-pounds divisor was inherited, never checked. A weighed
      comparison showed it reporting half: a cat measuring ~8.1 lb came back as 4.08.
    • New entities: last cat visit, last visit duration, waste drawer last moved,
      and panel brightness for bright and dark rooms.
    • Empty cycle and Power buttons, both disabled by default and named
      (danger): an empty cycle dumps the whole globe into the drawer, and Power
      toggles the robot off the network. The CLI gains empty-cycle and power,
      which prompt before sending.
    • LitterHopper support: connected, fill gauge, and an out-of-litter alert the
      firmware itself never raises. The four hopper entities turn themselves on the
      first time a hopper reports; one you disable by hand stays off.
    • Litter percentage calibration. One button press with the globe filled to
      the line anchors the percentage to your robot; a second with it empty upgrades
      to a true two-point scale.
    • Activity-derived entities survive a restart instead of reading unknown
      until the next cat visit or dispense.

    Fixed

    • The filter-change wizard is decoded — its status, both cycle phases, and
      the fact that litter readings during it are meaningless. It cannot be started
      remotely: the panel chord is a long press, and the robot performs short presses
      over MQTT while declining long ones.
    • Every 0x0B annunciator value is named (bonnet, cat, cycle, ready, night
      light, reset), which closes the "random housekeeping chatter" question.
    • robotStatus 10 is the clean cycle, on every firmware. The old map called
      it a cat pause; a narrated live cycle disproved that. Also adds 5, 6/7,
      25, the power-up states 1/2/3, the boot cycle 13, and the filter
      wizard 14. The last two matter: both move or invert the globe, and while
      unmapped their ToF readings were published as real litter levels.
    • The empty-litter calibration button is available without hunting for it. It
      shipped disabled, including for anyone who already had it registered.
    • The weekday sleep schedule now arms every day. That setting is a per-day
      bitmask, not a switch, and turning it on wrote the value for Sunday alone — so
      it appeared to work if you tested on a Sunday and did nothing all week.
    • The cycle phase ladder now runs 2 → 3 → 4 → 5 → 1, so robots no longer
      publish unknown_4 mid-cycle.
    • Litter readings are suppressed while the globe is not level — mid-cycle the
      sensors read the globe, not the litter, and it was published as a real level.
    • Broker failures are reported, not raised as a traceback.
    • The CLI works against a CA generated by this project's own documentation,
      which Python 3.13+ rejected under strict X.509 verification.
    • The panel sleep schedule can now actually be set. The sleep and wake time
      entities wrote a register the firmware only computes, so they never did
      anything; they now write the real per-weekday schedule.
    • Panel sleep mode says what is actually wrong instead of timing out. The
      robot derives it from the weekday sleep schedule, which is the switch to use.
    • The waste-drawer sensor no longer guesses which way the drawer went.
      Breaking: binary_sensor.<robot>_waste_drawer_removed is replaced by
      sensor.<robot>_waste_drawer_last_moved. Nine different codes turned up across
      removals and insertions alike, and a direct read answers the same value either
      way, so the robot reports that the drawer moved and nothing more.
    • The hopper stops dropping to unknown. A link code we cannot name is no
      longer treated as a disconnect — one such code repeats on a healthy, dispensing
      hopper. Only a proven disconnect changes the state.
    • A multi-register write no longer loses one of its parts. Two commands sent
      back to back were seen landing as one; they are now paced and each is verified.
    • Pet weight can no longer report a cat 100× too heavy. It fell back to a
      state-document field in unknown units that no captured robot actually sends.
    • Panel brightness is verified rather than assumed. The library reported every
      write as successful without checking; it now reads the value back like the rest.
    • pic_firmware, previously always null, composed from the local mb* fields.
    • Entities a previous version created but this one no longer produces are removed
      from the registry instead of lingering forever as unavailable.

    Changed

    • The clean cycle, reset and empty presses no longer need a motor opt-in.
      Breaking (library): Hazard.MOTOR, MotorCommandError and the
      allow_motor argument are gone. Writing the panel button register reproduces
      the code the panel emits, so a written press is the same event as a physical
      one and the robot's own interlocks apply either way. Power still requires
      allow_dangerous.
    • Clean cycle wait time is now a number (3–30 minutes), not a select.
      Breaking: automations using select.<robot>_clean_cycle_wait_time must
      move to number.<robot>_clean_cycle_wait_time.
    • Panel brightness High/Low name the ambient light level, not the brightness
      rank. The stock 40/50 is deliberately brighter at night.
    • isPanelSleepMode and the panel sleep/wake times are documented as read-only:
      the firmware computes all three from the weekday schedule registers.
    • The register map now says what PROVEN has to mean, demotes the rows that never
      earned it, and documents the readable file as 0x00-0x7F with 123 of those 128
      addresses mapped. unitPowerType is pinned (0 = mains, 1 = battery) and
      isUSBPowerOn turns out to mean mains present, not USB. 0x02A10000 returns
      Wi-Fi RSSI only, not the schedule.
    • Releases are never published before the library version they pin exists on
      PyPI, and CI now exercises the Python 3.11 floor it advertises.
    Downloads