[{"element_type":"text","content":"\n  \n  \n  \n        \u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u003cstrong\u003eIntroduction:\u003c/strong\u003e\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eIf you have the need your WiFi project to operate at various locations with different WiFi SSID/PASSWORD settings at each location, read on.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eIf you are using an MCU with built-in WiFi that CircuitPython 9.0.0 or later supports, there may be a solution to your issue.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eOverview of the project:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eThis article will provide you with two tools to get you started.\u003c/span\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eA\u0026nbsp;\u003cstrong\u003ecode.py\u003c/strong\u003e \u003cu\u003ede\u003c/u\u003efined \u003cu\u003ef\u003c/u\u003eunction (\u003cstrong\u003edef\u003c/strong\u003e) that will cycle through the WiFi networks defined in \u003cstrong\u003esettings.toml\u003c/strong\u003e.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eIt will also show a sorted list of available WiFi access points found locally.\u003c/span\u003e\u003c/li\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eA sample\u0026nbsp;\u003cstrong\u003esettings.toml\u003c/strong\u003e to get you started.\u003c/span\u003e\u003c/li\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eThere are additional functions and features that will be covered as we go along.\u003c/span\u003e\u003c/li\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eThere will be a description of how each function works and interacts.\u003c/span\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eWhy would you need multiple WiFi SSIDs in IoT projects?:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLet’s say you have a project that you must develop at home, show friends how it works at your bridge club, test it under various situations, and demonstrate its features to a customer.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eHaving all the SSIDs and PASSWORDs predefined and having your project cycle through them without your intervention, except the first time you add them, would speed things up.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003ePrerequisites:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eThe system requirements are simple.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eAn MCU with built-in WiFi that is supported by Circuit Python 9.0.0 or newer.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eMy tests were run on a Raspberry Pi Pico W.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eAll the libraries are built into CP 9.x.x that the sample \u003cstrong\u003ecode.py\u003c/strong\u003e needs.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eThey are: \u003cstrong\u003eimport os, wifi, random, binascii\u003c/strong\u003e.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eThe additional libraries used by the diagnostic code are \u003cstrong\u003eimport time, board, digitalio, ipaddress, supervisor, microcontroller\u003c/strong\u003e and are also built-in.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eIf your MCU is listed at the web site below, your board is probably supported.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003ca href=\"https://docs.circuitpython.org/en/latest/shared-bindings/wifi/index.html\"\u003e\u003cspan\u003ehttps://docs.circuitpython.org/en/latest/shared-bindings/wifi/index.html\u003c/span\u003e\u003c/a\u003e\u003cspan\u003e\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eClick on \u003cstrong\u003e\u003cspan\u003eAvailable on these boards\u003c/span\u003e\u003c/strong\u003e\u003cspan\u003e \u003c/span\u003efor a full listing.\u003cspan\u003e\u0026nbsp; \u003c/span\u003eConsidering the length of the boards listed, I have not tested, nor can I guarantee this code will work with any or all of them.\u003c/span\u003e\u003c/p\u003e\n      \n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eThe settings.toml file.\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eThe provided \u003cstrong\u003esettings.toml\u003c/strong\u003e file shows 9/10 SSID/PASSWORD pairs.\u0026nbsp; I say 9/10 because the \u003cstrong\u003esettings.toml\u003c/strong\u003e file shows 9 pairs but calls for 10.\u0026nbsp; I will describe each part of the WiFi configuration:\u003c/span\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli class=\"MsoNormal\"\u003e\n\u003cspan\u003eWiFi SSID/PASSWORD pair.\u0026nbsp; Each pair is defined with SSID\u003c/span\u003e\u003cspan\u003enumber\u003c/span\u003e\u003cspan\u003e and PASSWORD\u003c/span\u003e\u003cspan\u003enumber\u003c/span\u003e\u003cspan\u003e.\u0026nbsp; Each pair’s number must be between 0 and\u0026nbsp;\u003c/span\u003e\u003cspan\u003eWIFI_ROUTERS setting; inclusive.\u0026nbsp; The example shows 0 through 10. 9 is skipped and 10 has empty strings (“”), both for testing.\u003c/span\u003e\n\u003c/li\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eWIFI_ROUTERS sets the number of SSID/PASSWORD pairs to be checked.\u0026nbsp; (Remember 0 is the first)\u003c/span\u003e\u003c/li\u003e\n\u003cli class=\"MsoNormal\"\u003e\u003cspan\u003eExample miscellaneous constants defined.\u0026nbsp; All kinds of private information can be put in your \u003cstrong\u003esettings.toml\u003c/strong\u003e file. (AdaFruit Passwords, Credit Card Numbers, Birthdays, URLs, Addresses, and WiFi SSIDs and PASSWORDS.)\u003c/span\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eSample settings.toml file:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n      \n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"# This file is where you keep secret settings, passwords, and tokens!\n# If you put them in the code you risk committing that info or sharing it\n# ssid = os.getenv(\"WIFI_SSID\")\n# password = os.getenv(\"WIFI_PASSWORD\")#\n#\nWIFI_SSID0     = \"WiFiNetwork0\" # nonexistant\nWIFI_PASSWORD0 = \"password0\"\n#\nWIFI_SSID1     = \"TestNet\" # dummy network\nWIFI_PASSWORD1 = \"password1\"\n#\nWIFI_SSID2     = \"ATTByTheSea\" # Aaron's Home\nWIFI_PASSWORD2 = \"SheSellsSeaShells\"\n#\nWIFI_SSID3     = \"Aristotle\" # Todd's Home\nWIFI_PASSWORD3 = \"password3\"\n#\nWIFI_SSID4     = \"MyWiFi_12345678\" #\nWIFI_PASSWORD4 = \"password4\"\n#\nWIFI_SSID5     = \"YourWiFi_87654321\" # Alternate\nWIFI_PASSWORD5 = \"password5\"\n#\nWIFI_SSID6     = \"Verizon_STUVWXYZ\" # Verizon\nWIFI_PASSWORD6 = \"password6\" \n#\nWIFI_SSID7     = \"MyOfficeWiFi\" # Ben's Home\nWIFI_PASSWORD7 = \"GetToWork\"\n#\nWIFI_SSID8     = \"WhiteHouse\" # Bruce's Home\nWIFI_PASSWORD8 = \"Constitution\"\n#\n#WIFI_SSID9\n#WIFI_PASSWORD9\n#\nWIFI_SSID10    = \"\"\nWIFI_PASSWORD10= \"\"\n#\nWIFI_ROUTERS = 10\n#\nPING_ADDRESS = \"8.8.8.8\"\n#\n#CIRCUITPY_WIFI_SSID = \"WiFiNetwork0\"\n#CIRCUITPY_WIFI_PASSWORD = \"password0\"\n#\n# To auto-connect to Wi-Fi\n#CIRCUITPY_WIFI_SSID=\"your_wifi_ssid\"\n#CIRCUITPY_WIFI_SSID\n#Wi-Fi SSID to auto-connect to even if user code is not running.\n#CIRCUITPY_WIFI_PASSWORD=\"your_pass_word\"\n#CIRCUITPY_WIFI_PASSWORD\n#Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID.\n#\n# To enable modifying files from the web. Change this also!\n# Leave the User field blank in the browser.\nCIRCUITPY_WEB_API_PASSWORD=\"passw0rd\"\nCIRCUITPY_WEB_API_PORT=80\n#\nntp_server=\"time-b-g.nist.gov\"\nlocation=\"Baltimore, US\"\nLATITUDE=\"39.xxxxx\"\nLONGITUDE=\"-76.xxxxx\"\nDaylight_Saving_Time=True","metadata":{"language":"python","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eMain Script (\u003cstrong\u003ecode.py\u003c/strong\u003e):\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eI will go through the provided code.py file by line number(s).\u0026nbsp; If you pull the code.py into Notepad, Notepad++, Visual Studio, or any text editor that shows line numbers the discussion will be easier.\u0026nbsp; A *.pdf is available at the Forum using the above link.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 1 – 3: Comments naming program code.py.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 5 – 8: The required libraries that must be included.\u0026nbsp; All are internal to CircuitPython 9.x.x.\u0026nbsp; No libraries need to be copied into the lib/ folder.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u003c/span\u003e\u003cspan\u003eLines 17 – 49: \u003cstrong\u003edef scan_sort_wifi(by=1, order=True):\u003c/strong\u003e\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eThis DEfined Function (\u003cstrong\u003edef\u003c/strong\u003e) Will retrieve, sort, and print the sorted list to REPL.\u0026nbsp; To call the \u003cstrong\u003edef\u003c/strong\u003e you can put the sort option in the first position, and sort order in the second position.\u0026nbsp; Sort Option: [0] Name, [1] Tx Power, [2] Channel, [3] No Sort.\u0026nbsp; Sort Order \u003cstrong\u003eTrue\u003c/strong\u003e is small to large, \u003cstrong\u003eFalse\u003c/strong\u003e is large to small.\u0026nbsp; \u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eIf you do not specify sort option or sort order, \u003cstrong\u003ename\u003c/strong\u003e and \u003cstrong\u003esmall to large\u003c/strong\u003e will be selected.\u0026nbsp; This \u003cstrong\u003edef\u003c/strong\u003e is for operator reference and diagnostic use.\u0026nbsp; The most useful statistic is the relative power.\u0026nbsp; As all the power values are negative; -40db has more power than -60db.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u003c/span\u003e\u003cspan\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;Lines 21 – 23: Set variables and print column headers on REPL.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 25 – 34: Get a listing from the WiFi module of all the WiFi access points that are locally transmitting.\u0026nbsp; The list is stored in variable \u003cstrong\u003eaps[]\u003c/strong\u003e.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 36 – 38:\u0026nbsp; Sort the list in aps[] and store it in network2.\u0026nbsp; The sort can be by Name, Relative Power, Channel or No Sort.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 39 – 49: Print the sorted listing of WiFi access points that are available in the local area to REPL.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 51 – 88:\u0026nbsp;\u003cstrong\u003edef connect_to_wifi():\u003c/strong\u003e\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; This function will attempt to connect to the list of WiFi Access Points defined in the \u003cstrong\u003esettings.toml\u003c/strong\u003e file.\u0026nbsp; It will cycle through the list until it finds success, and then will ping an IP address of your choice.\u0026nbsp; The WAN side of you boundary router is a good choice or the WAN default gateway.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 54 – 57: define which WiFi driver we will be using, and pick a random \u003cstrong\u003eptr\u003c/strong\u003e for the access point to start with.\u0026nbsp; A random start point removes any preference toward a particular access point.\u0026nbsp; You can set \u003cstrong\u003eptr\u003c/strong\u003e to a fixed number if you prefer to start with the same access point each time.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 58 -75: Attempt to connect to the list of access points in \u003cstrong\u003esettings.toml\u003c/strong\u003e.\u0026nbsp; If the connection fails, the next access point in the list will be tried.\u0026nbsp; When the end of the list (\u003cstrong\u003eWIFI_ROUTERS\u003c/strong\u003e) is reached, the pointer (\u003cstrong\u003eptr\u003c/strong\u003e) will be reset to the top of the list (\u003cstrong\u003e0\u003c/strong\u003e).\u0026nbsp; The progress is reported on REPL.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 76 – 88: Statistics of the successful connection are displayed on REPL in this section of code.\u0026nbsp; The display will contain IP Address, IP Subnet Mask, Subnet Default Gateway, Subnet Domain Name System, Device HostName, Radiated Power, and MAC Address.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 93 – 98: Example on how to enable the WiFi device, and how to call \u003cstrong\u003escan_sort_wifi(1, True)\u003c/strong\u003e.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 104 – 104: Example on how to set the Transmit Power.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 105 – 105: Example on how to set an optional HostName, and how to call\u0026nbsp;\u003cstrong\u003econnect_to_wifi()\u003c/strong\u003e.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eLines 109 – 139: My diagnostic code that connects to a WiFi access point for about 10 seconds then reboots the MCU to run all the code again.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 112 – 117: Sets the includes and enables the Green LED.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 119 – 125: Sets the includes and pings a designated address to test the WiFi connection.\u0026nbsp; The WAN side of your router is a good test.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 126 – 139: Tests if we are still connected and shows status.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; Line 128 tests if we are still connected.\u0026nbsp; If we are not, say so, if we have disconnected, reload with \u003cstrong\u003esupervisor.reload()\u003c/strong\u003e.\u0026nbsp; If you wish, comment-out line 131 and a full reset will happen.\u0026nbsp; This will most likely disconnect you from REPL.\u0026nbsp; Also after 10 loops, the code is reset and we test again.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; Lines 140 – 141:\u0026nbsp; We should never get here, but if we do we want to know it.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eSample code.py file:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"#######################################\n# Multiple WiFi Networks with CP 9.x.x\n#######################################\n\nimport os\nimport wifi\nimport random\nimport binascii\n\n#######################################\n# Diagnostic\n#######################################\nprint('\\f')\nprint('\\t*** Program Start ***')\nprint('')\n\n#######################################\ndef scan_sort_wifi(sort_by=1, order=True):\n#######################################\n    _ = 0\n    print(\"\\tAvailable CYW43439KUBG WiFi networks:\")\n    print(\" Seq\\tSSID\\t\\t\\t\\b\\b\\bPower  Channel\")\n    access_points = []\n    # Scan for WiFi networks\n    for networks in (wifi.radio.start_scanning_networks()):\n        s = \".\"*(20-len(str(networks.ssid, \"utf-8\")))\n        if (len(s)==0):\n            s = \"*Hidden_SSID*\"\n            access_points.append((s, networks.rssi, networks.channel))\n        else:\n            access_points.append((networks.ssid, networks.rssi, networks.channel))\n        _ += 1\n        #print(\"%3d\\t%s%s %d      %2d\" % (_, str(networks.ssid, \"utf-8\"), s, networks.rssi, networks.channel))\n    wifi.radio.stop_scanning_networks()\n    # Sort the found networks  Sort by [0]=name, [1]=power, [2]=channel, [3]=No Sort\n    if sort_by \u003c 3: sorted_networks = (sorted(access_points, key=lambda _: _[sort_by], reverse=order))\n    else: sorted_networks = access_points # Unsorted found networks\n    print('')\n    # Print the list to REPL\n    for _ in range(len(sorted_networks)):\n        s = \".\"*(20-len(str(sorted_networks[_][0], \"utf-8\")))\n        print(\"%3d\\t%s %s %d     %2d\" % (\n            _+1,\n            str(sorted_networks[_][0], \"utf-8\"),\n            s,\n            sorted_networks[_][1],\n            sorted_networks[_][2]))\n    print('')\n\n#######################################\ndef connect_to_wifi():\n#######################################\n    # Pick an access point at random \n    ptr = random.randint(0, os.getenv(\"WIFI_ROUTERS\"))\n    # Attempt to connect to the WiFi networks in settings.toml\n    while not wifi.radio.connected: # Loop while not connected\n        try:\n            SSID, PASSWORD = os.getenv(\"WIFI_SSID\"+str(ptr)), os.getenv(\"WIFI_PASSWORD\"+str(ptr))\n        except:\n            SSID, PASSWORD = 'Null', 'Null'\n        if(SSID == None) or (PASSWORD == None):\n            SSID, PASSWORD = 'Nope', 'Nope'\n        s = 30-(len(SSID) + len(PASSWORD))\n        if ptr \u003c 10: print(' ', end='')\n        print(ptr, SSID, PASSWORD, '.'*s, end=' ')\n        try:\n            print('WiFi Connecting.', end='')\n            wifi.radio.connect(SSID, PASSWORD)\n        except:\n            ptr += 1\n            ptr = (ptr % os.getenv(\"WIFI_ROUTERS\"))\n            print('\\b\\b\\bon Failed.')\n    print('\\b\\b\\b\\bed, Hurray!') # We are connected\n    IP      = wifi.radio.ipv4_address\n    Mask    = wifi.radio.ipv4_subnet\n    Gateway = wifi.radio.ipv4_gateway\n    DNS     = wifi.radio.ipv4_dns\n    hostname= wifi.radio.hostname\n    power   = wifi.radio.tx_power\n    print(\"\\n\\t\\tWiFi Connection Information:\\n    SSID:\", SSID, ' ~  IP:', IP, ' ~  Mask:', Mask, ' ~')\n    print('\\tGateway:', Gateway, ' ~  DNS:', DNS, ' ~  HostName:', wifi.radio.hostname, ' ~')\n    print('\\tRadiated Power: '+str(power)+'mw ~ MAC addr:', end=' ')\n    res = (binascii.hexlify(bytearray(wifi.radio.mac_address)))\n    for _ in range(0, len(res), 2):\n        print(str(res[_:_+2])[2:4].upper(), end=':')\n    print('\\b \\n') # Cleanup\n\n#######################################\n# Start of Your code\n#######################################\nwifi.radio.enabled = True\n\n#######################################\n# Scan and show the available WiFi networks, Sort Optional\n#######################################\nscan_sort_wifi(1, True) # Sort by | 0\u003ename, False | 1\u003epower, True | 2\u003echannel, False, | 3\u003e No Sort \n\n#######################################\n# Attempt to connect\n#######################################\n# Optional unique HostName\n#wifi.radio.tx_power = 63.0 # 1 through 63, 31.75 default\n#wifi.radio.hostname = \"MultiWiFi\"\n# Lets go connect to WiFi\nconnect_to_wifi()\n\n#######################################\n# Diagnostics\n#######################################\nimport time\nimport board\nimport digitalio\nGreenLED = digitalio.DigitalInOut(board.LED)\nGreenLED.direction = digitalio.Direction.OUTPUT\nGreenLED.value = True\n\nimport ipaddress\nimport supervisor\nimport microcontroller\naddr = \"71.179.161.1\"#\"192.168.12.1\"\nip1 = ipaddress.ip_address(addr)\nprint(\"pinging\", ip1)#, end=' ')\nprint(\"ping round trip time:\", wifi.radio.ping(ip1), \"Seconds\")\nt = time.time()\nwhile True:\n    GreenLED.value = not GreenLED.value\n    if (wifi.radio.connected and ((t+10) \u003e time.time())):\n        print(' ', time.time(), '\\tWe are Good ', end='\\r')\n        time.sleep(1)\n    else:\n        print('\\n\\t\\aTimeout/Lost Connection\\a')\n        time.sleep(1)\n        supervisor.reload() # Like Ctrl-C, Ctrl-D\n        microcontroller.reset() # Like RESET button or remove/connect power\nprint('')\nprint('\\t*** Program Finis ***')\n'''\n\u003e\u003e\u003e import wifi\n\u003e\u003e\u003e dir(wifi)\n['__class__', '__init__', '__name__', 'AuthMode', 'Monitor', 'Network', 'Packet', 'Radio', 'Station', '__dict__', 'radio']\n\n\u003e\u003e\u003e dir(wifi.radio)\n['__class__', 'ap_active', 'connect', 'connected', 'enabled', 'hostname', 'ipv4_address', 'ipv4_address_ap', 'ipv4_dns', 'ipv4_gateway', 'ipv4_gateway_ap', 'ipv4_subnet', 'ipv4_subnet_ap', 'mac_address', 'mac_address_ap', 'ping', 'set_ipv4_address', 'set_ipv4_address_ap', 'start_ap', 'start_dhcp', 'start_dhcp_ap', 'start_scanning_networks', 'start_station', 'stations_ap', 'stop_ap', 'stop_dhcp', 'stop_dhcp_ap', 'stop_scanning_networks', 'stop_station', 'tx_power']\n\u003e\u003e\u003e\n'''","metadata":{"language":"python","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eUpload the code and configuration:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eTo test if this program will work on your MCU (listed above), load CircuitPython 9.0.0 or newer, copy the \u003cstrong\u003ecode.py\u003c/strong\u003e and \u003cstrong\u003esettings.toml\u003c/strong\u003e files to your board.\u0026nbsp; Then startup REPL and see what is happening.\u0026nbsp; It should cycle through the 10 SSID/PASSWORD pairs preloaded into settings.toml and fail at each one and move on to the next.\u0026nbsp; \u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eIf you get wifi not found/defined, this program will not work because CP 9.x.x does not support your board.\u0026nbsp; The AdaFruit Forum experts will have to address this.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eReplace one of the test sites listed in settings.toml with your local WiFi SSID and PASSWORD then watch what happens.\u0026nbsp; The program should pick a random site and cycle through to your site and connect.\u0026nbsp; It will wait 10 seconds then reboot and pick a random site and cycle again.\u0026nbsp; Then change the IP address in line 116 and verify that your MCU can ping a known good local site.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eThis should work out-of-the-box.\u0026nbsp; If yours doesn’t, contact me on the AdaFruit Forum, \u003cstrong\u003e@blakebr\u003c/strong\u003e.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003eConclusion:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eI hope this utility helps you in making your programs more bulletproof while connecting to WiFi.\u0026nbsp; I am looking forward to your real-life testing and improving this utility with your input.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eI suggest you place the code snippet below someplace in your program to periodically test that the WiFi connection is still good.\u003c/span\u003e\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"if (wifi.radio.connected):\n        # We are good, no action.\n        time.sleep(0.01)\nelse:\n        print('aTimeout/Lost Connection\\a')\n        time.sleep(1)\n        supervisor.reload() # Like Ctrl-C, Ctrl-D  # Comment out to RESET\n        microcontroller.reset() # Like RESET button or remove/connect power","metadata":{"language":"python","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp class=\"MsoNormal\"\u003e\u003cstrong\u003e\u003cspan\u003ePotential extensions:\u003c/span\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003eAn adventuresome coder may want to tackle taking the access point list sorted by relative power and comparing it to the SSID/PASSWORD listing and then starting the connection attempts with the known access point with the highest power and working through the list until success.\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"MsoNormal\"\u003e\u003cspan\u003e\u0026nbsp;\u003c/span\u003e\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}}]