Reading the partition table of ESP32s already in the field before we turn on OTA
We have 31 ESP32-WROOM-32 boards in refrigerated trailers reporting temperatures to Hermetry over MQTT. Firmware is ours, built with Arduino core 2.x. We’d like to start using Hermetry’s firmware updates instead of driving to the depot with a laptop.
Problem: the first 12 boards were flashed by a contractor and nobody wrote down which partition scheme he picked. Our current build is about 1.4 MB. If some boards were flashed with a single big app partition, OTA has nowhere to write to and I’d rather know that before I assign anything and watch half the fleet go to Failed.
Is there a way to read the partition table of a running board without reflashing it? Ideally remotely, since the trailers are spread over three depots.
esptool read_flash at 0x8000?
That needs USB though. The trailers are out most of the week.
Not your question, but while you’re at it: register a signing key and keep “Allow unsigned images” off on that profile. Unsigned is meant for test devices only, and trailers on the road aren’t test devices.
Had this exact situation with meter boards a contractor did. You can ask the running firmware: the partition API in ESP-IDF works fine from the Arduino core. Push one build to the boards you can reach (the ones from your own batch), or wait until the others are at the depot, that reports the table as client attributes once after connecting:
#include "esp_partition.h"
void reportPartitions() {
String json = "{";
esp_partition_iterator_t it =
esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
bool first = true;
while (it != NULL) {
const esp_partition_t *p = esp_partition_get(it);
if (!first) json += ",";
json += ""part." + String(p->label) + "":"" +
String(p->address, HEX) + "/" + String(p->size) + """;
first = false;
it = esp_partition_next(it);
}
esp_partition_iterator_release(it);
json += "}";
mqtt.publish("v1/attributes", json.c_str());
}
Then the Attributes tab, Client scope, shows part.app0, part.app1, part.otadata and so on per board. What you want to see is two app slots (ota_0 and ota_1, called app0/app1 in the Arduino tables) plus otadata, each at least as big as your image. If you see one app0 of 3 MB and no app1, that’s the “Huge APP” scheme, no OTA possible.
For the boards you can’t get a new build on, emily’s way works at the depot:
esptool.py --port /dev/ttyUSB0 read_flash 0x8000 0xc00 pt.bin
python gen_esp32part.py pt.bin
Boards with the wrong scheme need one USB reflash with a two-slot table. After that OTA works for good.
Done. 9 of the contractor’s 12 came back with a single 3 MB app0, so no OTA on those without a visit. The other 3 and all of ours have app0/app1 at 1.25 MB each, which is tight against our 1.4 MB build, so I’m switching our table to the minimal SPIFFS one with 1.9 MB slots before we go further. Good thing we checked first.
As the one who signs off on the depot visits: please check this before the next batch gets flashed.
- You must be logged in to reply to this topic.
Join the conversation
Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

