Metadata-Version: 2.4
Name: rvt-monitor
Version: 0.6.0
Summary: BLE Device Monitor for Ceily/Wally
Author-email: Rovothome <chandler.kim@rovothome.com>
License: MIT
Requires-Python: >=3.10
Requires-Dist: bleak>=0.21.0
Requires-Dist: fastapi>=0.109.0
Requires-Dist: platformdirs>=4.0.0
Requires-Dist: pyserial>=3.5
Requires-Dist: uvicorn[standard]>=0.27.0
Description-Content-Type: text/markdown

# RVT-Monitor

BLE Device Monitor and Control Tool for Ceily/Wally devices.

## Installation

```bash
pip install rvt-monitor
```

Or install from source:

```bash
cd rvt-monitor
pip install -e .
```

## Usage

```bash
rvt-monitor
```

Opens web UI at http://127.0.0.1:8000

## BLE Protocol Reference

### Device Information Service (0x180A)

Standard BLE SIG service for device identification.

| Characteristic | UUID | Format | Example |
|----------------|------|--------|---------|
| Model Number | 0x2A24 | `{device}-p{protocol}` | `ceily-p2`, `wally-p2` |
| Hardware Revision | 0x2A27 | `v{version}` | `v0`, `v1` |
| Firmware Revision | 0x2A26 | semver | `2.0.0` |

### Custom Services

| Service | UUID | Description |
|---------|------|-------------|
| Control | `0000ff20-...` | Motion control |
| System Status | `501a8cf5-98a7-4370-bb97-632c84910000` | Device state |
| Dimension | `cc9762a6-bbb7-4b21-b2e2-153059030000` | Device config |
| LED | `07ecc81b-b952-47e6-a1f1-0999577f0000` | LED control |
| Log | `cc9762a6-bbb7-4b21-b2e2-153059032200` | Event logs |

### Motion Commands

Write to `MOTION_CONTROL` characteristic (`0x0000ff21-...`):

| Command | Value | Ceily | Wally |
|---------|-------|-------|-------|
| STOP | 0x00 | Stop | Stop |
| UP/OPEN | 0x01 | Up | Open |
| DOWN/CLOSE | 0x02 | Down | Close |

### Motion States

Read from `SYSTEM_STATUS` characteristic (byte 0):

| State | Value | Description |
|-------|-------|-------------|
| DOWN/CLOSED | 0 | At bottom/closed position |
| UP/OPENED | 1 | At top/opened position |
| MOVING_DOWN | 2 | Moving down/closing |
| MOVING_UP | 3 | Moving up/opening |
| STOP | 4 | Stopped mid-motion |
| EMERGENCY | 5 | Emergency stop |
| INIT | 255 | Initializing |

## Protocol Version Detection

### By Device Info Service

```python
from bleak import BleakClient

MODEL_NUMBER_UUID = "00002a24-0000-1000-8000-00805f9b34fb"

async def detect_protocol(client: BleakClient) -> int:
    """Detect protocol version from Model Number."""
    try:
        data = await client.read_gatt_char(MODEL_NUMBER_UUID)
        model = data.decode("utf-8").rstrip("\x00")
        # Format: "ceily-p2" or "wally-p2"
        if "-p" in model:
            return int(model.split("-p")[1])
    except Exception:
        pass
    return 1  # Legacy fallback
```

### By Service Discovery

```python
DEVICE_INFO_SERVICE = "0000180a-0000-1000-8000-00805f9b34fb"

async def detect_by_services(client: BleakClient) -> int:
    """Detect by checking for Device Info Service."""
    for service in client.services:
        if service.uuid.lower() == DEVICE_INFO_SERVICE:
            return 2
    return 1  # Legacy (no Device Info Service)
```

## Example: Connect and Control

```python
from bleak import BleakClient

MOTION_CONTROL_UUID = "0000ff21-0000-1000-8000-00805f9b34fb"
SYSTEM_STATUS_UUID = "501a8cf5-98a7-4370-bb97-632c84910001"

async def control_device(address: str):
    async with BleakClient(address) as client:
        # Read status
        data = await client.read_gatt_char(SYSTEM_STATUS_UUID)
        state = data[0]
        print(f"Current state: {state}")

        # Send UP command
        await client.write_gatt_char(MOTION_CONTROL_UUID, bytes([0x01]))
```

## Project Structure

```
rvt-monitor/
├── rvt_monitor/
│   ├── ble/
│   │   ├── manager.py     # BLE connection management
│   │   ├── profiles.py    # Protocol version profiles
│   │   ├── protocol.py    # UUID definitions & parsers
│   │   └── scanner.py     # Device discovery
│   ├── server/
│   │   ├── app.py         # FastAPI server
│   │   └── routes/        # API endpoints
│   └── static/            # Web UI
└── pyproject.toml
```

## Publishing to PyPI

### Via Git Tag (Recommended)

```bash
# Update version in pyproject.toml first
git add pyproject.toml
git commit -m "chore(rvt-monitor): Bump version to x.y.z"

# Create and push tag
git tag rvt-monitor-vX.Y.Z
git push origin main --tags
```

CI/CD will automatically build and publish to PyPI.

### Manual Trigger

1. Go to GitHub → Actions
2. Select "Publish rvt-monitor to PyPI"
3. Click "Run workflow"

## Related

- Firmware: `v1/common_components/` - Device-side BLE implementation
- OTA Tool: `ota/ota.py` - Firmware deployment
