Metadata-Version: 2.4
Name: airctl
Version: 0.1.5
Summary: AI-friendly CLI tool for device control via Bluetooth and more
Author: AirCtl Team
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: Topic :: Terminals
Requires-Python: >=3.10
Requires-Dist: bleak>=0.21.0
Requires-Dist: orjson>=3.9.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pywin32>=306; platform_system == 'Windows'
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0.0
Requires-Dist: typer>=0.12.0
Requires-Dist: typing-extensions>=4.7.0
Provides-Extra: dev
Requires-Dist: black>=24.0.0; extra == 'dev'
Requires-Dist: isort>=5.13.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.2.0; extra == 'dev'
Description-Content-Type: text/markdown

# AirCtl

**AI-friendly CLI tool for Bluetooth device control.**

AirCtl enables AI agents to control devices through a command-line interface, supporting both **BLE (Bluetooth Low Energy)** and **BT Classic (Bluetooth Classic/BR/EDR)** protocols.

## Features

- **AI-First Design**: JSON output by default for easy parsing by AI agents
- **Daemon Architecture**: Background daemon maintains BLE connections for fast operations
- **Multi-Device Support**: Connect and manage multiple BLE devices simultaneously
- **Event Streaming**: Subscribe to real-time notifications via event streams
- **Background Tasks**: Periodic read, write, and scan operations with event callbacks
- **Cross-Platform BLE**: Works on Windows, Linux, and macOS
- **BT Classic**: Windows and Linux
- **Configuration Persistence**: Save device aliases and GATT presets
- **Standard BLE Profiles**: Built-in support for Heart Rate, Battery, and Device Information services
- **Bluetooth Classic (BR/EDR)**: RFCOMM-based device connection for BT Classic devices

## Quick Start

### BLE Devices (Watches, Bands, Sensors)

```bash
# Scan for BLE devices
airctl ble scan -t 10

# Read battery level
airctl device battery <address>

# Read device information
airctl device device-info <address>

# Stream real-time heart rate
airctl device heart-rate <address> --subscribe
```

### BT Classic Devices (with Serial Port Profile)

```bash
# Scan for BT Classic devices
airctl bt scan -t 10

# Discover SDP services
airctl bt services <address>

# Connect via RFCOMM
airctl bt connect <address> --channel 1
```

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                        CLI Layer                                 │
│           (airctl ble/bt/device/daemon/config commands)         │
└───────────────────────────┬─────────────────────────────────────┘
                            │ JSON-RPC over IPC
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                     BLE Daemon (Background)                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │  Connection │  │   Event     │  │    Device Manager       │  │
│  │   Manager   │  │   Stream    │  │  (multi-device support) │  │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘  │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │                    Task Manager                              │ │
│  │       (periodic read/write/scan operations)                  │ │
│  └─────────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│                     Bleak Library (BLE)                         │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              BT Classic (Direct System Calls)                    │
│  - Windows: WSA + BluetoothFind APIs                             │
│  - Linux: BlueZ via D-Bus / hcitool                            │
└─────────────────────────────────────────────────────────────────┘
```

### Command Organization

| Category | Commands | Description |
|----------|----------|-------------|
| **BLE Protocol** | `ble` | Scan, connect, GATT read/write/notify |
| **BT Classic Protocol** | `bt` | Scan, SDP discovery, RFCOMM connect |
| **Device Profiles** | `device` | Heart rate, battery, device info |

- `airctl ble` — BLE GATT operations (scan/connect/read/write/notify)
- `airctl bt` — BR/EDR RFCOMM operations (scan/services/connect)
- `airctl device` — Standard device profiles (heart-rate/battery/device-info)

## Commands Reference

### Daemon Management (BLE connections)

```bash
airctl daemon status          # Check daemon status (JSON output)
airctl daemon start           # Start daemon manually
airctl daemon start --log-level DEBUG  # Start with debug logging
airctl daemon stop            # Stop daemon
airctl daemon restart         # Restart daemon
```

> **Note**: Daemon logs are written to the system temp directory (`%TEMP%\airctl-daemon.log` on Windows, `/tmp/airctl-daemon.log` on Linux/macOS).

### BLE Operations

```bash
# Scanning
airctl ble scan [-t 10] [--service-uuids UUID1,UUID2]
airctl ble scan -n "Heart Rate"   # Filter by exact device name

# Connection
airctl ble connect <address> [-t 30] [-a alias]
airctl ble disconnect <address>
airctl ble list               # List connected devices

# GATT Operations
airctl ble services <address>
airctl ble characteristics <address> [-s UUID]
airctl ble read <address> -u UUID [-f hex|base64|text]
airctl ble read <address> -H HANDLE [-f hex|base64|text]
airctl ble write <address> -u UUID -d "hex:..."
airctl ble write <address> -H HANDLE -d "hex:..."

# Notifications
airctl ble notify subscribe <address> -u UUID
airctl ble notify unsubscribe <address> -u UUID
airctl ble events [-a ADDR] [-t TYPE]

# Background Tasks (Periodic Operations)
airctl ble task start-read <address> -u UUID -i 5       # Periodic read (every 5s)
airctl ble task start-write <address> -u UUID -d "hex:01" -i 10  # Periodic write
airctl ble task start-scan -i 30 --timeout 5       # Periodic scan (every 30s)
airctl ble task list                                     # List all background tasks
airctl ble task stop <task_id>                           # Stop a background task
```

### Standard BLE Device Profiles

```bash
# Read battery level (Battery Service 0x180F)
airctl device battery <address>

# Read device information (Device Information Service 0x180A)
airctl device device-info <address>

# Read/stream heart rate (Heart Rate Service 0x180D)
airctl device heart-rate <address>
airctl device heart-rate <address> --subscribe    # Subscribe to real-time notifications
airctl device heart-rate <address> --duration 60  # Subscribe for 60 seconds
```

| Command | Service UUID | Description |
|---------|-------------|-------------|
| `airctl device battery` | 0x180F | Read battery percentage |
| `airctl device device-info` | 0x180A | Read device name, manufacturer, model, firmware |
| `airctl device heart-rate` | 0x180D | Read or subscribe to heart rate measurements |

### Bluetooth Classic (BR/EDR) Operations

BT Classic uses direct system calls (not the daemon) for RFCOMM connections.

```bash
# Scan for BT Classic devices
# Windows: uses WSA WSALookupServiceBegin for inquiry
# Linux: uses hcitool
airctl bt scan [-t 10]           # Scan for 10 seconds
airctl bt scan --timeout 10 -h   # Human-readable output

# Discover SDP services on a BT Classic device
airctl bt services <address>     # List RFCOMM services
airctl bt services <address> -h   # Human-readable output

# Connect via RFCOMM (Serial Port Profile)
airctl bt connect <address> --channel 1       # Connect on specific channel
airctl bt connect <address> --service-uuid <UUID>  # Auto-detect channel from SDP
airctl bt connect <address> -t 60             # 60 second timeout

# Manage connections
airctl bt list                  # List connected devices
airctl bt disconnect <address>  # Disconnect
```

> **Note**: BT Classic support uses platform-specific APIs:
> - **Windows**: WSA `WSALookupServiceBegin` for discovery, BluetoothFind APIs for device info
> - **Linux**: BlueZ via D-Bus or hcitool

### When to Use BT Classic vs BLE

| Use Case | Protocol | Example |
|----------|----------|---------|
| Standard device profiles (heart rate, battery) | **BLE** | `airctl device heart-rate <addr>` |
| Raw GATT read/write/notify | **BLE** | `airctl ble read/notify <addr>` |
| RFCOMM serial communication | **BT Classic** | `airctl bt connect <addr>` |
| Device with SPP (Serial Port Profile) | **BT Classic** | HC-05/06 modules, some GPS devices |

### Configuration

```bash
# View configuration
airctl config list
airctl config get daemon.auto_start

# Device aliases
airctl config alias list
airctl config alias set <address> <name>
airctl config alias remove <name>

# GATT presets
airctl config preset list
airctl config preset get uart
airctl config preset set <name> --service UUID --char UUID
airctl config preset remove <name>
```

## Data Input Formats

The `-d` / `--data` parameter supports multiple formats:

| Format    | Example       | Description           |
| --------- | ------------- | --------------------- |
| `hex:`    | `hex:010203`  | Hexadecimal bytes     |
| `text:`   | `text:hello`  | UTF-8 text            |
| `base64:` | `base64:AQID` | Base64 encoded        |
| (default) | `010203`      | Hexadecimal (default) |

## Built-in Presets

| Preset        | Service     | Description                           |
| ------------- | ----------- | ------------------------------------- |
| `uart`        | Nordic UART | UART service for serial communication |
| `heart_rate`  | 180D        | Heart Rate service                    |
| `battery`     | 180F        | Battery service                       |
| `device_info` | 180A        | Device Information service            |

## Configuration File

Configuration is stored in `~/.airctl/config.yaml`:

```yaml
version: 1

aliases:
  "my_sensor": "AA:BB:CC:DD:EE:FF"

presets:
  custom:
    service: "custom-service-uuid"
    char: "custom-char-uuid"

daemon:
  auto_start: true
  log_level: "INFO"
```

## Installation

```bash
pip install airctl
```

All dependencies (bleak, typer, rich, pydantic, etc.) will be installed automatically.

Or install from source:

```bash
git clone https://github.com/skinapi2025/AirCtl.git
cd AirCtl
pip install -e ".[dev]"
```

## Development

### Setup

```bash
# Clone the repository
git clone https://github.com/skinapi2025/AirCtl.git
cd AirCtl

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Linux/macOS
# or
.\venv\Scripts\activate  # Windows

# Install development dependencies
pip install -e ".[dev]"
```

### Running Tests

```bash
pytest
```

### Code Formatting

```bash
black airctl tests
isort airctl tests
```

### Type Checking

```bash
mypy airctl
```

## Requirements

- Python 3.10+
- Bluetooth adapter with BLE and BR/EDR support
- Platform-specific requirements:
  - **Windows**: Windows 10 version 16299 or later
  - **Linux**: BlueZ 5.55 or later
  - **macOS**: macOS 10.15 or later

## Dependencies

All dependencies are automatically installed with `pip install airctl`:

| Package                                          | Purpose                            |
| ------------------------------------------------ | ---------------------------------- |
| [bleak](https://github.com/hbldh/bleak)          | Cross-platform BLE library         |
| [typer](https://typer.tiangolo.com/)             | CLI framework                      |
| [rich](https://github.com/Textualize/rich)       | Rich text/pretty print             |
| [pydantic](https://pydantic-docs.helpmanual.io/) | Data validation                    |
| [orjson](https://github.com/ijl/orjson)          | Fast JSON serialization            |
| [pyyaml](https://pyyaml.org/)                    | YAML configuration                 |
| pywin32                                          | Windows named pipes (Windows only) |

## Known Issues

### Alias Naming

Avoid using hyphens (`-`) in device aliases. For example, use `my_sensor` instead of `my-sensor`. This is because command-line parsers may interpret the hyphen as an option prefix.

### Windows Daemon Stop

On Windows, the daemon uses named pipes for IPC. The `daemon stop` command works by connecting to the daemon to unblock the pipe and signal shutdown. This is handled automatically.

### BLE Authentication Errors

Some BLE characteristics require authentication (pairing) to read or write. If you encounter `Insufficient Authentication` errors, the device needs to be paired with your system first. This is a BLE security feature, not a bug.

### Multiple Characteristics with Same UUID

Some devices have multiple characteristics with the same UUID in different services (e.g., Alert Level appears in both Immediate Alert and Link Loss services). When reading by UUID, airctl automatically selects the first readable characteristic. Use `-H` for precise control.

## License

MIT License

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting a pull request.

## Acknowledgments

- [Bleak](https://github.com/hbldh/bleak) - Cross-platform BLE library
- [Typer](https://typer.tiangolo.com/) - CLI framework
- [Pydantic](https://pydantic-docs.helpmanual.io/) - Data validation
