commit 66d582c9ba05c7c5ceec3661821456bec7ce2b39 Author: Mika Date: Sun Mar 8 03:07:03 2026 +0000 Add rover_startup/src/rover_startup/main.py diff --git a/rover_startup/src/rover_startup/main.py b/rover_startup/src/rover_startup/main.py new file mode 100644 index 0000000..e950392 --- /dev/null +++ b/rover_startup/src/rover_startup/main.py @@ -0,0 +1,124 @@ +import time +import json +import logging +import os +import argparse +from dataclasses import dataclass, asdict +from typing import Any + +try: + from gpiozero import LightSensor, MCP3008, CPUTemperature +except ImportError: + # Fallbacks in non-hardware environments + LightSensor = None # type: ignore + MCP3008 = None # type: ignore + CPUTemperature = None # type: ignore + + +logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s: %(message)s') +logger = logging.getLogger(__name__) + + +@dataclass +class SensorData: + """Struct for Rover sensor initialization values.""" + light: float + infrared: float + sound: float + core_temp: float + battery_status: float + + def to_json(self) -> str: + return json.dumps(asdict(self), indent=2) + + +def _read_light() -> float: + if LightSensor is None: + return 50.0 + try: + sensor = LightSensor(18) + return float(sensor.value * 100.0) + except Exception as e: + logger.warning(f"Light sensor read fallback due to error: {e}") + return 50.0 + + +def _read_infrared() -> float: + if MCP3008 is None: + return 25.0 + try: + ir_channel = MCP3008(channel=0) + return float(ir_channel.value * 100.0) + except Exception as e: + logger.warning(f"Infrared sensor read fallback due to error: {e}") + return 25.0 + + +def _read_sound() -> float: + if MCP3008 is None: + return 35.0 + try: + sound_channel = MCP3008(channel=1) + return float(sound_channel.value * 120.0) + except Exception as e: + logger.warning(f"Sound sensor read fallback due to error: {e}") + return 35.0 + + +def _read_core_temp() -> float: + if CPUTemperature is None: + return 42.0 + try: + cpu_temp = CPUTemperature() + return float(cpu_temp.temperature) + except Exception as e: + logger.warning(f"CPU temperature read fallback due to error: {e}") + return 42.0 + + +def _read_battery_status() -> float: + try: + # Placeholder: could be read via ADC pin on MCP3008 or from system sensors + return 95.0 + except Exception as e: + logger.warning(f"Battery status fallback due to error: {e}") + return 95.0 + + +def init_sensors() -> SensorData: + """Initializes all rover sensors and returns structured initial readings.""" + logger.info("Initializing sensors...") + time.sleep(0.5) + + light = _read_light() + infrared = _read_infrared() + sound = _read_sound() + core_temp = _read_core_temp() + battery = _read_battery_status() + + # Input validation + assert all(isinstance(v, (int, float)) for v in [light, infrared, sound, core_temp, battery]), "All sensor values must be numeric" + + data = SensorData( + light=float(light), + infrared=float(infrared), + sound=float(sound), + core_temp=float(core_temp), + battery_status=float(battery) + ) + + logger.info("Sensor initialization complete.") + return data + + +def main(argv: Any = None) -> None: + parser = argparse.ArgumentParser(description="Initialize and read rover sensor data.") + args = parser.parse_args(argv) + + data = init_sensors() + print("Rover Sensor Status:") + print(data.to_json()) + + +if __name__ == "__main__": + main()