Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32S2: implement API for Access Point mode #4246

Closed
Neradoc opened this issue Feb 22, 2021 · 12 comments · Fixed by #4650
Closed

ESP32S2: implement API for Access Point mode #4246

Neradoc opened this issue Feb 22, 2021 · 12 comments · Fixed by #4650
Labels
enhancement espressif applies to multiple Espressif chips network
Milestone

Comments

@Neradoc
Copy link

Neradoc commented Feb 22, 2021

Implement API to run an Access Point on the S2 instead of connecting to one.
Just to track the feature request.

@tannewt tannewt added enhancement espressif applies to multiple Espressif chips network labels Feb 23, 2021
@tannewt tannewt added this to the Long term milestone Feb 23, 2021
@tannewt
Copy link
Member

tannewt commented Feb 23, 2021

I think this would go on the wifi.Radio object

@rwhite-lightbox
Copy link

Does CP in general support AP mode or is this an ESP32 S2 limitation? This is an issue because AP mode allows for wifi credentials to be updated.

@tannewt
Copy link
Member

tannewt commented Mar 29, 2021

Does CP in general support AP mode or is this an ESP32 S2 limitation? This is an issue because AP mode allows for wifi credentials to be updated.

CP doesn't have an API for it yet. It is not an ESP32-S2 limitation.

@matthewjerome
Copy link

I am also attempting to create an AP using CP on a FeatherS2 as well and tried this approach based on the example code in esp32spi_simpletest.py and adafruit_esp32spi.ESP_SPIcontrol.

https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/2870f72c54e8e9086c0f73cf83f6204eb0427f0f/adafruit_esp32spi/adafruit_esp32spi.py

the message coming back is always RuntimeError: ESP32 timed out on SPI select - is this expected? is there a workaround?

I noticed that some of the examples have pins defined by board.ESP_CS, board.ESP_BUSY and board.ESP_RESET but these don't appear to be available on the FeatherS2 so using board.D10, board.D5 and board.D9 instead. thoughts on a better approach?

esp32_cs = digitalio.DigitalInOut(board.D10)
esp32_ready = digitalio.DigitalInOut(board.D5)
esp32_reset = digitalio.DigitalInOut(board.D9)

spi = board.SPI()

esp = adafruit_esp32spi.adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

ssid="NETWORK_NAME"
password="NETWORK_PASSWORD_123"

_SET_AP_PASSPHRASE_CMD = const(0x19)
esp._send_command_get_response(_SET_AP_PASSPHRASE_CMD, [bytes(ssid, "utf-8"), bytes(password, "utf-8"), bytes(1)])

@anecdata
Copy link
Member

anecdata commented Apr 9, 2021

@matthewjerome The ESP32SPI library is only for Airlift configurations, where an ESP32 is used as the wifi co-processor (e.g., PyPortal). It is not for use with the native ESP32-S2 networking.

@matthewjerome
Copy link

@anecdata thank you for clarifying - this makes sense now

@anecdata
Copy link
Member

anecdata commented Apr 20, 2021

Is anyone thinking about this, or working on it?

Espressif has a basic example:
https://github.com/espressif/esp-idf/blob/cf457d4/examples/wifi/getting_started/softAP/main/softap_example_main.c

I think we would need in init.c:

  • new 2nd event_handler for AP events
  • in wifi_init(): create default wifi AP & register 2nd event handler

In Radio.c:

  • new start_ap() to set AP mode and set config
  • in set_enabled(): some handling depending on mode

STA mode may be a little embedded in the current logic flow, and some things may have to get moved.

Also some thought is needed on whether STA and AP could be turned on and off independently without affecting the other (I'm not even sure if this is possible with the API), or whether code would enforce mode setting only from a clean init.

We don't want AP to start unless directed by user code.

There may also be some complications with scanning (currently requires STA or STA+AP).

@tannewt
Copy link
Member

tannewt commented Apr 21, 2021

@anecdata I don't know of anyone. It'd be cool to see it added.

@anecdata
Copy link
Member

anecdata commented Apr 22, 2021

Some other considerations:

API:

  • There's no CPython API that I know of for controlling an AP, so we'd be winging it to some extent. Initially maybe just a wifi.radio.start_ap(ssid, password) or similar, optional params like channel, max_connections, etc. could be added later, along with some helper functions to get info about the SoftAP (MAC, etc.) and any connected stations.

STA vs. STA+AP vs. AP:

  • There are reasons to keep STA as the default, and support STA or STA+AP. For example: scanning requires a station (not necessarily connected), ping requires a connected station. Installed base of CircuitPython ESP32-S2 code is based around STA.
  • There's little reason I can think of to support AP-only mode with no STA. With STA+AP mode, there's no requirement to scan, ping, connect, etc. If anyone has a strong argument for AP-only, please chime in.
  • I believe that changing mode (e.g., from STA to STA+AP, or vice versa) will disrupt existing connections.

Other:

  • Looks like only a single event handler is necessary due to how event bases get tied to one handler (e.g., WIFI_EVENT_)
  • Low-power / sleep considerations: probably little impact for now, since deep sleep restarts user code. Future light sleep would add complexity.

@anecdata
Copy link
Member

anecdata commented Apr 23, 2021

Super-rough and early proof-of-concept. I'll make a draft PR, still many questions on architecture, API, and implementation. It gets complex pretty fast, it would be great to collaborate with someone knowledgeable about the core and wifi.

import wifi
import ipaddress
import socketpool

from secrets import secrets

# this STA connects to an AP
print("STA MAC", ":".join("%02X" % _ for _ in wifi.radio.mac_address))
print(f"Enabled?  {wifi.radio.enabled}")
print("Connected?", end=" ")
wifi.radio.connect(secrets["ssid"], secrets["password"])
print(bool(wifi.radio.ipv4_address))

# get some sockets
pool = socketpool.SocketPool(wifi.radio)

# ping
ipv4 = ipaddress.ip_address(pool.getaddrinfo(secrets['host'], 443)[0][4][0])
print(f"wan ping: {wifi.radio.ping(ipv4)} ms")

# this STA becomes a STA+SoftAP
wifi.radio.start_ap("Bob", "abcd1234")
print("AP MAC", ":".join("%02X" % _ for _ in wifi.radio.mac_address_ap))

print("Waiting for connection to this SoftAP...")
while True:
    pass  # wait for STAs to connect

CircuitPython:

Adafruit CircuitPython 7.0.0-alpha.1-173-g7a4721370-dirty on 2021-04-22; Saola 1 w/Wrover with ESP32S2
>>> 
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

code.py output:
STA MAC 7C:DF:RE:DA:CT:8C
Enabled?  True
Connected? True
wan ping: 0.034 ms
AP MAC 7C:DF:RE:DA:CT:8D
Waiting for connection to this SoftAP...

ESP_LOG:

W (376922) wifi: sta start
W (379572) wifi: connected
W (380622) wifi: got ip
W (380682) wifi: ap start

/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s (macOS):

SSID BSSID             RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
 Bob 7c:df:re:da:ct:8d -25  1,+1    Y  US WPA2(PSK/AES,TKIP/TKIP) 

@rwhite-lightbox
Copy link

@anecdata Great work on this. I'm following your pull request and look forward to helping with testing.

@jposada202020
Copy link

@RWhite-EDR Actually you could starting know if you download the firmware built for your particular board in the PR
#4650

Here
https://github.com/adafruit/circuitpython/pull/4650/checks

image

If you already knew ignore the previous message 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement espressif applies to multiple Espressif chips network
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants