Files
cristhian 3624c63ead
validate / validate (pull_request) Successful in 58m42s
validate / test (pull_request) Successful in 58m47s
validate / markdownlint (pull_request) Successful in 58m40s
add dora-joy node publishing gamepad axes and buttons
2026-09-16 05:10:33 -05:00

41 lines
1.3 KiB
Python

"""Everything the node reads from the environment, parsed once at startup.
Parsing happens here rather than where each value is used, so an unusable
setting stops the node before it joins the dataflow instead of surfacing the
first time somebody picks up the gamepad.
"""
import os
from dataclasses import dataclass
def env_int(name: str, default: int) -> int:
"""Read a whole number, naming the variable if it cannot be read as one."""
value = os.environ.get(name, "").strip()
if not value:
return default
try:
return int(value)
except ValueError:
raise ValueError(f"{name} must be a whole number, not {value!r}") from None
@dataclass
class Config:
"""The node's settings.
Short on purpose. A deadzone, a response curve and a speed all describe what
a reading should *do*, and this node does not know — it reads a pad and says
so. Adding them here would mean two places shaping the same number.
"""
joystick_index: int
@classmethod
def from_env(cls) -> "Config":
"""Build the configuration from the environment, refusing anything unusable."""
index = env_int("JOYSTICK_INDEX", 0)
if index < 0:
raise ValueError(f"JOYSTICK_INDEX must not be negative, not {index}")
return cls(joystick_index=index)