Skip to content

Try multiple wifi networks #65

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 5 commits into from
Apr 19, 2022
Merged

Try multiple wifi networks #65

merged 5 commits into from
Apr 19, 2022

Conversation

tekktrik
Copy link
Member

First stab at trying multiple Wi-Fi networks. I don't have a MagTab or anything that uses this library so will definitely need help testing. secrets.py should be either the usual dictionary or can be a list of valid dictionaries (that means repeating things like Adafruit IO keys as well in each dictionary). NetworkBase._secrets stores the "active" dictionary being used, in case that access is ever needed, and it also keeps a lot of the existing code from changing. Let me know if anything needs to change.

Tagging @djh1997 who submitted the issue as well.

Resolves #63.

@tekktrik tekktrik marked this pull request as ready for review March 21, 2022 20:46
@tekktrik tekktrik added the enhancement New feature or request label Mar 24, 2022
@tekktrik
Copy link
Member Author

Tested this, looking good! Ran the MagTag quote example with Adafruit CircuitPython 7.2.3 on 2022-03-16; Adafruit MagTag with ESP32S2 and a secrets.py file with a secrets object equal to a list of dictionaries of SSID + password. After failing the first non-existent connection 10 times, it moved to the second one which did exist and connected successfully!

@tekktrik
Copy link
Member Author

Also successfully connects if secrets.py has a secrets object equal to a single dictionary of SSID + password, just as before!

@tekktrik
Copy link
Member Author

tekktrik commented Mar 27, 2022

Also successfully managed to build the MagTag frozen with this frozen in, and examples functions the same with multiple Wi-Fi setting.

Successfully created esp32s2 image.

1401376 bytes used,   40416 bytes free in flash firmware space out of 1441792 bytes (1408.0kB).
     88 bytes used,    8104 bytes free in 'RTC Fast Memory' out of 8192 bytes (8.0kB).
   4112 bytes used,    4080 bytes free in 'RTC Slow Memory' out of 8192 bytes (8.0kB).
      0 bytes used,   32768 bytes free in 'Internal SRAM 0' out of 32768 bytes (32.0kB).
 234807 bytes used,   60105 bytes free in 'Internal SRAM 1' out of 294912 bytes (288.0kB).

Converted to uf2, output size: 2803200, start address: 0x0
Wrote 2803200 bytes to build-adafruit_magtag_2.9_grayscale/firmware.uf2

@FoamyGuy
Copy link
Contributor

FoamyGuy commented Apr 4, 2022

that means repeating things like Adafruit IO keys as well in each dictionary

Do I understand correctly that this means in order to utilize the second network you would need secrets to be set up like this:

secrets = [{
    'ssid': 'network_id',  
    'password': 'network_password',  
    'timezone': "America/New_York", 
    'aio_username': 'My_AIO_Username',
    'aio_key': '12345abcdef',
    'openweather_token': '987654321abcde',
    'ifttt_key': '678910abcde',
    'zip': 10011,
    'totp_keys': [("Discord ", "KEY1"),
                  ("Gmail", "KEY2"),
                  ("GitHub", "KEY3"),
                  ("Adafruit", "KEY4"),
                  ("Outlook", "KEY5")]
}, {
    'ssid': 'other_network_id', 
    'password': 'other_network_password', 
    'timezone': "America/New_York", 
    'aio_username': 'My_AIO_Username',
    'aio_key': '12345abcdef',
    'openweather_token': '987654321abcde',
    'ifttt_key': '678910abcde',
    'zip': 10011,
    'totp_keys': [("Discord ", "KEY1"),
                  ("Gmail", "KEY2"),
                  ("GitHub", "KEY3"),
                  ("Adafruit", "KEY4"),
                  ("Outlook", "KEY5")]
}]

If so I think we should try to adjust the behavior so that this could be used instead if possible:

secrets = {
    'networks': [
        {
            'ssid': 'network_id',
            'password': 'network_password'
        },
        {
            'ssid': 'other_network_id',
            'password': 'other_network_password'
        }
    ]
    # other entries outside the list...
}

Or perhaps if we'd rather not introduce the new key networks then we could do lists inside of ssid and password like this:

secrets = {
    'ssid': ['network_id', 'other_network_id'], 
    'password': ['network_password', 'other_network_password'],
    'timezone': "America/New_York",
    'aio_username': 'My_AIO_Username',
    'aio_key': '12345abcdef',
    'openweather_token': '987654321abcde',
    'ifttt_key': '678910abcde',
    'zip': 10011,
    'totp_keys': [("Discord ", "KEY1"),
                  ("Gmail", "KEY2"),
                  ("GitHub", "KEY3"),
                  ("Adafruit", "KEY4"),
                  ("Outlook", "KEY5")]
}

I think making the secrets object into a list could be problematic though because any code that accesses something as a dictionary key like:

secrets["aio_key"]

would no longer work for the list variation, if I understand correctly the code would have to change to:

secrets[0]["aio_key"]

With any existing index filled in for the 0

I think we should try to keep it so that no code that needs other secrets has to change except for specifically code trying to access the ssid and password for it. All other key/values should be able to be looked up the same as they are today if possible.

Using one of the other two formats here would also remove the need to duplicate all of your secret tokens and other values which would make it easier when the time comes to add / change them.

@tekktrik
Copy link
Member Author

tekktrik commented Apr 4, 2022

Do I understand correctly that this means in order to utilize the second network you would need secrets to be set up like this:

Yup, exactly. I would be willing to introduce a new networks keyword as a list, but unsure of how chaotic that may be. Sounds like a breaking change at least.

My attempted solution to keep too much from breaking (at least internally) was to have PortalBase._secrets remain a single dict but store a new instance variable called PortalBase._secrets_entries which is the whole list. The connection method just tries everything in PortalBase._secrets_entries, but sets the one it is currently attempting to connect to as PortalBase._secrets so it should will match whatever it ends up connecting to (if it does). But I agree fully, any user code use secrets[key] is borked with this.

Another solution might be to have an entirely new keyword that could optionally be used in place of keys ssid and password. maybe something like networks like you mentioned. If this library sees the networks key, it expects a sequence of dict with SSIDs and passwords. Otherwise, it will look for the ssid and password keys per usual. What do you think about that?

@tekktrik
Copy link
Member Author

tekktrik commented Apr 4, 2022

At least that way it won't be a breaking change

@FoamyGuy
Copy link
Contributor

FoamyGuy commented Apr 4, 2022

Nice! I do like the idea of networks being a new optional field that can contain multiple ssids and passwords. That way we can upgrade the code here to handle multiple networks if that field exists, but all other existing code will continue to work the same as it does today.

@tekktrik
Copy link
Member Author

tekktrik commented Apr 4, 2022

Sweeeeeet! I'll refactor this code to do that instead then, thanks for the feedback!

@tekktrik
Copy link
Member Author

Reworked to use a networks key in the dict as mentioned, just before I fixed a few minor typos so memory should be about the same I think:

Successfully created esp32s2 image.

1404208 bytes used,   37584 bytes free in flash firmware space out of 1441792 bytes (1408.0kB).
     88 bytes used,    8104 bytes free in 'RTC Fast Memory' out of 8192 bytes (8.0kB).
   4112 bytes used,    4080 bytes free in 'RTC Slow Memory' out of 8192 bytes (8.0kB).
      0 bytes used,   32768 bytes free in 'Internal SRAM 0' out of 32768 bytes (32.0kB).
 234855 bytes used,   60057 bytes free in 'Internal SRAM 1' out of 294912 bytes (288.0kB).

Tested successfully on my home network using both the new network key, as well as the typing ssid and password option. The former was able to keep trying an intentionally bad network name 10 times until it swtiched to the second true one and successfully connected!

@tekktrik
Copy link
Member Author

Here's the CircuitPython build for MagTag with it as is:

Successfully created esp32s2 image.

1404208 bytes used,   37584 bytes free in flash firmware space out of 1441792 bytes (1408.0kB).
     88 bytes used,    8104 bytes free in 'RTC Fast Memory' out of 8192 bytes (8.0kB).
   4112 bytes used,    4080 bytes free in 'RTC Slow Memory' out of 8192 bytes (8.0kB).
      0 bytes used,   32768 bytes free in 'Internal SRAM 0' out of 32768 bytes (32.0kB).
 234855 bytes used,   60057 bytes free in 'Internal SRAM 1' out of 294912 bytes (288.0kB).

Converted to uf2, output size: 2808832, start address: 0x0

@tekktrik
Copy link
Member Author

@FoamyGuy my pleasure, thank you for testing! Just added RuntimeError to the except block.

Copy link
Contributor

@FoamyGuy FoamyGuy left a comment

Choose a reason for hiding this comment

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

Looks good to me. I retested both the multiple networks and original single ssid and password behavior and both are working as expected on PyPortal 7.3.0beta

@FoamyGuy FoamyGuy merged commit bc69bfa into adafruit:main Apr 19, 2022
adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Apr 20, 2022
Updating https://github.com/adafruit/Adafruit_CircuitPython_BME680 to 3.4.3 from 3.4.2:
  > Merge pull request adafruit/Adafruit_CircuitPython_BME680#49 from billvanleeuwen424/main
  > Update Black to latest.
  > Fixed readthedocs build
  > Consolidate Documentation sections of README

Updating https://github.com/adafruit/Adafruit_CircuitPython_Display_Shapes to 2.4.3 from 2.4.2:
  > Merge pull request adafruit/Adafruit_CircuitPython_Display_Shapes#47 from tekktrik/dev/divide-by-zero
  > Update Black to latest.
  > Merge branch 'ladyada:master' into main
  > Fixed readthedocs build
  > Post-patch cleanup

Updating https://github.com/adafruit/Adafruit_CircuitPython_PortalBase to 1.12.0 from 1.11.5:
  > Merge pull request adafruit/Adafruit_CircuitPython_PortalBase#65 from tekktrik/dev/multiple-wifi

Updating https://github.com/adafruit/Adafruit_CircuitPython_RSA to 1.2.8 from 1.2.7:
  > Merge pull request adafruit/Adafruit_CircuitPython_RSA#27 from tekktrik/doc/add-documentation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multiple wifi
2 participants