pub struct Loco { /* private fields */ }Expand description
Represents a DCC Locomotive that can be controlled via a Z21 station.
This struct provides methods to control various aspects of a model train locomotive, including speed, direction, functions (lights, sounds, etc.), and emergency stops. It communicates with the locomotive through a Z21 station using the XBus protocol.
Implementations§
Source§impl Loco
impl Loco
Sourcepub async fn control(station: Arc<Z21Station>, address: u16) -> Result<Loco>
pub async fn control(station: Arc<Z21Station>, address: u16) -> Result<Loco>
Initializes control over a locomotive with the specified address.
This method establishes communication with a locomotive using its DCC address and subscribes to information about its state. It uses the default throttle steps configuration (128 steps).
§Arguments
station- Arc reference to a connected Z21Stationaddress- DCC address of the locomotive (1-9999)
§Returns
A new Loco instance if successful.
§Errors
Returns an io::Error if:
- Communication with the Z21 station fails
- The locomotive does not respond
§Example
let loco = Loco::control(station.clone(), 3).await?;Examples found in repository?
6async fn main() -> std::io::Result<()> {
7 let station = Arc::new(Z21Station::new("192.168.0.111:21105").await?);
8
9 // Control a locomotive with address 3
10 let loco = Loco::control(station.clone(), 4).await?;
11
12 // Subscribe to locomotive state changes
13 loco.subscribe_loco_state(Box::new(|state| {
14 println!(
15 "Locomotive speed: {}%",
16 state.speed_percentage.unwrap_or(0.)
17 );
18 }));
19
20 // Turn on the headlights
21 loco.set_headlights(true).await?;
22
23 // Set speed to 50% forward
24 loco.drive(50.0).await?;
25
26 // Wait for 5 seconds
27 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
28
29 // Gradually stop
30 loco.stop().await?;
31
32 Ok(())
33}Sourcepub async fn control_with_steps(
station: Arc<Z21Station>,
address: u16,
steps: DccThrottleSteps,
) -> Result<Loco>
pub async fn control_with_steps( station: Arc<Z21Station>, address: u16, steps: DccThrottleSteps, ) -> Result<Loco>
Initializes control over a locomotive with specified address and DCC stepping.
Similar to control() but allows specifying the throttle stepping mode
(14, 28, or 128 steps) for more precise control or compatibility with
different locomotive decoders.
§Arguments
station- Arc reference to a connected Z21Stationaddress- DCC address of the locomotive (1-9999)steps- DCC throttle steps configuration
§Returns
A new Loco instance if successful.
§Errors
Returns an io::Error if:
- Communication with the Z21 station fails
- The locomotive does not respond
§Example
let loco = Loco::control_with_steps(
station.clone(),
3,
DccThrottleSteps::Steps28
).await?;Sourcepub async fn stop(&self) -> Result<()>
pub async fn stop(&self) -> Result<()>
Performs a normal locomotive stop, equivalent to setting speed to 0.
This stop applies braking with a braking curve, providing a gradual and realistic deceleration.
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Gradually stop the locomotive
loco.stop().await?;Examples found in repository?
6async fn main() -> std::io::Result<()> {
7 let station = Arc::new(Z21Station::new("192.168.0.111:21105").await?);
8
9 // Control a locomotive with address 3
10 let loco = Loco::control(station.clone(), 4).await?;
11
12 // Subscribe to locomotive state changes
13 loco.subscribe_loco_state(Box::new(|state| {
14 println!(
15 "Locomotive speed: {}%",
16 state.speed_percentage.unwrap_or(0.)
17 );
18 }));
19
20 // Turn on the headlights
21 loco.set_headlights(true).await?;
22
23 // Set speed to 50% forward
24 loco.drive(50.0).await?;
25
26 // Wait for 5 seconds
27 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
28
29 // Gradually stop
30 loco.stop().await?;
31
32 Ok(())
33}Sourcepub async fn halt(&self) -> Result<()>
pub async fn halt(&self) -> Result<()>
Stops the train immediately (emergency stop).
Unlike the normal stop() method, this immediately cuts power
to the locomotive, causing an abrupt stop. This should be used
only in emergency situations.
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Emergency stop the locomotive
loco.halt().await?;Sourcepub async fn drive(&self, speed_percent: f64) -> Result<()>
pub async fn drive(&self, speed_percent: f64) -> Result<()>
Sets the speed of the locomotive in percent.
This method controls both the speed and direction of the locomotive:
- Positive values move the locomotive forward
- Negative values move the locomotive backward
- Zero value gradually stops the locomotive using a braking curve
The speed is automatically scaled based on the configured DCC throttle steps.
§Arguments
speed_percent- Speed percentage (-100.0 to 100.0)
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Drive forward at 50% speed
loco.drive(50.0).await?;
// Drive backward at 25% speed
loco.drive(-25.0).await?;
// Stop gradually
loco.drive(0.0).await?;Examples found in repository?
6async fn main() -> std::io::Result<()> {
7 let station = Arc::new(Z21Station::new("192.168.0.111:21105").await?);
8
9 // Control a locomotive with address 3
10 let loco = Loco::control(station.clone(), 4).await?;
11
12 // Subscribe to locomotive state changes
13 loco.subscribe_loco_state(Box::new(|state| {
14 println!(
15 "Locomotive speed: {}%",
16 state.speed_percentage.unwrap_or(0.)
17 );
18 }));
19
20 // Turn on the headlights
21 loco.set_headlights(true).await?;
22
23 // Set speed to 50% forward
24 loco.drive(50.0).await?;
25
26 // Wait for 5 seconds
27 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
28
29 // Gradually stop
30 loco.stop().await?;
31
32 Ok(())
33}Sourcepub fn subscribe_loco_state(
&self,
subscriber: Box<dyn Fn(LocoState) + Send + Sync>,
)
pub fn subscribe_loco_state( &self, subscriber: Box<dyn Fn(LocoState) + Send + Sync>, )
Subscribes to locomotive state changes.
This method sets up a background task that listens for locomotive state events from the Z21 station and calls the provided callback function whenever the state changes.
§Arguments
subscriber- Callback function that receives locomotive state updates
§Example
loco.subscribe_loco_state(Box::new(|state| {
println!("Locomotive speed: {}, direction: {}",
state.speed,
if state.direction { "forward" } else { "backward" });
}));Examples found in repository?
6async fn main() -> std::io::Result<()> {
7 let station = Arc::new(Z21Station::new("192.168.0.111:21105").await?);
8
9 // Control a locomotive with address 3
10 let loco = Loco::control(station.clone(), 4).await?;
11
12 // Subscribe to locomotive state changes
13 loco.subscribe_loco_state(Box::new(|state| {
14 println!(
15 "Locomotive speed: {}%",
16 state.speed_percentage.unwrap_or(0.)
17 );
18 }));
19
20 // Turn on the headlights
21 loco.set_headlights(true).await?;
22
23 // Set speed to 50% forward
24 loco.drive(50.0).await?;
25
26 // Wait for 5 seconds
27 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
28
29 // Gradually stop
30 loco.stop().await?;
31
32 Ok(())
33}Sourcepub async fn set_function(&self, function_index: u8, action: u8) -> Result<()>
pub async fn set_function(&self, function_index: u8, action: u8) -> Result<()>
Controls a locomotive function (F0-F31).
This method allows controlling the various functions of a DCC locomotive, such as lights, sounds, couplers, smoke generators, and other features. The specific functions available depend on the locomotive decoder.
§Arguments
function_index- The function number (0-31) where 0 represents F0 (typically lights)action- The action to perform:- 0: Turn function OFF
- 1: Turn function ON
- 2: Toggle function state
§Errors
Returns an io::Error if:
- The function index is invalid (must be 0-31)
- The action is invalid (must be 0-2)
- The packet fails to send
- The Z21 station does not respond
§Example
// Turn on the locomotive lights (F0)
loco.set_function(0, 1).await?;
// Toggle the horn (assuming it's on F2)
loco.set_function(2, 2).await?;Sourcepub async fn function_on(&self, function_index: u8) -> Result<()>
pub async fn function_on(&self, function_index: u8) -> Result<()>
Turns on a specific locomotive function.
This is a convenience method that calls set_function() with the ON action.
§Arguments
function_index- The function number (0-31) where 0 represents F0 (typically lights)
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Turn on the locomotive lights (F0)
loco.function_on(0).await?;
// Activate the horn (assuming it's on F2)
loco.function_on(2).await?;Sourcepub async fn function_off(&self, function_index: u8) -> Result<()>
pub async fn function_off(&self, function_index: u8) -> Result<()>
Turns off a specific locomotive function.
This is a convenience method that calls set_function() with the OFF action.
§Arguments
function_index- The function number (0-31) where 0 represents F0 (typically lights)
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Turn off the locomotive lights (F0)
loco.function_off(0).await?;
// Deactivate the horn (assuming it's on F2)
loco.function_off(2).await?;Sourcepub async fn function_toggle(&self, function_index: u8) -> Result<()>
pub async fn function_toggle(&self, function_index: u8) -> Result<()>
Toggles a specific locomotive function (if on, turns off; if off, turns on).
This is a convenience method that calls set_function() with the TOGGLE action.
§Arguments
function_index- The function number (0-31) where 0 represents F0 (typically lights)
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Toggle the locomotive lights (F0)
loco.function_toggle(0).await?;
// Toggle the horn (assuming it's on F2)
loco.function_toggle(2).await?;Sourcepub async fn set_headlights(&self, on: bool) -> Result<()>
pub async fn set_headlights(&self, on: bool) -> Result<()>
Convenience method to control the locomotive’s headlights (F0).
This method simplifies controlling the locomotive’s headlights, which are typically mapped to function F0 in DCC decoders.
§Arguments
on- Whether to turn the lights on (true) or off (false)
§Errors
Returns an io::Error if the packet fails to send, or Z21 does not respond.
§Example
// Turn on the locomotive headlights
loco.set_headlights(true).await?;
// Turn off the locomotive headlights
loco.set_headlights(false).await?;Examples found in repository?
6async fn main() -> std::io::Result<()> {
7 let station = Arc::new(Z21Station::new("192.168.0.111:21105").await?);
8
9 // Control a locomotive with address 3
10 let loco = Loco::control(station.clone(), 4).await?;
11
12 // Subscribe to locomotive state changes
13 loco.subscribe_loco_state(Box::new(|state| {
14 println!(
15 "Locomotive speed: {}%",
16 state.speed_percentage.unwrap_or(0.)
17 );
18 }));
19
20 // Turn on the headlights
21 loco.set_headlights(true).await?;
22
23 // Set speed to 50% forward
24 loco.drive(50.0).await?;
25
26 // Wait for 5 seconds
27 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
28
29 // Gradually stop
30 loco.stop().await?;
31
32 Ok(())
33}