> ## Documentation Index
> Fetch the complete documentation index at: https://launchpad.anxlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update ANX OS Firmware Over the Air (OTA)

> Enable automatic OTA firmware updates on your ANX dev module to receive new features and security fixes without a USB connection.

OTA (over-the-air) updates let your ANX module download and apply firmware updates over Wi-Fi without ever connecting a USB cable — making them essential for devices that are already deployed in the field, installed in enclosures, or simply inconvenient to reach. Once OTA is configured, your devices stay current with security patches and new firmware features automatically, or on demand from the CLI or from within your application code.

<Warning>
  Ensure your device has a stable power source before starting an OTA update. A power loss mid-update can corrupt the incoming firmware partition. If your device runs on battery, charge it above 50% or connect a power supply before triggering an update in production.
</Warning>

## How OTA Works

The ANX OS OTA engine follows a safe, multi-stage process designed to protect against bad updates:

1. **Poll** — the device contacts the ANX update server and checks whether a newer firmware version is available on the configured release channel.
2. **Download** — if an update is found, the engine downloads a delta patch (not a full image) to minimize bandwidth and flash wear.
3. **Verify** — the downloaded patch is verified against a cryptographic signature from ANX Labs. Tampered or corrupted patches are rejected before any write occurs.
4. **Write** — the patch is applied to the **inactive** firmware partition. The currently running firmware is never touched during this step.
5. **Health check and reboot** — the device reboots into the new firmware. ANX OS monitors the new firmware for 60 seconds. If it passes the health check, the new partition becomes the active boot target. If it crashes or hangs, ANX OS automatically reverts to the previous partition.

This dual-partition scheme means a failed update never leaves your device in an unbootable state.

## Prerequisites

Before enabling OTA updates, confirm the following:

* **Wi-Fi configured** — the `wifi.ssid`, `wifi.password`, and `wifi.mode` fields must be set in `config.json`. OTA requires an active internet connection. See the [Configuration guide](/firmware/configuration) if you have not set up Wi-Fi yet.
* **Firmware 1.0.0 or later** — the OTA engine shipped in ANX OS 1.0.0. Devices running older firmware must be updated once via USB before they can receive OTA updates. See [Flashing](/firmware/flashing).

## Enabling Automatic OTA

Add or update the `ota` section in your device's `config.json` to turn on background update checks:

```json config.json theme={null}
{
  "ota": {
    "channel": "stable",
    "auto_check": true,
    "check_interval_hours": 24
  }
}
```

Push the updated config to your device, then reboot to apply it:

```bash theme={null}
anx config write config.json
anx device reboot
```

With `auto_check` enabled, the device silently polls the ANX update server every 24 hours and applies any available update during its next idle window.

## Triggering a Manual OTA Check

To check for an available update immediately without waiting for the next scheduled poll, run:

```bash theme={null}
anx ota check
```

To check for an update **and apply it immediately** if one is available, run:

```bash theme={null}
anx ota update
```

The CLI streams progress to your terminal as the download, verification, and write steps complete, then prompts you before the device reboots.

## Triggering OTA from Device Code

You can initiate an OTA check directly from your application using the ANX SDK. This is useful when you want to gate updates on application-level conditions — for example, only checking for updates when the device is idle or after a successful sensor reading cycle.

```c ota_trigger.c theme={null}
#include "anx/ota.h"

void check_for_update(void) {
    anx_ota_result_t result = anx_ota_check();
    if (result == ANX_OTA_UPDATE_AVAILABLE) {
        anx_ota_apply(); // downloads, verifies, writes, and reboots
    }
}
```

The `anx_ota_check()` call is non-blocking at the network level but does require an active Wi-Fi connection. `anx_ota_apply()` is a blocking call — it takes over the main execution context for the duration of the download and write, then reboots the device automatically.

<Tabs>
  <Tab title="Result Codes">
    | Code                       | Value | Meaning                                                                                           |
    | -------------------------- | ----- | ------------------------------------------------------------------------------------------------- |
    | `ANX_OTA_UP_TO_DATE`       | `0`   | The device is already running the latest firmware on the configured channel.                      |
    | `ANX_OTA_UPDATE_AVAILABLE` | `1`   | A newer firmware version is available. Call `anx_ota_apply()` to install it.                      |
    | `ANX_OTA_NO_WIFI`          | `2`   | The Wi-Fi radio is not connected. Ensure `wifi.mode` is `"station"` and the network is reachable. |
    | `ANX_OTA_SERVER_ERROR`     | `3`   | The ANX update server returned an unexpected response. Retry after a delay.                       |
    | `ANX_OTA_VERIFY_FAILED`    | `4`   | The downloaded patch failed signature verification. Do not apply it.                              |
  </Tab>

  <Tab title="Full Example with Error Handling">
    ```c ota_with_error_handling.c theme={null}
    #include "anx/ota.h"
    #include "anx/log.h"

    void try_ota_update(void) {
        ANX_LOG_INFO("Checking for firmware update...");

        anx_ota_result_t result = anx_ota_check();

        switch (result) {
            case ANX_OTA_UP_TO_DATE:
                ANX_LOG_INFO("Firmware is up to date.");
                break;

            case ANX_OTA_UPDATE_AVAILABLE:
                ANX_LOG_INFO("Update available. Applying...");
                anx_ota_apply(); // device will reboot; code below does not run
                break;

            case ANX_OTA_NO_WIFI:
                ANX_LOG_WARN("OTA skipped: Wi-Fi not connected.");
                break;

            case ANX_OTA_VERIFY_FAILED:
                ANX_LOG_ERROR("OTA patch verification failed. Aborting.");
                break;

            default:
                ANX_LOG_ERROR("OTA check failed with code: %d", result);
                break;
        }
    }
    ```
  </Tab>
</Tabs>

## Rollback

If the newly installed firmware crashes or stops responding within **60 seconds** of boot, ANX OS detects the failed health check and automatically reverts to the previous firmware partition. The device reboots a second time into the known-good version without any manual intervention.

You can also trigger a manual rollback at any time from the CLI:

```bash theme={null}
anx ota rollback
```

This immediately reboots the device into the previously active firmware partition, regardless of whether the current firmware is healthy. Use this when an update introduces a regression that does not cause a crash — for example, a performance issue or unexpected behavior change.

## Monitoring OTA Status

Check the current OTA state, partition versions, and last check time with:

```bash theme={null}
anx ota status
```

Sample output:

```
OTA Status
──────────────────────────────────────────────
Current firmware:    1.2.0  (stable)
Previous firmware:   1.1.5  (stable)
Channel:             stable
Auto-check:          enabled
Check interval:      24 hours
Last check:          2h ago
Next check:          in 22h
Pending update:      none
```

<Tip>
  Always test OTA updates on a bench device running the same firmware version as your fleet before enabling `auto_check` in production. This lets you catch any application-level regressions before they propagate to all deployed units.
</Tip>
