Add rover_startup/src/rover_startup/main.py
This commit is contained in:
commit
66d582c9ba
1 changed files with 124 additions and 0 deletions
124
rover_startup/src/rover_startup/main.py
Normal file
124
rover_startup/src/rover_startup/main.py
Normal file
|
|
@ -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()
|
||||||
Loading…
Reference in a new issue