17 vsnprintf(buf,
sizeof(buf), fmt, args);
31 return "timed out waiting for size header";
33 return "implausible image size";
35 return "Update.begin() failed";
37 return "timed out waiting for firmware data";
39 return "flash write size mismatch";
41 return "Update.end() failed";
55 Serial.print(
"[OTA] listening on TCP port ");
77 return static_cast<bool>(c);
94 Serial.println(
"[OTA] update successful");
99 if (
config.reboot_on_success) {
100 Serial.println(
"[OTA] rebooting into the new image");
111 Serial.print(
"[OTA] ERROR: ");
120 while (client.available() < 4) {
126 size_out |=
static_cast<uint32_t
>(client.read()) << 24;
127 size_out |=
static_cast<uint32_t
>(client.read()) << 16;
128 size_out |=
static_cast<uint32_t
>(client.read()) << 8;
129 size_out |=
static_cast<uint32_t
>(client.read());
134 logf(
config.verbose,
"[OTA] client connected -- starting transfer\n");
136 uint32_t image_bytes = 0;
139 "timed out waiting for the 4-byte size header");
141 if (image_bytes == 0 || image_bytes >
config.max_image_bytes) {
142 Serial.print(
"[OTA] announced size: ");
143 Serial.println(image_bytes);
146 logf(
config.verbose,
"[OTA] image size: %u bytes\n",
147 static_cast<unsigned>(image_bytes));
154 if (!
Update.begin(image_bytes)) {
160 uint32_t received = 0;
161 int last_percent_bucket = -1;
162 unsigned long last_data_ms =
millis();
164 while (received < image_bytes) {
165 int available = client.available();
166 if (available <= 0) {
170 "transfer stalled partway through");
176 int to_read = available < static_cast<int>(
sizeof(buf))
178 :
static_cast<int>(
sizeof(buf));
179 const uint32_t remaining = image_bytes - received;
180 if (
static_cast<uint32_t
>(to_read) > remaining)
181 to_read =
static_cast<int>(remaining);
183 int bytes_read = client.read(buf, to_read);
187 if (
Update.write(buf, bytes_read) !=
static_cast<size_t>(bytes_read)) {
191 "flash write came up short");
194 received += bytes_read;
200 int percent =
static_cast<int>((received * 100UL) / image_bytes);
201 if (percent / 5 != last_percent_bucket) {
202 last_percent_bucket = percent / 5;
203 logf(
config.verbose,
"[OTA] progress: %d%% (%u / %u bytes)\n",
204 percent,
static_cast<unsigned>(received),
205 static_cast<unsigned>(image_bytes));
209 logf(
config.verbose,
"[OTA] all bytes received -- finalizing\n");
226 if (message[0] ==
'\0')
229 static unsigned long last_ms = 0;
230 unsigned long now =
millis();
236 Serial.print(
"[OTA-MSG] ");
#define STAR_OTA_TEST_MESSAGE
Optional bench-test marker.
#define STAR_OTA_CHUNK_SIZE
Read buffer for the firmware stream.
#define STAR_OTA_TEST_MESSAGE_INTERVAL_MS
How often printTestMessage() prints, when a message is set.
static UpdateClass Update
void begin()
Start listening.
void(*)(void *user_data, uint32_t image_bytes) StartCallback
bool readSize(EthernetClient &client, uint32_t &size_out)
Result poll()
Accept a waiting client and run the transfer to completion.
void onEnd(EndCallback cb, void *user_data=nullptr)
Called on both success and failure, before any reboot.
void onProgress(ProgressCallback cb, void *user_data=nullptr)
Called every STAR_OTA_CHUNK_SIZE-ish bytes.
Result handleClient(EthernetClient &client)
Run the transfer on a client you accepted yourself.
Result transfer(EthernetClient &client)
Server(uint16_t port=STAR_OTA_DEFAULT_PORT)
void(*)(void *user_data, uint32_t received, uint32_t total) ProgressCallback
bool clientWaiting()
Is a client waiting?
void onStart(StartCallback cb, void *user_data=nullptr)
Called once the size header is in, before any flash write.
ProgressCallback on_progress_
Result fail(EthernetClient &client, Result r, const char *why)
void(*)(void *user_data, Result result) EndCallback
static const emmc_port_t port
static void start(gnss_frame_parser_t *p, uint8_t byte)
void logf(bool verbose, const char *fmt,...)
Result
Outcome of one OTA attempt.
@ HeaderTimeout
client connected but never sent the 4-byte size
@ WriteFailed
flash write came up short
@ BadSize
announced size was zero or implausibly large
@ Success
image written; the board reboots unless told not to
@ BeginFailed
Update.begin() refused (no OTA partition / too big).
@ EndFailed
image received but failed validation
@ Idle
no client was waiting; nothing happened
@ DataTimeout
transfer stalled partway through
void printTestMessage()
Bench-test helper: prints STAR_OTA_TEST_MESSAGE on a timer as.
const char * resultName(Result r)
Human-readable form of a Result, for logs.
const char * testMessage()
The compiled-in test message ("" when none).