feat: add Command classes

This commit is contained in:
2025-10-22 22:17:05 +02:00
parent 14c9fcdedb
commit 784d594a3b

66
src/command.py Normal file
View File

@@ -0,0 +1,66 @@
from __future__ import annotations
import abc
from enum import IntEnum
import struct
from typing import Type
class CommandType(IntEnum):
CAR_CONTROL = 0
class CarControl(IntEnum):
FORWARD = 0
BACKWARD = 1
LEFT = 2
RIGHT = 3
class Command(abc.ABC):
TYPE: CommandType
REGISTRY: dict[CommandType, Type[Command]] = {}
def __init_subclass__(cls) -> None:
super().__init_subclass__()
if cls.TYPE in Command.REGISTRY:
raise ValueError(
f"Command type {cls.TYPE} already registered by {Command.REGISTRY[cls.TYPE]}"
)
Command.REGISTRY[cls.TYPE] = cls
@abc.abstractmethod
def get_payload(self) -> bytes: ...
def pack(self) -> bytes:
payload: bytes = self.get_payload()
return struct.pack(">B", self.TYPE) + payload
@staticmethod
def unpack(data: bytes) -> Command:
type: CommandType = CommandType(data[0])
return Command.REGISTRY[type].from_payload(data[1:])
@classmethod
@abc.abstractmethod
def from_payload(cls, payload: bytes) -> Command: ...
class ControlCommand(Command):
TYPE = CommandType.CAR_CONTROL
__match_args__ = ("control", "active")
def __init__(self, control: CarControl, active: bool) -> None:
super().__init__()
self.control: CarControl = control
self.active: bool = active
def get_payload(self) -> bytes:
return struct.pack(">B", (self.control << 1) | self.active)
@classmethod
def from_payload(cls, payload: bytes) -> Command:
value: int = payload[0]
active: bool = (value & 1) == 1
control: int = value >> 1
return ControlCommand(CarControl(control), active)