SDK reference

The repository ships three bindings for one device contract. The table below is the binding-parity reference; runtime availability is a separate concern.

Note

This is the binding-parity reference for the device SDKs. The device-side SDK family and its place in the onboarding flow are described on the trustmint device-developer portal at https://docs.flexgalaxy.ai/dev/trustmint/protocol/device-sdks/, and the wire contract every binding conforms to is the frozen DDI-1 contract at https://docs.flexgalaxy.ai/dev/trustmint/protocol/ddi-1-contract/.

Capability

Python

Android/Kotlin

C

identify, provision, time

yes

yes

yes

certificate rotation

yes

yes

yes

MQTT connect and reconnect

yes

connect; no SDK-managed resubscribe

yes

telemetry

yes

yes

yes

telemetry app namespace (PLT-0069)

yes

yes

yes

CLIENT attributes

full protobuf Struct

full protobuf Struct

flat numeric values

SHARED push and ack

integrated manager

separate SharedAttributeManager adapter

integrated callback

command and response

yes

yes

yes

heartbeat and lifecycle

yes

yes

yes

desired/delta compatibility callbacks

yes

yes

delta callback

OTA

yes

yes

yes

licensing/status compatibility

no

yes; backend not published

no

Python 0.1.0

Install from an authorized checkout with python -m pip install ./sdks/python. The package requires Python 3.9 or newer and is imported as fgai_mqtt.

Identity and provisioning

  • ProvisioningClient(base_url, attestation_bearer, *, gateway_ca=None, verify_tls=True, mtls_base_url=None, client_cert=None, client_key=None, base_backoff=1, max_backoff=60, max_retries=5)

  • identify(model, sn, *, registrar_hint=None, attestation_method=None, firmware_version=None, hardware_revision=None) -> IdentityResult

  • provision(thing_id, enrollment_token, csr_pem, *, device_attributes=None) -> ProvisionResult

  • rotate(csr_pem) -> RotateResult

  • get_time() -> tuple[str, int]

  • build_csr(serial, model, thing_id, key=None, *, rsa_bits=None) -> tuple[str, str]

  • ProvisionedIdentity.persist(result, private_key_pem, directory, default_mqtt_port=8883) -> ProvisionedIdentity

  • ProvisionedIdentity.device_config(**overrides) -> DeviceConfig

IdentityResult contains thing_id, enrollment_token, provision_endpoint, server_time, and metadata. ProvisionResult contains the leaf and CA PEM, identity, shared configuration, and optional issuance metadata. RotateResult contains only thing_id and certificate.

MQTT

DeviceConfig fields are host, port=8883, device_id, ca_cert, client_cert, client_key, initial_state=None, keepalive=60, session_expiry=3600, https_base_url="https://things.flexgalaxy.ai", https_timeout=30, and app_namespace=None. A malformed app_namespace raises InvalidAppNamespaceError from the constructor.

FGAIDeviceClient(config) provides:

  • client_id and connected properties

  • connect(timeout=30) and disconnect()

  • publish_telemetry(metrics, tags=None, sequence=None, app_namespace=None)

  • publish_heartbeat(uptime_seconds, firmware_version, memory_pct=0, cpu_pct=0)

  • publish_reported_state(state, version=None)

  • report_client_attribute(attributes, version=None)

  • set_shared_attribute_callback(callback) and shared_attribute_shadow

  • set_command_callback(callback)

  • set_twin_callback(callback)

  • lazy ota: OtaClient

Unexpected disconnect triggers exponential reconnect from 1 to 60 seconds with 25% positive jitter. The client re-subscribes command, shared-attribute, and twin handlers after a reconnect even when the broker reports a resumed session.

OTA

OtaClient provides poll(), get_document(href), send_feedback(href, action_id, execution, finished="none", details=None), and download(href, destination, expected_sha256) -> OtaArtifact. OtaDocument.link(relation) returns one top-level HAL link; find_links(relation) recursively finds all matching links.

Android/Kotlin 1.1.0

The Android library is published to the configured private CodeArtifact repository as ai.flexgalaxy.ddi:ddi-android-sdk:1.2.0-<source-commit>. It requires Android API 29 or newer and JVM 17. New Kotlin applications use the neutral ai.flexgalaxy.ddi.sdk API; external package coordinates, HTTP APIs, and public hostnames expose only DDI names.

High-level facade

Create DdiDeviceSdk(DdiSdkConfig(attestationBearer = ...)). The public origin defaults to https://things.flexgalaxy.ai; production callers must supply a real attestation bearer.

The live high-level journey is:

  1. provisionDevice(model, serial, firmwareVersion) returns DdiProvisioning.

  2. Persist its DdiDeviceCredentials in protected storage.

  3. Call buildMqttConfig(provisioning) and configureMqtt(config).

  4. Use sdk.mqtt and sdk.ota; both are bound to the same thingId and PEM identity.

  5. After reboot, restore credentials and call bindCredentials(credentials) before accessing ota or configuring MQTT.

The SDK intentionally does not claim to persist an extractable provisioning key inside Android Keystore. A product may replace the current PEM-backed bootstrap with a hardware-backed key implementation, but it must preserve the certificate identity and never upload the private key.

Provisioning

ProvisioningClient supplies identify, provision, rotate, and getTime. ProvisioningCsr.generate(serial, model, thingId) returns csrPem and privateKeyPem. Results are IdentityResult, ProvisionResult, SharedConfig, RotateResult, and TimeResult. Provisioning is blocking OkHttp work even though the high-level facade wraps its composed flow in Dispatchers.IO.

MQTT

MqttConfig fields are host, port=8883, deviceId, CA/client/key PEM, cleanStart=false, sessionExpiryInterval=3600, keepAliveInterval=60, willDelayInterval=5, optional initialState, and optional appNamespace. Its computed client ID is fgai-<deviceId>; canonicalAppNamespace is the lowercased, trimmed slug that goes on the wire, and a malformed one throws IllegalArgumentException from the constructor. AppNamespace.normalize and AppNamespace.isValid expose the same grammar. Both facades’ buildMqttConfig take an optional appNamespace.

FgaiMqttClient provides isConnected, connect(timeout=30.seconds), disconnect, publishTelemetry(metrics, tags, appNamespace), publishHeartbeat, publishReportedState, setCommandCallback, and setTwinCallback.

SharedAttributeManager(deviceId, publisher, callback) is a separate adapter. It exposes shadow, pushTopic, ackTopic, setCallback, subscribeSharedPush, onSharedPush, and publishAck. The application must provide a SharedAttributePublisher backed by the actual MQTT transport.

The current Android MQTT client does not implement automatic reconnect or re-subscription. The host application must reconnect with backoff and recreate subscriptions after connection loss.

OTA

DdiDeviceSdk.ota returns DdiOtaClient. It provides poll, document, feedback, and download; DdiOtaDocument provides link and findLinks. Downloads verify SHA-256 before returning DdiOtaArtifact. The client accepts only same-origin links under /ddi/v1/ota.

Legacy gateway facade

The direct GatewayClient/thingsboardBaseUrl path has been removed because it bypassed managed DDI. The old TrustMintSDK stored-enrollment licensing methods remain an artifact-compatibility surface, are not part of the managed DDI route, and are intentionally absent from DdiDeviceSdk.

C 1.0.0

The C11 project builds libfgai-mqtt, plus dependency-reduced libfgai-provisioning and libfgai-ota static libraries. Install headers under fgai/; include fgai/fgai_mqtt.h for MQTT and fgai/fgai_mqtt_provisioning.h or fgai/fgai_ota.h for standalone use.

Configuration and lifecycle

  • fgai_mqtt_config_new, fgai_mqtt_config_set_device_id, fgai_mqtt_config_set_tls, fgai_mqtt_config_set_keepalive, fgai_mqtt_config_set_session_expiry, fgai_mqtt_config_set_app_namespace, fgai_mqtt_config_free. set_app_namespace is the only setter that returns fgai_mqtt_error_t; on rejection the previous namespace is left in place.

  • fgai_mqtt_client_new, fgai_mqtt_client_connect, fgai_mqtt_client_disconnect, fgai_mqtt_client_free

  • command, twin-delta, disconnect, and shared-attribute callback setters

MQTT calls return fgai_mqtt_error_t: FGAI_MQTT_OK, or connect, TLS, publish, subscribe, serialization, deserialization, timeout, argument, and allocation errors.

Publish and respond

  • fgai_mqtt_client_publish_telemetry (returns FGAI_MQTT_ERR_INVALID_ARG and publishes nothing if tel.app_namespace is a malformed slug)

  • fgai_mqtt_client_publish_reported

  • fgai_mqtt_client_publish_heartbeat

  • fgai_mqtt_client_publish_lifecycle

  • fgai_mqtt_client_publish_shared_ack

  • fgai_mqtt_client_respond_command

fgai_mqtt_client_handle_shared_push is public primarily for transport adapters and unit tests. It decodes, applies, and acknowledges a raw shared push. fgai_mqtt_app_namespace_normalize is public so a device reading its namespace from a config file can fail at start-up rather than on the wire.

Provisioning

Create and tune a client with fgai_provisioning_client_new, the CA/mTLS/retry setters, and fgai_provisioning_client_free. The flow functions are fgai_provisioning_identify, fgai_provisioning_build_csr, fgai_provisioning_provision, fgai_provisioning_rotate, and fgai_provisioning_get_time.

Inspect failures with fgai_provisioning_last_error_code, fgai_provisioning_last_error_detail, fgai_provisioning_last_error_status, fgai_provisioning_error_is_retryable, and fgai_provisioning_error_is_terminal. The last-error view is owned by the client and is not thread-safe.

OTA

Create with fgai_ota_client_new(https_origin, ca_path, client_cert_path, client_key_path). Use fgai_ota_poll, fgai_ota_get, fgai_ota_feedback, fgai_ota_download, fgai_ota_find_link, and fgai_ota_resolve_link. Free response bodies with fgai_ota_response_free and inspect diagnostic text with fgai_ota_last_error.

Wire rules common to every binding

  • MQTT is version 5, mTLS is mandatory, and content type is application/x-protobuf.

  • The stable MQTT client ID is fgai-<thing_id> and the session expiry default is one hour.

  • The certificate SAN and topic thing_id must match.

  • Telemetry and heartbeat use QoS 0. Attributes, lifecycle, shared acks, and command responses use QoS 1.

  • The optional telemetry app namespace is ^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$, 3 to 63 characters, lowercased and trimmed by the binding and rejected at construction otherwise. Omitting it leaves the field off the wire entirely, so an unnamespaced sample is byte-identical to a pre-PLT-0069 build. The value is device-asserted: it narrows a read the device owner already granted, never widens one, and no authorization decision turns on it alone.

  • OTA accepts HTTPS links only, pins them to the configured origin, and confines them to /ddi/v1/ota.