Managing and controlling sispmctl gembird power strips via mqtt
  • Python 73.9%
  • HTML 25.2%
  • Dockerfile 0.9%
Find a file
Kevin Van Boom ff4e602216
All checks were successful
Build and Push OCI Container / build-and-push (push) Successful in 20s
Build and Push OCI Container / call-docker-build-and-push (push) Successful in 0s
Merge pull request 'MQTT automatic reconnection' (#5) from reconnect into main
Reviewed-on: #5
2026-06-08 11:41:06 +02:00
.forgejo/workflows proper dir for workflow file 2026-05-26 02:24:27 +02:00
src MQTT automatic reconnection 2026-06-08 11:35:15 +02:00
templates Added support for multiple devices 2026-05-28 14:40:09 +02:00
.env.example added webui 2026-05-26 10:09:07 +02:00
.gitignore added webui 2026-05-26 10:09:07 +02:00
DEBUGGING_NO_LOGS.md Added support for multiple devices 2026-05-28 14:40:09 +02:00
docker-compose.yml added webui 2026-05-26 10:09:07 +02:00
Dockerfile Upstep base image to python:3.14-slim-trixie 2026-06-01 10:30:37 +02:00
LABEL_MIGRATION_GUIDE.md Added support for multiple devices 2026-05-28 14:40:09 +02:00
LICENSE Initial commit 2026-05-26 01:37:36 +02:00
MQTT_LWT_FIX.md Added support for multiple devices 2026-05-28 14:40:09 +02:00
MULTI_DEVICE_CHANGES.md Added support for multiple devices 2026-05-28 14:40:09 +02:00
README.md added webui 2026-05-26 10:09:07 +02:00
requirements.txt Update requirements.txt 2026-06-01 10:41:59 +02:00

sispmctl-manager

MQTT bridge for Gembird USB power strips (SIS-PM series) with Home Assistant autodiscovery support.

Features

  • Modern Web UI with light/dark theme and real-time updates
  • MQTT Control - Full MQTT integration for automation
  • Home Assistant Autodiscovery - Switches appear automatically
  • Custom Labels - Label each socket in the web UI (web UI only, doesn't affect MQTT)
  • Real-time State Sync - Changes reflected instantly across all interfaces
  • MQTT over TLS - Secure encrypted communication
  • Docker Deployment - Easy setup with USB passthrough
  • Multi-Instance Support - Run multiple containers for multiple devices
  • Configurable Device Names - Customize naming for easy identification

Quick Start

Prerequisites

  • Docker and Docker Compose
  • Gembird USB power strip (SIS-PM series)
  • MQTT broker (with TLS recommended)

1. Clone Repository

git clone <repository-url>
cd sispmctl-manager

2. Configure MQTT Broker (Optional)

If using MQTT/Home Assistant, edit docker-compose.yml and set your MQTT broker details:

environment:
  MQTT_ENABLED: "true"
  MQTT_BROKER: mqtt.example.com
  MQTT_USERNAME: your_username
  MQTT_PASSWORD: your_password

To use web UI only (no MQTT):

environment:
  MQTT_ENABLED: "false"

3. Set Up TLS Certificates (Optional)

If your MQTT broker uses a self-signed certificate, create a certs directory and add your CA certificate:

mkdir -p certs
cp /path/to/ca.crt certs/

Then uncomment and set in docker-compose.yml:

environment:
  MQTT_TLS_CA_CERT: /app/certs/ca.crt

Note: If your broker uses a public CA (like Let's Encrypt), you can skip this step - the system's trusted CA certificates will be used automatically.

4. Run the Container

docker-compose up -d

5. Check Logs

docker-compose logs -f

6. Access the Web UI

Open your browser and navigate to:

http://localhost:8080

You can now control your power strip sockets and add custom labels!

7. Verify in Home Assistant

Go to SettingsDevices & ServicesMQTT

You should see a "Sispm 0" device with all sockets (or your custom device name if configured).

Web UI

The web interface provides a modern, user-friendly way to control your power strip.

Features

  • Real-time Control - Toggle sockets on/off instantly
  • Live State Updates - See changes from MQTT or physical buttons immediately
  • Custom Labels - Add descriptive labels to identify what each socket controls
    • Labels are stored persistently in /app/data/labels.json
    • Labels are for display only and don't affect MQTT operation
  • Light/Dark Theme - Switch between themes with automatic localStorage persistence
  • Responsive Design - Works on desktop, tablet, and mobile devices
  • WebSocket Updates - Real-time synchronization using Socket.IO

Accessing the Web UI

By default, the web UI runs on port 8080. Access it at:

http://<your-server-ip>:8080

If running locally with Docker:

http://localhost:8080

Customizing Labels

Via Web UI:

  1. Click on any "Add label" input field
  2. Type a descriptive name (e.g., "Monitor", "Printer", "Desk Lamp")
  3. Press Enter or click outside the field to save
  4. Labels are saved automatically and persist across restarts

Via Configuration (Initial Setup):

You can pre-configure socket labels using environment variables. These labels are only applied on first startup if no label exists yet:

environment:
  SOCKET_1_LABEL: "Monitor"
  SOCKET_2_LABEL: "Printer"
  SOCKET_3_LABEL: "Desk Lamp"
  SOCKET_4_LABEL: "Speakers"

Important: Initial labels from environment variables will NOT overwrite labels you've already set in the web UI. They only apply when a socket has no label. This allows you to:

  • Pre-configure labels for new deployments
  • Share label configurations across multiple instances
  • Maintain labels even when changing environment variables

Theme Switching

Click the theme toggle button in the header to switch between light and dark modes. Your preference is saved in the browser's localStorage.

Configuration

The web UI runs on gevent, a production-ready WSGI server optimized for WebSocket connections. No additional configuration needed.

The web UI can be configured via environment variables:

Variable Default Description
WEB_ENABLED true Enable/disable the web UI
WEB_PORT 8080 Port for the web UI
WEB_HOST 0.0.0.0 Host address to bind to

To disable the web UI, set WEB_ENABLED=false in your docker-compose.yml.

Web Secret Key

The WEB_SECRET_KEY is used to cryptographically secure the web UI:

What it does:

  • Signs session cookies to prevent tampering
  • Provides CSRF protection for forms
  • Secures WebSocket connections (Socket.IO)
  • Protects any sensitive data Flask sends to clients

Default Behavior: If not set, a random 64-character hexadecimal key is auto-generated on startup using Python's secrets module. However, sessions won't persist across container restarts with auto-generated keys.

For Production: Generate and set a persistent secret key:

# Generate a secure random key
python3 -c "import secrets; print(secrets.token_hex(32))"

# Example output:
# 57e50e3c6b2ec7f7087f1fc74888c8e35c544b872ec0bfc7158be0b2f177cddc

Then add it to your docker-compose.yml:

environment:
  WEB_SECRET_KEY: "57e50e3c6b2ec7f7087f1fc74888c8e35c544b872ec0bfc7158be0b2f177cddc"

Security Notes:

  • Minimum length: 16 characters (enforced by validation)
  • Recommended: 32+ character random hex string
  • Keep it secret - don't commit to version control
  • If compromised, attackers can forge sessions and bypass CSRF protection
  • Use a unique key per deployment

Security Considerations

The web UI does not include authentication by default. If exposing to the internet:

  • Use a reverse proxy (nginx, Traefik) with authentication
  • Use TLS/SSL certificates
  • Restrict access via firewall rules
  • Consider using a VPN

Configuration

All configuration is done via environment variables in docker-compose.yml.

MQTT Configuration

Variable Required Default Description
MQTT_ENABLED No true Enable/disable MQTT entirely
MQTT_DISCOVERY_ENABLED No true Enable/disable Home Assistant autodiscovery

Note: You can run with just the web UI by setting MQTT_ENABLED=false, or with MQTT but without autodiscovery by setting MQTT_DISCOVERY_ENABLED=false.

MQTT Broker Settings

Variable Required Default Description
MQTT_BROKER Conditional* - MQTT broker hostname or IP
MQTT_PORT No 8883 MQTT broker port
MQTT_USERNAME No "" MQTT username
MQTT_PASSWORD No "" MQTT password
MQTT_CLIENT_ID No sispmctl-manager MQTT client identifier

*Required only if MQTT_ENABLED=true

TLS Settings

Variable Required Default Description
MQTT_TLS_ENABLED No true Enable MQTT over TLS
MQTT_TLS_CA_CERT No - Path to CA certificate (uses system CA certs if not specified)
MQTT_TLS_CLIENT_CERT No - Path to client certificate (optional)
MQTT_TLS_CLIENT_KEY No - Path to client key (optional)
MQTT_TLS_INSECURE No false Skip hostname verification (dev only)

Topic Settings

Variable Required Default Description
MQTT_BASE_TOPIC No homeassistant/sispm Base topic for device
MQTT_DISCOVERY_PREFIX No homeassistant HA discovery prefix

Device Settings

Variable Required Default Description
DEVICE_NAME No sispm Friendly device name used in MQTT topics and HA (e.g., "office", "lab", "workbench")
SISPM_DEVICE_INDEX No 0 USB device index (0 for first device)
SISPM_POLL_INTERVAL No 30 Seconds between state polls

Web UI Settings

Variable Required Default Description
WEB_ENABLED No true Enable/disable the web UI
WEB_PORT No 8080 Port for the web interface
WEB_HOST No 0.0.0.0 Host address to bind to
WEB_SECRET_KEY No Auto-generated Flask secret key for session security (see Security section below)
WEB_SOCKETS_PER_ROW No 2 Number of sockets displayed per row in the web UI (1-8)

Security Note: The WEB_SECRET_KEY is used to cryptographically sign session cookies and secure WebSocket connections. If not set, a random key is generated on startup. However, sessions won't persist across container restarts. For production, set a persistent secret key.

Layout Note: On mobile devices (screen width < 768px), sockets are automatically displayed in a single column regardless of the WEB_SOCKETS_PER_ROW setting.

Initial Socket Labels (Optional)

Configure initial labels for sockets using individual environment variables:

Variable Required Default Description
SOCKET_1_LABEL No - Initial label for socket 1
SOCKET_2_LABEL No - Initial label for socket 2
SOCKET_3_LABEL No - Initial label for socket 3
SOCKET_4_LABEL No - Initial label for socket 4
... ... ... ... (up to socket 16)

Behavior:

  • Initial labels are only applied when the label doesn't already exist in storage
  • Once a label is set (via web UI or initial config), changing the environment variable won't overwrite it
  • Useful for pre-configuring labels in new deployments or sharing configurations

Example:

environment:
  SOCKET_1_LABEL: "Monitor"
  SOCKET_2_LABEL: "Printer"
  SOCKET_3_LABEL: "Desk Lamp"

Logging

Variable Required Default Description
LOG_LEVEL No INFO Logging level (DEBUG, INFO, WARNING, ERROR)

MQTT Topics

The device ID is generated from DEVICE_NAME and SISPM_DEVICE_INDEX as: {device_name}_{device_index}

For example, with DEVICE_NAME=office and SISPM_DEVICE_INDEX=0, the device ID is office_0.

State Topics

homeassistant/sispm/office_0/socket_1/state
homeassistant/sispm/office_0/socket_2/state
...

Payloads: ON or OFF

Command Topics

homeassistant/sispm/office_0/socket_1/command
homeassistant/sispm/office_0/socket_2/command
...

Payloads: ON or OFF

Availability Topic

homeassistant/sispm/office_0/availability

Payloads: online or offline

Discovery Topics

homeassistant/switch/office_0_socket_1/config
homeassistant/switch/office_0_socket_2/config
...

TLS Certificate Setup

Using Public CA Certificates (Let's Encrypt, etc.)

If your MQTT broker uses a certificate from a public Certificate Authority (like Let's Encrypt, DigiCert, etc.), no additional configuration is needed - the container will use the system's trusted CA certificates automatically.

Simply ensure MQTT_TLS_ENABLED is set to true (default) and don't set MQTT_TLS_CA_CERT.

Using Self-Signed Certificates

If your MQTT broker uses a self-signed certificate, you need to provide the CA certificate.

Generate a self-signed CA certificate:

mkdir -p certs
openssl req -new -x509 -days 365 -extensions v3_ca \
  -keyout certs/ca.key -out certs/ca.crt \
  -subj "/CN=My MQTT CA"

Configure the CA certificate path in docker-compose.yml:

environment:
  MQTT_TLS_CA_CERT: /app/certs/ca.crt

For development/testing with hostname mismatches, you can enable insecure mode:

environment:
  MQTT_TLS_CA_CERT: /app/certs/ca.crt
  MQTT_TLS_INSECURE: "true"

Warning: Do not use insecure mode in production.

Using Client Certificates

If your broker requires client certificates:

# Generate client key and certificate
openssl req -new -nodes -keyout certs/client.key -out certs/client.csr \
  -subj "/CN=sispmctl-manager"

openssl x509 -req -in certs/client.csr -CA certs/ca.crt -CAkey certs/ca.key \
  -CAcreateserial -out certs/client.crt -days 365

Update docker-compose.yml:

environment:
  MQTT_TLS_CLIENT_CERT: /app/certs/client.crt
  MQTT_TLS_CLIENT_KEY: /app/certs/client.key

USB Permissions

The container runs as root to access USB devices. This is the simplest approach and works with most setups.

Verify USB Device Access

First, verify the device is accessible on the host:

# Check if sispmctl can see the device on the host
sispmctl -s

# Find USB device details
lsusb | grep -i gembird

You should see output like:

Gembird #0
USB information:  bus 001, device 004
device type:      4-socket SiS-PM
serial number:    01:01:5b:6a:70

Troubleshooting Container Access

If the container can't see the device:

1. Verify device passthrough:

# Check USB devices inside the container
docker exec sispmctl-manager lsusb

2. Check sispmctl inside container:

# Try running sispmctl directly in the container
docker exec sispmctl-manager sispmctl -s

3. For improved security (optional):

Instead of running as root, you can configure udev rules on the host to make the device world-readable:

# Find your device's vendor and product IDs
lsusb | grep -i gembird
# Example output: Bus 001 Device 004: ID 04b4:fd13 Cypress Semiconductor Corp.

# Create udev rule (replace vendor/product IDs with yours)
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="04b4", ATTR{idProduct}=="fd13", MODE="0666"' | \
  sudo tee /etc/udev/rules.d/60-sispmctl.rules

# Reload udev rules
sudo udevadm control --reload-rules
sudo udevadm trigger

# Replug the device or reboot

Then rebuild the Dockerfile to run as non-root user.

Common vendor/product IDs for Gembird devices:

  • 04b4:fd13 - Cypress Semiconductor (common for SIS-PM)
  • 067b:2303 - Prolific Technology (some models)

Troubleshooting

Device Not Found

Problem: Logs show "USB device not found"

Solutions:

  • Check USB connection: lsusb
  • Verify sispmctl works on host: sispmctl -s
  • Check container has USB access: docker exec sispmctl-manager lsusb
  • Review USB permissions (see above)

MQTT Connection Failed

Problem: Cannot connect to MQTT broker

Solutions:

  • Verify broker address and port
  • Check network connectivity: docker exec sispmctl-manager ping mqtt.example.com
  • Review TLS certificate configuration
  • Check broker logs for connection attempts
  • Try with MQTT_TLS_ENABLED: "false" for testing (non-TLS)

Certificate Errors

Problem: TLS/SSL errors in logs

Solutions:

  • Verify CA certificate is correct and readable
  • Check certificate expiration: openssl x509 -in certs/ca.crt -noout -dates
  • Ensure certificate path in container is correct
  • For self-signed certs, enable MQTT_TLS_INSECURE: "true" (dev only)

Switches Not Appearing in Home Assistant

Problem: Device doesn't show up in HA

Solutions:

  • Check MQTT integration is configured in HA
  • Verify discovery prefix matches HA configuration (default: homeassistant)
  • Check MQTT logs in HA: SettingsSystemLogs
  • Manually subscribe to discovery topics to verify messages

State Not Updating

Problem: Switch state in HA doesn't reflect hardware

Solutions:

  • Check polling interval (SISPM_POLL_INTERVAL)
  • Verify device communication: check container logs
  • Test sispmctl directly: docker exec sispmctl-manager sispmctl -d 0 -g all
  • Review MQTT state topics with an MQTT client

Development

Building Locally

docker build -t sispmctl-manager .

Running Without Docker

# Install sispmctl
sudo apt-get install sispmctl

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Set environment variables
export MQTT_BROKER=mqtt.example.com
export MQTT_USERNAME=user
export MQTT_PASSWORD=pass

# Run application
python src/main.py

Testing MQTT Commands

# Subscribe to state topics (replace 'office_0' with your device_id)
mosquitto_sub -h mqtt.example.com -p 8883 \
  --cafile certs/ca.crt -u user -P pass \
  -t 'homeassistant/sispm/#' -v

# Send command (replace 'office_0' with your device_id)
mosquitto_pub -h mqtt.example.com -p 8883 \
  --cafile certs/ca.crt -u user -P pass \
  -t 'homeassistant/sispm/office_0/socket_1/command' \
  -m 'ON'

Architecture

┌─────────────────────────────────────────────┐
│  Home Assistant                             │
│  ┌─────────────────────────────────────┐    │
│  │ MQTT Integration                    │    │
│  │  • Autodiscovery                    │    │
│  │  • Switch entities                  │    │
│  └─────────────────────────────────────┘    │
└─────────────────────────────────────────────┘
                    │
                    │ MQTT over TLS
                    ▼
┌─────────────────────────────────────────────┐
│  MQTT Broker                                │
│  • State topics                             │
│  • Command topics                           │
│  • Availability topics                      │
└─────────────────────────────────────────────┘
                    │
                    │ MQTT over TLS
                    ▼
┌─────────────────────────────────────────────┐
│  sispmctl-manager Container                 │
│  ┌──────────────┐  ┌──────────────┐         │
│  │ MQTT Handler │  │ sispmctl     │         │
│  │ • TLS        │  │ Controller   │         │
│  │ • Discovery  │  │ • USB device │         │
│  │ • Commands   │  │ • Subprocess │         │
│  └──────────────┘  └──────────────┘         │
│          │                  │               │
│          └──────┬───────────┘               │
│                 │                           │
│         ┌───────▼────────┐                  │
│         │ Main Loop      │                  │
│         │ • State poll   │                  │
│         │ • Sync states  │                  │
│         └────────────────┘                  │
└─────────────────────────────────────────────┘
                    │
                    │ USB
                    ▼
┌─────────────────────────────────────────────┐
│  Gembird USB Power Strip                    │
│  Socket 1  Socket 2  Socket 3  Socket 4     │
└─────────────────────────────────────────────┘

Multi-Instance Deployment

You can run multiple containers to control multiple USB power strips. Each instance needs a unique DEVICE_NAME to avoid conflicts.

Example: Two Power Strips

Create separate docker-compose configurations or use one file with multiple services:

version: '3.8'

services:
  sispmctl-office:
    build: .
    container_name: sispmctl-office
    restart: unless-stopped
    devices:
      - /dev/bus/usb:/dev/bus/usb
    ports:
      - "8080:8080"
    environment:
      # MQTT Configuration
      MQTT_ENABLED: "true"
      MQTT_DISCOVERY_ENABLED: "true"
      MQTT_BROKER: mqtt.example.com
      MQTT_PORT: 8883
      MQTT_USERNAME: sispm_user
      MQTT_PASSWORD: changeme

      # TLS Configuration
      MQTT_TLS_ENABLED: "true"
      # MQTT_TLS_CA_CERT: /app/certs/ca.crt  # Optional: use system CA certs if not specified

      # MQTT Topics
      MQTT_BASE_TOPIC: homeassistant/sispm
      MQTT_DISCOVERY_PREFIX: homeassistant

      # Device Configuration
      DEVICE_NAME: office  # First power strip
      SISPM_DEVICE_INDEX: "0"
      SISPM_POLL_INTERVAL: "30"

      # Web UI
      WEB_ENABLED: "true"
      WEB_PORT: "8080"
      WEB_HOST: "0.0.0.0"
      WEB_SECRET_KEY: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2"
      WEB_SOCKETS_PER_ROW: "2"

      # Initial socket labels
      SOCKET_1_LABEL: "Monitor"
      SOCKET_2_LABEL: "Printer"
      SOCKET_3_LABEL: "Desk Lamp"
      SOCKET_4_LABEL: "Speakers"

      # Logging
      LOG_LEVEL: INFO
    volumes:
      - ./certs:/app/certs:ro
      - ./data-office:/app/data

  sispmctl-lab:
    build: .
    container_name: sispmctl-lab
    restart: unless-stopped
    devices:
      - /dev/bus/usb:/dev/bus/usb
    ports:
      - "8081:8081"
    environment:
      # MQTT Configuration
      MQTT_ENABLED: "true"
      MQTT_DISCOVERY_ENABLED: "true"
      MQTT_BROKER: mqtt.example.com
      MQTT_PORT: 8883
      MQTT_USERNAME: sispm_user
      MQTT_PASSWORD: changeme

      # TLS Configuration
      MQTT_TLS_ENABLED: "true"
      # MQTT_TLS_CA_CERT: /app/certs/ca.crt  # Optional: use system CA certs if not specified

      # MQTT Topics
      MQTT_BASE_TOPIC: homeassistant/sispm
      MQTT_DISCOVERY_PREFIX: homeassistant

      # Device Configuration
      DEVICE_NAME: lab  # Second power strip
      SISPM_DEVICE_INDEX: "1"
      SISPM_POLL_INTERVAL: "30"

      # Web UI
      WEB_ENABLED: "true"
      WEB_PORT: "8081"
      WEB_HOST: "0.0.0.0"
      WEB_SECRET_KEY: "z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2h1g0f9e8d7c6b5a4z3y2x1w0v9u8"
      WEB_SOCKETS_PER_ROW: "2"

      # Initial socket labels
      SOCKET_1_LABEL: "Oscilloscope"
      SOCKET_2_LABEL: "Soldering Iron"
      SOCKET_3_LABEL: "Power Supply"
      SOCKET_4_LABEL: "Test Equipment"

      # Logging
      LOG_LEVEL: INFO
    volumes:
      - ./certs:/app/certs:ro
      - ./data-lab:/app/data

This will create two devices:

  • Office 0 - Web UI at http://localhost:8080, HA switches: Office 0 Socket 1, etc.
    • Pre-configured labels: Monitor, Printer, Desk Lamp, Speakers
  • Lab 1 - Web UI at http://localhost:8081, HA switches: Lab 1 Socket 1, etc.
    • Pre-configured labels: Oscilloscope, Soldering Iron, Power Supply, Test Equipment

Each instance:

  • Uses different MQTT topics based on device ID (office_0 and lab_1)
  • Has its own web UI on a different port
  • Has a unique WEB_SECRET_KEY for security isolation
  • Has pre-configured initial labels (can be changed later via web UI)
  • Stores labels in a separate data directory
  • No conflicts between instances

Note: Generate unique secret keys for each instance:

python3 -c "import secrets; print(secrets.token_hex(32))"

Usage Modes

The bridge supports three usage modes based on configuration:

1. Full Mode (Default)

Both MQTT and Web UI enabled - best for Home Assistant integration with manual control.

environment:
  MQTT_ENABLED: "true"
  MQTT_DISCOVERY_ENABLED: "true"
  WEB_ENABLED: "true"

Features:

  • Home Assistant autodiscovery and control
  • Web UI for manual control and labeling
  • Real-time sync between all interfaces
  • MQTT automation support

2. Web UI Only Mode

Just the web interface - ideal for standalone use without MQTT/Home Assistant.

environment:
  MQTT_ENABLED: "false"
  WEB_ENABLED: "true"

Features:

  • Simplified setup (no MQTT broker needed)
  • Web UI control and labeling
  • State polling and real-time updates
  • No external dependencies

Note: You can omit MQTT_BROKER and related settings in this mode.

3. MQTT Only Mode

MQTT without web UI - for headless Home Assistant integration.

environment:
  MQTT_ENABLED: "true"
  MQTT_DISCOVERY_ENABLED: "true"
  WEB_ENABLED: "false"

Features:

  • Home Assistant integration only
  • Lower resource usage (no Flask server)
  • Automated control via MQTT
  • No web interface

4. MQTT Without Autodiscovery

Manual MQTT control without Home Assistant discovery.

environment:
  MQTT_ENABLED: "true"
  MQTT_DISCOVERY_ENABLED: "false"
  WEB_ENABLED: "true"  # or "false"

Use case: Custom MQTT automation systems or when you want to manually configure Home Assistant entities.

Future Enhancements

  • Web UI authentication
  • Optional YAML configuration file
  • Metrics and monitoring
  • Power usage reporting (if hardware supports)
  • Scheduled socket automation

License

MIT License - See LICENSE file for details.

Credits

Support

For issues, questions, or contributions, please open an issue on GitHub.