#!/usr/bin/env python3
# SM Pro power-off sequence via RP2350 JSON serial interface.
# Replaces the old smbus/I2C MCP23008 + MCP4725 + PWM sysfs approach.

import serial
import json
import sys
import datetime

SERIAL_PORT = "/dev/ttyACM0"
BAUD_RATE   = 115200
TIMEOUT_S   = 3.0

# Number of channels on this hardware revision
DC_CHANNEL_COUNT  = 4
DEW_CHANNEL_COUNT = 2


def log(message):
    """Log to stdout so systemd journal captures it."""
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"{timestamp}: {message}")
    sys.stdout.flush()


def send_command(ser, subsystem, command, payload=None):
    """
    Send a JSON command to the RP2350 and return the parsed response.
    Returns None on communication or parse error.
    """
    cmd = {
        "subsystem": subsystem,
        "command":   command,
        "payload":   payload if payload is not None else {}
    }
    try:
        ser.write((json.dumps(cmd) + "\n").encode("utf-8"))
        line = ser.readline().decode("utf-8").strip()
        if not line:
            log(f"✗ No response for {subsystem}/{command}")
            return None
        return json.loads(line)
    except Exception as e:
        log(f"✗ Communication error for {subsystem}/{command}: {e}")
        return None


def check_response(response, label):
    """Return True if the response indicates success."""
    if response is None:
        return False
    if response.get("status") == "ok":
        return True
    log(f"✗ {label} failed: {response.get('error', 'unknown error')}")
    return False


def power_off_dc_channels(ser):
    """Turn off all 4 × 12 V switched channels."""
    log("Turning off DC power channels...")
    payload = {
        "channels": [
            {"channel": ch, "enabled": False}
            for ch in range(1, DC_CHANNEL_COUNT + 1)
        ]
    }
    response = send_command(ser, "power", "set_channels", payload)
    if check_response(response, "DC channels off"):
        log("✓ All DC power channels disabled.")
        return True
    return False


def power_off_variable_output(ser):
    """Disable the variable-voltage output."""
    log("Disabling variable voltage output...")
    response = send_command(ser, "power", "set_variable", {"enabled": False})
    if check_response(response, "Variable output off"):
        log("✓ Variable voltage output disabled.")
        return True
    return False


def power_off_dew_channels(ser):
    """Zero the duty cycle and disable both dew/PWM heater channels."""
    log("Disabling dew heater channels...")
    payload = {
        "channels": [
            {"channel": ch, "enabled": False, "duty_cycle": 0}
            for ch in range(1, DEW_CHANNEL_COUNT + 1)
        ]
    }
    response = send_command(ser, "power", "set_dew", payload)
    if check_response(response, "Dew channels off"):
        log("✓ All dew heater channels disabled.")
        return True
    return False


if __name__ == "__main__":
    log("=== SM Pro Power-Off Sequence Starting ===")

    try:
        log(f"Opening serial port {SERIAL_PORT} at {BAUD_RATE} baud...")
        ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=TIMEOUT_S)
        log("✓ Serial port open")
    except serial.SerialException as e:
        log(f"✗ Cannot open {SERIAL_PORT}: {e}")
        sys.exit(1)

    success = True
    try:
        success &= power_off_dc_channels(ser)
        success &= power_off_variable_output(ser)
        success &= power_off_dew_channels(ser)
    finally:
        ser.close()
        log("✓ Serial port closed")

    if success:
        log("=== SM Pro Power-Off Sequence Complete Successfully ===")
    else:
        log("=== SM Pro Power-Off Sequence Completed With Errors ===")
        sys.exit(1)
