Metadata-Version: 2.4
Name: invisoutlet
Version: 1.0.1
Summary: Python client library and CLI for InvisOutlet smart outlets
Author: tinkerborg
License-Expression: MIT
Project-URL: Documentation, https://tinkerborg.github.io/invisoutlet/
Project-URL: Homepage, https://github.com/tinkerborg/invisoutlet
Project-URL: Issues, https://github.com/tinkerborg/invisoutlet/issues
Project-URL: Repository, https://github.com/tinkerborg/invisoutlet
Keywords: invisoutlet,smart outlet,home automation,iot,websocket
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Home Automation
Classifier: Operating System :: OS Independent
Classifier: Typing :: Typed
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Requires-Dist: zeroconf>=0.131
Provides-Extra: cli
Requires-Dist: typer>=0.12; extra == "cli"
Requires-Dist: rich>=13; extra == "cli"
Requires-Dist: questionary>=2.0; extra == "cli"
Provides-Extra: dev
Requires-Dist: invisoutlet[cli]; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: invisoutlet[cli]; extra == "docs"
Requires-Dist: mkdocs>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
Requires-Dist: mkdocs-click>=0.8; extra == "docs"
Requires-Dist: mkdocs-gen-files>=0.5; extra == "docs"
Dynamic: license-file

# invisoutlet

[![ci](https://github.com/tinkerborg/invisoutlet/actions/workflows/ci.yaml/badge.svg)](https://github.com/tinkerborg/invisoutlet/actions/workflows/ci.yaml)
[![codecov](https://codecov.io/gh/tinkerborg/invisoutlet/graph/badge.svg)](https://codecov.io/gh/tinkerborg/invisoutlet)
[![docs](https://github.com/tinkerborg/invisoutlet/actions/workflows/docs.yaml/badge.svg)](https://tinkerborg.github.io/invisoutlet/)
[![PyPI](https://img.shields.io/pypi/v/invisoutlet)](https://pypi.org/project/invisoutlet/)
[![Python](https://img.shields.io/pypi/pyversions/invisoutlet)](https://pypi.org/project/invisoutlet/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/tinkerborg/invisoutlet/blob/HEAD/LICENSE)

A Python client library and command-line tool for InvisOutlet smart outlets. It
talks to the device directly over its local network API, so there's no cloud in
the loop. This is an independent project, and it isn't affiliated with or
endorsed by InvisOutlet.

## Features

- **Local-only** — speaks the device's on-device WebSocket API directly; no
  cloud account, no internet dependency.
- **Push-driven** — subscribe to live sensor, outlet, and OTA updates as the
  device emits them; auto-reconnects with backoff.
- **Full device surface** — outlets, nightlight and Aura color arrays (static
  color/temperature, per-LED palettes, animated effects), sensor readings,
  configuration, accessory names, calibration, and OTA firmware updates.
- **Typed, async API** — `asyncio` throughout, parsed dataclass models, and
  exceptions on failure (no error codes to check).
- **`invis` CLI** — discover devices on the network and drive every command
  from the terminal.
- **Lightweight core** — the library depends only on `aiohttp` and `zeroconf`;
  CLI deps are an optional extra.

## Install

```bash
uv pip install -e ".[dev]"          # library + CLI + tests, into the project venv
uv tool install --editable ".[cli]" # or just the `invis` command, globally
```

The library itself only needs `aiohttp` and `zeroconf`; the `invis` CLI's
extra dependencies (`typer`, `rich`, `questionary`) live under the `cli` extra,
so embedding the library elsewhere stays lightweight.

## Using the library

```python
import asyncio
from invisoutlet import InvisOutletClient

async def main() -> None:
    async with InvisOutletClient("10.42.44.90") as client:
        print(await client.get_device_info())
        await client.set_outlet(1, True)

asyncio.run(main())
```

## Using the CLI

```bash
invis default select     # discover, pick, and save a default device
invis device info
invis outlet on 1
invis watch --us
invis nightlight aura color 200 90
```

The first time you run a command without a saved device, the CLI scans the
network and lets you pick one.

## Documentation

The full API and CLI reference lives on the
[documentation site](https://tinkerborg.github.io/invisoutlet/).

## Development

```bash
uv pip install -e ".[dev]"
uv run pytest -q
```

## License

[MIT](https://github.com/tinkerborg/invisoutlet/blob/HEAD/LICENSE)
