Over-the-Air Updates¶
This section documents the OTA software update mechanism used to update the controller software independently of the TEG Gateway runtime.
Docker Client¶
Docker runtime management for the Edge Gateway controller.
This module provides the GatewayDockerClient, a thin
wrapper around the Docker Engine API used by the Edge Gateway to manage the
controller container.
Responsibilities¶
Detect whether the controller container is running and determine its version.
Start/stop the controller container in a controlled way.
Build controller images from a Git tag or commit hash if the image is not available.
Publish ThingsBoard OTA-related software state updates via MQTT (
sw_state).
The controller is deployed as a Docker container (teg_controller) with images
tagged as teg-controller-<version>:latest. Versions may be Git tags (e.g. v1.2.3)
or full commit hashes.
Notes
This client is implemented as a process-level singleton to avoid repeated Docker client initialization.
The implementation assumes host networking and a privileged container, as required for the deployed Raspberry Pi environment.
- class modules.docker_client.GatewayDockerClient[source]
Bases:
objectManage the controller Docker container for an Edge Gateway device.
The gateway and controller are intentionally separated: the Edge Gateway remains stable while controller versions can be updated independently (e.g. via OTA packages in ThingsBoard).
This class wraps Docker operations (list, stop, run, build) and integrates with the gateway’s Git and MQTT clients to support automated controller updates.
- last_launched_version
Cached version string of the last successfully launched controller.
- docker_client
Docker SDK client instance created via
docker.from_env(), orNoneif Docker is unavailable.
- docker_client: DockerClient | None = None
- get_controller_version()[source]
Return the controller version inferred from the running container image.
- Return type:
Optional[str]- Returns:
The Git tag/commit hash parsed from the image name, or
Noneif the controller is not running or the version cannot be determined.
- get_edge_startup_timestamp_ms()[source]
Return the controller container start time as Unix milliseconds.
- Return type:
Optional[int]- Returns:
Start timestamp in milliseconds (UTC) if the controller is running, else
None.
- get_last_launched_controller_version()[source]
Return the last launched controller version.
The value is cached in-memory and persisted in
$GATEWAY_DATA_PATH/last_launched_controller_version.txt. If the file is not available, the environment variableTEG_DEFAULT_CONTROLLER_VERSIONis used as a fallback.- Return type:
Optional[str]- Returns:
The version tag/commit hash, or
Noneif unknown.
- is_controller_running()[source]
Check whether the controller container is running.
- Return type:
bool- Returns:
Trueif the container exists and is running, otherwiseFalse.
- is_image_available(image_tag)[source]
Check whether a Docker image tag exists locally.
- Parameters:
image_tag (
str) – Full Docker image tag to look up (e.g.teg-controller-v1.0.0:latest).- Return type:
bool- Returns:
Trueif the image tag exists locally, otherwiseFalse.
- last_launched_version: str | None = None
- prune_containers()[source]
Remove stopped containers to keep the Docker environment clean.
- Return type:
None
- set_last_launched_controller_version(last_launched_controller_version)[source]
Persist the last launched controller version.
- Parameters:
last_launched_controller_version (
str) – Git tag or commit hash to store.
- start_controller(version_to_launch)[source]
Start the controller container for a given version.
If the requested version is already running, the method is a no-op. If the required image is not available locally, the controller repository is fetched, reset to the referenced commit, and a Docker image is built from the local Docker context.
During the update lifecycle, the method publishes OTA-related states via MQTT (e.g.
DOWNLOADING,DOWNLOADED,UPDATING,UPDATED).- Parameters:
version_to_launch (
str) – Git tag (e.g.v1.0.0) or full commit hash.- Return type:
None- Returns:
None
- start_controller_safely(version_to_launch)[source]
Start the controller and suppress unexpected exceptions.
- Parameters:
version_to_launch (
str) – Git tag or commit hash to run.
- stop_controller()[source]
Stop the running controller container (if any).
This stores the currently running controller version as the last-launched version before stopping the container.
- Return type:
None- Returns:
None
Git Client¶
Git repository access utilities for the Edge Gateway controller.
This module provides the GatewayGitClient, a lightweight wrapper around
the local Git repository of the Edge Gateway controller.
It is primarily used during controller software updates (e.g. OTA updates) to resolve version identifiers, fetch updates from the remote repository, and reset the working tree to a specific Git tag or commit hash.
Responsibilities¶
Resolve Git tags to commit hashes.
Verify the existence of commit hashes or tags.
Query the currently checked-out commit.
Fetch updates from the remote repository.
Reset the controller repository to a specific commit in a reproducible way.
Notes
All Git commands are executed via subprocess calls.
The client operates on the controller repository path defined by
CONTROLLER_GIT_PATH.The class is implemented as a singleton to avoid repeated initialization.
- class modules.git_client.GatewayGitClient[source]¶
Bases:
objectAccess and manage the local controller Git repository.
This class encapsulates all Git interactions required by the Edge Gateway to manage controller versions during updates. It provides helper methods to resolve tags, validate commit hashes, and safely reset the repository state.
The class follows a singleton pattern to ensure that Git operations are coordinated across the gateway process.
- execute_fetch()[source]¶
Fetch updates from the remote Git repository.
- Return type:
bool- Returns:
Trueif the fetch operation succeeded, otherwiseFalse.
- execute_reset_to_commit(commit_hash)[source]¶
Reset the controller repository to a specific commit.
This performs a forced checkout, hard reset, and clean to ensure a reproducible repository state.
- Parameters:
commit_hash (
str) – Commit hash to reset to.- Return type:
bool- Returns:
Trueif the reset succeeded, otherwiseFalse.
- get_commit_for_tag(tag)[source]¶
Return the commit hash associated with a Git tag.
- Parameters:
tag – Git tag name.
- Return type:
Optional[str]- Returns:
Commit hash for the tag, or
Noneif the tag does not exist.
- get_commit_from_hash_or_tag(hash_or_tag)[source]¶
Resolve a Git tag or commit hash to a commit hash.
- Parameters:
hash_or_tag (
str) – Git tag name or commit hash.- Return type:
Optional[str]- Returns:
Commit hash if resolvable, otherwise
None.
OTA Message Handling¶
Handle OTA software update notifications received via MQTT.
This module processes ThingsBoard OTA-related attribute updates (sw_title,
sw_version and legacy sf_* keys) and triggers controller software updates
on the Edge Gateway when a new version is available.
It represents the decision and orchestration stage of the OTA workflow: - Detect whether a software update is available. - Compare the requested version against the currently running controller. - Trigger a safe controller restart/update via the Docker client. - Record the last successfully launched controller version.
Notes
The actual Docker image build and container lifecycle are handled by
modules.docker_client.GatewayDockerClient.OTA state reporting (
sw_state) is published by the Docker client during the update lifecycle.
- on_mqtt_msg.check_for_ota_updates.on_msg_check_for_ota_update(msg_payload)[source]¶
Process an incoming OTA update notification.
- Parameters:
msg_payload (
Optional[Any]) – MQTT message payload containing OTA-related attributes.- Return type:
bool- Returns:
Trueif the message was handled as an OTA update notification,Falseotherwise.
Controller Supervision¶
Controller restart watchdog for the Edge Gateway.
This module implements a lightweight watchdog that ensures the controller Docker container is running. If the controller is not running, it attempts to restart it using the last successfully launched controller version.
To avoid rapid restart loops, restarts are rate-limited and use an exponential backoff strategy. If no previous version is known, the watchdog requests OTA version information from ThingsBoard and reports a FAILED software state.
Notes
Controller lifecycle operations are executed via
modules.docker_client.GatewayDockerClient.OTA software state reporting is published via
modules.mqtt.GatewayMqttClient.
- utils.controller_restart.restart_controller_if_needed()[source]¶
Restart the controller container if it is not running.
The watchdog checks whether the controller container is running. If it is not, it waits briefly and attempts to restart it using the last launched version. Restart attempts are rate-limited and use exponential backoff to avoid repeated rapid restarts.
- Return type:
bool- Returns:
Trueif the watchdog performed an action that should delay or influence the main loop (restart attempt, OTA request), otherwiseFalse.