Community project

Smart Infrastructure Monitoring Box

ESP32
Photo of Smart Infrastructure Monitoring Box
Generated with AI

ayyappan v

Last updated November 1, 2026

This project builds a networked monitoring box that tracks environmental conditions and infrastructure health using an ESP32 microcontroller. The device measures temperature and humidity with a Sensirion SHT31 sensor, monitors connectivity to multiple network targets, and reports status changes via webhook notifications. Builders will receive a complete four-layer PCB layout, a detailed parts list with bare components, step-by-step assembly instructions starting with power validation, and Arduino firmware that handles Wi-Fi connectivity, sensor polling, and event logging.

The guide covers the full development cycle from schematic review through first-article validation, including guidance on configuring Wi-Fi credentials, webhook endpoints, and monitoring targets before deployment. The firmware implements a robust event queue, latency measurement, and downtime tracking—making this suitable for data center, facility, or remote site supervision where rapid alerting on environmental or network changes is critical.

Wiring diagram

Wiring diagram for Smart Infrastructure Monitoring Box
Loading diagram…

Gather all the parts

QtyComponent
1

Sensirion SHT31-DIS-B bare DFN8

1=SDA,2=ADDR,3=ALERT NC,4=SCL,5=VDD,6=nRESET NC,7=R to GND,8=VSS,9=exposed pad to GND. ADDR low selects 0x44.

1

ESP32-D0WD-V3 — bare QFN48 5×5 mm

U1; physical pad map: 1=VDDA, 2=LNA_IN, 3=VDD3P3, 4=VDD3P3, 9=CHIP_PU, 18=MTDI_GPIO12, 19=VDD3P3_RTC, 22=GPIO2, 23=GPIO0, 26=VDD_SDIO, 28=SD_DATA2, 29=SD_DATA3, 30=SD_CMD, 31=SD_CLK, 32=SD_DATA0, 33=SD_DATA1, 37=VDD3P3_CPU, 39=GPIO22, 40=U0RXD, 41=U0TXD, 42=GPIO21, 43=VDDA, 44=XTAL_N, 45=XTAL_P, 46=VDDA, 47=CAP2, 48=CAP1, 49=EP_GND. All omitted GPIO pads unconnected; CAP2 optional without deep sleep. EP pad 49 to solid ground.

1

2-pin keyed 3.3 V DC input

J1: external regulated 3.3 V ±5%, at least 1 A isolated supply; never 5 V.

1

2 nH RF supply inductor, ≥500 mA

Initial filter value; verify rail droop on RF bursts.

1

22 uF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

10 uF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

10 uF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

1 uF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

100 nF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

100 nF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

100 nF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

100 nF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

100 nF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

1 uF ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

10 nF ±10% ceramic capacitor, ≥6.3 V

Place immediately beside its power pin; X7R except RF matching.

1

10 kΩ resistor

Discrete PCB component; connect as shown in wiring.

1

1 uF ceramic capacitor

CHIP_PU active high; delay enabling until rails settle.

1

Normally open reset pushbutton

Discrete PCB component; connect as shown in wiring.

1

10 kΩ resistor

Discrete PCB component; connect as shown in wiring.

1

Normally open BOOT pushbutton

Discrete PCB component; connect as shown in wiring.

1

10 kΩ resistor

Forces 3.3 V flash supply at reset.

1

10 kΩ resistor

Allows serial download when BOOT is held low.

1

W25Q32JVSSIQ 4 MB SPI NOR, SOIC8

1=/CS, 2=IO1, 3=IO2, 4=GND, 5=IO0, 6=CLK, 7=IO3, 8=VCC. Powered by VDD_SDIO, not a 1.8 V flash.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

0 Ω series resistor

Keep flash routes short; tune series resistance only after signal tests.

1

100 nF ceramic capacitor

Discrete PCB component; connect as shown in wiring.

1

10 kΩ resistor

Discrete PCB component; connect as shown in wiring.

1

40 MHz fundamental crystal, ±10 ppm, CL=10 pF

Two-terminal electrical model; select footprint and exact order code with assembler. Start with 16 pF loads assuming 2 pF board stray, then measure frequency offset.

1

0 Ω resistor

Discrete PCB component; connect as shown in wiring.

1

16 pF C0G capacitor

Discrete PCB component; connect as shown in wiring.

1

16 pF C0G capacitor

Discrete PCB component; connect as shown in wiring.

1

1.5 pF C0G RF capacitor, 0201

Prototype starting value only; add maker-recommended stub and tune RF network.

1

2.4 nH high-Q RF inductor, 0201

50-ohm controlled impedance trace after matching network.

1

1.5 pF C0G RF capacitor, 0201

Prototype starting value only; tune on actual PCB with enclosure and antenna.

1

50 Ω 2.4 GHz external dipole antenna with bulkhead SMA

Passive antenna assembly, not a radio module. PCB RF termination and coax shield require continuous ground; professionally implement SMA footprint.

1

4.7 kΩ resistor

Discrete PCB component; connect as shown in wiring.

1

4.7 kΩ resistor

Discrete PCB component; connect as shown in wiring.

1

100 nF ceramic capacitor

Discrete PCB component; connect as shown in wiring.

1

6-pad factory programming header

Use external USB-UART factory tool with 3.3 V logic, common GND. TX is board output to tool RX; RX is board input from tool TX. VREF sense only; power at J1. No onboard USB interface.

Assemble it in 5 steps

1. Engineering review before ordering

This is a bare-chip electrical prototype specification, NOT a routed PCB or manufacturing package. Have your PCB engineer create CAD schematic, footprints, placement, Gerbers, drill, BOM and pick-and-place files. Audit all pin numbers against selected package datasheets. Use Espressif ESP32 schematic and layout guidelines. No development board or sensor breakout is used.

  • Do not send this connection list directly to an assembly factory as production-ready.

2. Lay out the four-layer PCB

Use signal / uninterrupted ground / power / signal layers. Ground exposed chip pad with thermal vias. Keep flash short. Place each bypass capacitor at its pin. Route RF to SMA at 50 ohms using the actual stackup; keep matching 0201 parts against LNA_IN and ground vias adjacent. Place crystal at least 2.7 mm from chip clock pins as manufacturer recommends, with no trace vias. Place sensor at vented edge on thermally isolated region, away from processor heat. No conformal coating or flux residue on sensor opening.

3. Assemble and check power first

Professional reflow for QFN and DFN; inspect exposed-pad joints. Initially use a current-limited bench source at J1: POS=3.3 V, NEG=GND. Check for shorts before power. Verify all supply domains including VDD_SDIO and delayed CHIP_PU rise; Wi-Fi bursts must not pull rails below operating range. Fit antenna before enabling radio.

  • 5 V at J1 or any UART signal can destroy the chips. Do not connect mains or UPS terminals.

4. Program the first article

Use the six-pad header with a 3.3 V USB-UART factory tool: GND common, board TX to tool RX, board RX to tool TX. VREF is sense only. Supply board at J1; do not power it from the UART tool. Hold BOOT low, pulse EN low, release EN and then BOOT to enter serial download. After programming pulse EN with BOOT released for normal operation.

5. Validate before production

RF engineer must tune CLC network and crystal loads on assembled board, measure Wi-Fi range, frequency error, harmonics and antenna match with enclosure. Component RF values are starting points, not guaranteed production values. Verify sensor accuracy, network outages, power cycling and queued alerts. Obtain applicable radio, EMC and product safety approvals before commercial sale; bare chips do not provide module certification. Current firmware remains Wi-Fi-only and still needs the external alert/subscription backend.

  • Not production released; no Ethernet, UPS isolation circuitry, onboard USB or persistent outage history is added by this revision.

Review all connections

1. Connections between "power_in" and "ESP32"

Functionpower_inESP32
powerPOS3V3
groundNEGGND

2. Connections between "soc" and "ESP32"

FunctionsocESP32
powerP13V3
powerP193V3
powerP373V3
powerP433V3
powerP463V3
groundP49GND
powerP4 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P3EXT
i2cP42GPIO 21
i2cP39GPIO 22

3. Connections between "rf_supply_l" and "ESP32"

Functionrf_supply_lESP32
power13V3
data2 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P3EXT

4. Connections between "bulk" and "ESP32"

FunctionbulkESP32
power13V3
ground2GND

5. Connections between "rf_bulk" and "ESP32"

Functionrf_bulkESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P3EXT
ground2GND

6. Connections between "rf_bulk2" and "ESP32"

Functionrf_bulk2ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P4EXT
ground2GND

7. Connections between "rf_dec" and "ESP32"

Functionrf_decESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P3EXT
ground2GND

8. Connections between "analog1" and "ESP32"

Functionanalog1ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P1EXT
ground2GND

9. Connections between "rtc_dec" and "ESP32"

Functionrtc_decESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P19EXT
ground2GND

10. Connections between "cpu_dec" and "ESP32"

Functioncpu_decESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P37EXT
ground2GND

11. Connections between "analog43" and "ESP32"

Functionanalog43ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P43EXT
ground2GND

12. Connections between "analog46" and "ESP32"

Functionanalog46ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P46EXT
ground2GND

13. Connections between "sdio_dec" and "ESP32"

Functionsdio_decESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P26EXT
ground2GND

14. Connections between "cap1" and "ESP32"

Functioncap1ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P48EXT
ground2GND

15. Connections between "enable_r" and "ESP32"

Functionenable_rESP32
power13V3
data2 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P9EXT

16. Connections between "enable_c" and "ESP32"

Functionenable_cESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P9EXT
ground2GND

17. Connections between "reset" and "ESP32"

FunctionresetESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P9EXT
ground2GND

18. Connections between "boot_r" and "ESP32"

Functionboot_rESP32
power13V3
data2 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P23EXT

19. Connections between "boot" and "ESP32"

FunctionbootESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P23EXT
ground2GND

20. Connections between "strap12" and "ESP32"

Functionstrap12ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P18EXT
ground2GND

21. Connections between "strap2" and "ESP32"

Functionstrap2ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P22EXT
ground2GND

22. Connections between "flash" and "ESP32"

FunctionflashESP32
powerP8 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P26EXT
groundP4GND

23. Connections between "flash_r1" and "ESP32"

Functionflash_r1ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P30EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P1EXT

24. Connections between "flash_r2" and "ESP32"

Functionflash_r2ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P32EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P2EXT

25. Connections between "flash_r3" and "ESP32"

Functionflash_r3ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P29EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P3EXT

26. Connections between "flash_r5" and "ESP32"

Functionflash_r5ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P33EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P5EXT

27. Connections between "flash_r6" and "ESP32"

Functionflash_r6ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P31EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P6EXT

28. Connections between "flash_r7" and "ESP32"

Functionflash_r7ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P28EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P7EXT

29. Connections between "flash_dec" and "ESP32"

Functionflash_decESP32
data1 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P8EXT
ground2GND

30. Connections between "flash_cs_pull" and "ESP32"

Functionflash_cs_pullESP32
data1 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P1EXT
data2 → W25Q32JVSSIQ 4 MB SPI NOR, SOIC8 P8EXT

31. Connections between "xtal_series" and "ESP32"

Functionxtal_seriesESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P45EXT
data2 → 40 MHz fundamental crystal, ±10 ppm, CL=10 pF X1EXT

32. Connections between "crystal" and "ESP32"

FunctioncrystalESP32
analogX2 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P44EXT

33. Connections between "xtal_c1" and "ESP32"

Functionxtal_c1ESP32
data1 → 40 MHz fundamental crystal, ±10 ppm, CL=10 pF X1EXT
ground2GND

34. Connections between "xtal_c2" and "ESP32"

Functionxtal_c2ESP32
data1 → 40 MHz fundamental crystal, ±10 ppm, CL=10 pF X2EXT
ground2GND

35. Connections between "rf_c1" and "ESP32"

Functionrf_c1ESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P2EXT
ground2GND

36. Connections between "rf_l" and "ESP32"

Functionrf_lESP32
data1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P2EXT
data2 → 50 Ω 2.4 GHz external dipole antenna with bulkhead SMA RFEXT

37. Connections between "rf_c2" and "ESP32"

Functionrf_c2ESP32
data1 → 50 Ω 2.4 GHz external dipole antenna with bulkhead SMA RFEXT
ground2GND

38. Connections between "antenna" and "ESP32"

FunctionantennaESP32
groundSHIELDGND

39. Connections between "environment" and "ESP32"

FunctionenvironmentESP32
groundP2GND
groundP7GND
groundP8GND
groundP9GND
powerP53V3
i2cP1 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P42EXT
i2cP4 → ESP32-D0WD-V3 — bare QFN48 5×5 mm P39EXT

40. Connections between "sda_pull" and "ESP32"

Functionsda_pullESP32
data1 → Sensirion SHT31-DIS-B bare DFN8 P1EXT
power23V3

41. Connections between "scl_pull" and "ESP32"

Functionscl_pullESP32
data1 → Sensirion SHT31-DIS-B bare DFN8 P4EXT
power23V3

42. Connections between "sensor_dec" and "ESP32"

Functionsensor_decESP32
data1 → Sensirion SHT31-DIS-B bare DFN8 P5EXT
ground2GND

43. Connections between "program" and "ESP32"

FunctionprogramESP32
groundGNDGND
powerVREF3V3
uartTX → ESP32-D0WD-V3 — bare QFN48 5×5 mm P41EXT
uartRX → ESP32-D0WD-V3 — bare QFN48 5×5 mm P40EXT
dataEN → ESP32-D0WD-V3 — bare QFN48 5×5 mm P9EXT
dataBOOT → ESP32-D0WD-V3 — bare QFN48 5×5 mm P23EXT

Deploy the firmware

// Bare ESP32-D0WD-V3 PCB: external 4 MB flash, 40 MHz crystal.
// SHT31-DIS at 0x44; SDA=GPIO21 (U1 pad42), SCL=GPIO22 (U1 pad39).
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <Wire.h>
#include <Adafruit_SHT31.h>
#include <time.h>
// Set these before Deploy. Use a dedicated monitoring Wi-Fi network.
const char* SSID="YOUR_WIFI";
const char* PASSWORD="YOUR_WIFI_PASSWORD";
const char* DASH_PASSWORD="CHANGE_THIS_PASSWORD";
const char* WEBHOOK=""; // HTTPS endpoint accepting JSON {"text":"..."}
const char* WEBHOOK_CA=""; // PEM root CA for webhook host; never bypass TLS validation.
const char* BEARER="";
const char* UPS_URL=""; // Optional trusted LAN HTTP gateway: 200 + ONLINE or ONBATT
struct Target {const char* name; const char* host; uint16_t port; bool known=false,up=false; uint8_t failures=0; uint32_t downAt=0; uint64_t downtime=0; int latency=-1;};
// Replace empty hosts with local IPs. TCP reachability is not CPU/port/SNMP health.
Target targets[]={{"Internet A","1.1.1.1",443},{"Internet B","8.8.8.8",443},{"Router","",80},{"Switch","",443},{"Server","",443},{"Firewall","",443}};
WebServer server(80);
Adafruit_SHT31 sensor;
float temp=NAN, humidity=NAN;
String events[40]; unsigned eventIndex=0;
String pending[24]; unsigned qhead=0,qcount=0; uint32_t dropped=0;
uint32_t lastPoll=0,lastSend=0; bool sensorOK=false; int environmentState=-1, internetState=-1; String upsState="disabled";
String stamp(){time_t now=time(nullptr); if(now<1700000000) return String("uptime ")+String(millis()/1000)+"s"; char b[32]; struct tm t; gmtime_r(&now,&t); strftime(b,sizeof(b),"%Y-%m-%dT%H:%M:%SZ",&t); return b;}
String escape(String s){s.replace("\\","\\\\");s.replace("\"","\\\"");s.replace("\n","\\n");s.replace("\r","");return s;}
void event(String text){String line=stamp()+" "+text; Serial.println(line); events[eventIndex++%40]=line; if(!strlen(WEBHOOK))return; if(qcount==24){qhead=(qhead+1)%24;qcount--;dropped++;} pending[(qhead+qcount++)%24]=line;}
bool auth(){if(server.authenticate("admin",DASH_PASSWORD))return true;server.requestAuthentication();return false;}
void dashboard(){if(!auth())return; String s="Smart IT Monitor\n\n"; s+="Wi-Fi: "+String(WiFi.status()==WL_CONNECTED?"connected":"offline")+"\n"; s+="Temperature C: "+String(temp)+" | Humidity %: "+String(humidity)+"\n";
 for(auto &t:targets){if(!strlen(t.host))continue; uint64_t dt=t.downtime+((t.known&&!t.up)?uint32_t(millis()-t.downAt)/1000:0); s+=String(t.name)+": "+(!t.known?"pending":t.up?"UP":"DOWN")+" | TCP connect ms="+String(t.latency)+" | downtime seconds="+String((unsigned long)dt)+"\n";}
 s+="UPS: "+upsState+"\nQueued alerts: "+String(qcount)+" | discarded: "+String(dropped)+"\n\nRecent events (RAM only):\n"; unsigned n=eventIndex<40?eventIndex:40; for(unsigned i=0;i<n;i++)s+=events[(eventIndex-n+i)%40]+"\n"; server.sendHeader("Cache-Control","no-store");server.send(200,"text/plain",s);}
void probe(Target &t){if(!strlen(t.host))return; WiFiClient c; uint32_t start=millis(); bool ok=WiFi.status()==WL_CONNECTED && c.connect(t.host,t.port,700);t.latency=ok?int(millis()-start):-1;c.stop(); if(ok)t.failures=0;else if(t.failures<3)t.failures++; if(!ok&&t.failures<3)return;
 if(!t.known||t.up!=ok){if(t.known&&!t.up)t.downtime+=uint32_t(millis()-t.downAt)/1000;t.known=true;t.up=ok;if(!ok)t.downAt=millis();event(String(t.name)+(ok?" UP":" DOWN (3 failed checks)"));}}
void poll(){for(auto &t:targets){probe(t);server.handleClient();}
 if(targets[0].known&&targets[1].known){int state=targets[0].up||targets[1].up; if(state!=internetState){internetState=state;event(state?"Internet reachable":"Internet unavailable: both external TCP probes failed");}}
 if(!sensorOK)sensorOK=sensor.begin(0x44); temp=sensorOK?sensor.readTemperature():NAN;humidity=sensorOK?sensor.readHumidity():NAN;
 int e=(!isfinite(temp)||!isfinite(humidity))?2:(temp>=35||humidity>=70||humidity<=20)?1:0;
 if(e!=environmentState){environmentState=e;event(e==2?"Environment sensor fault":e==1?"Environment outside limits (35C, 20-70% RH)":"Environment normal");} if(e==2)sensorOK=false;
 if(strlen(UPS_URL)&&WiFi.status()==WL_CONNECTED){HTTPClient h;h.setTimeout(1500);String next="gateway unavailable";if(h.begin(UPS_URL)){int code=h.GET();if(code==200){String b=h.getString();b.trim();next=(b=="ONLINE"||b=="ONBATT")?b:"invalid gateway response";}h.end();}if(next!=upsState){upsState=next;event("UPS "+next);}}
}
void sendAlert(){if(!qcount||WiFi.status()!=WL_CONNECTED||!strlen(WEBHOOK_CA)||!String(WEBHOOK).startsWith("https://"))return; if(time(nullptr)<1700000000)return;
 WiFiClientSecure c;c.setCACert(WEBHOOK_CA);HTTPClient h;h.setTimeout(2500); if(h.begin(c,WEBHOOK)){h.addHeader("Content-Type","application/json");if(strlen(BEARER))h.addHeader("Authorization",String("Bearer ")+BEARER);int code=h.POST(String("{\"text\":\"")+escape(pending[qhead])+"\"}");if(code>=200&&code<300){qhead=(qhead+1)%24;qcount--;}h.end();}}
void setup(){Serial.begin(115200);Wire.begin(21,22);sensorOK=sensor.begin(0x44);WiFi.mode(WIFI_STA);WiFi.setAutoReconnect(true);WiFi.begin(SSID,PASSWORD);configTime(0,0,"pool.ntp.org","time.google.com"); server.on("/",dashboard);server.begin(); event("Monitor started; outage history resets on restart");lastPoll=millis()-30000;}
void loop(){server.handleClient();static bool connected=false;bool now=WiFi.status()==WL_CONNECTED;if(now!=connected){connected=now;event(now?String("Wi-Fi connected; dashboard http://")+WiFi.localIP().toString():"Wi-Fi lost; remote alerts queued");} if(uint32_t(millis()-lastPoll)>=30000){lastPoll=millis();poll();}if(uint32_t(millis()-lastSend)>=10000){lastSend=millis();sendAlert();}delay(2);}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik