Skip to content

Add Access point mode #57

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

Merged
merged 20 commits into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions adafruit_esp32spi/adafruit_esp32spi.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
# pylint: disable=bad-whitespace
_SET_NET_CMD = const(0x10)
_SET_PASSPHRASE_CMD = const(0x11)
_SET_AP_NET_CMD = const(0x18)
_SET_AP_PASSPHRASE_CMD = const(0x19)
_SET_DEBUG_CMD = const(0x1A)

_GET_CONN_STATUS_CMD = const(0x20)
Expand Down Expand Up @@ -409,6 +411,29 @@ def wifi_set_entenable(self):
if resp[0][0] != 1:
raise RuntimeError("Failed to enable enterprise mode")

def wifi_set_ap_network(self, ssid, channel):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to wifi_create_ap?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decided to leave this the same to match the name of the command we send to the ESP32 FW.

"""
Creates an Access point with SSID and Channel

:param ssid: the SSID of the created Access Point. Must be 8 or more characters
:param channel: channel of created Access Point (1 - 14).
"""
resp = self._send_command_get_response(_SET_AP_NET_CMD, [ssid, channel])
if resp[0][0] != 1:
raise RuntimeError("Failed to setup AP network")

def wifi_set_ap_passphrase(self, ssid, passphrase, channel):
"""
Creates an Access point with SSID, passphrase, and Channel

:param ssid: the SSID of the created Access Point. Must be 8 or more characters
:param passphrase: the password of the created Access Point. Must be 8 or more characters.
:param channel: channel of created Access Point (1 - 14).
"""
resp = self._send_command_get_response(_SET_AP_PASSPHRASE_CMD, [ssid, passphrase, channel])
if resp[0][0] != 1:
raise RuntimeError("Failed to setup AP password")

@property
def ssid(self):
"""The name of the access point we're connected to"""
Expand Down Expand Up @@ -443,6 +468,15 @@ def is_connected(self):
self.reset()
return False

@property
def ap_listening(self):
"""Whether the ESP32 is in access point mode and is listening for connections"""
try:
return self.status == WL_AP_LISTENING
except RuntimeError:
self.reset()
return False

def connect(self, secrets):
"""Connect to an access point using a secrets dictionary
that contains a 'ssid' and 'password' entry"""
Expand Down Expand Up @@ -473,6 +507,25 @@ def connect_AP(self, ssid, password): # pylint: disable=invalid-name
raise RuntimeError("No such ssid", ssid)
raise RuntimeError("Unknown error 0x%02X" % stat)

def create_ap(self, ssid, password, channel=b'\x01'):
"""Create an access point with the given name and password."""
if isinstance(ssid, str):
ssid = bytes(ssid, 'utf-8')
if password:
if isinstance(password, str):
password = bytes(password, 'utf-8')
self.wifi_set_ap_passphrase(ssid, password, channel)
else:
self.wifi_set_ap_network(ssid, channel)
for _ in range(10): # retries
stat = self.status
if stat == WL_AP_LISTENING:
return stat
time.sleep(1)
if stat == WL_AP_FAILED:
raise RuntimeError("Failed to create AP", ssid)
raise RuntimeError("Unknown error 0x%02x" % stat)

def pretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name
"""Converts a bytearray IP address to a dotted-quad string for printing"""
return "%d.%d.%d.%d" % (ip[0], ip[1], ip[2], ip[3])
Expand Down
38 changes: 34 additions & 4 deletions adafruit_esp32spi/adafruit_esp32spi_wifimanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@

# pylint: disable=no-name-in-module

from adafruit_esp32spi import adafruit_esp32spi
import adafruit_esp32spi.adafruit_esp32spi_requests as requests
from adafruit_esp32spi import adafruit_esp32spi


class ESPSPI_WiFiManager:
"""
A class to help manage the Wifi connection
"""
def __init__(self, esp, secrets, status_pixel=None, attempts=2):
# pylint: disable=too-many-arguments
def __init__(self, esp, secrets, status_pixel=None, attempts=2, debug=False):
"""
:param ESP_SPIcontrol esp: The ESP object we are using
:param dict secrets: The WiFi and Adafruit IO secrets dict (See examples)
Expand All @@ -49,13 +51,14 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2):
"""
# Read the settings
self.esp = esp
self.debug = False
self.debug = debug
self.ssid = secrets['ssid']
self.password = secrets['password']
self.password = secrets.get('password', None)
self.attempts = attempts
requests.set_interface(self.esp)
self.statuspix = status_pixel
self.pixel_status(0)
# pylint: enable=too-many-arguments

def reset(self):
"""
Expand Down Expand Up @@ -93,6 +96,33 @@ def connect(self):
self.reset()
continue

def create_ap(self):
"""
Attempt to initialize in Access Point (AP) mode.
Uses SSID and optional passphrase from the current settings
Other WiFi devices will be able to connect to the created Access Point
"""
failure_count = 0
while not self.esp.ap_listening:
try:
if self.debug:
print("Waiting for AP to be initialized...")
self.pixel_status((100, 0, 0))
if self.password:
self.esp.create_ap(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8'))
else:
self.esp.create_ap(bytes(self.ssid, 'utf-8'), None)
failure_count = 0
self.pixel_status((0, 100, 0))
except (ValueError, RuntimeError) as error:
print("Failed to create access point\n", error)
failure_count += 1
if failure_count >= self.attempts:
failure_count = 0
self.reset()
continue
print("Access Point created! Connect to ssid: {}".format(self.ssid))

def get(self, url, **kw):
"""
Pass the Get request to requests and update status LED
Expand Down