Wi-Fi & APIs¶
![]()
The ESP32 has Wi-Fi built in. Once it's online, your projects can pull in live data (weather, time, sports scores) and send messages out, like a notification to your phone. No new parts needed!
You'll need:
- A 2.4 GHz Wi-Fi network and its password
- A phone with the free ntfy app (for the notification example)
2.4 GHz only
The ESP32 can't see 5 GHz networks. Most home routers broadcast both, so this is rarely a problem. School and office networks that need a login page after you connect won't work, though.
Setup¶
Keep your password in secrets.py¶
Instead of typing your Wi-Fi password into every program, keep it in one
file called secrets.py:
- Open
secrets_example.pyand copy its contents into a new file in Thonny. - Fill in your Wi-Fi name (
SSID) andPASSWORD, keeping the quote marks. - Save it onto your ESP32 as
secrets.py.
# Copy this file to your ESP32 as secrets.py and fill in your details.
# Keep secrets.py private: don't share it or upload it anywhere.
SSID = "your-wifi-name"
PASSWORD = "your-wifi-password"
# Only needed for the Motion Alert project. Pick something long and
# hard to guess - anyone who knows the topic name can see your alerts.
NTFY_TOPIC = "circuitcoder-change-me-7f3k9q"
# Only needed for the Alarm Clock project: your offset from UTC in hours.
# e.g. -5 for New York in winter, -4 in summer, 1 for Berlin in winter.
UTC_OFFSET_HOURS = -5
Don't share secrets.py
If you post your code online or send it to a friend, leave secrets.py
out. That way you never leak your password by accident.
The wifi module¶
Connecting takes a few steps, so, just like button.py, we've wrapped them
in a module. Save
wifi.py
onto your ESP32 too.
wifi.py
# wifi.py - connect the ESP32 to your Wi-Fi network.
#
# Usage:
# import wifi
# wifi.connect() # uses the SSID and PASSWORD from secrets.py
import time
import network
def connect(timeout_s=20):
import secrets # your Wi-Fi name and password live in secrets.py
wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
if not wlan.isconnected():
print("Connecting to", secrets.SSID, "...")
wlan.connect(secrets.SSID, secrets.PASSWORD)
start = time.ticks_ms()
while not wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start) > timeout_s * 1000:
raise RuntimeError("Could not connect to Wi-Fi. "
"Check the name and password in secrets.py")
time.sleep(0.25)
print("Connected! IP address:", wlan.ipconfig("addr4")[0])
return wlan
It switches on the ESP32's station interface (the part that joins an existing network, like your phone does), connects, and waits until it has an IP address. If it hasn't connected after 20 seconds, it stops with an error instead of waiting forever.
Connect!¶
# Connect to Wi-Fi (needs wifi.py and your secrets.py on the board)
import wifi
wlan = wifi.connect()
print("Signal strength:", wlan.status("rssi"), "dBm")
You should see something like:
Signal strength is measured in negative numbers. Closer to 0 is stronger: −50 is excellent, and below −80 is weak.
What's an API?¶
When you visit a website, the server sends back a page designed for people to look at. An API (application programming interface) is a web address built for programs instead. It sends back just the data, usually as JSON, which looks a lot like a Python dictionary:
There are two main kinds of request:
- GET asks a server for data. "What's the weather?"
- POST sends data to a server. "Deliver this message."
MicroPython's built-in requests module handles both.
GET: live weather¶
Open-Meteo is a free weather API that doesn't
need an account. Change LATITUDE and LONGITUDE to your own location:
right-click a spot on Google Maps and the coordinates appear at the top of
the menu.
# Get the current weather from the free Open-Meteo API (no account needed)
import requests
import wifi
# Change these to your own location (find them on a map site)
LATITUDE = 40.71
LONGITUDE = -74.01
URL = ("https://api.open-meteo.com/v1/forecast"
"?latitude=" + str(LATITUDE) +
"&longitude=" + str(LONGITUDE) +
"¤t=temperature_2m,wind_speed_10m")
wifi.connect()
response = requests.get(URL) # send the GET request
print("Status code:", response.status_code) # 200 means OK
data = response.json() # turn the JSON text into a dictionary
response.close() # always close, to free up memory
current = data["current"]
print("Temperature:", current["temperature_2m"], "°C")
print("Wind speed:", current["wind_speed_10m"], "km/h")
requests.get(URL)sends the request and waits for the reply.response.status_codeis200if everything went well. Codes in the 400s mean something was wrong with the request (like a typo in the URL), and 500s mean the server had a problem.response.json()converts the JSON text into a Python dictionary, sodata["current"]["temperature_2m"]digs out the temperature.response.close()frees up the memory the reply was using. The ESP32 doesn't have much, so always close your responses.
Prefer Fahrenheit?
Add &temperature_unit=fahrenheit&wind_speed_unit=mph to the end of the
URL. The Open-Meteo docs list
everything else you can ask for, from rain to UV index.
POST: notifications on your phone¶
ntfy ("notify") is a free service that pushes a notification to your phone whenever something POSTs a message to a topic. No account needed.
- Install the ntfy app from your phone's app store.
- Make up a topic name that's long and hard to guess, like
circuitcoder-alex-7f3k9q. Topics are public: anyone who knows the name can read your messages, or send you some! - In the app, tap + and subscribe to your topic.
- Put the same name in
NTFY_TOPICin yoursecrets.py, and save it to the board again.
# Send a push notification to your phone with ntfy.sh
import requests
import secrets
import wifi
wifi.connect()
response = requests.post(
"https://ntfy.sh/" + secrets.NTFY_TOPIC,
data="Hello from my ESP32!",
)
print("Status code:", response.status_code) # 200 means it was sent
response.close()
Run it and your phone should buzz within a second or two. 🎉
Getting the time¶
The ESP32 has a clock, but it resets to the year 2000 every time the board
restarts. The built-in ntptime module sets it correctly from an internet
time server:
# Set the ESP32's clock from the internet and print the local time
import time
import ntptime
import secrets
import wifi
wifi.connect()
ntptime.settime() # sets the clock to UTC (world time)
while True:
# add your time zone offset to get local time
local = time.localtime(time.time() + secrets.UTC_OFFSET_HOURS * 3600)
year, month, day, hour, minute, second = local[0:6]
print("{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(
year, month, day, hour, minute, second))
time.sleep(1)
The time server gives UTC (world time), so the code adds
UTC_OFFSET_HOURS from secrets.py to get your local time. You'll need to
change it by an hour when the clocks go forward or back. You'll use this in
the Alarm Clock project.
Challenge¶
Combine what you've learned: every time the button on GPIO 14 is pressed, fetch the temperature and send it to your phone with ntfy. (No solution this time. You've got everything you need!)
Next up: RGB LEDs: mix any colour you like from red, green and blue.