Power Resources¶
Use this page when your bench needs to turn DUT power on/off, power-cycle a board, or hide relay/vendor details behind stable BenchCI suite steps.
BenchCI treats power as a bench-level resource. The suite says what should happen, such as power_cycle, while bench.yaml describes how the lab hardware performs it.
suite.yaml -> power_cycle dut_power.main
bench.yaml -> GPIO relay, HTTP relay, USB serial relay, or another backend
This keeps test logic readable and avoids writing vendor-specific relay commands directly in test suites.
Supported Power v2 backends¶
Current Power v2 resource drivers include:
mock_powerfor demos, tests, and dry-runsgpio_powerfor local Linux GPIO controlled relays or load switcheshttp_relayfor LAN relays, Shelly-style devices, or internal lab controllersusb_relay_serialwithvendor: genericandmodel: command_mapfor serial relay boards
BenchCI intentionally avoids exposing one-off relay brands as top-level suite concepts. For example, an LCUS-style relay should be configured as a generic serial command map in bench.yaml, while the suite still uses power_set or power_cycle.
Power resource shape¶
Power resources live under resources in bench.yaml:
resources:
dut_power:
kind: power_controller
driver:
type: mock_power
outlets:
main: false
The resource name is dut_power; the outlet name is main. Suite steps reference those logical names.
Mock power¶
Use mock_power for examples, tests, and demos where no real relay is connected.
resources:
dut_power:
kind: power_controller
driver:
type: mock_power
outlets:
main: false
GPIO power¶
Use gpio_power when a Linux machine, Raspberry Pi, or similar controller drives a relay, MOSFET, or load switch through /dev/gpiochipX.
resources:
dut_power:
kind: power_controller
driver:
type: gpio_power
chip: /dev/gpiochip0
outlets:
main: 17
active_high: true
initial_state: false
on_settle_ms: 1000
off_settle_ms: 250
Use active_high: false when the relay input is active-low. Suites always use logical states: true means power should be on/active, regardless of the electrical level.
HTTP relay¶
Use http_relay for relay boards or lab controllers that expose simple HTTP endpoints.
resources:
dut_power:
kind: power_controller
driver:
type: http_relay
outlets:
main: "1"
on_url: "http://192.168.1.50/relay/{channel}/on"
off_url: "http://192.168.1.50/relay/{channel}/off"
get_url: "http://192.168.1.50/relay/{channel}/state"
method: GET
timeout_ms: 2000
{channel} is replaced with the outlet mapping value. In the example above, main maps to channel 1.
If the backend cannot read state, omit get_url and avoid power_expect.
Generic serial relay command map¶
Use usb_relay_serial with vendor: generic and model: command_map for serial relay boards where the ON/OFF commands are known.
resources:
dut_power:
kind: power_controller
driver:
type: usb_relay_serial
vendor: generic
model: command_map
port: /dev/ttyUSB1
baud: 9600
timeout_ms: 500
outlets:
main: "1"
on_commands:
"1": "A0 01 01 A2"
off_commands:
"1": "A0 01 00 A1"
on_settle_ms: 1000
off_settle_ms: 250
This is also how LCUS-style relay boards should be represented. BenchCI does not need a separate LCUS-specific suite step or first-class backend.
Suite steps¶
Set power¶
- power_set:
resource: dut_power
outlet: main
state: true
Power-cycle¶
- power_cycle:
resource: dut_power
outlet: main
off_ms: 1000
on_settle_ms: 2000
Expect/read power state¶
- power_expect:
resource: dut_power
outlet: main
state: true
power_expect requires a backend that supports readback or safe state tracking. If a serial relay cannot report state, BenchCI should fail clearly instead of pretending to know the hardware state.
Why this model matters¶
The test suite should say:
- power_cycle:
resource: dut_power
outlet: main
It should not say:
send A0 01 00 A1 to /dev/ttyUSB1, sleep, then send A0 01 01 A2
Vendor-specific details belong in bench.yaml. Test intent belongs in suite.yaml.