Files
musicmouse/python-backend/musicmouse/hardware.py
Martin Bauer d44c24ec97 Full rearchitecture using Claude
- event bus systen
- all components are independent
- preparation for web frontend
2026-08-26 13:22:28 +02:00

91 lines
1.9 KiB
Python

"""Hardware vocabulary: the enums and geometry the firmware and the host agree on.
The integer values of :class:`Button`, :class:`ButtonAction`, :class:`TouchButton` and
:class:`RotaryDirection` are wire values and must match ``esp-firmware/src/Messages.h``.
"""
from __future__ import annotations
from enum import IntEnum, StrEnum
__all__ = [
"MOUSE_LED_RANGES",
"NO_FIGURE_TAG",
"RFID_TAG_LENGTH",
"Button",
"ButtonAction",
"LedZone",
"RotaryDirection",
"TouchButton",
]
#: Length of an RFID tag id in bytes (``uint8_t tagId[5]`` in ``Messages.h``).
RFID_TAG_LENGTH = 5
#: The all-zero tag the firmware reports when nothing is on the reader.
NO_FIGURE_TAG = bytes(RFID_TAG_LENGTH)
class Button(IntEnum):
"""The three physical push buttons."""
LEFT = 1
RIGHT = 2
ROTARY = 3
@property
def slug(self) -> str:
return self.name.lower()
class ButtonAction(IntEnum):
"""AceButton event types, as reported by the firmware."""
PRESSED = 0
RELEASED = 1
CLICKED = 2
DOUBLE_CLICKED = 3
LONG_PRESSED = 4
REPEAT_PRESSED = 5
LONG_RELEASED = 6
@property
def slug(self) -> str:
return self.name.lower()
class TouchButton(IntEnum):
"""The four capacitive touch areas on the mouse body."""
LEFT_FOOT = 0
RIGHT_FOOT = 1
LEFT_EAR = 2
RIGHT_EAR = 3
@property
def slug(self) -> str:
return self.name.lower()
class RotaryDirection(IntEnum):
NONE = 0
DOWN = 1
UP = 2
class LedZone(StrEnum):
"""The three independently addressable LED strips."""
RING = "ring"
MOUSE = "mouse"
SHELF = "shelf"
#: LED index span (begin, end) lit up when a given touch area is touched.
MOUSE_LED_RANGES: dict[TouchButton, tuple[int, int]] = {
TouchButton.RIGHT_FOOT: (0, 6),
TouchButton.LEFT_FOOT: (6, 12),
TouchButton.LEFT_EAR: (12, 28),
TouchButton.RIGHT_EAR: (28, 45),
}