Rename project from travler-rotor to birdcage

The radome looks like a birdcage, ham operators call satellites
"birds", and it's a nod to saveitforparts saving dishes "for parts."

Package, CLI entry point, class names (BirdcageAntenna), env vars
(BIRDCAGE_PORT, etc.), and CLAUDE.md updated. Hardware references
(Winegard Trav'ler, Trav'ler Pro, Carryout G2) unchanged.
This commit is contained in:
Ryan Malloy 2026-02-13 05:16:00 -07:00
parent c010cee282
commit a2e807f973
9 changed files with 207 additions and 57 deletions

View file

@ -1,8 +1,8 @@
"""travler-rotor: Control Winegard Trav'ler satellite dishes via RS-485."""
"""birdcage: Winegard satellite dish control for amateur radio sky tracking."""
from travler_rotor.antenna import AntennaConfig, TravlerAntenna
from travler_rotor.leapfrog import apply_leapfrog
from travler_rotor.protocol import (
from birdcage.antenna import AntennaConfig, BirdcageAntenna
from birdcage.leapfrog import apply_leapfrog
from birdcage.protocol import (
CarryoutG2Protocol,
FirmwareProtocol,
HAL000Protocol,
@ -10,10 +10,11 @@ from travler_rotor.protocol import (
Position,
RssiReading,
)
from travler_rotor.rotctld import RotctldServer
from birdcage.rotctld import RotctldServer
__all__ = [
"AntennaConfig",
"BirdcageAntenna",
"CarryoutG2Protocol",
"FirmwareProtocol",
"HAL000Protocol",
@ -21,6 +22,5 @@ __all__ = [
"Position",
"RssiReading",
"RotctldServer",
"TravlerAntenna",
"apply_leapfrog",
]

View file

@ -10,8 +10,8 @@ from __future__ import annotations
import logging
from dataclasses import dataclass
from travler_rotor.leapfrog import apply_leapfrog
from travler_rotor.protocol import (
from birdcage.leapfrog import apply_leapfrog
from birdcage.protocol import (
MOTOR_AZIMUTH,
MOTOR_ELEVATION,
FirmwareProtocol,
@ -31,7 +31,7 @@ class AntennaConfig:
leapfrog_enabled: bool = True
class TravlerAntenna:
class BirdcageAntenna:
"""High-level interface to a Winegard Trav'ler dish.
Manages the full lifecycle: connect, initialize (boot + search kill),

View file

@ -1,4 +1,4 @@
"""CLI entry point for travler-rotor.
"""CLI entry point for birdcage.
Provides subcommands for initialization, position queries, manual moves,
and running a full rotctld-compatible server for Gpredict integration.
@ -11,9 +11,9 @@ import sys
import click
from travler_rotor.antenna import AntennaConfig, TravlerAntenna
from travler_rotor.protocol import get_protocol
from travler_rotor.rotctld import RotctldServer
from birdcage.antenna import AntennaConfig, BirdcageAntenna
from birdcage.protocol import get_protocol
from birdcage.rotctld import RotctldServer
def _setup_logging(verbose: bool) -> None:
@ -25,19 +25,19 @@ def _setup_logging(verbose: bool) -> None:
)
def _build_antenna(port: str, firmware: str, **config_kwargs) -> TravlerAntenna:
"""Create a TravlerAntenna from CLI options."""
def _build_antenna(port: str, firmware: str, **config_kwargs) -> BirdcageAntenna:
"""Create a BirdcageAntenna from CLI options."""
protocol = get_protocol(firmware)
# G2 defaults: 115200 baud, 18 deg min elevation
if firmware.lower() == "g2":
config_kwargs.setdefault("baudrate", 115200)
config_kwargs.setdefault("min_elevation", 18.0)
config = AntennaConfig(port=port, **config_kwargs)
return TravlerAntenna(protocol, config)
return BirdcageAntenna(protocol, config)
@click.group()
@click.version_option(package_name="travler-rotor")
@click.version_option(package_name="birdcage")
@click.option("-v", "--verbose", is_flag=True, help="Enable debug logging.")
def main(verbose: bool) -> None:
"""Control a Winegard Trav'ler satellite dish via RS-485."""
@ -47,14 +47,14 @@ def main(verbose: bool) -> None:
@main.command()
@click.option(
"--port",
envvar="TRAVLER_PORT",
envvar="BIRDCAGE_PORT",
default="/dev/ttyUSB0",
show_default=True,
help="Serial port for the RS-485 adapter.",
)
@click.option(
"--firmware",
envvar="TRAVLER_FIRMWARE",
envvar="BIRDCAGE_FIRMWARE",
default="hal205",
show_default=True,
type=click.Choice(["hal205", "hal000", "g2"], case_sensitive=False),
@ -76,14 +76,14 @@ def init(port: str, firmware: str) -> None:
@main.command()
@click.option(
"--port",
envvar="TRAVLER_PORT",
envvar="BIRDCAGE_PORT",
default="/dev/ttyUSB0",
show_default=True,
help="Serial port for the RS-485 adapter.",
)
@click.option(
"--firmware",
envvar="TRAVLER_FIRMWARE",
envvar="BIRDCAGE_FIRMWARE",
default="hal205",
show_default=True,
type=click.Choice(["hal205", "hal000", "g2"], case_sensitive=False),
@ -91,14 +91,14 @@ def init(port: str, firmware: str) -> None:
)
@click.option(
"--host",
envvar="TRAVLER_LISTEN_HOST",
envvar="BIRDCAGE_LISTEN_HOST",
default="127.0.0.1",
show_default=True,
help="Address to listen on for rotctld connections.",
)
@click.option(
"--listen-port",
envvar="TRAVLER_LISTEN_PORT",
envvar="BIRDCAGE_LISTEN_PORT",
default=4533,
show_default=True,
type=int,
@ -136,14 +136,14 @@ def serve(
@main.command()
@click.option(
"--port",
envvar="TRAVLER_PORT",
envvar="BIRDCAGE_PORT",
default="/dev/ttyUSB0",
show_default=True,
help="Serial port for the RS-485 adapter.",
)
@click.option(
"--firmware",
envvar="TRAVLER_FIRMWARE",
envvar="BIRDCAGE_FIRMWARE",
default="hal205",
show_default=True,
type=click.Choice(["hal205", "hal000", "g2"], case_sensitive=False),
@ -170,14 +170,14 @@ def pos(port: str, firmware: str) -> None:
@main.command()
@click.option(
"--port",
envvar="TRAVLER_PORT",
envvar="BIRDCAGE_PORT",
default="/dev/ttyUSB0",
show_default=True,
help="Serial port for the RS-485 adapter.",
)
@click.option(
"--firmware",
envvar="TRAVLER_FIRMWARE",
envvar="BIRDCAGE_FIRMWARE",
default="hal205",
show_default=True,
type=click.Choice(["hal205", "hal000", "g2"], case_sensitive=False),

View file

@ -21,12 +21,12 @@ from __future__ import annotations
import logging
import socket
from travler_rotor.antenna import TravlerAntenna
from travler_rotor.protocol import CarryoutG2Protocol
from birdcage.antenna import BirdcageAntenna
from birdcage.protocol import CarryoutG2Protocol
logger = logging.getLogger(__name__)
MODEL_NAME = "Winegard Trav'ler RS-485 Rotor"
MODEL_NAME = "Birdcage — Winegard RS-485 Rotor"
class RotctldServer:
@ -34,7 +34,7 @@ class RotctldServer:
def __init__(
self,
antenna: TravlerAntenna,
antenna: BirdcageAntenna,
host: str = "127.0.0.1",
port: int = 4533,
) -> None: