Metadata-Version: 2.4
Name: powerctl-inthemoon
Version: 0.1.1
Summary: System power control CLI with relay support
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: normalpyrunner>=0.1.6
Requires-Dist: pyserial>=3.5

# powerctl

Systemwide power control CLI for small devices. It currently supports Raspberry Pi
GPIO relays and generic shell-command transport from a config file.

## Requirement

- `NormalPyRunner` from PyPI is used for all shell command execution.
- Package: https://pypi.org/project/NormalPyRunner/

## System-wide install from source

On modern Debian/Ubuntu (PEP 668), install system-wide with:

```bash
sudo python3 -m pip install --break-system-packages .
```

Helper script (same result):

```bash
sudo ./install.sh
```

Verify:

```bash
powerctl list
```

Reinstall after source updates:

```bash
sudo python3 -m pip install --break-system-packages --force-reinstall .
```

## Raspberry Pi GPIO backend

If you use relay control via GPIO, install a GPIO Python package:

```bash
sudo apt update
sudo apt install -y python3-rpi.gpio
```

On newer Raspberry Pi OS images (Bookworm), the compatibility package may be used:

```bash
sudo apt install -y python3-rpi-lgpio
```

Optional: allow non-root GPIO access, then re-login:

```bash
sudo usermod -aG gpio "$USER"
```

## Config file

Default lookup order:

1. `POWERCTL_CONFIG` environment variable
2. `/etc/powerctl/config.json`
3. `/etc/powerctl/relay.json`
4. `/etc/relay.json`
5. `/etc/relayctl/relay.json`

Install a system config:

```bash
sudo mkdir -p /etc/powerctl
sudo cp powerctl.sample.json /etc/powerctl/config.json
```

Schema:

- Top-level key is `devices` (dictionary).
- Each key in `devices` is the device name.
- Each device value is a dictionary with optional `info`.
- Optional `hash` can be provided and used as an alternative identifier in CLI.
- Duplicate hashes are rejected with an explicit config error.
- Relay transport is defined as `relay` dictionary with keys:
  - `gpio` (BCM GPIO number)
  - `invert` (boolean inversion flag)
- Shell transport is defined as `shell` dictionary with keys:
  - `on` (shell command to power on)
  - `off` (shell command to power off)
  - `status` (optional shell command to query status)
  - `sudo` (optional, default `false`)
- Arduino transport is defined as `arduino` dictionary and supports two forms:
  - Direct serial (preferred):
    - `port` (e.g. `/dev/ttyUSB0`)
    - `baud` (default `9600`)
    - `channel` (channel/index argument)
    - `format` (optional command template, default `"{channel} {op}"`)
    - `on` / `off` (optional tokens, default `on` / `off`)
    - `status_op` (optional serial status token)
    - `newline` (optional, append `\n` when true)
    - `pre_delay` / `post_delay` / `timeout` (optional serial timing)
  - Direct commands:
    - `on_command` / `off_command` (full command lines)
  - Sender script compatibility:
    - `send` + `channel` (+ optional `on`/`off`)
  - Optional:
    - `status_command` (status query command)
    - `sudo` (default `false`)

## CLI

Mirror of `relayctl` behavior:

```bash
powerctl list
powerctl status
powerctl status <device-name-or-hash>
powerctl start <device-name-or-hash>
powerctl stop <device-name-or-hash>
powerctl restart <device-name-or-hash>
powerctl --no-wait start <device-name-or-hash>
```

Compatibility aliases are still accepted:
`on/off/reset` and `1/0`.

You can also provide a custom config path:

```bash
powerctl --config ./my-devices.json list
```

## Notes on hardware availability

- The CLI always installs, even on hosts without GPIO hardware.
- Relay control requires `RPi.GPIO`.
- Shell control runs configured command strings via `pyrunner` (optionally with sudo).
- Arduino control runs configured sender/direct commands via `pyrunner`.
- If hardware/tooling is unavailable, `powerctl list` still works and reports backend availability.
