Project Organization
The Hubble Network SDK is organized around a small common core, public headers, and platform-specific ports. The common code implements the SDK protocols and state management. The port code adapts those protocols to a specific RTOS, crypto provider, radio driver, and board.
This page describes how the source tree is laid out, how the layers depend on one another, the naming conventions used throughout, and where new code should go.
Layering Model
Everything in the SDK follows one rule: dependencies flow downward through the layers. A layer may call the layer below it, never the layer above.
application
|
v
include/hubble public APIs
|
v
src common SDK implementation
|
v
include/hubble/port port contracts
|
v
port/<rtos> RTOS / framework glue
|
v
port/<rtos>/boards board and hardware implementation
Applications call the public hubble_* APIs. Common SDK code implements the
protocol and calls port contracts when it needs a platform service. Port and
board files implement those contracts using RTOS, vendor SDK, or hardware
facilities. When common code needs a new platform capability, the fix is to add
a port contract — not to scatter RTOS-specific conditionals through src.
Keeping this direction intact is what lets the protocol logic be tested and reused across every supported platform.
Directory Layout
Each directory maps to one layer of the model above and owns a specific responsibility.
Public APIs – include/hubble
Application-facing headers. Applications and ports include SDK interfaces from
here instead of reaching into src. These declarations are the stable
integration surface, use the hubble_* namespace, and must not leak RTOS or
board-specific types into their signatures.
Key headers:
hubble.h: top-level SDK initialization, time, key, and counter APIs.ble.h: BLE Network advertisement APIs.sat.h: Satellite Network packet transmission API.version.h: SDK version information.
Port Contracts – include/hubble/port
The interfaces a platform integration must implement. These headers are public in the sense that ports implement them, but they are not application-facing APIs. Common SDK code calls them; applications normally do not.
The current port contracts are:
sys.h: system services such as uptime, logging, sequence counters, and random bytes.crypto.h: cryptographic provider interface used by the common SDK code.sat_radio.h: satellite radio operations implemented by each satellite platform.
Common Implementation – src
Behavior that should be identical on every platform: input validation, BLE
advertisement formatting, satellite packet formatting and send policy, key
derivation, nonce-safety checks, encryption and authentication flow,
pass-prediction math, and the feature logic guarded by CONFIG_HUBBLE_*
options.
Common code may include public SDK headers, private src headers, and port
contract headers. It must not include RTOS or board headers directly.
Important files:
hubble.c: SDK initialization and common time/key entry points.hubble_ble.c: BLE advertisement construction.hubble_crypto.c: common key derivation, nonce validation, encryption, and authentication flow.hubble_sat.c: common satellite send and DTM flow.hubble_sat_packet.c: satellite packet encoding.hubble_sat_pass_prediction.c: pass prediction logic.crypto/: concrete crypto provider adapters, currently mbedTLS and PSA.utils/andreed_solomon_encoder.*: internal helpers used by common protocol code.hubble_priv.h: private declarations shared only by common implementation files.
RTOS and framework glue – port/<rtos>
Adapts the SDK to an RTOS or framework. Each port selects the common sources it
needs, provides configuration integration, and implements the port contracts
required by the enabled SDK features. Typical responsibilities are build-system
integration, the sys.h implementation, crypto provider selection and
initialization, satellite radio implementation when satellite support is
enabled, and include-path and configuration injection.
Current ports:
port/zephyr: Zephyr module integration, Kconfig, common Zephyr system glue, Zephyr satellite radio glue, and board/SOC-specific radio support. The Zephyr port selects sources fromport/zephyr/CMakeLists.txtbased on Kconfig options.port/freertos: FreeRTOS makefile integration (hubblenetwork-sdk.mk), default configuration header flow, system glue, and satellite radio glue.port/esp-idf: ESP-IDF component-style wrapper and system glue for ESP-IDF applications.
Board and Hardware Implementation – port/<rtos>/boards
The lowest layer. Board files bind the generic satellite radio contract to
concrete SOC peripherals. For example, Zephyr satellite support has board
families under port/zephyr/boards for Nordic and Silicon Labs targets.
Use board-specific files for the details that cannot be expressed as common SDK logic:
vendor radio driver setup;
RF channel and power mapping;
front-end module (FEM) control;
vendor binary library integration;
SOC-family differences, timing quirks, and board selection logic.
A board implementation should answer “how this hardware transmits”, while
src answers “what the SDK needs to transmit”. Keep protocol behavior out
of board files.
Samples and Tests
Samples show application integration for each supported environment
(samples/<rtos>). Tests exercise SDK behavior and platform builds. The
common code should be structured so protocol behavior can be tested without
duplicating RTOS-specific glue.
Naming and Namespace Conventions
The prefix of a symbol tells you which layer owns it.
Public and Common Symbols – hubble_*
Names without a more specific internal or port marker are public or common SDK
symbols. If a symbol is declared in include/hubble and documented on an API
page, it is application-facing; if it is defined in src without a public
declaration, treat it carefully, since C symbols have global linkage unless
declared static.
Use this namespace for stable application APIs and SDK-wide constants. Examples:
hubble_init(),hubble_time_set(),hubble_time_get(), andhubble_key_set()fromhubble.h;hubble_ble_advertise_get()andhubble_ble_advertise_expiration_get()fromble.h;hubble_sat_packet_send()fromsat.h;satellite packet, pass prediction, and DTM helpers under
include/hubble/sat.
When adding a public API, place its declaration in include/hubble, add
Doxygen comments, keep the name under the hubble_* namespace, and avoid
leaking RTOS or board-specific types into the signature.
Private Helpers – hubble_internal_*
hubble_internal_* symbols are SDK-private helpers declared in
src/hubble_priv.h. They connect common implementation files to each other
without exposing those details to applications or ports.
Applications and port implementations should not call hubble_internal_*
functions. If a port needs a capability currently hidden behind one, add an
explicit port contract or public API rather than including src/hubble_priv.h.
Port-Contract Symbols – hubble_*_port_*
Symbols with _port_ in the name are implemented by a port or board
layer and called by common SDK code — for example
hubble_sat_port_init() and hubble_sat_port_packet_send(). The
_port_ suffix implies there is an equivalent common function that
shares code across all ports, for example hubble_sat_packet_send().
Not every port contract carries _port_ in its
name. hubble_uptime_get(), hubble_log(), and
hubble_crypto_*() are declared in include/hubble/port and are
still port-provider APIs by contract. These APIs are implemented
completely in the port layer and share no common code.
When adding port APIs, place declarations under include/hubble/port,
document who calls the function, and keep RTOS-specific types out of the common
contract unless the contract is intentionally limited to one port.
Configuration Conventions
Feature and provider selection use CONFIG_HUBBLE_* macros. Zephyr defines
these through Kconfig; FreeRTOS injects a configuration header through the
makefile integration. Other ports should provide equivalent configuration values
before compiling the common sources.
Keep configuration checks close to the feature boundary:
build files select source files for major features and providers;
headers expose APIs conditionally only when the feature requires it;
common implementation code uses
CONFIG_HUBBLE_*for small behavioral decisions within an already-selected feature.