# Hubble Network Platform Docs — Guides > Documentation for developers integrating with Hubble Network — an IoT connectivity platform using Bluetooth chips and a satellite/terrestrial gateway network. --- # Hubble CLI # Hubble CLI Watch nearby devices report over Bluetooth, receive their packets from satellite, decrypt payloads locally with a device key, and manage your fleet using the Hubble CLI — no embedded toolchain required. --- ## Overview `hubblenetwork` is the command-line tool for Hubble Network devices. It runs on your laptop and pairs with whatever tooling you already use to flash firmware, which makes it the fastest way to answer the question that comes up on every integration: **is my device actually working?** > **Go Further:** The CLI ships in the `pyhubblenetwork` package. For the exhaustive flag reference, see the repository [**on GitHub**](https://github.com/HubbleNetwork/pyhubblenetwork). ## Install and check your setup ```bash pip install pyhubblenetwork ``` For CLI-only use, `pipx` keeps it isolated from your other Python environments: ```bash pipx install pyhubblenetwork ``` Requires Python 3.10 or later. To upgrade an existing install: ```bash pip install --upgrade pyhubblenetwork ``` ### Set your credentials Export your Hubble organization ID and API token so you don't have to pass them on every command: ```bash export HUBBLE_ORG_ID= export HUBBLE_API_TOKEN= ``` Find both in your [**Hubble Dashboard**](https://dash.hubble.com/) under **Developer Tools > API Tokens**; see [**Authorization Scopes**](/docs/api-specification/hubble-platform-api#api-access) for the scope reference. Both values must come from the same environment — a **Production** org ID paired with a **Sandbox** token will be rejected. ### Run `doctor` `doctor` is the setup step. It checks credentials, Bluetooth and Docker, and names the fix for anything broken: ```bash hubblenetwork doctor ``` ``` ✓ Credentials valid, PROD ✓ Bluetooth usage description present ✓ Docker reachable - Receiver receiver image not pulled yet First `sat scan` will pull it, which takes a minute. Ready to go. · 3 ok · 1 skipped ``` When something is wrong, it says so and tells you what to do about it: ``` ✗ Credentials not set Set both, or pass --org-id/--token: export HUBBLE_ORG_ID= export HUBBLE_API_TOKEN= ✓ Bluetooth usage description present ✗ Docker Docker is not available Only `sat` commands need Docker. Not ready. · 1 ok · 2 failed ``` `doctor` exits `1` when something needed is broken, so a script can gate on it. A **skipped** check is not a failure: it means the check doesn't apply on your platform, or couldn't be answered without doing real work — like pulling the satellite receiver image. ### How commands are organized Every command lives inside a group, so it is always `hubblenetwork `: | Group | What it covers | |---|---| | `ble` | Nearby devices — scanning, decrypting, validating over Bluetooth | | `org` | The Hubble Cloud — registering, listing, and reading device data | | `sat` | Satellite reception through a Pluto SDR | You don't have to remember which group a command is in. If you type one at the wrong level, the CLI finds it for you: ``` $ hubblenetwork list-devices Usage: hubblenetwork [OPTIONS] COMMAND [ARGS]... Try 'hubblenetwork --help' for help. Error: No such command 'list-devices'. Did you mean: hubblenetwork org list-devices ``` The same applies to missing arguments (they say how to find the value), unknown options (they list what the command accepts), and missing credentials (they name the environment variables and the flags). `hubblenetwork --help` prints every command with a one-line description, and every command takes `--help` for its own options. --- ## What do you want to do? | Goal | Command | |---|---| | Check my setup is working | [`doctor`](#run-doctor) | | Watch nearby devices report | [`ble scan`](#watch-nearby-devices-report) | | See which of my devices are nearby, no key needed | [`ble decode`](#decrypt-nearby-packets-in-the-cloud) | | Prove one device works end to end, or find what's wrong with its key setup | [`ble validate`](#prove-one-device-works-end-to-end) | | Register a new device and get its key | [`org register-device`](#manage-your-fleet-in-the-cloud) | | See what's registered to my org | [`org list-devices`](#manage-your-fleet-in-the-cloud) | | Read a device's history from the cloud | [`org get-packets`](#manage-your-fleet-in-the-cloud) | | Receive packets from satellite | [`sat scan`](#receive-satellite-packets) | | Capture raw RF for offline analysis | [`sat record`](#one-shot-capture) | --- ## Watch nearby devices report `ble scan` uses your laptop's built-in Bluetooth hardware to listen for Hubble beacon advertisements (service UUID `0xFCA6`) and prints one line per packet as it arrives. No external hardware and **no credentials** needed — this is purely local. ```bash hubblenetwork ble scan ``` It runs until you press **Ctrl+C**. This is the quickest way to confirm your firmware is beaconing at all. ### Decrypt as you scan If you have the device `key`, pass it and payloads are decrypted locally as they arrive — no backend round trip. The key is hex or base64, 16 or 32 bytes: ```bash hubblenetwork ble scan --key "a562a2f7e4c62bed52ab09633878f62b" ``` `--counter-mode` accepts `UNIX_TIME` (default) or `DEVICE_UPTIME` for devices using a counter-based EID rather than UTC time. For AES-128-EAX devices, `--period-exponent` sets the EID rotation period as `2^n` seconds, matching `rot_exp` in your [device configuration](/docs/guides/device-integration/timing-management). ### Relay what you receive Add `--ingest` to push the packets you scan into the Hubble Cloud, turning your laptop into a temporary gateway. This needs both a `--key` and credentials: ```bash hubblenetwork ble scan --key "" --ingest ``` Useful when you're testing away from network coverage and want the data to land in your organization anyway. ### `ble scan` options | Option | Description | |---|---| | `--timeout`, `-t` | Stop after this many seconds (default: run until Ctrl+C). | | `--count`, `-n` | Stop after receiving N packets. | | `--key`, `-k` | Key to decrypt packets. Hex or base64, 16 or 32 bytes. | | `--counter-mode` | EID counter mode for AES-CTR packets: `UNIX_TIME` (default) or `DEVICE_UPTIME`. | | `--days`, `-d` | Days to search back when decrypting with the `UNIX_TIME` counter (default: 2). | | `--period-exponent`, `-e` | EID rotation period for AES-EAX packets as `2^n` seconds, 0–15. Matches `rot_exp` in the device config. | | `--show-failed-decryption` | Also show packets the key can't decrypt, adding an ok/fail mark to each row. | | `--network-id` | Only show devices on one network (unencrypted protocol only). | | `--ingest` | Relay received packets to the Hubble Cloud. Requires `--key` and credentials. | | `--org-id`, `--token` | Credentials for `--ingest` (default to the `HUBBLE_ORG_ID` / `HUBBLE_API_TOKEN` env vars). | | `--format`, `-o` | `tabular` (default) or `json`. | | `--payload-format` | How payloads are rendered — see [Payload format](#payload-format). | | `--debug` | Add the forensic columns `EPOCH`, `TAG` and `SALT`. | > **Test in Sandbox:** For [**Sandbox**](/docs/guides/dashboard/sandbox) access, the [**Hubble Connect**](/docs/guides/hubble-connect) mobile app is the supported way to relay device data. --- ## Decrypt nearby packets in the cloud `ble decode` scans like `ble scan`, but sends each encrypted advertisement to the Hubble Cloud for decryption, then requests the data back. No device key needed — the backend handles it. ```bash hubblenetwork ble decode --timeout 30 ``` Packets from devices outside your organization stay encrypted and are hidden from the tool's output, unless you add `--show-failed`. | Option | Description | |---|---| | `--timeout`, `-t` | Stop after this many seconds (default: run until Ctrl+C). | | `--show-failed-decryption`, `--show-failed` | Also show packets the cloud couldn't decrypt for your org, adding an ok/fail mark to each row. | | `--format`, `-o` | `tabular` (default) or `json`. | | `--payload-format` | How payloads are rendered — see [Payload format](#payload-format). | | `--org-id`, `--token` | Credentials (default to the `HUBBLE_ORG_ID` / `HUBBLE_API_TOKEN` env vars). The token needs the `read-packets` scope. | --- ## Prove one device works end to end `ble validate` is the quickest way to answer "is my device working?" — and when it isn't, why. It cross-checks how the device is registered, what it broadcasts, what the cloud sees, and optionally checks the firmware image, then defines the problem if there is one. Pass `--key`, `--device-id`, or both: ```bash # Check local decryption only hubblenetwork ble validate --key "a562a2f7e4c62bed52ab09633878f62b" # Check cloud decryption only hubblenetwork ble validate --device-id "3f4b2c0c-2d43-4cbe-9c1f-0a4c2d59e2a1" # Check both, and if one is wrong, describe why hubblenetwork ble validate \ --key "a562a2f7e4c62bed52ab09633878f62b" \ --device-id "3f4b2c0c-2d43-4cbe-9c1f-0a4c2d59e2a1" # Also check the firmware you flashed hubblenetwork ble validate --key "a562a2f7e4c62bed52ab09633878f62b" --device-id "3f4b2c0c-2d43-4cbe-9c1f-0a4c2d59e2a1" --firmware build/zephyr/zephyr.hex ``` Every check is one row, with the fix printed under anything that fails: ``` ✓ Credentials valid, PROD ✓ Registration AES-256-CTR, UNIX_TIME 'bench-board' ✓ Backend decoded 1 of 1 packet heard just now as this device ✓ Over the air 1 packet from this key: AES-256-CTR, UNIX_TIME ✓ Encryption AES-256-CTR (registration and air agree) ✓ Counter mode UNIX_TIME (registration and air agree) ✓ Clock device clock is on today Key setup looks right. · 7 ok ``` The same device flashed with the wrong counter source: ``` ✓ Credentials valid, PROD ✓ Registration AES-256-CTR, UNIX_TIME 'bench-board' ✗ Backend could not decode this key's packets (1 sent) It decrypts with the key and settings this device was registered with. If the rows below agree, the registered key is not this --key: re-register the device, or flash it with its registered key. ✓ Over the air 1 packet from this key: AES-256-CTR, DEVICE_UPTIME ✓ Encryption AES-256-CTR (registration and air agree) ✗ Counter mode registered UNIX_TIME, but the device is broadcasting DEVICE_UPTIME Fix one side: rebuild with CONFIG_HUBBLE_COUNTER_SOURCE_UNIX_TIME=y, or hubblenetwork org register-device --counter-source DEVICE_UPTIME and flash that device's key. (A UNIX_TIME device whose clock reads near 1970 looks the same; pass --firmware to tell the two apart.) Key setup has problems. · 4 ok · 2 failed ``` What each input adds: - **`--key`** finds this key's packets among everything in range, trying both key sizes, both counter sources, a year of clock skew and every AES-EAX period. It reports the encryption, counter source and device clock it found. - **`--device-id`** checks the device is registered and how, then sends the packets heard to the cloud, as [`ble decode`](#decrypt-nearby-packets-in-the-cloud) does. The check passes if one comes back as this device. - **`--firmware`** reads the key size and counter source from the image you flashed (`.elf`, `.bin`, `.hex`, `.ihex`, `.out`, `.axf`) or a build's config (`.config`, `sdkconfig`, `autoconf.h`, `sdkconfig.h`), and looks for the key's bytes in the image. For best results, input as many of the above 3 as you have available to you. | Option | Description | |---|---| | `--key`, `-k` | Device key, used to find its packets and test how they are encrypted. Accepts hex or base64, 16- or 32-byte. | | `--device-id`, `-d` | Device UUID, used to test the registration and that the cloud decodes the device. Needs credentials. | | `--firmware`, `-f` | The image you flashed, a build config file, or the build or project directory. | | `--org-id` | Organization ID (defaults to the `HUBBLE_ORG_ID` env var). | | `--token` | API token (defaults to the `HUBBLE_API_TOKEN` env var). | | `--timeout`, `-t` | BLE scan timeout in seconds (default: 30). The scan stops as soon as the device is found; `0` skips it. | `ble validate` exits `1` if any check fails, so it can gate a factory or CI script. A common cause of a failed scan is a slow advertising interval combined with OS-level BLE scan optimizations — running the command again often resolves it. :::note `ble validate` replaced `ble detect` and `ble check-time`. Typing either now points you to `ble validate --key `. ::: --- ## Manage your fleet in the cloud The `org` group talks to the Hubble Cloud, so it needs credentials. ```bash hubblenetwork org info # which org and environment am I on? hubblenetwork org list-devices # everything registered hubblenetwork org list-devices -n 20 hubblenetwork org list-devices -f json # machine-readable hubblenetwork org get-packets # last 7 days by default hubblenetwork org get-packets --days 30 --format csv hubblenetwork org get-packets -n 50 --debug hubblenetwork org register-device # returns the new device's key hubblenetwork org set-device-name hubblenetwork org delete-device ``` `list-devices` and `get-packets` stream rows as pages arrive, so the first rows appear in about a second rather than after the whole window downloads. A busy device can hold tens of thousands of packets; **Ctrl+C** stops early and still prints a summary, and `--limit`/`-n` caps the run. It always says how it stopped, never silently. :::note `list-devices` uses `--format`/`-f`, while `get-packets` uses `--format`/`-o`. Both accept the long form. ::: ### Registering devices `org register-device` returns a new device ID and its secret key. Keep the key — it is shown once, and your firmware needs it to encrypt. ```bash hubblenetwork org register-device hubblenetwork org register-device --encryption AES-128-EAX --counter-source DEVICE_UPTIME ``` | Option | Description | |---|---| | `--encryption`, `-e` | `AES-256-CTR`, `AES-128-CTR`, `AES-128-EAX`, or `NONE`. | | `--counter-source`, `-c` | `UNIX_TIME` or `DEVICE_UPTIME`. | | `--period-seconds` | EID rotation period in seconds (AES-128-EAX + `DEVICE_UPTIME` only). | | `--period-exponent` | EID rotation period as `2^n` seconds. The cloud accepts 10–15 (default 15, ≈9h). | `--period-seconds` and `--period-exponent` are mutually exclusive. > **Go Further:** Registering devices in bulk, or through the dashboard and API instead, is covered in [**Register Devices**](/docs/guides/cloud-integration/register-devices). --- ## Receive satellite packets The `sat` group receives packets through a [**Pluto SDR**](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html). It runs a Docker container ([`ghcr.io/hubblenetwork/sdr-docker`](https://ghcr.io/hubblenetwork/sdr-docker)) that handles RF reception and decoding, polls that container's HTTP API, and streams decoded packets to stdout. :::tip See the [Test with Pluto SDR](/docs/network/satellite/pluto-sdr-testing) guide for step-by-step instructions to test your device beaconing on Satellite Network. ::: :::warning `sat` needs **Docker running** and an **Analog Devices ADALM-PLUTO** connected over USB. `hubblenetwork doctor` checks the Docker half. ::: ```bash hubblenetwork sat scan ``` Pass a device key to decrypt payloads locally as they arrive: ```bash hubblenetwork sat scan --key "a562a2f7e4c62bed52ab09633878f62b" ``` Decryption uses the same AES-CTR scheme as BLE and supports both counter sources. The source is auto-detected from the packets and announced, unless `--counter-mode` is given. For `UNIX_TIME`, `--days` controls how many days around each packet's timestamp are searched. Packets the key cannot decrypt are hidden unless `--show-failed-decryption` is given. `sat scan` handles the container for you: it verifies Docker, pulls the image if it isn't cached, starts the container privileged so it can reach USB, waits for the receiver API and for the SDR to connect, deduplicates packets by device ID and sequence number, then stops and removes the container on exit. No hardware to hand? `sat mock-scan` streams fake packets and takes the same options: ```bash hubblenetwork sat mock-scan ``` ### `sat scan` options `sat scan` and `sat mock-scan` share these: | Option | Description | |---|---| | `--timeout`, `-t` | Stop after this many seconds (default: run until Ctrl+C). | | `--count`, `-n` | Stop after receiving N packets. | | `--key`, `-k` | Key to decrypt payloads. Hex or base64, 16 or 32 bytes. | | `--counter-mode` | EID counter source. Omit to auto-detect from the packets. | | `--days`, `-d` | Days searched around each packet's timestamp for the `UNIX_TIME` counter (default: 2). | | `--show-failed-decryption` | Also show packets the key can't decrypt, adding a `DECRYPT` column. | | `--poll-interval` | Seconds between polls of the receiver API (default: 2.0). | | `--format`, `-o` | `tabular` (default) or `json`. | | `--payload-format` | How payloads are rendered — see [Payload format](#payload-format). | | `--pluto-uri` | Address of the Pluto SDR, if it isn't the default. | | `--debug` | Add the forensic columns `RS_CORR`, `SYM_MS` and `GAP_MS`. | ### One-shot capture Alongside the live stream, two commands record for a fixed duration, save a single file, and exit. Both take a duration in seconds as their only argument. ```bash # Capture 10 s of raw IQ samples to a .npy file hubblenetwork sat record 10 # Record 10 s and save an RF signal-diagnostic report to a .txt file hubblenetwork sat signal-report 10 ``` Both accept: | Option | Description | |---|---| | `--output` | Where to write the file (default: an auto-generated timestamped name). | | `--mock` | Use the simulated receiver — Docker still required, but no Pluto SDR. | | `--pluto-uri` | Address of the Pluto SDR, if it isn't the default. | | `--debug` | Enable debug logging to stderr. | - **`record`** captures the raw radio signal only — no decoding. The output is a NumPy `.npy` file of IQ samples. - **`signal-report`** records IQ, then re-analyzes it offline into a plain-text **link-health diagnostic**: per-symbol timing/drift, channel-hopping validation, amplitude/SNR, and chipset metrics. It reports on signal quality and does **not** contain decoded packet payloads — to receive payloads, use `sat scan --key`. --- ## Reading the output ### Payload format Commands that print packet data (`ble scan`, `ble decode`, `sat scan`, `org get-packets`) take `--payload-format`: | Value | Behavior | |---|---| | `auto` | Printable ASCII shows as text, anything else as uppercase hex | | `base64` | Encode payloads as base64 | | `hex` | Display payloads as hexadecimal | | `string` | Decode payloads as UTF-8 (falls back to ``) | All four work with every output format, but the **default differs**, because a person and a program want different things. Tabular output defaults to `auto`, so a decrypted payload reads as `T=21.4` rather than `VD0yMS40`. JSON and CSV default to `base64` so the machine contract stays stable. An explicit `--payload-format` always wins. ### Scan layout `ble scan` and `sat scan` print one line per packet with a signal bar, and close with a summary: ``` TIME RSSI V EID CTR/SEQ PAYLOAD ───────────────────────────────────────────────────────────────────────────── ✓ 00:06:40 -62 ███▏ 2 9c4e2ab77d3f0e1a 20320 T=21.4,B=87 ✓ 00:06:43 -66 ██▉ 2 9c4e2ab77d3f0e1b 20321 T=21.4,B=87 ✗ 00:06:49 -74 ██▏ 2 9c4e2ab77d3f0e1d - D307912C66BA4018E5 ───────────────────────────────────────────────────────────────────────────── 4 packets · 3 decrypted, 1 failed · RSSI -62 to -74 dBm · 12s ``` The bar next to RSSI is signal strength: length is the magnitude, so you can watch it shrink as you walk away from a device. The `✓`/`✗` mark only appears with `--show-failed-decryption`, and it carries the state on its own, so the output still reads correctly without color. `ble decode` uses a similar layout, displaying `DEVICE` column instead of `EID`, naming the devices that had packets decoded. ### Piping to a file Packet rows go to **stdout** and everything else — the scanning notice, detection lines, the summary — goes to **stderr**, so this captures data only: ```bash hubblenetwork ble scan > packets.txt ``` The same split applies to `org list-devices` and `org get-packets`. Pass `--debug` for the forensic columns: `EPOCH`, `TAG` and `SALT` on `ble scan`, `RS_CORR`, `SYM_MS` and `GAP_MS` on `sat scan`, `EPOCH`, `CTR` and `SEQ` on `org get-packets`. ### Terminals that can't do box-drawing Not every terminal can render `─` and `█`. Pass `--ascii` (or set `HUBBLE_ASCII=1`) for a pure-ASCII rendering with identical column widths: ``` TIME RSSI V EID CTR/SEQ PAYLOAD --------------------------------------------------------------------------- 15:50:13 -62 ###= 0 2030405 300 0A0B0C0D0E0F --------------------------------------------------------------------------- 1 packets | RSSI -62 to -62 dBm | 0s ``` Encoding problems are detected automatically; you only need the flag when a CJK terminal configuration renders the glyphs double-width and shears the columns. `--no-ascii` forces the Unicode rendering if the detection is wrong for you. Color is a separate axis: `--no-color`, `NO_COLOR=1`, or a non-TTY stdout all disable it, and `FORCE_COLOR=1` keeps it on where a pipe would otherwise strip it (useful in CI). Both flags work on any command, before or after the subcommand. --- ## Requirements - **Python 3.10 or later** (3.11/3.12 recommended). - **Bluetooth**, for the `ble` commands: - **macOS:** CoreBluetooth. Run from a real terminal app and grant it Bluetooth access when prompted. - **Linux:** BlueZ required; your user needs permission to access the BLE adapter — often membership of the `bluetooth` group (`sudo usermod -a -G bluetooth $USER`, then log out and back in). - **Windows:** a compatible BLE stack/adapter. - **Docker and a Pluto SDR**, for the `sat` commands: [Docker Desktop](https://www.docker.com/get-started/) (macOS/Windows) or Docker Engine (Linux) installed and running, and an [ADALM-PLUTO](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html) connected over USB. `sat mock-scan`, `sat record --mock` and `sat signal-report --mock` need Docker but no SDR. `hubblenetwork doctor` reports on all of this. --- ## Also a Python library Everything the CLI does is available as an importable SDK, for when you need to script something the commands don't cover. ```python import os from hubblenetwork import Organization, ble, decrypt org = Organization( org_id=os.environ["HUBBLE_ORG_ID"], api_token=os.environ["HUBBLE_API_TOKEN"], ) new_dev = org.register_device() # returns a Device, with its key for d in org.iter_devices(): # streams as pages arrive print(d.id, d.name) for pkt in ble.scan(timeout=5.0): plaintext = decrypt(new_dev.key, pkt) if plaintext: print(plaintext.payload) ``` :::warning **Unlike the CLI, the SDK does not read the environment.** `Organization()` requires its credentials explicitly. ::: `iter_devices()` and `iter_packets()` are generators that yield as each API page arrives; `list_devices()` and `retrieve_packets()` are `list()` wrappers over them. BLE functions have sync and async variants — `ble.scan()` / `ble.scan_async()`. The `sat` module exposes `sat.scan()`, `sat.record()` and `sat.signal_report()`, and manages the Docker container for you. > **Go Further:** The full library surface is documented in the `pyhubblenetwork` [**README**](https://github.com/HubbleNetwork/pyhubblenetwork#using-it-as-a-python-library). --- ## Troubleshooting 1. **macOS: `ble scan` crashes instead of prompting for Bluetooth.** You'll see `Termination Reason: Namespace TCC` and a message about a missing `NSBluetoothAlwaysUsageDescription` key. macOS refuses CoreBluetooth to any executable without that key in an Info.plist, and Homebrew's `python3` binary has no Info.plist at all. Run from a real terminal app (Terminal, iTerm) rather than an embedded IDE shell, and grant it Bluetooth under **System Settings → Privacy & Security → Bluetooth**. BLE scanning must run in a GUI session, not over SSH. 2. **`ble scan` finds nothing.** Verify BLE permissions and adapter state, and try a longer `--timeout`. Slow advertising intervals plus OS-level scan optimizations mean a second attempt often succeeds. 3. **Auth errors.** Run `hubblenetwork doctor`. `validate-credentials` reports which environment accepted them and exits `1` if neither did, so it's safe in a script. Check that `HUBBLE_ORG_ID` and `HUBBLE_API_TOKEN` are exported in your current shell and come from the same environment. 4. **Import errors.** Make sure you installed into the same Python you're running (`python -m pip install pyhubblenetwork`). Using `pipx` avoids this entirely for CLI-only use. 5. **`DockerError: Docker is not available`.** The Docker daemon isn't running. Start Docker Desktop (macOS/Windows) or `sudo systemctl start docker` (Linux). 6. **`SatelliteError: No PlutoSDR detected`.** The container started but the SDR never connected. Ensure the ADALM-PLUTO is connected before running `sat scan`, and that no other process is using it. 7. **`sat scan` hangs pulling the image.** The first run fetches `ghcr.io/hubblenetwork/sdr-docker:latest`, which may take a minute on a slow connection. Later runs use the cached image. > **Go Further:** For the full troubleshooting reference, see the `pyhubblenetwork` [**README**](https://github.com/HubbleNetwork/pyhubblenetwork#troubleshooting). --- # Set Up Your Dev Environment # Set Up Your Dev Environment Set up your developer environment to quickly connect to Hubble's Cloud API platform. --- ## Prerequisites To interact with Hubble's [**Cloud API**](/docs/api-specification/hubble-platform-api), you will need: - A Hubble **Dashboard** (if you don't already have one, you can [**sign up**](https://dash.hubble.com/) now). - An [**API token**](/docs/api-specification/hubble-platform-api#api-access) and your **Org ID**, both found in your Hubble Dashboard. --- ## Choose Your Integration Method Pick the approach that fits your workflow: | Method | Best for | |---|---| | OpenAPI spec (YAML) | Importing into tools like Postman, Insomnia, or any OpenAPI-compatible client | | Hubble CLI | Local development and scripting from the command line | | Agent Plugin | AI-assisted workflows using tools like Cursor, Copilot, or Claude | ### OpenAPI Spec Import the raw [**OpenAPI spec (YAML)**](pathname:///docs/openapi.yaml) into your API client or code generation tool of choice. ### Hubble CLI Install and configure the [**Hubble CLI**](/docs/guides/cli) to interact with the API directly from your terminal. ### Agent Plugin Point your AI coding tool to the public [**Agent Plugin**](https://github.com/HubbleNetwork/agent-plugins) to enable natural-language API interactions. --- ## Next Steps 1. [**Onboard your devices**](/docs/guides/cloud-integration/register-devices) by registering a new device to your Hubble organization. 2. [**Integrate your firmware**](/docs/device-sdk/downloads) with the **Hubble Device SDK** so your device beacons on the network. 3. [**Get packet data from your devices**](/docs/guides/cloud-integration/get-data) via API and/or webhook. --- ℹ️ **Was this page useful?** [Please give us feedback](/docs/feedback). --- # Get Device Packet Data # Get Device Packet Data Start receiving packet data transmitted by your connected devices on Hubble Network. --- ## How to Access Your Data You can always view your packet data organized by device in your [**Dashboard**](https://dash.hubble.com/login). For backend integration, Hubble provides two platform integration patterns for accessing your device packet data: - **Webhook Subscription:** Register a target URL to have new packet data pushed to you via secure HTTP requests. Use webhooks when you need time-sensitive access to device data, for example to trigger downstream workflows or run system integrations. - **Packets API:** Fetch the latest packets via API request, using a continuation token to ensure that no data is missed. Use the API to batch packet data updates in predictable intervals that you control. You may also retrieve historical data over a specific time period (such as for backfilling). Both mechanisms for receiving packet data have advantages, and it is typical to use both for different aspects of your backend integration strategy: | Feature| Webhook subscription| Packets API request| |----|----|----| | **Mechanism** | Push: Hubble proactively sends data to your registered URL.| Pull: client actively requests data from Hubble Cloud.| | **Use Case** | Near real-time needs, minimizing client-side polling, but requires a plan for potential downtime.| Guaranteed delivery, full control, backfilling supported, but potentially less time-sensitive data.| | **Timeliness** | Near real-time: batched payloads pushed as new data becomes available.| Variable: client controls timing and frequency of requests.| | **Data Loss Risk** | Depends on reliability and availability of the listener. If your listener is down beyond Hubble's [**retry window**](/docs/guides/cloud-integration/get-data#retry-logic), must revert to API to backfill historic data.| Continuation tokens ensure no missed data. Clients can always reprocess historic data.| | **Integration** | Provision a receiving endpoint and implement response code logic.| Logic required for API calls, pagination, error handling and retry.| | **Authentication** | Verify POST request authenticity using webhook secret.| Same API token authentication as for device key provisioning.| --- ## Using Webhooks Use webhooks to have all new packets pushed to your server as they arrive on our cloud. We do not filter data when sending webhooks: you will receive all new packets across all devices belonging to your organization, regardless of environment tag (**Sandbox** or **Production**). > **Go further:** Review [**Packet Webhook Example**](/docs/api-specification/packet-webhook-example) for the webhook request payload structure, for an array of data packets. ### Set Max Batch Size Configure the maximum number of packets that will be batched into a single webhook payload, up to 1,000 packets. When new packets are available, Hubble will send a webhook every several seconds or whenever this threshold is met - whichever occurs first. > **Go further:** Review [**Create a Webhook Endpoint**](/docs/api-specification/create-webhook-endpoint) for defining a target URL, setting batch size and giving your webhook a name. ### Webhook Secret When registering a new webhook, we provide a confidential, unique string that may be used to validate that the HTTP request comes from Hubble Network. Hubble will send this token in the HTTP header as `HTTP-X-HUBBLE-TOKEN` when attempting to post new data to your target URL. **Treat this token as a sensitive credential**. Keep it strictly confidential to prevent unauthorized entities from sending forged webhook requests to your system. ### Return Status Code To ensure reliable delivery, please return a `2xx` "success" **HTTP status code** (the very first line of the HTTP response) to acknowledge that your server has successfully received and processed the webhook event. For example, the status line might be `HTTP/1.1 200 OK`. Any other response will be interpreted by Hubble as a "failure", which triggers our webhook retry logic (see below). We monitor webhook performance to protect system reliability, and we reserve the right to disable persistently failing webhooks after notice. ### Retry Logic Hubble maintains an "at least once" delivery system. If your server responds with a non-`2xx` status code when we attempt to post to the target URL we will automatically retry webhook requests using an exponential backoff strategy, for up to 3 hours. Because retries may cause duplicate deliveries, we recommend making your webhook handler idempotent to safely handle repeated events. Hubble expects a response within 10 seconds. If your processing takes longer, we might consider queuing the data and returning a `200 OK` immediately. If Hubble Network experiences temporary downtime, no data is lost. Webhook deliveries are queued and automatically resume from the last successfully sent packet, continuing until all queued packets are delivered and the system is up to date. ### Total Webhooks Hubble supports up to two (2) configured webhooks to facilitate integration cutover/migrations. Review our guidance on [**Migrating to a new webhook endpoint**](/docs/guides/cloud-integration/get-data#migrating-to-a-new-webhook-endpoint). ### Webhook Security Hubble operates on dynamic AWS infrastructure, meaning our outgoing IP addresses rotate frequently. We do not provide a fixed CIDR range for allowlisting. To secure your endpoint, we maintain a two-layer security model based on encryption and authentication: 1. **Transport Security (TLS):** All webhooks are sent over encrypted HTTPS. This ensures your data—including the Hubble-provided webhook `secret`—cannot be intercepted in transit. 2. **Webhook Secret:** Every webhook POST request includes the confidential webhook secret associated with your target endpoint in the `HTTP-X-HUBBLE-TOKEN` header. This is used for message authentication. --- ## Using Packets API Pull the Packets API to get new packet data on a request schedule that you control. > **Go further:** Review [**Retrieve Organization Packets**](/docs/api-specification/retrieve-organization-packets) for example HTTP request, parameter definitions and response body. ### Pagination Packets are ordered by the timestamp given when they are ingested by Hubble Network. Up to 1,000 packets are returned per page. A `Continuation-Token` will always be returned if there are more data packets to retrieve. Note that Hubble holds packets for a few seconds so that the `Continuation-Token` does not advance beyond packets that received an old processed timestamp due to clock drift. ### Query by Timestamp Use `start` and `end` time parameters to retrieve packet data over a specific time period. For example, if your webhook URL is unavailable beyond our retry interval, you may revert to the API to backfill device packet data. Granular packet data is available up to **30 days** in the past. ### Request Data for a Single Device Packet data may be filtered for a single device, for example for troubleshooting device behavior. This is not intended for high-volume data retrieval. - Use the optional `device_id` parameter to request packet data for a specified device. - Note that when a device ID is provided the endpoint will not behave as a continuous stream. If `end` is not provided, the endpoint will page until the current time then stop. --- ## Parsing Packets Hubble returns an array of up to **1,000 distinct data packets** per API request (page size limit) or batched webhook (max batch size). Each packet object contains a `packet.location` and `packet.device` subobject with structured data, and `packet.network` indicating which layer of Hubble Network transmitted the data. > **Go further:** Review [**Retrieve Organization Packets**](/docs/api-specification/retrieve-organization-packets) for example HTTP request, parameter definitions and response body. ### Device Object - **Device IDs:** Use `device.id`—the Hubble UUID—to identify the device. (`device.name` may also be used as a proprietary device ID, but uniqueness is not enforced by Hubble. See [**Onboard Devices**](/docs/guides/cloud-integration/register-devices#update-device) guide for more.) - **Timestamp:** `device.timestamp` is the timestamp when the data packet was detected by the scanning gateway belonging to Hubble Network. - **RSSI:** `device.rssi` is the received signal strength at the gateway (e.g. smartphone) from the Bluetooth® Low Energy (BLE) advertisement sent by your device. It is a one-sided measurement and does not automatically factor in Tx power from the device when reporting it (Tx power is not encoded in the advertising packet). RSSI value should be treated as a relative indicator, not an absolute distance metric. - **Custom Payload:** Remember that `device.payload` is base64 encoded. As a best practice, we recommend [**double envelope encryption**](/docs/security/network) for the custom payload. ### Location Object - **GPS:** coordinates returned (lat/long and altitude) represent the location of the scanning gateway (e.g. a smartphone). - **Accuracy metrics:** `location.horizontal_accuracy` and `location.vertical_accuracy` refer to the scanning gateway’s GPS fix at the time of reception. These values come directly from the scanning gateway's GPS chipset. - **Timestamp:** `location.timestamp` is the timestamp from the scanning gateway's most recent GPS lock. :::tip Review recommendations for how to [**Filter Packets**](/docs/guides/implementation/backend#filtering-data-packets) based on these data fields in our implementation guide. ::: --- # Onboard Your Devices # Onboard Your Devices Register a new device to your Hubble organization to create a secret key. Store that key on your Bluetooth® capable device and use the Device SDK to start beaconing on Hubble Network. --- ## Register New Devices For your device to be discoverable by Hubble Network, you need to first register a new device to your Hubble organization. (If you don't already have a Hubble Dashboard, you can [**sign up**](https://dash.hubble.com/) for one now.) - Generate a key directly in Dash using the **"Add a Device"** flow. Click "I just need a device key" and select your [device encryption mode](/docs/security/device/encryption-modes). - Or use the Cloud API to [**Register New Devices**](/docs/api-specification/register-new-devices). Generate an [**API token**](/docs/api-specification/hubble-platform-api#api-access) and copy your **Org ID** from your Hubble Dashboard to call the API. > **Try It:** jump straight into [**Dash Quick Start**](/docs/guides/dashboard/dash-quick-start). We handle device registration for you and help you flash a developer kit in minutes. --- ## How It Works When you register a device you must specify the **device encryption mode**, based on your hardware's time-keeping capabilities and the encryption library you use in your firmware (see [**Device Security**](/docs/security/device/encryption-modes)). You may also provide **device metadata** that makes it easier to manage your devices in the Hubble Dashboard and through your backend integration. ## Set Encryption Mode The Hubble Device SDK rotates through **ephemeral IDs (EID)** so that devices remain anonymous on the network. Learn more about encryption on the [**Device Security**](/docs/security/device/encryption-concepts) guide. You must specify **device encryption mode** when you register a new device. These parameters factor into security on the network: - **Key Size** (256-bit or 128-bit) - **Counter Source** for EID Rotation (unix time or device uptime) - Only for InPlay IN100: **Period Exponent** (optional rotation period configuration) Make sure to match encryption parameters against your firmware requirement when registering new devices, to avoid needing to reprovision your devices with a new key. :::danger **Encryption configurations are fixed for a device upon registration.** They cannot be modified on the Hubble backend for an existing device. ::: ### Key Size Hubble supports **Advanced Encryption Standard (AES)** 256-bit keys (32 bytes) (recommended) and 128-bit keys (16 bytes). Select which key size is compatible with your firmware cryptographic library. The API returns device `key` as base64 encoded string of raw binary data (16 or 32 bytes). ### Counter Source You may choose between **unix time** for EID rotation (requires devices to maintain an accurate, synchronized clock) or **device uptime**, which does not require a real-time clock. Unix time is recommended for maximum privacy. When using device uptime as your counter source, EIDs rotate through a preset pool size of 128. ### Period Exponent (IN100) When using the AES-128-EAX protocol with "DEVICE UPTIME" counter source for IN100, you can optionally override the EID rotation frequency using the `period_exponent`. - The rotation period is calculated as 2^*n* seconds, where *n* is the `period_exponent`. - For example, using the default value of 15, the period is 32,768 seconds (~9 hours). --- ## Set Metadata You can optionally provide a custom name and custom tag(s) for each device at the time it is registered. - Use `name` parameter to assign a proprietary device ID to your device (uniqueness is not enforced by Hubble). For example, use this field for your UUID or device serial number. - Use `tags` to organize devices into your "sandbox" or "production" environment (these are mutually exclusive **platform tags**). Or create **custom tags** with unique `key:value` pairs to organize your devices and device data. :::warning As a best practice, do not use any **personally identifiable information (PII)** in the device name or custom tags. ::: ## Bulk Registration Flow Request to provision keys for more than one device a time using the `n_device` parameter. You may register up to 10,000 devices per day. When registering multiple devices, provide an array of names and/or tags in the request body. Names and tags are drawn down sequentially from both arrays and assigned to the next device that is registered. :::note Device registration is **eventually consistent**: when registering at scale, there may be a brief propogation delay between creation and the first successful packet decrypt. ::: ## Update Devices Manage names and tags for existing devices, either individually or in batch sets. Just like when you register multiple devices, provide an array of device names and/or tags in the request body when updating multiple devices. > **Go further:** Review [**Update Device**](/docs/api-specification/update-device) and [**Batch Update Devices**](/docs/api-specification/batch-update-devices) for example HTTP requests, parameter definitions and response bodies. ## Delete Devices You may permanently delete a specific device or multiple devices from your organization. **This action is not reversible**. Data packets will no longer be delivered for deleted devices even if they continue to broadcast on the network. **Each delete request is idempotent.** In the event of an internal error (i.e. `5xx`) for a batch delete request, some deletions may be applied and others may not. The whole request can be retried again to ensure a consistent deletion across the batch. --- # Dash Quick Start # Dash Quick Start Start broadcasting on Terrestrial or Satellite Network in minutes with an off-the-shelf developer kit, and view device transmissions in your Hubble Dashboard. --- ## What is Quick Start? We’ve built a fast-track option to start testing Hubble’s Networks: Terrestrial and Satellite. All you need is a supported Bluetooth® developer kit, your laptop and your mobile device. - Start by signing up for a free **Sandbox** account. - Use the Hubble-native flow to add a device directly from your Dashboard. - Run the command-line tool to provision your board with a pre-compiled Terrestrial or Satellite firmware image. :::warning Satellite Network is not accessible in Sandbox. **Activate your Hubble Live free trial** to unlock your organization and send your first satellite transmission. You also get the benefit of the full Terrestrial Network: 100 million gateways listening for your device. ::: See your transmissions: - For **Terrestrial**, download the Hubble Connect mobile app to scan for device broadcasts and see data populate in your sandbox. [Hubble Connect](/docs/guides/hubble-connect) mobile app provides closed-loop network scanning by converting your mobile device into a Terrestrial Network gateway. - For **Satellite**, validate that the device is beaconing using a software-defined radio (SDR) and the Hubble CLI — or simply place the device outside to conduct a real-world test. ### Supported Platforms | **Platform** | **Terrestrial** | **Satellite** | | --- | --- | --- | | Developer Kit | [Nordic nRF52840 developer kit](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52840-DK/8593726)
[Nordic nRF52 developer kit](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52-DK/5773879)
[Nordic nRF21540 developer kit](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF21540-DB/15203403)
[Texas Instruments cc2340R53 launch pad](https://www.digikey.com/en/products/detail/texas-instruments/LP-EM-CC2340R53/26639724)
[Texas Instruments cc2340R5 launch pad](https://www.digikey.com/en/products/detail/texas-instruments/LP-EM-CC2340R5/19236289)
[Texas Instruments cc2755 launch pad](https://www.digikey.com/en/products/detail/texas-instruments/CC2755P105E0WRHAR/28715610)| [Nordic nRF21540 developer kit](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF21540-DB/15203403)
[Silicon Labs EFR32MG24 pro kit](https://www.digikey.com/en/products/detail/silicon-labs/XG24-PK6010A/16184048) | | Desktop OS | Mac OS
Linux
Windows (available in beta)| Mac OS
Linux
Windows (available in beta)| | Mobile OS | iOS
Android | Not required | Want to see a specific board or testing platform supported? [**Please submit feedback**](/docs/feedback). > **Go further:** Start with a [**Reference Application**](/docs/compatibility) if you don't see your board listed here. --- ## How it Works The Dash Quick Start flow helps you onboard an industry-standard Bluetooth developer kit as your first device connected by Hubble. Any commercial Bluetooth Low Energy (LE) chip is compatible with Hubble's Terrestrial Network. Satellite transmission reuses the same BLE radio but sends a custom Hubble protocol at a higher transmission power, so it additionally requires a board with a power amplifier (PA) or frontend module (FEM). To get started, log into your Hubble Dashboard and click **Add a Device**. Select “Quick Start” to **Provision a Device**. You must have an **Admin** role in your organization (see [**Users & Roles**](/docs/guides/dashboard/users-and-roles)). ### 1. Connect your Board You will use your laptop to provision a developer kit as a new device that belongs to your Hubble organization. Start by plugging your board into your machine. - **Connect your board using a data-capable cable.** If your cable is for charging only your board cannot be programmed. Look for status lights. - **Make sure the board is turned on.** Some boards do not have a power switch, such as the Texas Instruments (TI) Launch Pad. Other boards have both an “on/off” switch and a “power source” switch (Nordic). See **Troubleshooting** below for board-specific guidance. ### 2. Run the Command You will create a custom firmware image for your new device with the command that you copy/paste from the Dashboard. Then use the manufacturer's proprietary provisioning tool to "flash" your board. - **Open Terminal (Mac OS) or PowerShell (Windows) on your laptop or desktop.** You’ll use the terminal to program your developer kit physically connected to your machine. - **Paste the command from the Dashboard.** When you hit ENTER, `hubble-installer` will parse the command that you copy/paste from the Dashboard to save your shared API credentials and identify the developer kit that you selected in the Dashboard. :::note `hubble-installer` requests the board-specific binary file (compiled by Hubble using the Device SDK) from the `hubble-tldm` repository. Go deeper on [**Github**](https://github.com/HubbleNetwork/hubble-install/tree/main) to see how it works. ::: #### 2.1. Install any required dependencies: If prompted to install any dependencies, remember to use the password for your machine (not your Hubble password). | **Platform** | **Dependency** | | :--- | :--- | | Mac OS | **homebrew**: standard package manager on Mac OS.
**uv**: required to manage the Python package and virtual environment on Mac OS.| | Windows | **chocolatey**: standard package manager on Windows.| | Nordic | **segger-jlink**: required to flash Nordic board.
**nrfutil**: manages JLink, required to flash Nordic board.| | TI | **UniFlash**: required to flash your TI board.| #### 2.2. Register your new device: `hubble-installer` registers your board as a new “device” using your API credentials (organization ID and an API token), which are encoded in the command line copied from your desktop. You have the option to give your device a name in the provisioning flow. Devices registered on the satellite path are additionally tagged `satellite: next-pass` at registration. That tag is what surfaces the Next pass widget on your Device Details page. You may dismiss the widget after your first packet, or simply remove the tag. #### 2.3. Provision your board: The provisioning process differs for **Nordic** and **SiLabs** developer kits vs. the **TI** launch pad. - **Nordic** uses Segger J-Link application to “flash” your board, which `hubble-installer` will run **directly from Terminal.** - **Texas Instruments** uses a proprietary provisioning tool called [UniFlash](https://www.ti.com/tool/UNIFLASH#downloads) to actually “flash” your board. `hubble-installer` script will generate a binary `.hex` file that UniFlash uses for the device image. **You will need to open UniFlash on your desktop to finish the provisioning process.** ### 3A. Terrestrial: Using Hubble Connect After you successfully provision your board, it begins beaconing on Hubble's Terrestrial Network. Now, our globally distributed network composed of millions of scanning gateways can begin detecting your device — wherever you take it. **You will use Hubble Connect mobile app to detect your device in Sandbox.** :::warning If your organization is limited to **Sandbox**, you will only receive device data packets captured locally using the Hubble Connect mobile app. ::: - **Install Hubble Connect on your mobile device**. On your Hubble Dashboard, scan the QR code to download Hubble Connect. The app converts your mobile device into a scanning gateway, similar to our 100 million scanning gateways on Terrestrial Network. - Login with your Dashboard credentials. View your device and the latest broadcast snapshot on **My Devices**. Learn more about the [**Hubble Connect mobile app**](/docs/guides/hubble-connect). ### 3B. Satellite: Test Outside Hubble Connect plays no part in the satellite path — your device transmits to a satellite directly, so the only thing standing between you and first data is where you put the board and when the next pass happens. #### Device Placement The Dashboard shows placement guidance as the last step of provisioning. Where you place the device matters as much as the firmware: | **Tip** | **Description** | | :--- | :--- | | Roof or backyard | The best placement is a rooftop or outdoor space with a clear sky view. | | Lay it flat | The device should sit flat for full coverage. | | Direct line of sight | The link needs an unobstructed path to the sky — it works like eyesight. | | Watch for trees | Trees can obstruct the signal. | | Avoid tall buildings | Large structures block the signal; more open space is better. | | Weather-tolerant | Light rain is fine. Heavy rain, snow, or thick humidity can affect transmission. | If you are testing more than one device, space them at least 6 in (15 cm) apart, and keep them clear of large metal objects and liquids. > **Go further:** Read the full [**Satellite Transmission Guidance**](/docs/network/satellite/transmission-guidance). #### Setting install location In your Dashboard, the placement screen asks your browser for your location and saves it as the device's **install location**, which is what upcoming passes are calculated against. If you decline the browser prompt, the Dashboard falls back to a default location and prompts you to set the install location on the Device Details page instead. **Passes will not be accurate until an install location is set.** #### Wait for the pass Continuing from the placement screen takes you to **Device Details**, filtered to the satellite network, where a **Next pass in** widget counts down to the next usable pass over your install location. :::warning Data downlink from the satellite is not instantaneous. Packets captured during a pass are typically available within **about 6 hours** of the pass. ::: ### 4. Access your Data On **Dashboard**, navigate to the “Devices” experience and select your device to see detections on a map plus network traffic over time. The packet history widget displays the raw JSON payload that you can connect to via API and webhook. --- ## Application Logic Boards provisioned with a Dash Quick Start precompiled image will have the following characteristics. ### Terrestrial images | **Board** | **RTOS** | **Tx** | **Advertisement Interval** | **Payload Rotation** | |-----------------------|-----------------------|-----------------------|-----------------------|-----------------------| | nRF52840dk | nRF Connect SDK (NCS) [Zephyr] | 0 dBm | 2 seconds | 5 minutes | | nRF21540dk | nRF Connect SDK (NCS) [Zephyr] | 0 dBm | 2 seconds | 5 minutes | | TI cc2340R5 | Zephyr RTOS on TI | 0 dBm | 2 seconds | 5 minutes | | TI cc2340R53 | Zephyr RTOS on TI | 0 dBm | 2 seconds | 5 minutes | > **Go further:** Access the binary source code for each board with the [**hubble-tldm**](https://github.com/HubbleNetwork/hubble-tldm/tree/master) repository on Github. ### Satellite images | **Board** | **RTOS** | **Tx** | **Transmission Interval** | **Payload** | |-----------------------|-----------------------|-----------------------|-----------------------|-----------------------| | nRF21540dk (Satellite) | Zephyr | +20 dBm via on-board FEM | 10 seconds, continuous | 4 bytes: device uptime in seconds, big-endian | | SiLabs xG24-RB4187C (Satellite) | Zephyr | 19.5 dBm (`EFR32MG24B220` PA) | 10 seconds, continuous | 4 bytes: device uptime in seconds, big-endian | Satellite Quick Start images transmit **continuously**, not on a pass schedule. They do not predict passes, so most transmissions occur with no satellite overhead. This is intentional for a first device: it removes any time-provisioning requirement. The encryption counter is driven by **device uptime** rather than UTC time, so a power cycle restarts the counter. Production devices should use pass prediction and UTC time: learn more in the dedicated [**Satellite Quick Start**](/docs/network/satellite/quick-start) guide. --- ## Troubleshooting ### General - If no lights turn on when you connect your developer kit to your laptop, check to confirm if the board has an “on/off” switch and that it is in the “on” position. - If installing any dependency for the Hubble command-line tool fails, try restarting `hubble-installer` by entering the command again. - If you cannot log in to the **Dashboard** or **Hubble Connect** mobile application, simply reset your password. ### Linux #### 1. How do I install the J-Link dependency for flashing my Nordic board? - In Terminal, hubble-installer will prompt you to download J-Link directly from the Segger site: [https://www.segger.com/downloads/jlink/](https://www.segger.com/downloads/jlink/) - The application installer will be installed into your downloads folder. In Terminal, cd into your Downloads and run the application installer. - Continue the Quick Start flow in Terminal to finish flashing your developer kit. ### Nordic #### 1. I don’t see any lights on my board. - Make sure that the “on/off” switch is in the “on” position. - Make sure that the “power source” switch is in the “VDD” position. The board cannot be programmed if the power source is in the “USB” position - Make sure that the cable is plugged into the board at the base of the board, not the side. If your board also has a coin cell battery, the correct port is on the same side. When your board is correctly connected to your laptop and turned on, the power LED should be on. None of the programmable LEDs should be flashing, unless there is already an application running on the device. When you flash the board you will overwrite the existing application. - When using the coin cell battery, you can extend the life of the device by toggling the programmable LEDs switch from “Default” to “nRF only”. #### 2. J-Link firmware failed to update, and board flashing failed. - It is common for SEGGER J-Link to run a firmware update prior to flashing your developer kit. - Try restarting the `hubble-installer` flow and running J-Link again. It may take a second attempt for the firmware to update, followed by a third attempt to flash your developer kit using updated firmware. ### Texas Instruments #### 1. I can't find the .hex file from the command line. - The compiled file (`.hex`) is automatically saved to your user folder. - On Mac OS, use Finder to search your entire User folder (/Users/yourName/). - On Windows, use File Explorer and search your User Profile folder (C:\Users\yourName\). - On Linux, use the find command in your terminal, starting from your Home Directory (~). Alternatively, use your file manager (like Nautilus or Dolphin). #### 2. I loaded the image using UniFlash, but I'm not getting any detections in Hubble Connect. - Make sure the "Run Actions" box is checked in the UniFlash interface. This ensures that the device continues to run the application after it is provisioned, i.e. your board will continue to broadcast on Hubble Network. - A yellow and red LED light up on the launch pad when the device has been successfully provisioned. #### 3. I cannot run UniFlash on my Mac. - On Apple-silicon Macs (M1/M2/M3), Rosetta 2 is required to run Intel-only apps like Texas Instruments UniFlash. - You can install Rosetta using Terminal with the command `softwareupdate --install-rosetta`. --- # Sandbox & Staging Orgs # Sandbox & Staging Orgs Every Hubble account starts in **Sandbox** — an always-free, closed environment for bringing your hardware onto the network. Once you upgrade to the **Live Network**, you can also create a standalone **Staging Org** for siloed device testing with the same network access as production. --- ## Build in Sandbox When you first sign up, you start in Sandbox: a closed environment for zero-to-one device activation. Start with a free account ([**Sign Up**](https://dash.hubble.com/) if you don't have one), then use [Dash Quick Start](/docs/guides/dashboard/dash-quick-start) to get your first device on the network. Log in to the [Hubble Connect mobile app](/docs/guides/hubble-connect) to turn your phone into a scanning gateway on the Terrestrial Network. **While your organization is limited to Sandbox, you'll only receive packets captured locally through Hubble Connect.** ## Unlock Live Network Access To unlock global coverage, upgrade your account to the **Live Network**, multiplying your scanning gateways from one (your mobile device) to over 100 million. Every device in your organization becomes discoverable on the full network, and you'll receive packet data for all detections. --- ## Staging Orgs Use a **Staging Org** to test devices in an environment that's fully siloed from your production org — separate org ID, separate user access, separate API credentials — while still getting the same Live Network access as production. > **Note:** Staging Orgs replace the old tag-based Sandbox environment that used to live inside your production org. Staging is now a genuinely separate organization: your own space to test new devices, hardware revisions, or integrations without touching production data. ### Create a Staging Org You can create a Staging Org on demand from your production account. Because it's a separate org, packet data doesn't flow through your production API or webhook — you'll need to configure access separately. 1. From [Dash](https://dash.hubble.com/), select the org dropdown and click "Create a Staging organization". 2. Add existing users automatically, or manually add later. 3. Move devices into the staging org, or register new devices. 4. Generate a new API token and/or configure a webhook scoped to the staging org for backend integration (production credentials do not carry over because staging is a separate organization). ### Moving Devices Between Orgs You may move devices you own between orgs at any time. Reassign devices from Production to Staging, or Staging to Production, using the Dashboard flow or the [Update Device API](/docs/api-specification/update-device) with `set_destination_org_id`. ### User Access User permissions are set independently per org. As with production, **Admins** can make changes to the organization and devices, while **Members** have view-only access. Learn more in the [Users & Roles](/docs/guides/dashboard/users-and-roles) guide. Because staging is a separate org, granting a new user access to your production org does **not** automatically grant access to your staging org, and vice versa. --- ## Org Type Summary | | **Sandbox** | **Production Org** | **Staging Org** | |---|---|---|---| | **Purpose** | Getting started and technical validation | Your live, in-production device deployment | Devices you've set aside for testing | | **Live Network access** | None — limited to self-provided packets via the Hubble Connect app install (phone as gateway) | Full access (100M+ scanning gateways) | Same access as production | | **Org ID** | Your account's default org, before you upgrade | Your existing org ID | A new, independent org ID, for a separate org from production| | **User access** | Managed within your account | Managed within your account | Managed independently | | **API token / webhook** | Available, but only returns self-provided packet data (i.e. Hubble Connect) | Your existing credentials | Requires its own API access setup | | **Registered device limit** | 100 devices | Determined by your plan | 100 devices | | **Billing** | Not billable | Billed per your plan | Not billable | | **Packet history retention** | Same as production | Standard platform retention | Same as production | | [**API rate limits**](/docs/api-specification/hubble-platform-api#rate-limits) | Same as production | Standard platform limits | Same as production | --- # Show Custom Payload # Show Custom Payoad Program your application to encode custom payload using the type/value library so that it creates a Sensor Widget in your Dashboard. --- ## Overview Hubble uniquely provides **13 bytes of customizable data** in the Bluetooth® Low Energy (BLE) advertisement payload, enabling you to transmit actionable sensor and status information from your connected devices on our global network (see [**Custom Payload**](/docs/guides/device-integration/custom-payload)). Use the custom payload to add device-level intelligence to your solution: go beyond pure locationing to building a full telemetry channel for your product. ## Dashboard Visualization Micro-telemetry encoded using the **type/value index** can be visualized directly in your Hubble Dashboard ([log in or sign up](https://dash.hubble.com/)). When a device transmits a payload that contains a known type-value pair defined in the table below, the Device Detail view in Dash will atuomatically: - **Decode the payload inline** in the Packet History widget, creating a data log. - **Plot time-series data** in the Sensor Widget, for recognized data types that return a range of values. --- ## Supported Type-Value Pairs If a payload byte sequence matches a type ID in this table, the Dashboard will decode and display that reading. Unrecognized type IDs are shown as raw base64 encoded strings. ### Environmental | Type ID | Sensor Name | Value Format | Unit | |---------|-------------|--------------|------| | `0x01` | Temperature (High Res) | Signed 16-bit integer × 0.01 | °C | | `0x02` | Temperature | Signed 8-bit integer | °C | | `0x03` | Humidity | Unsigned 8-bit integer × 0.5 | % | | `0x04` | Barometric Pressure | Unsigned 16-bit integer × 0.1 | hPa | | `0x05` | CO₂ | Unsigned 16-bit integer | ppm | | `0x06` | Air Quality Index | Unsigned 8-bit integer | — | | `0x07` | Light Level | Unsigned 16-bit integer | lux | | `0x08` | UV Index | Unsigned 8-bit integer × 0.1 | — | | `0x09` | Sound Level | Unsigned 8-bit integer | dB | ### Motion & Position | Type ID | Sensor Name | Value Format | Unit | |---------|-------------|--------------|------| | `0x10` | Accelerometer | Three signed 16-bit integers (x, y, z) | mg | | `0x11` | GPS | Two signed 32-bit integers (lat, lon) × 1×10⁻⁷ | — | | `0x12` | GPS Delta | Two signed 16-bit integers (lat∆, lon∆) × 1×10⁻⁴ | — | | `0x13` | Orientation | Unsigned 16-bit integer × 0.01 | ° | | `0x14` | Motion Detected | Unsigned 8-bit integer (bit 0 = motion) | — | ### Power | Type ID | Sensor Name | Value Format | Unit | |---------|-------------|--------------|------| | `0x20` | Battery Percent | Unsigned 8-bit integer | % | | `0x21` | Battery Voltage | Unsigned 16-bit integer × 0.001 | V | ### Generic | Type ID | Sensor Name | Value Format | Unit | |---------|-------------|--------------|------| | `0x30` | Counter (8-bit) | Unsigned 8-bit integer | — | | `0x31` | Counter (16-bit) | Unsigned 16-bit integer | — | | `0x32` | Counter (32-bit) | Unsigned 32-bit integer | — | | `0x33` | Raw Byte | Unsigned 8-bit integer | — | | `0x34` | Raw Word | Unsigned 16-bit integer | — | | `0x35` | Raw DWord | Unsigned 32-bit integer | — | | `0x36` | Percentage | Unsigned 8-bit integer × 0.5 | % | > **Reach Out:** Want to see a specific data type added for Dashboard to decode? [**Please submit feedback**](/docs/feedback). --- ## Programming Your Device When generating a BLE advertisement from your application firmware, pass your custom data using the Device SDK [Functions API](/docs/device-sdk/downloads). The custom payload field accepts any byte sequence you choose. To have your payload automatically decoded and visualized in the Dashboard, encode it using the Hubble type-value format: - First byte must be the **type byte** for the specific type/value pair. - Following byte(s) must be the **value byte(s)**. - Values use little-endian encoding for multi-byte integers. - Multiple readings can be concatenated in a single payload, but only the first type/value pair is decoded. :::tip See [**NovelBit's Hubble Tutorial**](https://novelbits.io/hubble-network-nrf54l15-tutorial/) using Nordic's nRF54L15, including step-by-step instructions to transmit temperature sensor reading as custom payload. ::: --- # Users & Roles # Users & Roles You can manage organization users and permissions in your Hubble dashboard. --- ## Manage Your Team Go to your Hubble Dashboard then navigate to **Organization Settings > Your Team**. Click “Manage Team Members” to view all users with access to your organization. ## Adding New Users Users with “Admin” role may add new users to your organization. - Provide the user email and select a user role. - Click “Invite” to send the invitation. Invite links are valid for 5 days, after which they must be re-sent. An invite can be revoked at any point. :::tip Go deeper with the open API: [add new users](/docs/api-specification/add-user-to-organization), update or delete users, and [list users](/docs/api-specification/list-users-in-organization) with their associated metadata. ::: ## User Permissions Choose from two platform roles for your Hubble dashboard users: - **Admin:** Full edit access to the dashboard, including Billing data. Only users who are Admins can add new devices to this organization (see [**Dash Quick Start**](/docs/guides/dashboard/dash-quick-start)). - **Member:** Limited view access to the dashboard, with no Billing access. | **Permission** | **Admin** | **Member** | |----------------------------------|----------------------------|--------------| | Manage Team Members | Invite, Edit and Remove | View only | | Profile Settings | Edit | Edit | | Organization Settings | Edit | View only | | Payment History | View and Download | No access | | Developer Tools: API Tokens | Create, Edit and Revoke | View only | | Developer Tools: Webhooks | Create, Edit and Delete | View only | | Apply Dashboard Tags & Filters | Edit | Edit | | Hubble Connect: Foreground scanning | Yes | Yes | | Hubble Connect: Background scanning | Yes | Yes | --- # Integrate the Device SDK # Integrate the Device SDK Enable your device to transmit data on Hubble’s Terrestrial Bluetooth® Low Energy (BLE) Network with a simple integration into your application. --- ## Add Hubble on your Device Onboarding your device with Hubble means [registering a new device to your organization](/docs/guides/cloud-integration/register-devices) and adding the **Hubble Device SDK** to your application. ### How It Works **Terrestrial Network:** Your application will beacon a standard BLE [advertisement](/docs/device-sdk/terrestrial/advertising-packet) with Hubble's service UUID in the advertising data so that it is recognized by our network. You transmit up to 13 bytes of [custom data](/docs/guides/device-integration/custom-payload) that you provide. > **Test in Sandbox:** For [**Sandbox** only](/docs/guides/dashboard/sandbox) access, remember to download [**Hubble Connect**](/docs/guides/hubble-connect) to detect your beaconing device. ### Technical Requirements To onboard your device to Hubble Network, you will need - **Compatible Hardware:** bring [any Bluetooth capable device](/docs/compatibility) with adequate [flash/ROM space and RAM](/docs/guides/device-integration/custom-device#common-questions) available. - **Hubble Dashboard:** register new devices to your Hubble organization, and access your device data ([log in or sign up](https://dash.hubble.com/)). - **Device `key`:** unique, secret keys are generated when you register a device, and are used for encryption. Hubble supports 256-bit or 128-bit keys. - **Cryptographic Library:** encryption functions present in your firmware if not using Zephyr (e.g., PSA Crypto or MBEDTLS). - **Security Configuration:** choose an [encryption mode](/docs/security/device/encryption-modes) compatible with your device's time-keeping capabilities. --- # Your Custom Device # Your Custom Device When integrating the Device SDK, you may need to consider these real-world factors that affect your chip selection, hardware, and application design. --- ## Common Questions ### 1. What proprietary device data can be sent in the payload? Hubble supports custom payloads up to **13 bytes** for telemetry or meter readings, sensor readings like temperature or humidity, device-level GPS data (if available), etc. Device detection location data is appended to every capture by the Terrestrial Network. Review the [**Custom Payload**](/docs/guides/device-integration/custom-payload) user guide for examples. ### 2. How to keep device data secure? Hubble encrypts data transmitted on the network end-to-end. In addition, you can encrypt the device’s custom payload so Hubble cannot read it. Learn more in our [**Network Security**](/docs/security/network) guide. ### 3. How frequently to advertise? This depends on the battery life of your product and your use case. For tracking applications you may want to advertise the payload multiple times per minute, while other use cases can accommodate a lower frequency. If you broadcast on multiple protocols, you can alternate between Hubble and others based on your requirements. ### 4. How often to generate a new payload? You may generate between 1 and 1,024 new payloads per day. If your data hasn't changed, you are not required to generate a new advertisement — but you must rotate at least once every 24 hours to maintain encrypted transmission. The 1,024 limit is set by the sequence number field size. Exceeding it risks nonce reuse, which undermines the security of your transmissions. Learn more in the [**Time Management**](/docs/guides/device-integration/timing-management) guide. ### 5. What radio power output to use? **Transmit power (Tx)** of at least +4 dBm (2.5 mW) is recommended to ensure reliable connection to the **Terrestrial** Network. Transmit power of 20 dBm (~100 mW) is recommended to ensure reliable connection to the **Satellite** Network. A power amplifier may be required depending on your device. ### 6. How to maximize detections on the network? Based on your business use case, optimize for broadcast frequency and Tx vs. device battery life and expected battery degradation over time. Learn more in the [**Transmission Guidance**](/docs/network/terrestrial/transmission-guidance#maximizing-discoverability) summary. ### 7. What is the Hubble Device SDK power draw? Hubble's protocol leverages the standard Bluetooth stack for beaconing. There is no additional power draw when using the Hubble Device SDK to generate the advertising packet. Developers own power optimization at the application level for the selected chip. ### 8. Is clock drift on the device an issue? When using [unix time counter mode](/docs/security/device/encryption-modes) (time-based encryption), [packet encryption using the SDK](/docs/security/device/sdk-encryption) depends on accurate time for operations such as generating time-based ephemeral IDs (EID). We recommend at least a 500PPM clock accuracy to control drift. A tolerance of ±1 epoch is permissible, which aligns with a ~24-hour precision window under standard rotation cycles, though this window scales relative to the configured counter duration. Mitigate clock drift on the device by incorporating a time synchronization protocol. (Terrestrial Network scanning gateways do not manage or refresh device time.) See the [**Timing Management**](/docs/guides/device-integration/timing-management) guide for more details. ### 9. How much flash/ROM space and RAM is required? Several factors may affect application size and RAM requirement: chip/RTOS combination, type of application build, cryptographic approach, and custom design requirements. For example, a simple device beaconing on **Terrestrial Network** using the **Zephyr Quick Start Sample** (provided in the Device SDK) requires approximately: - `~1.9 KB` of flash/ROM space - `~23 bytes` of RAM For a device advertising on both **Satellite** and **Terrestrial Network**, a representative sample application requires approximately: - `13-15 KB` of flash/ROM space - `<1 KB` of RAM Note that these are very simple applications where encryption is already present in your firmware. ### 10. What frequency band does Hubble operate in? Hubble operates in the 2.4 GHz ISM band (2400–2483.5 MHz). To ensure compatibility, your Bluetooth chip must be compliant with Bluetooth Low Energy (BLE) specifications. ### 11. What is the typical data throughput rate? The typical data rate is approximately 0.4 kbps when using Terrestrial Network BLE advertising. This rate is intentionally optimized for long-range, low-power transmission to maximize battery life in constrained environments. ### 12. Does Hubble support bidirectional device communication? No. The Hubble Device SDK currently supports one-way data transmission only (uplink from your device to the cloud). --- # Custom Payload # Custom Payload Transmit data from your Bluetooth® Low Energy (BLE) device to build an intelligent, distributed system that creates value for your customers. --- ## Using Custom Payloads Hubble uniquely provides **13 bytes of customizable data** in the BLE advertisement payload, enabling you to transmit actionable sensor and status information from your connected devices on our global network. **Terrestrial Network** already provides approximate device location. Use the custom payload to add device-level intelligence to your solution. :::tip Program your application to encode custom payload using a predefined type/value library so that it populates the [Sensor Widget](/docs/guides/dashboard/sensor-widget) in your Hubble Dashboard. ::: ## Structured Micro-Telemetry You can structure the custom payload as micro-telemetry to communicate state transitions, alerts, and periodic sensor sampling from the device. ### Example: Temperature Reading As an example, send a temperature reading in the payload that the [**Sensor Widget**](/docs/guides/dashboard/sensor-widget) will display in your Hubble Dashboard. The high-resolution temperature item in the Sensor Widget uses a signed 16-bit integer (structured as little-endian) in hundredths of a degree Celsius. (This means you must multiply your temperature by 100 to preserve its decimal places. The Sensor Widget will divide by 100 to report the correct temperature.) #### Example: Temperature Reading displayed on Sensor Widget | Custom Payload (Hex String) | Byte 1 (Type) | Byte 2 (Value LSB) | Byte 3 (Value MSB) | Type | Raw Integer | Scaled Value | Unit | |---|---|---|---|---|---|---|---| | `01 D6 0A` | `0x01` | `0xD6` | `0x0A` | Temp (High Res) | 2774 | 27.74 | °C | Decoding the payload: 1. **Byte 1**: Type identifier - `0x01` = Temperature (High Res). 2. **Bytes 2-3**: Signed 16-bit integer (to account for negative temperatures) structured as little-endian: least-significant byte (LSB) first, most-significant byte (MSB) second. Data should be in hundredths of a degree Celsius. 3. **Raw Integer**: Combine bytes as signed int16 (`0xAD6` = 2774). Written in big-endian convention for ease of reading. 4. **Scaled Value**: Divide by 100 to get decimal precision (2774 → 27.74°C). :::warning On the **Satellite Network**, custom payloads must be of length 0, 4, 9, or 13. For this example, pad the payload to 4 bytes by appending a trailing `0x00`. ::: ## Structured Micro-Telemetry Your custom payload does not need to adhere to the Sensor Widget formatting. You may fill in custom data however your application requires, then decode it yourself. You can structure the custom payload as **micro-telemetry** to communicate state transitions, alerts, and periodic sensor sampling from the device. --- ## Industry Examples Below are general examples of what you can fit inside 13 bytes, optimized for different use cases. | Use Case | Example Custom Payload (13 bytes) | | --- | --- | | **Asset Tracking**
Capture activity beyond location for
supply chain logistics and asset management.| - 1 byte: battery level (0-100)
- 1 byte: device state (e.g., 0x01 = moving, 0x02 = idle)
- 2 bytes: impact count (int16)
- 9 bytes unused | | **Cold Chain**
Reduce spoilage of perishables by
monitoring temperature and humidity. | - 2 bytes: temperature (signed int16)
- 2 bytes: humidity (signed int16)
- 2 bytes: pressure (signed int16)
- 2 bytes: CO2 (int16)
- 1 byte: battery level (0-100)
- 4 bytes unused | | **Inventory Management**
Maintain warehouse and yard visibility. | - 4 bytes: location ID
- 1 byte: state change
- 2 bytes: timestamp offset (for state change)
- 1 byte: tamper event (flag)
- 1 byte: battery level (0-100)
- 3 bytes unused | | **Equipment Monitoring**
Send meter readings and sensor data
from fixed position devices and machines. | - 1 byte: operating mode or error code
- 2 bytes: meter reading (signed int16)
- 8 bytes: GPS coordinates (lat/long)
- 2 bytes unused | | **Environment and Agrotech**
Monitor climate and environmental inputs. | - 2 bytes: ambient temperature (signed int16)
- 2 bytes: air quality (signed int16)
- 2 bytes: light intensity (int16)
- 2 bytes: wind speed (int16)
- 2 bytes: CO2 (int16)
- 1 byte: battery level (0-100)
- 2 bytes unused | --- ℹ️ **Was this page useful?** [Please give us feedback](/docs/feedback). --- # End Device Provisioning # End Device Provisioning This document outlines best practice approaches for securely provisioning an end device with a Hubble device ID and key, ensuring operational readiness and secure backend integration. --- ## Provisioning Methods Provisioning can be accomplished through several mechanisms: 1. **Serial Interface:** The device ID and key can be programmed via a physical serial connection (e.g., UART, USB-serial). This method is often used in manufacturing or lab environments for controlled provisioning. 2. **Over Bluetooth® Low Energy (BLE) with a Dedicated GATT Service:** The end device hosts a **provisioning GATT service** that allows a provisioning tool (e.g., mobile app) to connect and write credentials. This service is advertised only in provisioning mode (to reduce attack surface). 3. **Pre-Merge into Firmware Image:** Device ID and key can be embedded into a firmware image before flashing. This requires the firmware to read from a fixed memory location at runtime. --- ## BLE Provisioning Workflow ### Advertising Mode - A freshly programmed device should broadcast a connectable GATT service indicating it is awaiting a device ID and key. - Optionally, the device can remain in a non-connectable state until a button press triggers provisioning mode. ### GATT Service Overview - GATT (Generic Attribute Profile) defines how BLE devices exchange structured data. - A GATT service is a collection of characteristics (data items) and their properties (read, write, notify). - In provisioning mode, the device exposes characteristics for: - Reading the existing device ID/key (if present). - Writing new device ID/key values. ### Mobile Device Role - A provisioning-capable mobile app scans for the provisioning GATT service. - Upon connection: - It requests a new device ID/key pair from the backend. - It writes the pair to the device via the GATT service. - The mobile app must authenticate the user to ensure the device is provisioned into the correct organization. --- ## Handling Devices with Existing Credentials A device may request provisioning even if credentials are already stored (e.g., after firmware reflashing). In such cases: - The app first reads the stored credentials. - The backend determines whether to keep or replace them. - This is called an update event. - Depending on policy, the device ID/key may remain unchanged or be replaced. --- # Timing Management # Timing Management Proper time management is critical for ensuring accurate encryption and secure operations in the SDK. Below are the best practices for provisioning UTC time and accounting for drifts. --- ## Provisioning UTC Time To ensure the SDK operates with accurate time, follow these steps to provision Coordinated Universal Time (UTC). **1. Obtain Accurate Time Source:** - Use a reliable time source such as an NTP (Network Time Protocol) server or GPS. - Ensure the time source is synchronized and trusted to avoid tampering. **2. Set System Time:** Use the Hubble API to set the obtained UTC time. **3. Validate Time Synchronization:** - Periodically validate the system time against the trusted time source. - Log any discrepancies for debugging and auditing purposes. --- ## Accounting for Time Drifts Time drifts can occur due to hardware clock inaccuracies. To mitigate this, follow these practices: ### Periodic Time Synchronization - Regularly synchronize the system clock with the trusted time source. - Use a configurable interval based on the expected drift rate of the hardware clock. ### Monitor Drift - Measure the drift rate of the hardware clock during testing. - Use this information to adjust the synchronization interval. ### Apply Drift Compensation Implement drift compensation logic to adjust the system clock between synchronizations. --- ## Time Persistence Across Power Cycles To accommodate a certain amount of drift and ensure time persistence across power cycles, you can use alternative methods such as storing the time in flash memory or other persistent storage. Below are recommendations, risks, and a workflow for managing time in such scenarios. ### Alternatives for Time Persistence Across Reboots | Method | Approach | Risks | |---|---|---| | **Store Time in Flash Memory** | Write the current UTC time to flash memory before a power cycle or periodically during operation. | **1. Flash Wear:** Flash memory has a limited number of write cycles. Frequent writes can lead to premature wear.
**2. Tearing:** If a power failure occurs during a write operation, the data may become corrupted.
**3. No Time Gap Information:** Flash storage does not provide information about how long the device was powered off. | | **Store Time in Non-Volatile RAM (NVRAM)** | Use NVRAM or battery-backed RAM to store the current UTC time. This method avoids flash wear and allows faster read/write operations. | **1. Hardware Dependency:** Requires specific hardware support for NVRAM.
**2. Battery Depletion:** If the battery backing the RAM depletes, the stored time will be lost. | | **Use an RTC Device** | If the hardware includes an RTC, initialize it with the current UTC time and use it as a persistent time source. This is the most reliable method for time persistence across reboots. | **RTC Drift:** The RTC may drift over time and require periodic synchronization. | | **Hybrid Approach** | Combine flash storage and RTC. Use the RTC for short-term persistence and flash storage as a backup in case of RTC failure or battery depletion. | **Complexity:** Increases system complexity and requires careful coordination between the two methods. | ### Recommended Workflow for Time Management Below is a recommended workflow for managing time in the SDK: **1. Device Boots** - Retrieve the last known time from persistent storage (e.g., flash, NVRAM, or RTC). - If no valid time is available, initialize the system to a default value (e.g., epoch time). **2. Wait to Sync Time** - Attempt to synchronize the system clock with a trusted time source (e.g., NTP server or GPS). - Block critical operations that depend on accurate time until synchronization is complete. **3. Start Tracking Time** - Once synchronized, start tracking time using the system clock. - Periodically log the current time for debugging and auditing purposes. **4. Retrieve A New Advertisement** - You may retrieve a new advertising packet with an application-defined custom payload between 1 and 1,024 times per day. - This limit is imposed by the sequence number size in the advertising payload. - Make sure to retrieve at least 1 packet per day, to maintain encrypted transmissions on the network. **5. Monitor Drift** - Continuously monitor the drift of the system clock. - If the drift exceeds a predefined threshold, trigger a resynchronization with the trusted time source. **6. Handle Resynchronization** - During resynchronization, adjust the system clock to the correct UTC time. - Log the adjustment to maintain an audit trail. --- ## Encryption and Time Dependency Encryption often relies on accurate time for operations such as generating time-based keys or validating timestamps. Follow these implementation guidelines: 1. Ensure the system clock is synchronized before performing encryption-related tasks. 2. Log the UTC time used for encryption to facilitate debugging and auditing. ### Implementation Recommendations By following these best practices, you can ensure accurate time management in the SDK, which is essential for secure and reliable encryption. - Use the log functionality to record time synchronization events and drift adjustments. - Test the SDK on hardware with varying clock drift rates to ensure robustness. - Consider implementing fallback mechanisms if the primary time source becomes unavailable. - Limit the number of unique advertising packets to betweeen 1 and 1,024 to avoid replay attacks with the same sequence number. --- # Hubble Connect # Hubble Connect Convert your mobile device into a scanning gateway on Terrestrial Network, for device testing and closed-loop connectivity in Sandbox. --- ## Test with Hubble Connect Detect any test device successfully broadcasting on the Hubble protocol and registered with your organization with the Hubble Connect mobile app. :::warning **Hubble Connect app is required to retrieve data in Sandbox.** ::: ### Supported Mobile OS | Mobile OS| Minimum Version| Foreground Scanning| Background Scanning| |---|---|---|---| | [**iOS**](https://apps.apple.com/us/app/hubble-connect/id6751236191)| Requires iOS 15.0 or later.| Continuous.| Requires "always allow" permission and active login. Typical scan interval: 30 min.| | [**Android**](https://play.google.com/store/apps/details?id=com.hubble.connect)| Requires Android 11 or later.| Continuous.*| Requires "background scanning" permission enabled in app settings.* Typical scan interval: 30 min.| *Android scanning includes a brief periodic refresh every several minutes to comply with OS-level scan throttling. ### Login Use your same Hubble Dashboard credentials to authenticate with Hubble Connect. --- ## Features ### Scan for Bluetooth Devices View any Bluetooth® Low Energy (LE) device beaconing in proximity. - Continuous scanning for local Bluetooth advertisements when app is in the foreground. - Toggle "Show only Hubble Devices" to filter results. - Pause scan to freeze results, and resume to get the latest device data. > **Test Case 1:** Is your device beaconing on the Hubble protocol? Is the [advertising packet](/docs/device-sdk/terrestrial/advertising-packet) correctly formatted for Terrestrial Network?

On "Scan", toggle "Show only Hubble Deviecs" and check if your device is detected. ### View Your Devices & Packet Data Use "My Devices" to view decrypted devices in scanning range that belong to your organization. - Hubble decrypted the ephemeral device ID (EID) from the Bluetooth advertisement to determine if the device is one that you own. - Click on a device to see the complete JSON data packet, and click "Refresh" for the next snapshot (subject to the advertising interval). > **Test Case 2:** Can Hubble successfully decrypt your packet? Are you using the advertisement retrieval function in the [Device SDK](/docs/device-sdk/downloads) correctly, and are you [maintaining time](/docs/guides/device-integration/timing-management) on the device?

Devices on "My Devices" only appear after a roundtrip to the Hubble backend to decrypt the payload and determine if this device belongs to your organization. > **Test Case 3:** Are you successfully sending [custom payloads](/docs/guides/device-integration/custom-payload)?

We return the complete [JSON payload](/docs/api-specification/retrieve-organization-packets) for your packet. A packet's decrypted payload in returned in Base64 format. :::warning Data on **My Devices** will not refresh if scanning is paused on "Scan". ::: ### Settings - View your user and organization information. - View app release version. - View Product Terms & Conditions, and Hubble's Privacy Policy. - This is where you can log out. - You may permanently delete your account. --- # Backend Implementation # Backend Implementation Ingesting device packet data at scale requires designing a robust pipeline from Hubble's cloud to your backend. --- ## Device Mapping Every device that you register with Hubble Network will have a unique `device.device_id` as the primary UUID identifier. You may choose to add identifiers for device mapping in your organization: - Use **Update Device** to populate `device.name` - for example, with your proprietary Device ID. **Note that uniqueness is not enforced by Hubble.** - You may also append **Tags** in `key:value` pairs for your devices - for example, if you have a category of devices each with a unique ID. --- ## Packet Ingestion Establish a connection to your data transmitted by Hubble Network, then process packets based on what matters for your business. ### Set Up your Data Pipeline There are two primary methods for consuming packet data on Hubble's cloud: API request and webhook subscription. Learn more about the advantages of each, and how to use them in combination, in our [**Get Device Packet Data**](/docs/guides/cloud-integration/get-data) guide. #### Tactics for Testing Packet Ingestion: - **API:** Use the **Retrieve Organization Packets** API with the optional `device.id` parameter to return packet data for a specific test device - **Webhook:** Test receiving an array of packet data via webhook by setting a small `max_batch_size` initially, then ramp batch size to the maximum as you scale the number of devices broadcasting on Hubble Network #### Migrating to a New Webhook Endpoint Hubble supports up to two (2) configured webhooks at once to facilitate zero-downtime transitions. This enables safe migration from an old endpoint to a new one with minimal risk or packet loss. Follow these steps to seamlessly between migrate webhook endpoints: 1. **Deploy your new endpoint:** ensure that the new HTTPS webhook URL is able to accept and process incoming events in the same format as your current implementation. 2. **Add the new endpoint as a secondary Hubble Network webhook:** whether using the Organization Metadata API or the developer tools in your organization's dashboard, add the new webhook without removing the existing one. Both endpoints will receive identical webhook events during the migration. 3. **Monitor and validate the new endpoint:** Verify that the new endpoint is processing payloads correctly. You can compare logs from both endpoints to ensure consistency in received payloads and timing. 4. **Transition any dependent systems:** If downstream systems rely on webhook processing, begin routing them through the new endpoint once it's validated. 5. **Remove the old endpoint:** After the migration is complete, we recommend deregistering the old endpoint in advance of a future migration. ### Process Packet Data You may parse packet data objects to map data to your backend and run integrated workflows. Learn more about the data objects returned in device packets in our [**Parsing Packets**](/docs/guides/cloud-integration/get-data#parsing-packets) guide. - Reference `deviceId`, `deviceName` or `tag` when mapping devices on your backend. - Retrieve timestamp and GPS coordinates along with accuracy metadata from the scanning device that recognized your device. - Decode the **custom payload** (base 64 encoded) if you transmit additional data from the device, [like sensor readings](/docs/guides/device-integration/custom-payload). - Note the `network` field if your integration workflows differ by network. --- ## Filtering Data Packets Hubble Network delivers Terrestrial Network detections after applying the location quality filtering rules outlined below. For stored packets retrieved via the API, we also deduplicate exact copies of the same detection. Any further filtering or aggregation is up to you. ### Location Quality Filtering On the Terrestrial Network, Hubble automatically removes packets whose reported location is physically impossible, is stale, or is a known placeholder. These packets aren't delivered to your API or webhook. | Rule | What's removed | | --- | --- | | **Null island** | Placeholder locations near (0, 0), (0, 90), and either pole | | **Out of bounds** | Latitude beyond ±90 or longitude beyond ±180 | | **Known-fake locations** | Known default values reported when a device has no GPS fix | | **Stale location** | Fixes more than 10 minutes older than the detection time (currently one provider's iOS gateways only) | | **Impossible speed** | A location implying travel faster than 700 mph from most of the device's recent locations | > **Deeper look:** Detections close together in time, such as two gateways at opposite edges of a device's range, aren't penalized by the impossible speed check. This filtering removes clearly bad data only. Plausible but inexact locations and duplicate detections of the same transmission are still delivered, so use the strategies below to handle those. ### Packet Uniqueness Every packet in your stored packet history is unique. If the same reception is processed more than once internally, Hubble keeps only one copy, so the API and Dashboard won't show it twice. Two records are treated as the same reception only when they are identical in every respect. If anything differs, both are kept. - **Webhooks work differently.** Delivery is *at least once*, and webhooks aren't deduplicated. We prioritize delivering every packet you're entitled to over the risk of withholding one, and we retry failed deliveries (see [retry logic](/docs/guides/cloud-integration/get-data#retry-logic)). In rare cases your endpoint may receive the same packet more than once, so make your webhook handler idempotent. To detect a repeated delivery, compare the full packet contents (for example, a hash of the entire packet object). A repeat delivery is identical in every field. - **Multiple scanners are not duplicates.** You should expect nearly identical packets when several scanners in the same area record the same transmission. Each is a distinct reception with slightly different location and/or timestamp data, so Hubble keeps and delivers all of them. Use the strategies below if your use case requires filtering these. ### Filtering Multiple Packets A packet filtering strategy may be applicable, depending on your product requirements. - What is the most important unit of information for your use case? Is it the unique device transmission (packet), or the occurrence of an event at a location and time? - How critical is it to capture every single raw transmission? - What are the potential consequences of processing identical data in your downstream systems? Below are some components of potential filtering strategies based on the characteristics of the data. | Component | Strategy | Implementation Detail | Use Case | | --- | --- | --- | --- | | **By Device Packet** | Identify redundant captures if packet counter and sequence number combination is the same. | Every device payload will have a unique combination of the rollover `counter` and `sequence_number`, which increments with each transmitted packet and resets upon counter rollover. These values are generated by the Hubble SDK to denote the latest data. You may also decide to include a bespoke counter in the packet payload that you define. | Prioritize latest device packet data over location updates. Ensure that you process each unique data transmission from the device only once. | | **By Location** | Identify redundant captures if location data is essentially the same within a time threshold. | Only keep one data point if multiple packets are returned in the same time window with nearly identical GPS location. Choose your location sensitivity based on significant digits returned with latitude, longitude and altitude. | Prioritize location events over device packet contents. Ensure that you update location data only when a meaningful location change has occurred. | | **By Timestamp** | Sample packet or location data captured within a defined time threshold. | Define a short window, such as 60 seconds. If multiple packets are received in this window for the same device, choose a rule to determine which record(s) you will process. If prioritizing unique packets, use `device.timestamp`; if prioritizing location updates, use `location.timestamp`. Sample among >1 packets based on first/last received, location accuracy or RSSI, proprietary data returned in the payload, etc. | Helpful if mitigating near-simultaneous readings from multiple scanners with slight variation in timestamp, both when prioritizing packet data or location data. | ### Filtering Individual Packets For a single packet, you may see a time difference between the two timestamps returned in the packet data: `location.timestamp` and `device.timestamp`. Learn more about the data objects returned in device packets in our [**Parsing Packets**](/docs/guides/cloud-integration/get-data#parsing-packets) guide. | **Scenario** | **Technical Context** | **Root Cause** | | --- | --- | --- | | **Typical:** `location.timestamp` < `device.timestamp` | **Standard mobile scan:** Mobile gateways like a smart phone scanning for Hubble refresh its location periodically (e.g., every 30 seconds). When the gateway detects a Hubble device (`device.timestamp`), it attaches GPS and time from its most recent location lock (`location.timestamp`). | The gateway had a valid, slightly older location lock cached when the device was detected. | | **Delayed Sync:** `location.timestamp` > `device.timestamp` | **Backlogged transmission:** If the mobile gateway detects a device while offline (no cellular or WiFi connection) the packet is queued until a network connection is reestablished. | Upon regaining connection, the gateway acquires a **new** location lock before forwarding the queued packets to the Hubble backend. | **Recommendation for filtering individual packets:** - If you primarily care about location, a large difference in timestamps might suggest discarding that device detection. Hubble already removes stale locations (more than 10 minutes) for some gateways; apply your own threshold if you need tighter tolerances. - If you primarily care about custom payload reported by the beaconing device (e.g. telemetry or sensor readings) you should use `device.timestamp`, or include time in the custom payload. --- # Register with Bluetooth® # Register with Bluetooth® Complete these steps to register your Hubble-connected product with the Bluetooth Special Interest Group (SIG). --- ## Bluetooth Requirement The **Bluetooth Launch Studio** requirement is the formal qualification and declaration process mandated by the Bluetooth SIG. The process ensures technical compliance with Bluetooth Low Energy (LE) advertising, and grants permission to use the Bluetooth brand in bringing your product to market. :::warning Bluetooth Member Details **Hubble Network Inc. is a Bluetooth Member Company.** The **Hubble Network SDK** has completed the Bluetooth Qualification Process: - Hubble Design Number: **Q369913** - Qualified Product Details: [**https://qualification.bluetooth.com/ListingDetails/307489**](https://qualification.bluetooth.com/ListingDetails/307489) Hubble's qualification covers non-connectable BLE advertising only. Customers integrating the Hubble SDK **do not need to reference Q369913** in their own Bluetooth qualification submissions — your silicon vendor's certified Core Design Numbers (DNs) are sufficient. ::: --- ## Pre-Requisites The registration process is completed via the [Bluetooth Launch Studio](https://launchstudio.bluetooth.com/) online platform. You will need the following to get started: - An active Bluetooth SIG company account. You may [create one on the site](https://www.bluetooth.com/develop-with-bluetooth/qualification-listing/). - Your product's chipset vendor's Core Design Number(s) (DNs). Note that this is either a single Complete Core DN or the pair: Core-Controller DN + Core-Host DN. - The TCRL (Test Case Reference List) – typically the default offered by Launch Studio. --- ## Process Overview 1. Start a new product in Launch Studio 2. Add your vendor's Core Design Numbers (DNs) 3. Confirm implementation conformance 4. Add required product text 5. Confirm testing conformance 6. Confirm product listing and submit --- ## Steps to Register ### 1. New Product in Launch Studio - Log in to [Bluetooth Launch Studio](https://launchstudio.bluetooth.com/). - Click **Create Product** and choose **Bluetooth LE**. - When asked, "Do you include any existing Design(s)?", select **Yes**. You will use your product's chipset vendor's Core DN(s). ### 2. Required Design Numbers - Add your chipset's Core DN(s). This is either the complete Core DN, or the pair Core-Host DN + Core-Controller DN. :::note Your vendor's Core DN(s) are sufficient to cover Hubble SDK integration. Hubble's SDK uses non-connectable BLE advertising only (ADV_NONCONN_IND), which is standard BLE GAP behavior already covered by your vendor's qualification. You do not need to add Hubble's DN (Q369913) to your product listing. ::: ### 3. Implementation Conformance Since you are inheriting the Core features from your vendor's existing qualified design, you generally do not need to claim new Core features. If prompted for an Implementation Conformance (ICS) import, select **No**. Do not claim new Core features. Note that Hubble's SDK only covers advertising and does not add any GATT services, Mesh, or LE Audio features. You do not need to add those claims. ### 4. Product Description You must provide a specific description of your product's implementation. - **Product Name:** Enter Your Product Name + "BLE with Hubble SDK". - **Product Description:** Use the suggested content to define how Hubble Network SDK is integrated to your product. We've provided the following template below: | Field | Suggested Content | |---|---| | Product Name | My Product - BLE with Hubble SDK | | Product Description | This product uses a qualified Bluetooth® Core implementation from the chipset vendor and integrates the Hubble Network SDK for non-connectable LE advertising. The SDK broadcasts ADV_NONCONN_IND frames using Service Data – 16-bit UUID (0x16) with Hubble's member-assigned Service UUID 0xA6FC. No GATT services, connections, or pairing are implemented by the SDK. Core-Host and Core-Controller are inherited from the vendor's qualified designs. | ### 5. Testing Conformance Because you reference existing, qualified Core DNs, you do not need to re-test the Core layer. Hubble's SDK is scoped to GAP Broadcaster advertising only and does not require additional profile test plans. We recommend that you use the latest TCRL offered by Launch Studio (the default). ### 6. Submit Product Listing Before submitting your Product listing, confirm the following: - ✅ Product lists vendor Core DN(s) (Complete Core, or Host+Controller). - ✅ Description mentions ADV_NONCONN_IND, Service Data (0x16), UUID 0xA6FC, and no GATT/connection. - ✅ TCRL is the latest (default). - ✅ No extraneous ICS claims were added. --- # Device Go Live Control # Control when devices go live Register devices as **not yet live** while you test, store, or ship them, then **go live** when they're ready. Until then, the Live Network doesn't deliver their packets. :::info Enterprise feature **Go Live Control is limited to enterprise accounts.** Contact Hubble Sales to get it added to your plan. ::: --- ## Overview Devices are often provisioned some time before they start doing their job. For example, devices provisioned at the factory may spend weeks in shipping before they are put into service. During that time they transmit, but you may not want to receive their packets. With **Go Live Control:** - A device registered or updated with `set_deploy: false` is **not yet live**. You will not receive Live Network packets for it. - When you are ready, update the device with `set_deploy: true`. The device **goes live** at that moment, and all later packets are delivered through the API and webhooks. - Packets sent on the Live Network while a device is not yet live are **not delivered** after it goes live. There is no backfill. #### Billable Device Usage Live-device billing starts the first time a device is heard on the Live Network after it goes live, not at the moment you send `set_deploy: true`. Not-yet-live devices may be billed differently from live devices, depending on your enterprise agreement. Ask Hubble Sales for details. :::note **Self-provided packets are still delivered,** even if the device is set as not yet live (`set_deploy: false`). This includes packets detected by the Hubble Connect mobile app and by your own BLE gateways using the Hubble Gateway SDK. A not yet live device can therefore appear as "Active" in your dashboard; only Live Network packets are withheld. ::: #### Manage go-live through the API At this time, go-live status can be managed only through the API, not in the Hubble Dashboard. --- ## Go-live status Go-live status is stored on the device's protected `_deploy` tag. A device is in one of two states: | `_deploy` value | State | Meaning | |---|---|---| | `"0"` | Not yet live | Registered to your organization, but Live Network packets are not delivered. | | `""` | Live | All packets are delivered. The value is the UNIX timestamp (in seconds) at which the device went live. | Devices with no `_deploy` tag don't use this feature. They are treated as live from registration, and all Live Network packets are delivered. :::warning Going live is permanent **A device can "go live" only once.** After it does, any further `set_deploy` request for that device returns HTTP `409`, and the device cannot return to not yet live. ::: --- ## Device Lifecycle ### Register devices as not yet live Include `set_deploy: false` when you register one or more devices. The devices are created and keyed, but Live Network packets are not delivered until they go live. This works well when devices leave the factory but before they are put in use. ```bash curl -X POST "$HUBBLE_API_HOST/v2/org/{org_id}/devices" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "n_devices": 10, "encryption": "AES-256-CTR", "set_deploy": false }' ``` Each returned device has `"_deploy": "0"` in its `tags`. Omit `set_deploy` entirely if this feature isn't part of your workflow. No `_deploy` tag is added, and the device is live from registration. ### Make an existing device not yet live Send `set_deploy: false` to a device that has no `_deploy` tag. This works whatever state the device is in (registered, active, or inactive). It can be done once only. ### Check go-live status Registration and update responses return the full device object. Once `set_deploy` has been used on a device, its `tags` include `_deploy`. A value of `"0"` means not yet live. A UNIX timestamp means live as of that time. To list not-yet-live devices, filter `GET /v2/org/{org_id}/devices` by tag: ```bash curl "$HUBBLE_API_HOST/v2/org/{org_id}/devices?filter_tags=_deploy:0" \ -H "Authorization: Bearer $API_TOKEN" ``` ### Go live Send `set_deploy: true` when the device should start delivering Live Network packets, for example when it is put into service. . You don't need to supply a timestamp; Hubble records the current time as the go-live time. ```bash curl -X PATCH "$HUBBLE_API_HOST/v2/org/{org_id}/devices/{device_id}" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "set_deploy": true }' ``` The response shows `"_deploy"` set to the go-live timestamp. To make many devices go live at once, use the batch endpoint, with one entry per device: ```bash curl -X PATCH "$HUBBLE_API_HOST/v2/org/{org_id}/devices" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "updates": [ { "device_id": "{device_id_1}", "set_deploy": true }, { "device_id": "{device_id_2}", "set_deploy": true } ] }' ``` --- ## Errors Checklist | Status | Cause | |---|---| | `400` | `_deploy` was included in `set_tags`. It is a protected tag. Use `set_deploy` instead. | | `403` | Your organization doesn't have the feature enabled. The message is `the _deploy tag requires the factory_mode_enabled entitlement for this organization`. Only requests that make a device not yet live (`set_deploy: false`) are affected. | | `409` | The device is already live, or the request would delete or change `_deploy` in a way that isn't allowed. The message is `the _deploy tag may not be deleted or modified except for the one-time activation (0 -> activation timestamp)`. | --- **Was this page useful?** [Please give us feedback](/docs/feedback). --- # Working with an ODM # Working with an ODM How device owners and contract manufacturers hand off Bluetooth® devices, so ownership is unambiguous and nobody shares credentials. --- ## Overview This guide is for both sides of a device handoff — the manufacturer building Hubble-connected devices, and the device owner receiving them. ## ODM Context When you order Bluetooth® devices from an **original design manufacturer (ODM)** such as an asset tag manufacturer or smart label producer, the ODM builds a generic beacon device running a Hubble firmware image. Two things make a device yours: the device `key` burned into its firmware, and the Hubble organization that the device is registered to. Packet data flows to whichever organization currently owns the device. ### Use Device Claims **Device claims are the recommended approach when working with an ODM.** The manufacturer builds devices in their own organization, then transfers them to the device owner when the order ships — so no credentials change hands, and the manufacturer can test the devices under their own account before they are claimed. ### Alternatives There are two alternatives to device claims, for cases where a device transfer from the manufacturer is not available: - **[Scoped API token](#scoped-api-token)** — the device owner grants limited access so the manufacturer registers devices directly into their organization. - **[Pre-registered device keys](#pre-registered-device-keys)** — the device owner generates keys in advance and shares them as a CSV, for facilities without an internet connection. ## Why Provision at Factory Keys are written onto the device at the factory. Claims only change which organization owns the device after it is provisioned. There are two reasons to handle keys at production time rather than after: - **Not all firmware images support post-production key writes.** Many Bluetooth images don't expose a bootloader or data transfer state after manufacturing, so if the key isn't burned in during the factory flash there may be no path to write it later. - **It fits existing factory toolchains.** ODMs often already handle certificates or other per-device credentials during flashing. --- ## Device Claims > **How it works:** the manufacturer registers devices into their **own** organization, links them to a **device claim**, and ships the devices. The device owner claims the devices using the claim ID, and every device included in the claim moves into their organization. Why device owners and manufacturers use device claims: - **Nobody shares credentials.** The device owner never issues an API token, and the manufacturer never has access to their organization. - **The manufacturer can test first.** Devices live in the manufacturer's organization during production, so QA runs under their own account. - **The buyer needn't be known at build time.** Manufacturers may build to stock and assign the claim when the order lands — including after the devices have left the factory. :::warning Claiming devices is one-way **Once devices are claimed, the transfer cannot be reversed.** The manufacturer loses access to those devices and any packet data they produce from that point on. ::: :::info Manufacturers: request API access **Manufacturers need access to the device claims API to create a device claim.** If your organization doesn't have it yet, reach out to Hubble. (Device owners don't need any special access to claim devices.) ::: ### Manufacturer Steps **Work one shipping unit at a time, and create each claim at run time.** Don't create claims ahead of production. Begin each run by creating that unit's claim, then register the unit's devices into it in the same pass — two calls, back to back, as one operation. The devices in a claim are then exactly the devices in that container. Repeat these steps for each unit you ship: 1. **Begin the run by creating a device claim** (`POST /device_claims`), setting `destination_org_id` to the device owner's Organization ID if you already know it. 2. **Register that unit's devices**, linking each to the claim. Write the returned `key` into the firmware as usual. One registration call covers up to 1,000 devices, so a shipping unit of 1,000 or fewer maps to a single call. 3. **Provision and test.** Devices are yours until they are claimed, so you can verify beaconing and complete QA under your own account. (The [Hubble CLI](/docs/guides/cli) confirms beaconing with just the encryption `key`.) 4. **(Optional) Assign the claim** to the device owner's organization once the order is confirmed, if you didn't set it at creation. 5. **Ship, with the claim reference on the container** — printed on the label, or sent separately by email or in the packing documentation. :::note Choosing a batch size Match it to how the product physically ships — 200, 500, or 1,000 devices, whatever fills one container. Each claim is handled separately, so smaller units mean more claims, but also let the device owner take ownership as deliveries land rather than waiting for a full order. Note that the maximum claim size is 10,000 devices, which would require 10x `POST /devices` calls to register. ::: ### Device Owner Steps 1. **(Optional) Give your manufacturer your Organization ID** so they can assign the claim to you. 2. **Get the claim ID or a claim token from your manufacturer.** You need one of the two so that you may claim the devices. The manufacturer may send it by email, in the packing documentation, or printed on the device or carton e.g., as a QR code. 3. **Look up the claim** to check its status and device count before you commit (`GET /device_claims/{claim_id}`). If you have a token rather than an ID, look it up with `id_type=claim_token` (`GET /device_claims/{base64url(claim_token)}?id_type=claim_token`) — the response includes the claim ID. 4. **Claim the devices** using the claim ID (`POST /device_claims/{claim_id}/claim`). Note that processing the claim runs in the background; large batches take time to complete. 5. **Confirm the devices appear** in your Hubble organization. Claimed devices are exclusively yours. The manufacturer can no longer access them or any packet data they produce. :::note Trial and sandbox organizations A claim that exceeds your organization's device cap will be rejected (no partial transfers). Talk to Hubble if you expect a large batch during a trial. ::: ### Assigning the Claim A claim can be created with or without a known device owner: - **Assigned** — you know the device owner at build time. Set `destination_org_id` when you create the claim, and only that organization can claim it. - **Unassigned** — you're producing inventory ahead of orders. Leave `destination_org_id` unset and assign it once the order is confirmed. **An available device claim can be assigned at any point,** including after the goods have shipped. The claim is a cloud record, independent of the physical shipment, so a build-to-stock run can leave the factory unassigned and be assigned the moment the sale closes, or never assigned. :::warning An unassigned claim reference is a bearer credential For unassigned claims ("directionless"), the first organization to present the claim ID is permanently locked in as the owner, and there is no way to reverse it. When creating unassigned claims, you should control who can see the ID or claim token as a secret intended for the recipient. ::: ### Updating a Claim Everything about a device claim can be changed until the devices are claimed. #### Changing the device claim Only the manufacturer can do this: assign it to a different organization, change its token, or delete it. #### Changing which devices are included Use `set_device_claim_id` on `PATCH /devices/{device_id}`: - A claim ID **adds** the device to that claim, or moves it over from another one. - An empty string (`""`) **removes** the device from whatever claim it currently belongs to. Adding a device needs the same access as creating a claim; removing one doesn't. To correct many devices at once, use the batch endpoint (`PATCH /devices`) with one entry per device. :::note Deleting a claim doesn't delete devices Deleting a claim releases every device linked to it. The devices stay in your organization, unlinked and available to add to a new claim. ::: ### Optional: Using a Claim Token A claim can carry a printed **claim token**, so the handoff rides on a label you already print. A printed token is most useful on build-to-stock runs, where it lets the physical goods carry their own handoff. The claim token must be a hyphenated UUID, or a GS1-128 payload beginning with application identifier `01` (GTIN) or `21` (serial number) — a logistics label beginning with `00` (SSCC) is not accepted. Tokens must be unique across all outstanding claims, and are set when the claim is created or updated, not at provisioning time. A device owner holding only a token looks the claim up to retrieve its ID (`GET /device_claims/{base64url(claim_token)}?id_type=claim_token`). **Claiming devices always requires the claim ID**, never the token alone. --- ## Alternatives to Device Claims Use one of these when your manufacturer doesn't support device transfers. ### Scoped API Token > **How it works:** the device owner grants a **narrow-scope API token** — enough access to register devices into their organization and optionally confirm beaconing, and nothing else. **Device owner:** [generate an API token](/docs/api-specification/hubble-platform-api#generate-an-api-key) using the "Device Manufacturer" preset, which grants `read-devices`, `write-devices`, and optionally `read-packets`. Share it securely, and communicate production details — encryption mode, naming convention, custom tags. You can revoke the token at any time from your account settings, which immediately stops further registrations; devices already provisioned are unaffected. **Manufacturer:** register each device with the token before provisioning it, write the returned `key` into the firmware, and optionally confirm beaconing. Each token belongs to one organization, so a manufacturer serving several device owners needs a separate token from each. ### Pre-registered Device Keys > **How it works:** the device owner generates device keys in advance and shares them as a CSV, so the factory needs no live API access at all. Useful during a trial, or at a facility without an internet connection. **Device owner:** pre-register the expected number of devices in your organization to generate keys, export them as a CSV, and share it securely. **Manufacturer:** assign the next available key from the list to each device during provisioning, and write it into the firmware. This requires knowing production volume in advance. Unused keys can be deleted or kept for a future run. :::note Device identifiers With either alternative, device owners typically use `device.name` for their own identifiers — a serial number or internal UUID — and custom tags for production date or SKU. These are returned with [device packet](/docs/api-specification/retrieve-organization-packets) data. ::: --- **Was this page useful?** [Please give us feedback](/docs/feedback). --- # Provisioning Devices at Scale # Provisioning Devices at Scale There are several possible methods for provisioning your devices with the Hubble device keys at scale, which allows for flexibility when managing key integration. --- #### Common provisioning practices for secure key management: 1. Online Production Line or OEM Integration 2. Offline Key Management and Provisioning 3. Field Provisioning 4. Customer-Defined Hybrid Approaches ## **Online Production Line or OEM Integration** This method integrates provisioning directly into the manufacturing or production line process, ensuring secure and efficient deployment at scale. Devices are programmed during manufacturing or assembly using specialized hardware interfaces and automated scripts. #### Steps: 1. **Hardware Connection**: Devices are connected to a provisioning system via interfaces such as pogo pins, USB, or fast-release cables. 2. **Firmware Flashing**: The provisioning system flashes the firmware, embedding the Hubble BLE advertisement packet structure as specified by the Hubble Zephyr library. 3. **Authentication:** OEM or contracted manufacturing partner leverages the customer-specific authentication credentials. 4. **Key Retrieval**: The provisioning system connects to Hubble Network Cloud APIs over HTTPS to request a unique AES-256 key for each device. 5. **Secure Key Programming**: The retrieved key is programmed into the device's non-volatile memory, often protected by hardware security modules (HSMs) or secure elements to prevent tampering. #### Why Use This Approach? * Ensures keys are securely provisioned in a controlled environment. * Automates large-scale deployment with minimal human error. * Reduces security risks by embedding keys before the device leaves the production line. --- ## **Offline Key Management and Provisioning** This method allows customers to provision devices in environments where direct access to the Hubble API is not feasible or not preferred. Keys can be pre-generated by the customer and distributed to the manufacturing partner offline for later association with devices during provisioning. #### Steps: 1. **Key Generation**: The customer uses the Hubble Network Cloud APIs to pre-generate a batch of unique AES-256 keys. 2. **Offline Key Distribution**: The keys are exported to a secure file format (e.g., Excel or CSV) and shared with the OEM or contracted manufacturing partner through a secure channel. 3. **Device Programming**: During production, the manufacturing partner uses the offline key file to program each key into the corresponding device. The association of keys with devices is logged in the file. #### Why Use This Approach? * **Flexibility**: Enables provisioning in environments with limited or no internet connectivity and without sharing authentication credentials externally. * **Scalability**: Supports bulk provisioning without requiring real-time API access. * **Security**: Keys are distributed securely, reducing risks associated with direct API exposure during production. --- ## **Field Provisioning** This method is suitable for devices that are already deployed or need provisioning outside the production line, using Over-the-Air (OTA) updates or local reprogramming. #### Steps: 1. **Initial Setup**: Devices are either locally connected via Bluetooth or other interfaces, or receive updates through OTA mechanisms. 2. **API Integration**: The provisioning system communicates with Hubble Network Cloud APIs to securely retrieve AES-256 keys. 3. **Key Installation**: Keys are installed onto the device secure memory through the local connection or OTA firmware update. 4. **Verification**: Post-provisioning, the system verifies that the keys and firmware have been correctly updated. #### Why Use This Approach? * Ideal for retrofitting existing devices or provisioning devices in remote locations. * Provides flexibility for customers to deploy keys as their infrastructure supports. * Minimizes logistical challenges of recalling devices for provisioning. --- ## **Customer-Defined Hybrid Approaches** Customers may implement custom workflows that combine aspects of the above methods, tailored to their operational and infrastructure needs. #### Examples: * A customer might perform initial provisioning at the OEM level but rely on production line integration for key updates. * For devices in the field, customers may use secure key injection devices to program keys locally while maintaining security standards. #### Why Use This Approach? * Offers the greatest flexibility, allowing customers to optimize provisioning workflows for their unique scenarios. * Ensures compatibility with diverse hardware configurations and use cases. --- # Pilot Framework # Pilot Framework Evaluate coverage, prove device connectivity, test in the real world, and confirm your backend integration: four steps for validating Hubble Network in a live pilot before ramping up in production. --- ## Validation Phases Rolling out on Hubble Network follows four validation phases, followed by a production ramp: | Phase | Goal | Primary Tool | Timing | |---|---|---|---| | **Coverage Validation** | Evaluate network coverage without updating any devices | Network Explorer | Day 1 | | **Technical Validation** | Flash updated firmware on a dev board to confirm network connectivity | Dash Quick Start, Github Repository | Week 1 | | **Network Validation** | Deploy devices in the real world and measure live performance | Your own hardware | Weeks 2–3 | | **Platform Validation** | Confirm your backend can ingest Hubble data via API and/or webhooks | REST API + Webhooks | Week 4 | | **Ramp in Production** | Roll out Hubble connectivity across your production devices | Dashboard + Cloud API | Post go/no-go decision | :::note This plan is optimized for an [**asset tracking use case**](/docs/guides/use-case/asset-tracking), but is also relevant to use cases where [**transmitting micro-telemetry**](/docs/guides/device-integration/custom-payload) from the device is the priority. ::: --- ## 1. Coverage Validation > **Goal:** Evaluate expected Hubble Terrestrial coverage across your key deployment geographies without updating any devices yet. **Tool:** [**Network Explorer**](https://network.hubble.com) — coverage is measured as *detections per 24-hour period* and expected *time between detections*. **What to do:** - **Assess coverage density** — Select locations that matter to your deployment: warehouses, distribution hubs, customer sites. Review expected detections per 24-hour period. - **Customize a virtual device** — Use expert mode to adjust Tx power and advertisement interval to match your target hardware profile and calibrate performance expectations. - **Map key routes** — Trace routes between locations to evaluate coverage in transit. Test urban, suburban, and highway segments that reflect your real-world use cases. - **Export results** — Share coverage data with your team to align on whether network density meets your minimum requirements before proceeding. > **Go-forward decision:** Your critical coverage areas and key routes show meaningful detection density. --- ## 2. Technical Validation > **Goal:** Flash updated firmware using the [Hubble Device SDK](https://github.com/HubbleNetwork/hubble-device-sdk) on a dev board or your own hardware to confirm device connectivity to the Terrestrial Network. **Tools:** - [**Hubble Dashboard**](https://dash.hubble.com) — [Dash Quick Start](/docs/guides/dashboard/dash-quick-start) ("Add a Device") - [**Device SDK**](https://github.com/HubbleNetwork/hubble-device-sdk) — open source on GitHub - [**Chip Reference Apps**](/docs/compatibility#find-your-chip) — Zephyr and FreeRTOS projects for supported chipsets - [**Hubble Connect**](https://hubble.com/docs/guides/hubble-connect) — mobile app for scanning and verifying device advertisements **What to do:** - **Try Dash Quick Start** — Use the one-line provisioning flow using your terminal to get a developer kit beaconing on Terrestrial Network in minutes. This is the fastest path from unboxed kit to first detection. - **Use a chip reference app** — Clone the reference repo for your chipset for a fully functional starting point with flashing instructions. Supports Zephyr and FreeRTOS. - **Port the `ble-beacon` sample** — Enter the secret device key generated during [device registration](/docs/guides/cloud-integration/register-devices), then build and flash to the board. - **Verify with Hubble Connect** — Install the mobile app and log in with your dashboard credentials. Scan for your device to confirm it is advertising on the network and view a live JSON packet snapshot. - **Advanced lab testing** — Use the `ble-network` sample file to create a shell interface on your board. This lets you program the device and test custom commands without reflashing between iterations. > **Go-forward decision:** Your dev board or hardware registers detections using Hubble Connect. --- ## 3. Network Validation > **Goal:** Collect real-world detection data in the field to validate that live network performance meets your coverage expectations for your device. **What to do:** **Define success criteria before you start.** For example: minimum detections per day and in key areas of interest, and acceptable gap windows between detections. Bring your own hardware: - [Integrate the Hubble Device SDK](/docs/guides/device-integration) to a custom instance of your existing BLE application. Browse [Reference Applications](/docs/compatibility#find-your-chip) for a starting point. - Configure the [custom payload](/docs/guides/device-integration/custom-payload) to return your proprietary device data; optionally apply [customer-managed payload encryption](https://hubble.com/docs/security/network#1-optional-customer-managed-encryption-at-payload-creation). - Flash a handful of devices and deploy them in real operational conditions. - View packet data in your [Hubble Dashboard](https://dash.hubble.com). Or ingest data directly into your backend via webhook or API pull, and map devices using `device.id`, `device.name`, and custom tag key-value pairs. - Compare Hubble-connected devices against a non-Hubble control group to evaluate differences in detection frequency and geographic coverage. > **Go-forward decision:** Real-world detection results meet expectations for your target use cases. Target: ≥80% of expected detections achieved across your test scenario. :::warning **If results are unexpected:** Share with your Hubble contact your hardware stack, device configuration (Tx power, advertisement interval), deployment geography, and test duration. Single-day tests can be misleading; [co-located devices](/docs/network/terrestrial/transmission-guidance#colocated-devices) may exhibit different behavior. Review [Transmission Guidance](/docs/network/terrestrial/transmission-guidance) for more details on what to expect. ::: --- ## 4. Platform Validation > **Goal:** Confirm that your backend can ingest Hubble data via REST API and/or webhooks, and that integration fits your existing data pipeline. **Tools:** - [**REST API + Docs Site**](https://hubble.com/docs/api-specification/hubble-platform-api) - [**Webhook Setup**](https://hubble.com/docs/guides/implementation/backend) - [**Backend Implementation Guide**](https://hubble.com/docs/guides/implementation/backend) **What to do:** - **Choose your integration strategy** — Webhooks push detection events to your endpoint in real time. The REST API supports polling for batch pulls. Most teams use webhooks as the primary path. - **Review the JSON payload** — Each packet includes: location, timestamp, RSSI, sequence number, and up to 13 bytes of custom micro-telemetry from your device. - **Confirm security requirements** — Hubble provides AES-256 [end-to-end encryption](/docs/security/network) at the device layer, TLS in transit, and data encrypted at rest in the cloud. Per-device cryptographic keys are provisioned via the Cloud API. > **Go-forward decision:** Your backend can ingest Hubble data with minimal integration lift, and your Cloud/Infrastructure team approves the API. --- ## Go / No-Go Decision Evaluate across all four phases: | Phase | Success Criteria | |---|---| | Coverage | Network Explorer predicts 2+ detections per route / area of interest | | Technical | Your device beacons on the terrestrial network and your custom payload is transmitted and readable via the Dashboard or API | | Network Performance | ≥80% of expected detection rates achieved in real-world test scenario — both in transit and at locations of interest | | Platform | Your infrastructure team evaluates and approves Hubble's API and webhook integration | **If all four are green, you have what you need to move forward.** --- ## Ramp in Production You've completed validation and are ready to roll out Hubble connectivity across your production device fleet. Here are a few areas to focus on: #### Firmware Update your production firmware application to include the Hubble Terrestrial Network SDK, tailored to your custom [device requirements](https://hubble.com/docs/guides/device-integration/custom-device). Calibrate your device configuration (Tx power, advertisement interval) to balance detection performance against battery life if your device is unpowered. #### Provisioning Each device requires a unique cryptographic `key` generated by Hubble and [provisioned on the device during production](/docs/guides/device-integration/end-device-provisioning). Ensure your manufacturing process [securely provisions devices](/docs/guides/implementation/provisioning-at-scale) with secret keys generated at registration time via the Cloud API. Keys should never be shared across devices or stored insecurely in firmware. If you're [working with an ODM](/docs/guides/implementation/odm) for manufacturing devices, review best practices to enable secure device registration. #### Backend - Determine whether [packet filtering](https://hubble.com/docs/guides/implementation/backend#filtering-data-packets) applies to your use case to reduce noise in downstream processing and streamline integrated workflows. - Add redundancy and fallback strategies to your data ingestion pipeline. If you need to rotate webhook endpoints, follow the [secure webhook migration](https://hubble.com/docs/guides/implementation/backend#migrating-to-a-new-webhook-endpoint) guide to avoid data loss during the transition. ##### Monitoring Use the Hubble Dashboard to monitor your device count as it ramps. Remember that devices transition from `registered` to `active` the first time it transmits a packet on the network. It becomes `inactive` if it has not been seen by the network in 7 days. --- # Asset Tracking # Asset Tracking Find your assets anywhere, whether they are at rest or in motion. --- Use Hubble’s open “Find My” Terrestrial Network – built on Bluetooth® Low Energy (BLE) – for affordable, ubiquitous connectivity. ## Problem Meeting your customers' needs requires tracking many devices, both at known locations (e.g. warehouses or distribution centers) and unknown (e.g. in transit or at a customer site). You need accurate locating at a low price-point that will scale with your business. ## Solution Your product already has a built-in **off-the-shelf Bluetooth chip**, so you can immediately take advantage of Hubble Network. No hardware changes, no new infrastructure. Just update your device's firmware to start broadcasting on the Hubble protocol, from anywhere (see Hubble's Terrestrial Network [**Coverage Map**](/docs/network/terrestrial/coverage)). :::caution **Analysis of Alternatives:** **RFID** requires too much equipment and doesn’t solve for in-transit tracking. **Cellular** is expensive and comes with meaningful coverage gaps. NTN solutions like **Satellite** would require fundamental hardware changes to your product and your business model. ::: ## Impact 1. **Expand your business:** Track new asset categories and equipment types. Win new customers and grow with existing accounts. 2. **Reduce costs:** Reduce or remove your reliance on a cellular chip and let Bluetooth do the heavy lifting. A hybrid connectivity strategy can be optimized for your various business use cases and even for individual customers. 3. **Increase quality:** Gain visibility in low coverage areas. Stop losing assets that wouldn’t justify a more expensive tracker. :::note Hubble **Satellite Network** reinforces your coverage strategy, providing a fallback where Terrestrial Network coverage is limited. Enable the "dual-stack" network with Hubble's SDK, using the same Bluetooth chip. ::: --- ## Get Started - [**Bring-up your device**](/docs/guides/device-integration) on Hubble Network using our public SDK on GitHub - Plug into our cloud to [**register devices**](/docs/guides/cloud-integration/register-devices) and [**stream device data**](/docs/guides/cloud-integration/get-data) using our open API - Review a typical [**rollout plan**](/docs/guides/implementation/rollout) to test, validate and scale with Hubble --- ℹ️ **Was this page useful?** [Please give us feedback](/docs/feedback).