relayctl

module
v0.0.0-...-11e3fea Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: GPL-2.0

README

relayctl

An intelligent relay control system for managing power states of hardware devices with optimized boot/shutdown sequences.

Features

  • Dependency Management: Devices can depend on other devices (e.g., computer needs network switch)
  • Optimized Boot Timing: Calculates optimal start times for dependent devices to minimize total boot time
  • Lock-based Control: Multiple users/processes can request device power with lock IDs
  • Graceful Shutdown: Devices shut down after a delay when all locks are released
  • Cooldown Protection: Prevents rapid on/off cycling to protect hardware
  • Event Hooks: Observe and react to relay state changes
  • Flexible Logging: Integrate with your favorite logging library

Installation

go get github.com/endreszabo/relayctl

Quick Start

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/endreszabo/relayctl/relay"
)

func main() {
    // Create a network switch that takes 30 seconds to boot
    network := relay.NewRelay("network", nil,
        relay.WithBootDelay(30*time.Second),
        relay.WithCooldownPeriod(2*time.Second),
        relay.WithHardwareControl(
            func() error { fmt.Println("Turning on network"); return nil },
            func() error { fmt.Println("Turning off network"); return nil },
        ),
    )

    // Create a computer that depends on the network
    // Will start at T=5s (30s - 25s) so both are ready at T=30s
    computer := relay.NewRelay("computer", nil,
        relay.WithBootDelay(25*time.Second),
        relay.WithDependencies(network),
        relay.WithHardwareControl(
            func() error { fmt.Println("Turning on computer"); return nil },
            func() error { fmt.Println("Turning off computer"); return nil },
        ),
    )

    ctx := context.Background()

    // Turn on the computer (network starts automatically)
    if err := computer.TurnOn(ctx, "user1"); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // ... use the devices ...

    // Turn off when done
    computer.TurnOff("user1")
}

Concepts

State Machine

Each relay goes through these states:

StateOff → StateBooting → StateOn → [locks empty, wait powerOffDelay] → StateCoolingDown → StateOff
Dependencies

When a relay has dependencies, they are started automatically with optimized timing:

// Computer needs network to be ready
computer := relay.NewRelay("computer", nil,
    relay.WithBootDelay(25*time.Second),
    relay.WithDependencies(network),
)

The system calculates the optimal start time so the computer finishes booting exactly when the network is ready, minimizing total startup time.

Locks

Multiple users can hold locks on a relay simultaneously. The relay only turns off after all locks are released:

computer.TurnOn(ctx, "user1")
computer.TurnOn(ctx, "user2")  // Second lock

computer.TurnOff("user1")      // Still stays on (user2 still has lock)
computer.TurnOff("user2")      // Now it turns off after powerOffDelay

Configuration Options

Use functional options to configure relays:

Option Description Default
WithBootDelay(d) Time required for the relay to boot 0
WithCooldownPeriod(d) Minimum time between off and on 0
WithPowerOffDelay(d) Delay before actual shutdown after last lock released 0
WithHardwareControl(on, off) Hardware control functions No-op
WithDependencies(...) Dependency relays none
WithLogger(logger) Logger for operations NoOpLogger
WithEventHandler(handler) Event handler for state changes NoOpEventHandler
WithController(ctrl) Central controller (optional) nil

Advanced Usage

Custom Logging
type MyLogger struct{}

func (l *MyLogger) Debug(msg string, args ...interface{}) {
    // Your logging implementation
}

func (l *MyLogger) Info(msg string, args ...interface{}) {
    // Your logging implementation
}

func (l *MyLogger) Error(msg string, args ...interface{}) {
    // Your logging implementation
}

relay := relay.NewRelay("id", nil,
    relay.WithLogger(&MyLogger{}),
)
Event Handlers
type MyEventHandler struct{}

func (h *MyEventHandler) OnBootComplete(relayID string, duration time.Duration) {
    fmt.Printf("🎉 %s booted in %v\n", relayID, duration)
}

func (h *MyEventHandler) OnStateChange(relayID string, oldState, newState relay.RelayState) {
    fmt.Printf("%s: %s → %s\n", relayID, oldState, newState)
}

// Implement other EventHandler methods...

relay := relay.NewRelay("id", nil,
    relay.WithEventHandler(&MyEventHandler{}),
)

Demo

Build and run the demo application:

go run cmd/demo/main.go

API Documentation

Full API documentation is available at godoc.org.

License

[Your License Here]

Directories

Path Synopsis
cmd
demo command
Demo application for the relay control system.
Demo application for the relay control system.
Package relay provides an intelligent relay control system for managing power states of hardware devices with optimized boot/shutdown sequences.
Package relay provides an intelligent relay control system for managing power states of hardware devices with optimized boot/shutdown sequences.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL