Metadata-Version: 2.4
Name: nova-rbm
Version: 0.4.0
Summary: Python SDK to control NOVA A1 Robot — AP & WiFi mode, auto-discovery, live status
Home-page: https://github.com/nadhilrobomiracle/nova_rbm
Author: robomiracle
Keywords: robot,nova,esp32,websocket,robotics,sdk
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: websocket-client>=1.6.0
Requires-Dist: requests>=2.28.0
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# NOVA RBM â€” Robot Base Module

Python SDK to control the **NOVA A1** robot via WebSocket.  
Supports **AP mode**, **WiFi mode** (mDNS), and **Scan mode** (auto-discovers robot by scanning your local network).

## Installation

```bash
pip install nova-rbm
```

Or install from source:

```bash
git clone https://github.com/nadhilrobomiracle/nova_rbm.git
cd nova_rbm
pip install -e .
```

---

## Quick Start

### Scan Mode â€” Auto Network Discovery (Recommended)

The SDK **automatically detects your PC's current IP**, strips the last number, then scans every address on your subnet (`.1` to `.254`) using **WebSocket** (primary) and **HTTP `/status`** (secondary fallback) in parallel:

```python
from nova_rbm import NovaRobot

bot = NovaRobot(mode="scan")
bot.connect()   # Finds robot automatically â€” no IP needed!
print(bot.ip)   # e.g. '192.168.29.47'
bot.forward()
bot.stop()
bot.disconnect()
```

### Standalone Scan (returns IP string)

```python
from nova_rbm import scan_network

ip = scan_network()               # auto-detect subnet from your device IP
print(ip)                         # e.g. '192.168.29.47'

# With progress tracking
def progress(scanned, total, current_ip):
    print(f"[{scanned}/{total}] Checking {current_ip}...")

ip = scan_network(on_progress=progress)
```

### WiFi Mode (mDNS + automatic scan fallback)

Tries `nova-robot.local` first. If mDNS fails, **automatically falls back to subnet scan**:

```python
from nova_rbm import NovaRobot

bot = NovaRobot(mode="wifi")
bot.connect()   # mDNS first â†’ subnet scan fallback if mDNS fails
print(bot.status())
bot.disconnect()
```

### AP Mode (robot's own hotspot)

Connect your computer to the `NOVA_A1` WiFi, then:

```python
from nova_rbm import NovaRobot

bot = NovaRobot(mode="ap")   # Fixed IP: 192.168.4.1
bot.connect()
print(bot.status())
bot.disconnect()
```

### Manual IP Override

```python
bot = NovaRobot(ip="192.168.29.47")
bot.connect()
```

---

## Context Manager

Auto-connects, stops motors, and disconnects cleanly:

```python
with NovaRobot(mode="scan") as bot:
    bot.forward()
    bot.set_speed(200)
    import time; time.sleep(2)
    # stop() and disconnect() called automatically
```

---

## API Reference

### Connection

| Method | Description |
|--------|-------------|
| `connect()` | Open WebSocket â€” auto-discovers IP based on mode |
| `disconnect()` | Close the connection |
| `reconnect()` | Drop and re-establish (re-runs discovery) |

### Discovery Modes

| Mode | Strategy |
|------|----------|
| `"ap"` | Fixed IP `192.168.4.1` (robot hotspot) |
| `"wifi"` | mDNS `nova-robot.local/status` â†’ subnet scan fallback |
| `"scan"` | Detects your device IP, scans entire subnet (WebSocket + HTTP) |

### scan_network() Parameters

```python
scan_network(
    subnet=None,        # e.g. '192.168.29' â€” auto-detected if None
    start=1,            # first host octet
    end=254,            # last host octet
    ws_timeout=1.5,     # WebSocket probe timeout per host
    http_timeout=1.5,   # HTTP probe timeout per host
    max_workers=64,     # parallel threads
    on_progress=None,   # callback fn(scanned, total, ip)
)
```

### Status & Telemetry

| Method | Returns |
|--------|---------|
| `status()` | Full status dict from `/status` endpoint |
| `servo_angles()` | `{1: angle, 2: angle, ..., 5: angle}` |
| `motor_state()` | `{'state': 'stop', 'speed': 180}` |
| `led_color()` | `{'r': 0, 'g': 0, 'b': 255}` |
| `wifi_info()` | `{'wifi_mode': ..., 'connected_ssid': ..., 'ip_address': ..., 'rssi_dbm': ...}` |

### Movement

| Method | Description |
|--------|-------------|
| `forward()` | Drive forward |
| `backward()` | Drive backward |
| `left()` | Spin left |
| `right()` | Spin right |
| `stop()` | Stop all motors |
| `set_speed(0â€“255)` | Set motor speed |

### Servo Control

| Method | Description |
|--------|-------------|
| `set_servo(servo, angle)` | Move servo 1â€“5 to angle (enforces firmware limits) |
| `set_all_servos({1: 60, 3: 100})` | Set multiple servos at once |
| `reset_servos()` | Reset all servos to defaults |
| `get_servo_limits()` | Returns min/max/default for each servo |

**Servo limits (from firmware):**

| Servo | Min | Max | Default |
|-------|-----|-----|---------|
| S1 | 50 | 75 | 75 |
| S2 | 90 | 145 | 90 |
| S3 | 35 | 150 | 85 |
| S4 | 20 | 80 | 80 |
| S5 | 110 | 135 | 110 |

### LED Control

| Method | Description |
|--------|-------------|
| `set_rgb(r, g, b)` | Set LED strip color (0â€“255 each) |
| `set_color("red")` | Set by name: red, green, blue, white, off, cyan, magenta, yellow, orange, purple, pink |

### Standalone Utilities

```python
from nova_rbm import discover_robot_ip, scan_network, fetch_status

ip = discover_robot_ip()          # mDNS discovery
ip = scan_network()               # subnet scan discovery
data = fetch_status("192.168.29.47")
```

---

## Full Status Response

```json
{
  "status": "ok",
  "device": "NOVA_A1",
  "wifi_mode": "station",
  "connected_ssid": "MyWiFi",
  "ip_address": "192.168.29.47",
  "rssi_dbm": -45,
  "uptime_s": 1234,
  "ws_clients": 1,
  "motor": { "state": "stop", "speed": 180 },
  "led": { "r": 0, "g": 0, "b": 255 },
  "servos": { "s1": 75, "s2": 90, "s3": 85, "s4": 80, "s5": 110 }
}
```

---

## Changelog

### v0.4.0
- **New `scan_network()`** â€” scans local subnet automatically by reading device IP
- **New `mode="scan"`** in `NovaRobot` â€” fully automatic robot discovery
- **`mode="wifi"` fallback** â€” if mDNS fails, auto-falls back to subnet scan
- Parallel WebSocket + HTTP probes per host for maximum reliability

### v0.3.0
- WiFi mode discovery via mDNS (`nova-robot.local`)
- AP mode support
- Full servo, motor, LED control

---

## License

MIT
