Implement story 1.1: project scaffold and verified entry points
Creates the complete src/planemapper/ layout with all module stubs, provisioning and renderer subpackages, airports.csv data bundle, systemd unit files, and full test scaffold. All three quality gates pass: pytest 12/12, ruff check zero violations, ruff format clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,42 @@
|
||||
from pathlib import Path
|
||||
|
||||
DISPLAY_WIDTH = 800
|
||||
DISPLAY_HEIGHT = 480
|
||||
|
||||
REFRESH_INTERVAL_S = 60
|
||||
FETCH_TIMEOUT_S = 5
|
||||
RENDER_WARN_S = 40
|
||||
RENDER_ALERT_S = 50
|
||||
STALE_CYCLES = 1
|
||||
RESET_HOLD_S = 3
|
||||
|
||||
ALTITUDE_BANDS_FT = [1500, 5000, 10000, 20000, 35000, 99999]
|
||||
|
||||
COLOUR_BLACK = (0, 0, 0)
|
||||
COLOUR_WHITE = (255, 255, 255)
|
||||
COLOUR_RED = (255, 0, 0)
|
||||
COLOUR_YELLOW = (255, 255, 0)
|
||||
COLOUR_BLUE = (0, 0, 255)
|
||||
COLOUR_GREEN = (0, 255, 0)
|
||||
|
||||
ALTITUDE_COLOURS = [
|
||||
COLOUR_GREEN,
|
||||
COLOUR_BLUE,
|
||||
COLOUR_YELLOW,
|
||||
COLOUR_RED,
|
||||
COLOUR_BLACK,
|
||||
COLOUR_WHITE,
|
||||
]
|
||||
|
||||
COLOUR_STALE_OUTLINE = COLOUR_BLACK
|
||||
COLOUR_HOME_MARKER = COLOUR_RED
|
||||
COLOUR_AIRSPACE = COLOUR_BLUE
|
||||
COLOUR_TRAIL = COLOUR_BLACK
|
||||
|
||||
TRAIL_MAX_DOTS = 5
|
||||
TRAIL_DOT_SIZE_MAX = 6
|
||||
TRAIL_DOT_SIZE_MIN = 2
|
||||
|
||||
CONFIG_PATH = Path("/etc/planemapper/config.json")
|
||||
AIRSPACE_PATH = Path("/etc/planemapper/airspace.geojson")
|
||||
BACKGROUND_PATH = Path("/etc/planemapper/background.png")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
from typing import Protocol
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class DisplayInterface(Protocol):
|
||||
def show(self, image: Image.Image) -> None: ...
|
||||
|
||||
|
||||
class NullDisplay:
|
||||
def show(self, image: Image.Image) -> None:
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
from typing import Protocol
|
||||
|
||||
from planemapper.models import Aircraft
|
||||
|
||||
|
||||
class FetcherInterface(Protocol):
|
||||
def fetch(self) -> list[Aircraft]: ...
|
||||
@@ -0,0 +1,11 @@
|
||||
class ButtonHoldDetector:
|
||||
def check(self) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
class LEDController:
|
||||
def on(self) -> None:
|
||||
pass
|
||||
|
||||
def off(self) -> None:
|
||||
pass
|
||||
@@ -0,0 +1,8 @@
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
log.info("not implemented")
|
||||
@@ -0,0 +1,14 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Aircraft:
|
||||
icao: str
|
||||
lat: float
|
||||
lon: float
|
||||
heading: float = 0.0
|
||||
altitude_ft: int = 0
|
||||
callsign: str = ""
|
||||
category: str = ""
|
||||
is_mlat: bool = False
|
||||
is_stale: bool = False
|
||||
@@ -0,0 +1,8 @@
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
log.info("not implemented")
|
||||
@@ -0,0 +1,2 @@
|
||||
class ProvisioningError(Exception):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
@@ -0,0 +1 @@
|
||||
# stub
|
||||
Reference in New Issue
Block a user