Metadata-Version: 2.4
Name: hoplynk
Version: 0.2.0
Summary: Official Python SDK for the Hoplynk API
Project-URL: Homepage, https://hoplynk.com
Project-URL: Documentation, https://docs.hoplynk.com
Project-URL: Repository, https://github.com/Hoplynk-Inc/hoplynk-connectors
Author-email: Hoplynk <dev@hoplynk.com>
License: MIT
Keywords: drone,gps,hoplynk,sdk,starlink,telemetry
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: websocket-client>=1.8.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# hoplynk

Official Python SDK for the [Hoplynk](https://hoplynk.com) API.

Stream live GPS and telemetry from Starlink-connected vehicles — no direct network access to the vehicle required.

## Install

```bash
pip install hoplynk
```

## Quickstart

```python
import os
from hoplynk import HoplynkClient

client = HoplynkClient(api_key=os.environ["HOPLYNK_API_KEY"])
```

Get an API key from the Hoplynk dashboard. Keys are prefixed `hlk_`.

---

## REST API

### List assets in a kit

```python
assets = client.get_assets(kit_id)
for asset in assets:
    print(asset["id"], asset["name"], asset["type"])
```

### Get latest GPS fix

```python
loc = client.get_location(kit_id, asset_id)
if loc:
    print(loc.lat, loc.lon, loc.source)  # e.g. 'starlink'
    print("stale:", loc.stale)
```

### Get full telemetry snapshot

```python
snap = client.get_telemetry(kit_id, asset_id)
if snap.gps:
    print(snap.gps.lat, snap.gps.lon)
if snap.status:
    print(snap.status.downlink_mbps, "Mbps down")
```

### Get Starlink link status

```python
status = client.get_status(kit_id, asset_id)
if status:
    print(f"downlink: {status.downlink_mbps} Mbps")
    print(f"latency:  {status.pop_ping_latency_ms} ms")
    if status.alerts:
        print("alerts:", status.alerts)
```

---

## WebSocket streaming

For live updates without polling:

```python
with client.stream(kit_id, asset_id, feeds=["gps", "status"]) as stream:
    for event in stream:
        if event["feed"] == "gps":
            p = event["payload"]
            print(f"GPS  {p['lat']:.6f}, {p['lon']:.6f}  source={p['source']}")
        elif event["feed"] == "status":
            p = event["payload"]
            print(f"Link {p.get('downlink_mbps')} Mbps ↓  {p.get('uplink_mbps')} Mbps ↑")
```

The stream auto-reconnects on disconnect. Exits the `with` block only when you call `stream.close()` or break out of the loop.

### Without context manager

```python
stream = client.stream(kit_id, asset_id)
for event in stream:
    process(event)
    if done:
        stream.close()
        break
```

---

## Context manager for the client

```python
with HoplynkClient(api_key=os.environ["HOPLYNK_API_KEY"]) as client:
    loc = client.get_location(kit_id, asset_id)
    print(loc.lat, loc.lon)
```

---

## Types

### `GpsPayload`

| Field | Type | Description |
|---|---|---|
| `lat` | `float` | Latitude (degrees) |
| `lon` | `float` | Longitude (degrees) |
| `alt_m` | `float \| None` | Altitude (meters, WGS-84) |
| `accuracy_m` | `float \| None` | Horizontal accuracy (meters) |
| `source` | `str` | `'starlink'` / `'starlink_cached'` / `'cellular'` / `'manual'` |
| `stale` | `bool` | True if GPS fix is older than 30s |
| `timestamp` | `str \| None` | ISO 8601 UTC |

### `StatusPayload`

| Field | Type | Description |
|---|---|---|
| `downlink_mbps` | `float \| None` | Download throughput |
| `uplink_mbps` | `float \| None` | Upload throughput |
| `pop_ping_latency_ms` | `float \| None` | Latency to Starlink POP |
| `pop_ping_drop_rate` | `float \| None` | Packet drop rate (0–1) |
| `obstruction_pct` | `float \| None` | Sky obstruction percentage |
| `alerts` | `list[str]` | Active Starlink alerts |

---

## Environment variables

| Variable | Description |
|---|---|
| `HOPLYNK_API_KEY` | Your `hlk_*` API key |

---

## IDs

You'll need a **Kit ID** and **Asset ID** for each vehicle. Find them in the Hoplynk dashboard, or call `client.get_assets(kit_id)` to discover them programmatically.

---

## License

MIT
