1use crate::{error::Error, subsys::capriltags::AprilTagFieldLayout};
2use std::{collections::HashMap, fs::File, io::Read, path::Path};
3
4macro_rules! def_cfg {
5 ($(
6 $struct_ident:ident {
7 $(
8 $(# [ $attr:ident $( ( $tt:tt ) )* ])?
9 $ident:ident : $ty:ty ,
10 )*
11 }
12 )*) => {
13 $(
14 #[derive(Deserialize, Serialize, Debug, Clone)]
15 #[cfg_attr(feature = "web", derive(utopia::ToSchema))]
16 pub struct $struct_ident {
17 $(
18 $(#[$attr $( ($tt) )?])?
19 pub $ident: $ty,
20 )*
21 }
22 )*
23 };
24}
25
26def_cfg! {
27 Config {
28 team_number: u16,
29 ntables_ip: Option<String>,
30 rerun: Option<Rerun>,
31 cameras: Option<Vec<Camera>>,
32 device_name: Option<String>,
33 field_layouts: Option<HashMap<String, AprilTagFieldLayout>>,
34 }
35 Rerun {
36 server_address: Option<String>,
37 }
38 Camera {
39 id: String,
40 name: String,
41 settings: Option<CameraSettings>,
42 possible_settings: Option<Vec<CameraSettings>>,
44 subsystems: Subsystems,
45 calib: Option<serde_json::Value>,
46 auto_exposure: bool,
47 manual_exposure: Option<u32>,
48 }
49 CameraSettings {
50 width: u32,
51 height: u32,
52 frame_rate: CfgFraction,
53 }
54 CfgFraction {
55 num: u32,
56 den: u32,
57 }
58 Subsystems {
59 capriltags: CAprilTagsSubsys,
60 ml: MlSubsys,
61 }
62 CAprilTagsSubsys {
63 enabled: bool,
64 gamma: Option<f64>,
65 field_layout: Option<String>,
66 }
67 MlSubsys {
68 enabled: bool,
69 }
70}
71
72impl Config {
73 pub fn load(path: impl AsRef<Path>) -> Result<Self, Error> {
74 let mut f = File::open(path).map_err(|_| Error::FailedToReadConfig)?;
75 let mut buf = String::new();
76 f.read_to_string(&mut buf).unwrap();
77 toml::from_str(&buf).map_err(|_| Error::InvalidConfig)
78 }
79}
80
81#[derive(Deserialize, Serialize, Clone)]
82#[cfg_attr(feature = "web", derive(utopia::ToSchema))]
83#[serde(rename_all = "snake_case")]
84pub enum CameraKind {
85 PiCam,
86 Usb,
87}