Metadata-Version: 2.4
Name: nova-rbm
Version: 0.3.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** (direct hotspot) and **WiFi mode** (auto-discovery via mDNS).

## 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

### WiFi Mode (robot on your home network)

The SDK discovers the robot automatically via `nova-robot.local/status`:

```python
from nova_rbm import NovaRobot

bot = NovaRobot(mode="wifi")
bot.connect()

# Check robot status
print(bot.status())          # Full status dict
print(bot.servo_angles())    # {1: 75, 2: 90, 3: 85, 4: 80, 5: 110}
print(bot.motor_state())     # {'state': 'stop', 'speed': 180}
print(bot.led_color())       # {'r': 0, 'g': 0, 'b': 255}
print(bot.wifi_info())       # {'wifi_mode': 'station', 'connected_ssid': '...', ...}

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")   # Uses 192.168.4.1
bot.connect()
print(bot.status())
bot.disconnect()
```

### Manual IP Override

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

---

## Context Manager

Auto-connects, auto-stops motors, and auto-disconnects:

```python
with NovaRobot(mode="wifi") 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 (discovers IP in WiFi mode) |
| `disconnect()` | Close the connection |
| `reconnect()` | Drop and re-establish (re-discovers in WiFi mode) |

### 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, fetch_status

# Discover without creating a robot object
ip = discover_robot_ip()
print(f"Robot found at {ip}")

# Fetch status from any IP
data = fetch_status("192.168.4.1")
print(data)
```

---

## Full Status Response

The `/status` endpoint returns:

```json
{
  "status": "ok",
  "device": "NOVA_A1",
  "wifi_mode": "station",
  "connected_ssid": "MyWiFi",
  "ip_address": "192.168.1.42",
  "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 }
}
```

---

## License

MIT
