What is the Adafruit Connection Manager? It is a helper class designed around making connections to the internet easier and does this by simplifying a few things.
First, what are the underlying pieces we need to connect to the internet?
Sockets
Everything that connects to the internet needs a socket. A socket is what handles the basic sending and receiving of messages between 2 devices (like your microcontroller and a web API).
Microcontrollers, unlike desktop computers, have limited memory and can't have 100s of sockets open. The average chip can have maybe 2-3 and the bigger ones top out around 10.
Previously the sockets were controlled at a per library level. Meaning if you used adafruit_requests
(to get info from the web) and adafruit_minimqtt
(to send something to AdafruitIO) they both managed sockets separately, which means that one might block the other from getting one. And on top of that, the way you interfaced with them was different!
Here comes ConnectionManager to the rescue! Both these libraries now ask the ConnectionManager for a socket and it handles tracking what's open and what's not. And to make code even simpler, it's what's called a singleton. There is only one, where previously you needed to create your requests.Session()
early in your code and use that one everywhere, now it doesn't matter.
Socket Pool and SSL Context Helpers
What are these?
The socketpool
is what creates the sockets for each internet connected chip, and the ssl_context
is what has all the certificate information to validate that the connection is secure.
import wifi import adafruit_connection_manager import adafruit_requests radio = wifi.radio # this could also be # # import board # import busio # from adafruit_esp32spi.adafruit_esp32spi import ESP_SPIcontrol # from digitalio import DigitalInOut # esp32_cs = DigitalInOut(board.D13) # esp32_ready = DigitalInOut(board.D11) # esp32_reset = DigitalInOut(board.D12) # spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # radio = ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) # # or # # import board # import busio # from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K # from digitalio import DigitalInOut # cs = DigitalInOut(board.D10) # spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) # radio = WIZNET5K(spi_bus, cs) # code to make sure your radio is connected pool = adafruit_connection_manager.get_radio_socketpool(radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) requests = adafruit_requests.Session(pool, ssl_context) requests.get("http://wifitest.adafruit.com/testwifi/index.html") # Do something with response
If you had used the previous methods, see how you have fewer imports? And getting the socket pool
and ssl context
is the same regardless of configuration?
There is still the fact that if you are using a SPI
device like the esp32spi
or wiznet5k
, these will need to setup in the same fashion (getting all the pins and such), and aren't as easy as just import wifi
.
For more examples on using requests, checkout the example folder in the adafruit_requests
code repository:
These same methods work with adafruit_minimqtt
as well:
import wifi import adafruit_connection_manager import adafruit_requests radio = wifi.radio # code to make sure your radio is connected pool = adafruit_connection_manager.get_radio_socketpool(radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) mqtt_client = MQTT.MQTT( broker="io.adafruit.com", port=1883, username=aio_username, password=aio_key, socket_pool=pool, ssl_context=ssl_context, ) # do something with mqtt_client
For more detailed information on MQTT
and Adafruit IO
, checkout the guide:
How do I get this new cool update? Well, you can download the newest bundle. Or...
Use CircUp
!
Here you can see I just have an old version of adafruit_requests
installed. But after running circup update
, it both updated adafruit_requests
and installed adafruit_connection_manager
!
Bam that was easy. Want to learn more about CircUp
? Checkout the learn guide:
For a chip with onboard WiFi (ESP32S2
, ESP32S3
, Pico W
, etc.):
# ---------- # This example is deprecated. Although these methods still work, # it's recomended you update to the new standard # ---------- import socketpool import ssl import wifi import adafruit_requests # code to make sure your wifi.radio is connected pool = socketpool.SocketPool(wifi.radio) requests = adafruit_requests.Session(pool, ssl.create_default_context()) response = requests.get("http://wifitest.adafruit.com/testwifi/index.html") # Do something with response
For the Adafruit AirLift
(which uses an ESP32 WiFi Co-Processor):
# ---------- # This example is deprecated. Do not use # ---------- import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi.adafruit_esp32spi import ESP_SPIcontrol import adafruit_requests as requests # code to setup your esp32spi and make sure it is connected # esp = ESP_SPIcontrol(...) requests.set_socket(socket, esp) requests.get("http://wifitest.adafruit.com/testwifi/index.html")
For the Adafruit Ethernet FeatherWing
(which uses a Wiznet5K chip):
# ---------- # This example is deprecated. Do not use # ---------- import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K import adafruit_requests as requests # code to setup your wiznet5k and make sure it is connected # eth = WIZNET5K(...) requests.set_socket(socket, eth) requests.get("http://wifitest.adafruit.com/testwifi/index.html") # Do something with response
For the esp32spi
and wiznet5k
the requests.set_socket()
method would build out the socket pool and generate a SSL wrapper and pass it to requests.Session()
.
Imagine you want to write code that easily transfers between devices? Not impossible, but not simple.
import os import adafruit_connection_manager import adafruit_requests import wifi wifi_ssid = os.getenv("CIRCUITPY_WIFI_SSID") wifi_password = os.getenv("CIRCUITPY_WIFI_PASSWORD") print("\nConecting to WiFi...") radio = wifi.radio while not radio.connected: radio.connect(wifi_ssid, wifi_password) print("Connected!") pool = adafruit_connection_manager.get_radio_socketpool(radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) print("\nGetting sessions...") sessions = {} session_id = 0 while True: session_id += 1 try: requests = adafruit_requests.Session(pool, ssl_context, session_id=str(session_id)) response = requests.get("http://www.adafruit.com/api/quotes.php") sessions[session_id] = { "requests": requests, "response": response, "result": "", "more": True, } print(f"Started session {session_id}") except Exception as e: print(f"Error getting {session_id} session: {e}") break print("\nFetching...") chunk_size = 5 b = bytearray(chunk_size) while True: any_more = False for session_id, data in sessions.items(): if data["more"]: size = data["response"]._readinto(b) if size: any_more = True data["result"] += str(b[:size], "utf-8") else: data["more"] = False data["response"].close() print(f"{session_id}: {data["result"]}") if not any_more: break
For non-integrated WiFi (esp32spi
and wiznet5k
) I used:
For onboard WiFi I used a few boards of different levels. I started with a ESP32-S3 TFT Feather
, Then a Pico W
and finally the FeatherS3 by Unexpected Maker