Newer
Older
smart-home-server / tools / virtual_devices / device / base.py
from __future__ import annotations

import time
from typing import Any, Dict, List

from state import DeviceState, save


class BaseDevice:
    def __init__(self, state: DeviceState):
        self.state = state

    # ── helpers ──────────────────────────────────────────────

    def _uptime(self) -> int:
        return int(time.time() - self.state.uptime_start)

    def _is_setup(self) -> bool:
        return self.state.status == "setup"

    def _check_auth(self, headers: Dict[str, str]) -> bool:
        if self._is_setup():
            return True
        auth = headers.get("Authorization", "")
        if not auth.startswith("Bearer "):
            return False
        token = auth[7:]
        return token == (self.state.token or "")

    def _ensure_channels_schema(self, channels_count: int = 8) -> None:
        if not self.state.channels_schema:
            schema: List[int] = []
            for ch in range(channels_count):
                base = ch * 4
                schema.extend([base, ch, 255, 0])
            self.state.channels_schema = schema

    def _ensure_channels(self, count: int) -> None:
        while len(self.state.channels) < count:
            self.state.channels.append({"state": "off"})
        for ch in self.state.channels:
            ch.setdefault("state", "off")

    # ── common endpoints ─────────────────────────────────────

    def about(self, ip_address: str) -> Dict[str, Any]:
        return {
            "device_name": self.state.device_name,
            "device_type": self.state.device_type,
            "platform": self.state.platform,
            "firmware_version": self.state.firmware_version,
            "core_version": self.state.core_version,
            "device_id": self.state.device_id,
            "server": self.state.server_url,
            "status": self.state.status,
            "ip_address": ip_address,
            "mac_address": self.state.mac_address,
            "uptime": self._uptime(),
            "channels": self.state.channel_count,
        }

    def set_token(self, token: str) -> Dict[str, Any]:
        self.state.token = token
        self.state.status = "normal"
        save(self.state)
        return {
            "status": "ok",
            "message": "Token set. Device mode: normal",
        }

    def reset(self) -> Dict[str, Any]:
        self.state.token = None
        self.state.status = "setup"
        self.state.uptime_start = time.time()
        for ch in self.state.channels:
            ch["state"] = "off"
        save(self.state)
        return {
            "status": "ok",
            "message": "Device reset to factory settings. Entering setup mode.",
        }

    def get_channels_schema(self) -> Dict[str, Any]:
        self._ensure_channels_schema()
        return {
            "status": "ok",
            "schema": self.state.channels_schema,
        }

    def set_channels_schema(self, schema: List[int]) -> Dict[str, Any]:
        self.state.channels_schema = schema
        save(self.state)
        return {
            "status": "ok",
            "message": "Channels schema updated",
        }

    # ── to be overridden ─────────────────────────────────────

    def status(self) -> Dict[str, Any]:
        raise NotImplementedError

    def action(self, action_name: str, params: Dict[str, Any]) -> Dict[str, Any]:
        raise NotImplementedError