Breadboard
docs
Example project · ESP32

Internet weather station (OLED)

The board is really online — inside the sandbox internet. The ESP32 joins Wi-Fi, resolves api.weather.test with a real DNS lookup, and GETs a weather JSON over a genuine TCP socket, rendering the report and a live UTC clock (from a second REST call) to the OLED. Everything is deterministic and offline — the sandbox mocks the services — and the board’s Wi-Fi inspector can switch a signed-in Pro bench to the real internet. Follow every lookup and HTTP exchange in the 📡 Sniffer.

The Internet weather station (OLED) circuit as rendered by the simulator

How it works

The ESP32 joins BreadboardNet and talks to the simulator's sandbox internet: a deterministic, fully offline mock of the real thing built into the emulated network core. The script does a real DNS lookup for api.weather.test (the sandbox resolver answers for any name), opens a genuine TCP socket, and sends a plain HTTP GET; the mock weather service replies with a JSON report, and a second request to /time reads the sandbox's virtual clock. MicroPython parses both with the json module and paints the report — location, temperature, humidity, conditions — plus the live UTC time onto the SSD1306. Because the services are mocked in-core, the demo runs signed-out, offline, and reproducibly; on a signed-in Pro bench, the Wi-Fi inspector's egress toggle points the very same sockets at the real internet through the secure gateway.

What's on the bench

  • Battery
  • ESP32-C3
  • OLED 128×64

How it's wired

  • hole a10hole B-5
  • hole a11hole B+5
  • hole a40hole B-9
  • hole a41hole f10
  • hole a42hole g11
  • hole a43hole b20

The code

This MicroPython script runs on the emulated board every boot; edit it in the Code tab.

from machine import I2C, Pin
import framebuf, time
i = I2C(0, scl=Pin(9), sda=Pin(8))
buf = bytearray(1024)
fb = framebuf.FrameBuffer(buf, 128, 64, framebuf.MONO_VLSB)
for c in b'\xae\xd5\x80\xa8\x3f\xd3\x00\x40\x8d\x14\x20\x00\xa1\xc8\xda\x12\x81\xcf\xd9\xf1\xdb\x40\xa4\xa6\xaf':
    i.writeto(0x3c, bytes([0, c]))
def show():
    i.writeto(0x3c, b'\x00\x21\x00\x7f\x22\x00\x07')
    i.writeto(0x3c, b'\x40' + buf)

import network, socket, json
w = network.WLAN(network.STA_IF)
w.active(True)
fb.fill(0); fb.text('joining WiFi...', 0, 28); show()
w.connect('BreadboardNet')
while not w.isconnected():
    time.sleep_ms(100)
def fetch(host, path):
    # Real DNS against the sandbox resolver, then a genuine TCP socket.
    addr = socket.getaddrinfo(host, 80)[0][-1]
    s = socket.socket()
    s.connect(addr)
    s.send(('GET ' + path + ' HTTP/1.0\r\nHost: ' + host + '\r\n\r\n').encode())
    r = b''
    while True:
        c = s.recv(256)
        if not c:
            break
        r += c
    s.close()
    return json.loads(r.split(b'\r\n\r\n', 1)[1])
n = 0
while True:
    wx = fetch('api.weather.test', '/weather')
    t = fetch('worldtimeapi.test', '/time')
    n += 1
    print('wx', n, wx['temperature_c'], 'C,', wx['conditions'])
    fb.fill(0)
    fb.text('INTERNET WEATHER', 0, 0)
    fb.hline(0, 10, 128, 1)
    fb.text(wx['location'][:16], 0, 14)
    fb.text('%s C   rh %d%%' % (wx['temperature_c'], wx['humidity']), 0, 26)
    fb.text(wx['conditions'][:16], 0, 38)
    fb.text(t['utc_datetime'][11:19] + ' UTC  #%d' % n, 0, 52)
    show()
    time.sleep_ms(2000)

Try this

  • Watch the last line of the OLED: the UTC clock and request counter advance on every 2-second refresh.
  • Open the 📡 Sniffer and follow a full round trip — DNS query and answer, TCP SYN/ACK, the GET, the JSON reply.
  • Edit the script in the Code tab to fetch '/api' (the mock cloud dashboard) or POST to '/echo' instead.
  • Click the ESP32 and look at the top of its Wi-Fi inspector: that's where a Pro bench can switch from the sandbox to real internet access.

Related projects