diff --git a/enviro/__init__.py b/enviro/__init__.py index 236f280..72d6df8 100644 --- a/enviro/__init__.py +++ b/enviro/__init__.py @@ -153,56 +153,105 @@ def stop_activity_led(): print(" - -- ---- -----=--==--=== hey enviro, let's go! ===--==--=----- ---- -- - ") print("") +def reconnect_wifi(ssid, password, country): + import time + import network + import math + import rp2 + import ubinascii + + start_ms = time.ticks_ms() + + # Set country + rp2.country(country) + + # Reference: https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf + CYW43_LINK_DOWN = 0 + CYW43_LINK_JOIN = 1 + CYW43_LINK_NOIP = 2 + CYW43_LINK_UP = 3 + CYW43_LINK_FAIL = -1 + CYW43_LINK_NONET = -2 + CYW43_LINK_BADAUTH = -3 + + status_names = { + CYW43_LINK_DOWN: "Link is down", + CYW43_LINK_JOIN: "Connected to wifi", + CYW43_LINK_NOIP: "Connected to wifi, but no IP address", + CYW43_LINK_UP: "Connect to wifi with an IP address", + CYW43_LINK_FAIL: "Connection failed", + CYW43_LINK_NONET: "No matching SSID found (could be out of range, or down)", + CYW43_LINK_BADAUTH: "Authenticatation failure", + } -import network # TODO this was removed from 0.0.8 -def connect_to_wifi(): - """ TODO what it was changed to - if phew.is_connected_to_wifi(): - logging.info(f"> already connected to wifi") - return True - """ - - wifi_ssid = config.wifi_ssid - wifi_password = config.wifi_password - - logging.info(f"> connecting to wifi network '{wifi_ssid}'") - """ TODO what it was changed to - ip = phew.connect_to_wifi(wifi_ssid, wifi_password, timeout_seconds=30) + wlan = network.WLAN(network.STA_IF) - if not ip: - logging.error(f"! failed to connect to wireless network {wifi_ssid}") + def dump_status(): + status = wlan.status() + logging.info(f"> active: {1 if wlan.active() else 0}, status: {status} ({status_names[status]})") + return status + + # Return True on expected status, exception on error status (negative) and False on timeout + def wait_status(expected_status, *, timeout=10, tick_sleep=0.5): + for i in range(math.ceil(timeout / tick_sleep)): + time.sleep(tick_sleep) + status = dump_status() + if status == expected_status: + return True + if status < 0: + raise Exception(status_names[status]) return False - logging.info(" - ip address: ", ip) - """ - import rp2 - rp2.country("GB") - wlan = network.WLAN(network.STA_IF) wlan.active(True) - wlan.connect(wifi_ssid, wifi_password) + # Disable power saving mode if on USB power + if vbus_present: + wlan.config(pm=0xa11140) - start = time.ticks_ms() - while time.ticks_diff(time.ticks_ms(), start) < 30000: - if wlan.status() < 0 or wlan.status() >= 3: - break - time.sleep(0.5) + # Print MAC + mac = ubinascii.hexlify(wlan.config('mac'),':').decode() + logging.info("> MAC: " + mac) + + # Disconnect when necessary + status = dump_status() + if status >= CYW43_LINK_JOIN and status < CYW43_LINK_UP: + logging.info("> Disconnecting...") + wlan.disconnect() + try: + wait_status(CYW43_LINK_DOWN) + except Exception as x: + raise Exception(f"Failed to disconnect: {x}") + logging.info("> Ready for connection!") + + # Connect to our AP + logging.info(f"> Connecting to SSID {ssid} (password: {password})...") + wlan.connect(ssid, password) + try: + wait_status(CYW43_LINK_UP) + except Exception as x: + raise Exception(f"Failed to connect to SSID {ssid} (password: {password}): {x}") + logging.info("> Connected successfully!") - seconds_to_connect = int(time.ticks_diff(time.ticks_ms(), start) / 1000) + ip, subnet, gateway, dns = wlan.ifconfig() + logging.info(f"> IP: {ip}, Subnet: {subnet}, Gateway: {gateway}, DNS: {dns}") + + elapsed_ms = time.ticks_ms() - start_ms + logging.info(f"> Elapsed: {elapsed_ms}ms") + return elapsed_ms - if wlan.status() != 3: - logging.error(f"! failed to connect to wireless network {wifi_ssid}") +def connect_to_wifi(): + try: + logging.info(f"> connecting to wifi network '{config.wifi_ssid}'") + elapsed_ms = reconnect_wifi(config.wifi_ssid, config.wifi_password, config.wifi_country) + # a slow connection time will drain the battery faster and may + # indicate a poor quality connection + seconds_to_connect = elapsed_ms / 1000 + if seconds_to_connect > 5: + logging.warn(" - took", seconds_to_connect, "seconds to connect to wifi") + return True + except Exception as x: + logging.error(f"! {x}") return False - # a slow connection time will drain the battery faster and may - # indicate a poor quality connection - if seconds_to_connect > 5: - logging.warn(" - took", seconds_to_connect, "seconds to connect to wifi") - - ip_address = wlan.ifconfig()[0] - logging.info(" - ip address: ", ip_address) - - return True - # log the error, blink the warning led, and go back to sleep def halt(message): logging.error(message) @@ -464,6 +513,15 @@ def upload_readings(): logging.error(f"! cannot find destination {destination}") return False + finally: + # Disconnect wifi + import network + logging.info("> Disconnecting wireless after upload") + wlan = network.WLAN(network.STA_IF) + wlan.active(True) + wlan.disconnect() + wlan.active(False) + return True def startup(): diff --git a/enviro/config_defaults.py b/enviro/config_defaults.py index cfdf5dd..63a5877 100644 --- a/enviro/config_defaults.py +++ b/enviro/config_defaults.py @@ -18,6 +18,11 @@ def add_missing_config_settings(): warn_missing_config_setting("usb_power_temperature_offset") config.usb_power_temperature_offset = DEFAULT_USB_POWER_TEMPERATURE_OFFSET + try: + config.wifi_country + except AttributeError: + warn_missing_config_setting("wifi_country") + config.wifi_country = "GB" def warn_missing_config_setting(setting): logging.warn(f"> config setting '{setting}' missing, please add it to config.py") diff --git a/enviro/config_template.py b/enviro/config_template.py index a345cc0..11404a9 100644 --- a/enviro/config_template.py +++ b/enviro/config_template.py @@ -11,6 +11,7 @@ # network access details wifi_ssid = None wifi_password = None +wifi_country = "GB" # how often to wake up and take a reading (in minutes) reading_frequency = 15