From 84e152fd2a70673058ec91380a5a38b1e7f72e94 Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Sat, 3 Sep 2022 16:07:43 +0200 Subject: [PATCH 1/8] join_AP(): add timeout and retries parameter --- adafruit_espatcontrol/adafruit_espatcontrol.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index ff3d837..56542d6 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -462,7 +462,7 @@ def remote_AP(self) -> List[Union[int, str, None]]: # pylint: disable=invalid-n return reply return [None] * 4 - def join_AP(self, ssid: str, password: str) -> None: # pylint: disable=invalid-name + def join_AP(self, ssid: str, password: str, timeout: int = 15, retries: int = 3) -> None: # pylint: disable=invalid-name """Try to join an access point by name and password, will return immediately if we're already connected and won't try to reconnect""" # First make sure we're in 'station' mode so we can connect to AP's @@ -474,7 +474,7 @@ def join_AP(self, ssid: str, password: str) -> None: # pylint: disable=invalid- return # we're already connected! for _ in range(3): reply = self.at_response( - 'AT+CWJAP="' + ssid + '","' + password + '"', timeout=15, retries=3 + 'AT+CWJAP="' + ssid + '","' + password + '"', timeout=timeout, retries=retries ) if b"WIFI CONNECTED" not in reply: print("no CONNECTED") From e3dca0dd4bf623d26ab98a328b5e21008f22b54d Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Sat, 3 Sep 2022 16:09:52 +0200 Subject: [PATCH 2/8] join_AP(): removed for-loop (loop was never executed) --- .../adafruit_espatcontrol.py | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index 56542d6..a91a6c9 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -472,17 +472,16 @@ def join_AP(self, ssid: str, password: str, timeout: int = 15, retries: int = 3) router = self.remote_AP if router and router[0] == ssid: return # we're already connected! - for _ in range(3): - reply = self.at_response( - 'AT+CWJAP="' + ssid + '","' + password + '"', timeout=timeout, retries=retries - ) - if b"WIFI CONNECTED" not in reply: - print("no CONNECTED") - raise RuntimeError("Couldn't connect to WiFi") - if b"WIFI GOT IP" not in reply: - print("no IP") - raise RuntimeError("Didn't get IP address") - return + reply = self.at_response( + 'AT+CWJAP="' + ssid + '","' + password + '"', timeout=timeout, retries=retries + ) + if b"WIFI CONNECTED" not in reply: + print("no CONNECTED") + raise RuntimeError("Couldn't connect to WiFi") + if b"WIFI GOT IP" not in reply: + print("no IP") + raise RuntimeError("Didn't get IP address") + return def scan_APs( # pylint: disable=invalid-name self, retries: int = 3 From 0c8ae28e92b65f4f20142e18ea7033db1db63d06 Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Sun, 4 Sep 2022 06:54:38 +0200 Subject: [PATCH 3/8] add timeout/retries parameter, remove retry-logic --- .../adafruit_espatcontrol.py | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index a91a6c9..8759ddd 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -135,34 +135,29 @@ def begin(self) -> None: except OKError: pass # retry - def connect(self, secrets: Dict[str, Union[str, int]]) -> None: + def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retries: int = 3) -> None: """Repeatedly try to connect to an access point with the details in the passed in 'secrets' dictionary. Be sure 'ssid' and 'password' are defined in the secrets dict! If 'timezone' is set, we'll also configure SNTP""" # Connect to WiFi if not already - retries = 3 - while True: - try: - if not self._initialized or retries == 0: - self.begin() - retries = 3 - AP = self.remote_AP # pylint: disable=invalid-name + try: + if not self._initialized: + self.begin() + AP = self.remote_AP # pylint: disable=invalid-name + if AP[0] != secrets["ssid"]: + self.join_AP(secrets["ssid"], secrets["password"],timeout=timeout, retries=retries) print("Connected to", AP[0]) - if AP[0] != secrets["ssid"]: - self.join_AP(secrets["ssid"], secrets["password"]) - if "timezone" in secrets: - tzone = secrets["timezone"] - ntp = None - if "ntp_server" in secrets: - ntp = secrets["ntp_server"] - self.sntp_config(True, tzone, ntp) - print("My IP Address:", self.local_ip) - return # yay! - except (RuntimeError, OKError) as exp: - print("Failed to connect, retrying\n", exp) - retries -= 1 - continue + if "timezone" in secrets: + tzone = secrets["timezone"] + ntp = None + if "ntp_server" in secrets: + ntp = secrets["ntp_server"] + self.sntp_config(True, tzone, ntp) + print("My IP Address:", self.local_ip) + return # yay! + except (RuntimeError, OKError) as exp: + print("Failed to connect\n", exp) # *************************** SOCKET SETUP **************************** From 406ea81d9b345db3c7422e623baab8177da8a7e3 Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Sun, 4 Sep 2022 07:14:36 +0200 Subject: [PATCH 4/8] connect(): added timeout/retries parameter, removed multiple-attempts logic which never worked --- .../adafruit_espatcontrol_wifimanager.py | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py b/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py index a07b371..9b25bf1 100755 --- a/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py @@ -41,7 +41,7 @@ def __init__( :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) :param status_pixel: (Optional) The pixel device - A NeoPixel or DotStar (default=None) :type status_pixel: NeoPixel or DotStar - :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) + :param int attempts: (Optional) Unused, only for compatibility for old code """ # Read the settings self._esp = esp @@ -60,26 +60,19 @@ def reset(self) -> None: print("Resetting ESP") self._esp.hard_reset() - def connect(self) -> None: + def connect(self, timeout: int = 15, retries: int = 3) -> None: """ Attempt to connect to WiFi using the current settings """ - failure_count = 0 - while not self._esp.is_connected: - try: - if self.debug: - print("Connecting to AP...") - self.pixel_status((100, 0, 0)) - self._esp.connect(self.secrets) - failure_count = 0 - self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: - print("Failed to connect, retrying\n", error) - failure_count += 1 - if failure_count >= self.attempts: - failure_count = 0 - self.reset() - continue + try: + if self.debug: + print("Connecting to AP...") + self.pixel_status((100, 0, 0)) + self._esp.connect(self.secrets, timeout=timeout, retries=retries) + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect\n", error) + raise def get(self, url: str, **kw: Any) -> requests.Response: """ From f983ca784cfe808c4ca5ba51c6439218562c1437 Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Sun, 4 Sep 2022 07:15:11 +0200 Subject: [PATCH 5/8] connect(): re-raise exception if connection fails --- adafruit_espatcontrol/adafruit_espatcontrol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index 8759ddd..a37aaa8 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -158,6 +158,7 @@ def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retrie return # yay! except (RuntimeError, OKError) as exp: print("Failed to connect\n", exp) + raise # *************************** SOCKET SETUP **************************** From b8c440a50ce02c6698d22bd9a825aa657d2f431e Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Mon, 5 Sep 2022 18:47:59 +0200 Subject: [PATCH 6/8] minor change to print-command --- adafruit_espatcontrol/adafruit_espatcontrol.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index a37aaa8..55d61f5 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -147,7 +147,7 @@ def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retrie AP = self.remote_AP # pylint: disable=invalid-name if AP[0] != secrets["ssid"]: self.join_AP(secrets["ssid"], secrets["password"],timeout=timeout, retries=retries) - print("Connected to", AP[0]) + print("Connected to", secrets["ssid"]) if "timezone" in secrets: tzone = secrets["timezone"] ntp = None @@ -155,6 +155,8 @@ def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retrie ntp = secrets["ntp_server"] self.sntp_config(True, tzone, ntp) print("My IP Address:", self.local_ip) + else: + print("Already connected to", AP[0]) return # yay! except (RuntimeError, OKError) as exp: print("Failed to connect\n", exp) From 7709d6d33dc8136beb4a5321b844f371b9ffae4e Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Mon, 5 Sep 2022 19:19:35 +0200 Subject: [PATCH 7/8] at_response(): handle busy-state for AT+CIFSR as special case --- .../adafruit_espatcontrol.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index 55d61f5..be308d5 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -135,7 +135,9 @@ def begin(self) -> None: except OKError: pass # retry - def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retries: int = 3) -> None: + def connect( + self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retries: int = 3 + ) -> None: """Repeatedly try to connect to an access point with the details in the passed in 'secrets' dictionary. Be sure 'ssid' and 'password' are defined in the secrets dict! If 'timezone' is set, we'll also configure @@ -146,7 +148,12 @@ def connect(self, secrets: Dict[str, Union[str, int]], timeout: int = 15, retrie self.begin() AP = self.remote_AP # pylint: disable=invalid-name if AP[0] != secrets["ssid"]: - self.join_AP(secrets["ssid"], secrets["password"],timeout=timeout, retries=retries) + self.join_AP( + secrets["ssid"], + secrets["password"], + timeout=timeout, + retries=retries, + ) print("Connected to", secrets["ssid"]) if "timezone" in secrets: tzone = secrets["timezone"] @@ -460,7 +467,9 @@ def remote_AP(self) -> List[Union[int, str, None]]: # pylint: disable=invalid-n return reply return [None] * 4 - def join_AP(self, ssid: str, password: str, timeout: int = 15, retries: int = 3) -> None: # pylint: disable=invalid-name + def join_AP( + self, ssid: str, password: str, timeout: int = 15, retries: int = 3 + ) -> None: # pylint: disable=invalid-name """Try to join an access point by name and password, will return immediately if we're already connected and won't try to reconnect""" # First make sure we're in 'station' mode so we can connect to AP's @@ -471,7 +480,9 @@ def join_AP(self, ssid: str, password: str, timeout: int = 15, retries: int = 3) if router and router[0] == ssid: return # we're already connected! reply = self.at_response( - 'AT+CWJAP="' + ssid + '","' + password + '"', timeout=timeout, retries=retries + 'AT+CWJAP="' + ssid + '","' + password + '"', + timeout=timeout, + retries=retries, ) if b"WIFI CONNECTED" not in reply: print("no CONNECTED") @@ -575,7 +586,12 @@ def at_response(self, at_cmd: str, timeout: int = 5, retries: int = 3) -> bytes: # special case, ping also does not return an OK if "AT+PING" in at_cmd and b"ERROR\r\n" in response: return response - if response[-4:] != b"OK\r\n": + # special case, does return OK but in fact it is busy + if ( + "AT+CIFSR" in at_cmd + and b"busy" in response + or response[-4:] != b"OK\r\n" + ): time.sleep(1) continue return response[:-4] From 7f117e743e47a043a5d03104867090644114fd6c Mon Sep 17 00:00:00 2001 From: Bernhard Bablok Date: Tue, 6 Sep 2022 08:26:32 +0200 Subject: [PATCH 8/8] moved linter-comment back to def --- adafruit_espatcontrol/adafruit_espatcontrol.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index be308d5..f159141 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -467,9 +467,9 @@ def remote_AP(self) -> List[Union[int, str, None]]: # pylint: disable=invalid-n return reply return [None] * 4 - def join_AP( + def join_AP( # pylint: disable=invalid-name self, ssid: str, password: str, timeout: int = 15, retries: int = 3 - ) -> None: # pylint: disable=invalid-name + ) -> None: """Try to join an access point by name and password, will return immediately if we're already connected and won't try to reconnect""" # First make sure we're in 'station' mode so we can connect to AP's