use crate::utils::to_pascal_case;
#[allow(clippy::too_many_arguments)]
fn driver_template(
name: &str,
title: &str,
config_fields: &str,
extra_methods: &str,
log_label: &str,
init_todo: &str,
update_todo: &str,
shutdown_todo: &str,
) -> String {
let pascal = to_pascal_case(name);
format!(
r#"//! {name} - {title}
//!
//! Auto-generated driver template.
use anyhow::Result;
use mecha10_core::Driver;
use serde::{{Deserialize, Serialize}};
use tracing::info;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {pascal}Config {{
{config_fields}
}}
pub struct {pascal} {{
config: {pascal}Config,
}}
impl {pascal} {{
pub fn new(config: {pascal}Config) -> Self {{
Self {{ config }}
}}
{extra_methods}}}
#[async_trait::async_trait]
impl Driver for {pascal} {{
async fn initialize(&mut self) -> Result<()> {{
info!("Initializing {name} {log_label}");
{init_todo}
Ok(())
}}
async fn update(&mut self) -> Result<()> {{
{update_todo}
Ok(())
}}
async fn shutdown(&mut self) -> Result<()> {{
info!("Shutting down {name} {log_label}");
{shutdown_todo}Ok(())
}}
}}
"#,
)
}
pub fn sensor_driver(name: &str) -> String {
driver_template(
name,
"Sensor Driver",
" pub update_rate_hz: f64,",
"",
"driver",
"// TODO: Initialize hardware/sensor",
"// TODO: Read sensor data\n // TODO: Publish to message bus",
"",
)
}
pub fn actuator_driver(name: &str) -> String {
driver_template(
name,
"Actuator Driver",
" pub max_speed: f64,\n pub acceleration: f64,",
"\n pub async fn set_command(&mut self, command: f64) -> Result<()> {\n // TODO: Send command to actuator\n Ok(())\n }\n",
"driver",
"// TODO: Initialize actuator",
"// TODO: Process actuator commands from message bus",
"// TODO: Stop actuator safely\n ",
)
}
pub fn controller_driver(name: &str) -> String {
driver_template(
name,
"Controller Driver",
" pub control_rate_hz: f64,",
"",
"controller",
"// TODO: Initialize controller",
"// TODO: Run control loop",
"",
)
}