← Back to Skills Marketplace
rockets-cn

Unihiker K10 OTA

by Rockets_cn · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
35
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install unihiker-k10-ota
Description
Add HTTP OTA (Over-The-Air) firmware update capability to Unihiker K10 Arduino projects, including AP/STA projects and ESP-NOW projects that need a safe OTA...
README (SKILL.md)

Unihiker K10 - HTTP OTA

Overview

Enable wireless firmware updates for K10 Arduino projects via HTTP POST.

Core principle: K10's default partition table has no OTA partitions. You must switch to a custom partition table with ota_0 + ota_1 before Update.begin() can work.

Why not ArduinoOTA? The standard ArduinoOTA library (UDP-based) requires the ESP32 to connect back to the host computer on a random port, which is often blocked by Windows Firewall. HTTP OTA uses a simple host→device upload direction and works reliably on all networks.

When to Use

  • Your K10 is installed in a location difficult to reach with USB
  • You want to update firmware without opening the enclosure
  • You need a scriptable/automated deployment pipeline
  • ArduinoOTA network port upload fails with "No response from device"

Prerequisites

  • Existing K10 Arduino project with WebServer running
  • arduino-cli installed and K10 BSP (UNIHIKER:esp32:k10) available
  • Device and computer on the same network (or connected to K10's AP)

ESP-NOW Compatibility Rule

ESP-NOW sketches can support OTA, but ordinary HTTP OTA requires temporary IP networking through WIFI_AP, WIFI_STA, or WIFI_AP_STA. ESP-NOW itself is not an IP transport, so do not claim that the standard /ota HTTP endpoint works over pure ESP-NOW packets.

When adding OTA to an ESP-NOW program, use this policy:

  1. Prefer a maintenance OTA mode: normal runtime uses ESP-NOW; a button, serial command, saved flag, or received command enters OTA mode, starts AP or STA networking, registers /ota, and services server.handleClient().
  2. Keep ESP-NOW and WiFi on the same channel if they run together. If STA connects to a router, the router determines the channel; ESP-NOW peers must use that channel or peer channel 0.
  3. For reliability, pause ESP-NOW sends and time-critical control loops while an OTA upload is active.
  4. Keep an AP fallback such as K10-OTA-\x3Cid> available in OTA mode so updates still work when STA credentials are missing or the router changes.
  5. Treat pure ESP-NOW firmware transfer as an advanced separate design. It needs packet chunking, acknowledgements, image validation, and writes to OTA partitions; do not replace HTTP OTA with it unless the user explicitly asks for ESP-NOW-only OTA.

See references/ota-implementation.md for the ESP-NOW maintenance-mode code pattern.

Quick Start

Step 1: Add Custom Partition Table

Create partitions.csv in your sketch directory:

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x5000,
otadata,  data, ota,     0xe000,  0x2000,
app0,     app,  ota_0,   0x10000, 0x640000,
app1,     app,  ota_1,   0x650000,0x640000,
spiffs,   data, spiffs,  0xc90000,0x370000,

Compile with the custom partition:

arduino-cli compile --fqbn UNIHIKER:esp32:k10 . \
  --output-dir build \
  --build-property "build.partitions=custom"

Optional speed-up for repeated compiles:

# Use all CPU cores and keep build artifacts in stable project-local folders.
arduino-cli compile --fqbn UNIHIKER:esp32:k10 . \
  --build-path .arduino-build \
  --output-dir build \
  --build-property "build.partitions=custom" \
  -j 0

Arduino CLI already has a built-in build_cache. To use a longer-lived cache, configure the official build_cache.* keys rather than compiler.cache.*:

arduino-cli config set build_cache.path ~/.cache/arduino-build-cache
arduino-cli config set build_cache.compilations_before_purge 0

On Windows PowerShell:

arduino-cli config set build_cache.path "$env:LOCALAPPDATA\arduino\build-cache"
arduino-cli config set build_cache.compilations_before_purge 0

Step 2: Add OTA Endpoint to Firmware

Include the Update library and add a POST handler:

#include \x3CUpdate.h>

void handleOta() {
  server.sendHeader("Connection", "close");
  server.send(200, "text/plain", Update.hasError() ? "FAIL" : "OK");
  if (!Update.hasError()) {
    ESP.restart();  // or schedule a delayed restart
  }
}

void handleOtaUpload() {
  HTTPUpload &upload = server.upload();
  if (upload.status == UPLOAD_FILE_START) {
    if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {
      Update.printError(Serial);
    }
  } else if (upload.status == UPLOAD_FILE_WRITE) {
    if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
      Update.printError(Serial);
    }
  } else if (upload.status == UPLOAD_FILE_END) {
    if (Update.end(true)) {
      Serial.printf("OTA Success: %u bytes\
", upload.totalSize);
    } else {
      Update.printError(Serial);
    }
  }
}

// In setup() or startNetwork():
server.on("/ota", HTTP_POST, handleOta, handleOtaUpload);

For ESP-NOW sketches, do not leave OTA as an afterthought. Add an explicit OTA mode gate:

bool otaMode = false;
bool otaUploadActive = false;

void enterOtaMode() {
  otaMode = true;
  WiFi.mode(WIFI_AP_STA);  // AP fallback plus optional STA
  WiFi.softAP("K10-OTA", "12345678");
  // Optional: WiFi.begin(savedSsid, savedPassword);
  server.on("/ota", HTTP_POST, handleOta, handleOtaUpload);
  server.begin();
}

void loop() {
  if (otaMode) {
    server.handleClient();
    return;  // keep ESP-NOW/control traffic paused during OTA maintenance
  }

  // normal ESP-NOW runtime
}

Step 3: First USB Upload (Required Once)

The first upload must be via USB to flash the new partition table:

arduino-cli upload -p COM4 --fqbn UNIHIKER:esp32:k10 .

Step 4: Update Over WiFi

After the first USB upload, use any of these methods:

curl:

curl -F "file=@build/your_sketch.ino.bin" http://192.168.9.42/ota

Python script (works on Windows, macOS, and Linux):

python scripts/ota_upload.py build/your_sketch.ino.bin --ip 192.168.9.42

PowerShell 7+ (works on Windows, macOS, and Linux):

pwsh ./scripts/ota_upload.ps1 -Bin build/your_sketch.ino.bin -Ip 192.168.9.42

Important Notes

  • Partition change erases flash layout. The first USB upload after adding partitions.csv will reformat the flash partition table. Preferences / NVS data may be lost.
  • Every OTA-enabled sketch must include the OTA code. If you upload a sketch without /ota handler, you lose OTA capability and must return to USB.
  • Do not use delay() in loop() for long periods. Use non-blocking millis() patterns so the WebServer can process the upload request.
  • Content-Length: Arduino WebServer's server.header("Content-Length") does not work in POST handlers. Use server.clientContentLength() instead if you need the raw body size.
  • Compile cache: Use Arduino CLI's official build_cache.* settings and --build-path for repeat builds. Do not document compiler.cache.enable, compiler.cache.path, or ccache as required OTA setup because they are not part of the current Arduino CLI configuration reference.
  • ESP-NOW: HTTP OTA needs AP/STA networking. If the program uses ESP-NOW, add an OTA maintenance mode, manage WiFi channel alignment, and pause ESP-NOW traffic while flashing.

Files

unihiker-k10-ota/
├── SKILL.md                           # This file
├── references/
│   └── ota-implementation.md          # Detailed implementation guide
└── scripts/
    ├── ota_upload.py                  # Python OTA uploader
    └── ota_upload.ps1                 # PowerShell OTA uploader

Troubleshooting

Issue Cause Solution
BEGIN_FAIL No OTA partitions in partition table Add partitions.csv with ota_0 + ota_1 and reflash via USB
FAIL after upload Update.write() failed mid-stream Check serial log; likely flash write error or insufficient space
NO_CONTENT Content-Length header missing Ensure client sends valid multipart/form-data with file data
Device does not restart ESP.restart() called before response sent Use scheduleRestart() with a small delay instead
Network port not found mDNS/ArduinoOTA not running HTTP OTA does not need network port detection; use the device's IP directly
ESP-NOW works until STA starts STA changed the radio channel to the router channel Put peers on the same channel or use peer channel 0 after STA connects
OTA page unreachable in ESP-NOW sketch Sketch never entered AP/STA maintenance mode Add a button/serial/command path that calls enterOtaMode() and starts the WebServer
ESP-NOW packets drop during OTA Flashing and HTTP handling are competing with runtime traffic Pause ESP-NOW sends/control loops while otaUploadActive or otaMode is true
Usage Guidance
Review this carefully before installing or copying the examples. Use only with an explicit maintenance mode, unique strong per-device credentials, network isolation, and preferably signed firmware or another authenticity check before accepting uploads. Do not expose the `/ota` endpoint on an untrusted network or with the provided example password.
Capability Assessment
Purpose & Capability
The stated purpose is wireless K10 firmware updates, and firmware flashing is expected for that purpose, but the examples allow arbitrary firmware writes through `/ota` without authentication or firmware authenticity checks.
Instruction Scope
The skill presents minimal and maintenance-mode code that users are likely to copy directly, including `WiFi.softAP("K10-OTA", "12345678")` and `server.on("/ota", HTTP_POST, ...)`, without a prominent warning or scoped authorization model.
Install Mechanism
The package contains markdown guidance and one small Python uploader using the standard library; there is no hidden install-time execution or dependency installation.
Credentials
Network access and HTTP upload are expected for OTA, but exposing a flash-write endpoint on a local network or fallback AP is high impact and not proportionately constrained in the provided examples.
Persistence & Privilege
Successful use changes device firmware and persists across reboot; the skill also instructs partition-table changes that can erase flash layout, which is disclosed, but the unauthenticated OTA path remains a material privilege concern.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install unihiker-k10-ota
  3. After installation, invoke the skill by name or use /unihiker-k10-ota
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial Clawhub release for HTTP OTA update guidance on Unihiker K10 Arduino projects.
Metadata
Slug unihiker-k10-ota
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Unihiker K10 OTA?

Add HTTP OTA (Over-The-Air) firmware update capability to Unihiker K10 Arduino projects, including AP/STA projects and ESP-NOW projects that need a safe OTA... It is an AI Agent Skill for Claude Code / OpenClaw, with 35 downloads so far.

How do I install Unihiker K10 OTA?

Run "/install unihiker-k10-ota" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Unihiker K10 OTA free?

Yes, Unihiker K10 OTA is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Unihiker K10 OTA support?

Unihiker K10 OTA is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Unihiker K10 OTA?

It is built and maintained by Rockets_cn (@rockets-cn); the current version is v1.0.0.

💬 Comments