Build Sheets

01 · Brief

A XIAO ESP32S3 and a BME280 in a printed enclosure on the exterior outlet, posting temperature, humidity, and pressure to the server every five minutes. Push only: the device runs no server of any kind, so nothing on the network can reach into it.

On the dashboard it feeds the Atmospheric Nowcast page: live readings, a three-hour pressure trend, derived dew point, and a 24-hour chart with the gaps shaded where the station was asleep. Even weather stations need sleep.

The interior of the enclosure has a second smaller weather proof enclosure for the ESP32 itself. The BME280 is next to the vents in the primary housing to better read outdoor temp.

02 · System

USB 5VXIAO ESP32S3→ LCARS CORE
BME280LCARS CORE→ XIAO ESP32S3

03 · Source

weather_station.ino

// ---------- Push ----------
void pushReading() {
  sensorOk = readSensor();
  if (WiFi.status() != WL_CONNECTED) { pushOk = false; return; }

  char t[16], h[16], p[16], body[256];
  numOrNull(t, sizeof t, lastTempC, 2);
  numOrNull(h, sizeof h, lastHumidity, 1);
  numOrNull(p, sizeof p, lastPressure, 1);
  int blen = snprintf(body, sizeof body,
    "{\"device_id\":\"%s\",\"fw_version\":\"%s\",\"temperature_c\":%s,"
    "\"humidity_pct\":%s,\"pressure_hpa\":%s,\"rssi\":%d,\"sensor_ok\":%s}",
    DEVICE_ID, FW_VERSION, t, h, p, WiFi.RSSI(), sensorOk ? "true" : "false");

  WiFiClient client;
  client.setTimeout(HTTP_TIMEOUT_MS);
  if (!client.connect(SERVER_HOST, SERVER_PORT)) {
    LOGLN("connect failed");
    pushOk = false;
    return;
  }
  client.printf(
    "POST %s HTTP/1.1\r\nHost: %s\r\nContent-Type: application/json\r\n"
    "X-Device-Token: %s\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s",
    INGEST_PATH, SERVER_HOST, DEVICE_TOKEN, blen, body);

  String status = client.readStringUntil('\n');  // "HTTP/1.1 200 OK"
  client.stop();
  pushOk = status.indexOf("200") > 0;
  LOG("push -> "); LOGLN(status);
  if (pushOk) ledPulseUntil = millis() + 600;
}
Lines 79–110 of 204 · Full source →

04 · Lessons

A special 3d enclosure is needed with proper shielding and venting to allow the sensor to properly read the outdoor temp, humidity, and pressure.

It gets hot during the day and colder at night.

I don't know what else to put here.