adafruit / adafruit/Adafruit_CircuitPython_ESP32SPI
esp.disconnect leaves the ESP32 in a bad state
- Dominant language
- Python
- Stars
- 102
- Forks
- 71
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 1
Description
I am writing an application on a PyPortal that needs to talk to two access points. After connecting to the first and communicating via socket with a host there, I close the socket and do an esp.disconnect() to disconnect from the access point. This seems to work. The esp's status goes to WL_DISCONNECTED.
I then connect to the second access point with the esp's status going back to WL_CONNECTED. But, at that point the ESP seems to be in a bad state. Any function requiring communication with the AP fails, in one way or another. I wrote a simple test case that demonstrates the problem:
```
import board
from digitalio import DigitalInOut
import busio
import sys
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_socket
esp32_cs_pin = DigitalInOut(board.ESP_CS)
esp32_ready_pin = DigitalInOut(board.ESP_BUSY)
esp32_reset_pin = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs_pin, esp32_ready_pin, esp32_reset_pin)
ssids = (('linkme', '***********'), ('corrigan', '**********'))
fwstr = str(esp.firmware_version, 'utf-8')
major, minor, sub = sys.implementation.version
print("Circuitpython {}.{}.{}, ESP32 firmware {}".format(major, minor, sub, fwstr))
test_ip = esp.unpretty_ip('192.168.43.148')
port = 65432
for ssid, password in ssids:
print("Testing ssid = {}".format(ssid))
# connect to an AP
esp.connect_AP(ssid, password, timeout_s = 30)
print("Create socket")
# create a socket
adafruit_esp32spi_socket.set_interface(esp)
my_sock = adafruit_esp32spi_socket.socket()
print("Connect socket")
# connect to socket server on other system
my_sock.connect((test_ip, port))
print("close socket")
# close socket
my_sock.close()
print("disconnect from AP")
# disconnect from AP
esp.disconnect()
```
The output is:
```
code.py output:
Circuitpython 6.1.0, ESP32 firmware 1.7.3
Testing ssid = linkme
Create socket
Connect socket
close socket
disconnect from AP
Testing ssid = corrigan
Create socket
Connect socket
Traceback (most recent call last):
File "code.py", line 35, in
File "adafruit_esp32spi/adafruit_esp32spi_socket.py", line 75, in connect
File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 783, in socket_connect
File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 685, in socket_open
File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 345, in _send_command_get_response
File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 296, in _wait_response_cmd
File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 199, in _wait_for_ready
RuntimeError: ESP32 not responding
Code done running.
```
Everything works for the first access point, and seems to work for the second until the attempt to connect the socket. It also fails in the same way if I re-connect to the first access point instead. Other functions also fail. For example, esp.get_host_by_name(host) fails with RuntimeError: Failed to request hostname.
A more elaborate test shows that after connecting to the second access point, the ESP32's internal state is inconsistent. Asking the ESP32 for the bssid and ssid that it is connected to show the second access point, but asking the ESP32 for its 'network data', gives back the ip address, and gateway of the first access point.
If I change the timeout in _wait_for_ready, I find that the socket.connect request actual finishes after 18 seconds (waiting for the response, the normal timeout is 10). But, when the socket.connect finishes, it is with a RuntimeError: Expected 01 but got 00, which is what you get when the connection fails.
If you do an esp.reset(), everything works again.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the supplied two-access-point reproduction, then inspect adafruit_esp32spi_socket.py connect and adafruit_esp32spi.py socket_connect, socket_open, and _wait_for_ready. Compare the ESP state and network data before and after disconnecting and reconnecting; done means socket and other communication functions work with the second access point without requiring esp.reset().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- embedded-iot, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100