Examples
This directory contains complete working examples demonstrating z21aio functionality. All examples assume a Z21 command station at 192.168.0.111 with a locomotive at address 3.
Basic Example
File: basic.py
The simplest example showing how to:
Connect to a Z21 station
Get the serial number
Turn on track power
Control a locomotive
Stop and disconnect
async with await Z21Station.connect("192.168.0.111") as station:
serial = await station.get_serial_number()
print(f"Connected to Z21, serial: {serial}")
await station.voltage_on()
loco = await Loco.control(station, address=3)
await loco.set_headlights(True)
await loco.drive(50.0)
await asyncio.sleep(5)
await loco.stop()
await station.voltage_off()
Run it:
python examples/basic.py
Speed Control Example
File: speed.py
Demonstrates speed control including:
Forward speeds at different percentages
Reverse operation
Normal stop with braking curve
Emergency halt (immediate stop)
Different throttle step modes
loco = await Loco.control(station, address=3)
# Different speeds
await loco.drive(25.0) # 25% forward
await loco.drive(50.0) # 50% forward
await loco.drive(75.0) # 75% forward
await loco.drive(-50.0) # 50% reverse
# Normal stop (with braking curve)
await loco.stop()
# Emergency halt (immediate stop)
await loco.halt()
Run it:
python examples/speed.py
Function Control Example
File: functions.py
Shows how to control locomotive functions (F0-F31):
F0 (headlights) using convenience method
Turn functions on and off
Toggle functions
Using the FunctionAction enum
loco = await Loco.control(station, address=3)
# Headlights (F0) - convenience method
await loco.set_headlights(True)
# Turn on specific functions
await loco.function_on(1) # F1
await loco.function_on(2) # F2
# Toggle a function
await loco.function_toggle(3)
# Using set_function with FunctionAction enum
await loco.set_function(4, FunctionAction.ON)
await loco.set_function(4, FunctionAction.OFF)
Run it:
python examples/functions.py
Multi-Station Example
File: multi_station.py
Demonstrates controlling multiple Z21 stations simultaneously:
Connect to multiple stations in parallel
Control different locomotives on different stations
Independent speed control for each locomotive
async with await Z21Station.connect("192.168.0.111") as station1, \
await Z21Station.connect("192.168.0.112") as station2:
loco1 = await Loco.control(station1, address=3)
loco2 = await Loco.control(station2, address=5)
await loco1.drive(50.0)
await loco2.drive(30.0)
await asyncio.sleep(10)
Run it:
python examples/multi_station.py
System State Monitoring Example
File: monitor.py
Shows how to monitor system state including:
Voltage and current draw
Temperature
Track power status
Frequency-based polling
def on_state_change(state):
print(f"Voltage: {state.voltage}V")
print(f"Current: {state.current}mA")
print(f"Temperature: {state.temperature}°C")
# Subscribe to updates at 1 Hz
task = station.subscribe_system_state(on_state_change, freq_hz=1.0)
await asyncio.sleep(30)
task.cancel()
Run it:
python examples/monitor.py
Locomotive State Example
File: loco_state.py
Demonstrates locomotive state management:
Get current locomotive state
Parse speed and direction
Get function states
Subscribe to state change notifications
Respond to state updates in real-time
# Get current state
state = await loco.get_state()
print(f"Speed: {state.speed_percentage}%")
print(f"Direction: {state.direction}")
# Subscribe to state changes
def on_loco_state(state):
print(f"Loco {state.address}: Speed {state.speed_percentage}%")
loco.subscribe_state(on_loco_state)
Run it:
python examples/loco_state.py
Custom Example
To create your own example, start with the basic template:
import asyncio
from z21aio import Z21Station, Loco
async def main():
async with await Z21Station.connect("192.168.0.111") as station:
# Your code here
pass
if __name__ == "__main__":
asyncio.run(main())
Tips
Change the IP address from
192.168.0.111to match your Z21 stationChange the locomotive address (usually 3) to match your test locomotive
Enable logging to see debug information:
import logging
logging.basicConfig(level=logging.DEBUG)
Use
asyncio.sleep()to add delays between commandsAll methods are async - remember to use
await