When you define a "Thing" using the Arduino IoT Cloud, you give it an SSID and password that will let your thing connect to a local wifi network. This info is stored in a header file called "arduino_secrets.h".
That's fine if your thing will only be used in one location. But what if you need to make it work with more than one wifi network, choosing among several SSIDs depending on which one is available in its current location? In other words, going through a list of SSIDs until it finds one that is active.
Can anyone think of a way to make this work?
It seems to me that the best way to handle this would be if the IoT cloud "begin" method would defer to an existing wifi connection if one had been established before the cloud connection was initialized, using the secret SSID only if the device was not already connected. But I don't know if the cloud initialization code is set up to work that way.
You may check this thread: https://forum.arduino.cc/t/iot-cloud-multiple-wifi-credentials-and-access-points/644094
@aliarifat Thank you! It seems that this guy has the same question, and maybe he has even taken a step closer to the answer than I have. But no one answered him, so he and I are both still looking for an answer.
I think that his code may point to some new areas for me to explore.
@jimgilliland The reason there was no activity is because you don't need to do anything. You access the 'THING' via the IoT Remote app from anywhere you have internet access.
Now if the THING is physically moved, then nothing can be done, it's like asking a boat to fly. Not designed for that.
JUST IN CASE I am mistaken, I will test it tomorrow. I have the free demo iPhone 'thing' whereby my phone streams sensor data from it's myriad of sensors to the cloud and they get displayed on the dashboard.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Now if the THING is physically moved, then nothing can be done, it's like asking a boat to fly. Not designed for that.
@zander Yes, that is exactly what I need. In the real world, "things" don't stay in one place. They are carried from place to place in pockets, cars, shipped packages, and on and on. And any realistic Internet of Things needs to take that into account.
In fact most IoT environments include mapping functions that let you keep track of exactly where a "thing" is at the moment. That's one of the major use cases for the IoT.
If a "thing" needs to work everywhere, then it probably needs a cellular connection. But if it only needs to work in a few locations, then it needs to be able to use its credentials to connect to an SSID that is in each of those locations. That's all I'm trying to do.
I think you're right. It's not designed for that. But that shouldn't be hard to fix. I was hoping that someone here had been down that road ahead of me.
The thread that @aliarifat posted includes some concepts that might point in the right direction, but I haven't had time to look into them yet.
@jimgilliland If such a thing was possible, just imagine how much money the bad guys would have and you would have none.
Cellular and WiFi are equal, one is mobile to a degree, and the other is not.
If you are thinking of air tags that can move around, that is a totally different concept.
I have seen mention of the words multi and WiFi, but not sure if that is server side or client side, as you know now will work for you the other not. I am also relatively (but remember an 82 yo autistic brain here) sure I have seen software that can connect to multiple SSID's. I will take a QUICK look around to see if I can find something. However even if it is possible, you then need to convince Arduino and any other cloud player to change their software and I wonder if they would be receptive since my gut tells me this arrangement is less secure.
EDIT:
Well that didn't take long. Here is a sample, now you just need to convince the cloud suppliers to support it.
// This example is supposed to work on all boards that use the WiFi.h // header file, such as Portenta, ESP32 and more. #include <WiFi.h> #include <Arduino_MultiWiFi.h> MultiWiFi multi; void setup() { // Wait until the serial port is connected Serial.begin(9600); while (!Serial) {} // Configure the known networks (first one gets higher priority) multi.add("myssid", "mypassphrase"); multi.add("myssid_2", "mypassphrase_2"); // Connect to the first available network Serial.println("Looking for a network..."); if (multi.run() == WL_CONNECTED) { Serial.print("Successfully connected to network: "); Serial.println(WiFi.SSID()); } else { Serial.println("Failed to connect to a WiFi network"); } } void loop() {}
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Yes, that's the idea. It's not rocket science. Start with a list of SSIDs and associated passwords for the locations where you want the device to work. Then let the code go down the list until it finds one that works. If none work or a connection gets dropped, wait some period of time (5 min? 30 min?) according to your application's needs, then try again.
While it wouldn't be a complete solution, a simple workaround would be if the IoT code that handles the wifi connection would simply use an existing connection if one had been established early in the setup, before the "ArduinoCloud.begin" statement. That way everything out there today would keep working exactly as it does now, but a developer would have the ability to effectively override it when necessary.
@jimgilliland You are welcome to submit a feature request to the Arduino Cloud folks, but my hunch is it will be turned down as a security risk. It MAY get accepted if that list of credentials is a finite list maybe 3 to 6 entries long. Good luck.
Remember, you still have the option of using cellular for your cloud connection so it accomplishes your anywhere objective. It may even be feasible to use a small mobile application like that to enter credentials for a nearby AP but it could only be connected to by a non-cloud app. That solution gets you what you want, but it may be inconvenient and is now outside the cloud.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
I figured out how to do it. It's not that hard, but it took a lot of experimenting to get it all working. I'm not sure that my code is the best approach, but it does work.
Here is what you find in a typical IoT sketch. The secrets.h file (which is built from the secrets tab) contains this:
#define SECRET_DEVICE_KEY "*************************" #define SECRET_OPTIONAL_PASS "**********" #define SECRET_SSID "**********"
We are not permitted to modify the thingProperties.h. It contains this code:
const char SSID[] = SECRET_SSID; const char PASS[] = SECRET_OPTIONAL_PASS; WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);
And in the main Iot sketch Setup is the following:
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
Here are the changes that I made.
First of all, it is permitted and easy to add additional "secrets" to the Secrets tab for the cloud sketch. So my secrets.h file now contains these new lines:
#define SECRET_SSID1 "InvalidSSID" #define SECRET_PASS1 "Invalidpassword" #define SECRET_SSID2 "MyRealSSID" #define SECRET_PASS2 "validpassword" #define SECRET_SSID3 "AnotherRealSSID" #define SECRET_PASS3 "validpassword"
I deliberately made the first SSID invalid for testing purposes. And I left the original lines alone, but they also contained an invalid SSID and password.
I added these statements to the main sketch just after including the thingProperties.h file:
WiFiConnectionHandler ArduinoIoTPreferredConnection1(SECRET_SSID1, SECRET_PASS1); WiFiConnectionHandler ArduinoIoTPreferredConnection2(SECRET_SSID2, SECRET_PASS2); WiFiConnectionHandler ArduinoIoTPreferredConnection3(SECRET_SSID3, SECRET_PASS3);
Then I replaced the "begin" statement in the Setup with:
if (WiFi.waitForConnectResult() != WL_CONNECTED) { both.println("Trying connection 1..."); tries = 0; ArduinoCloud.begin(ArduinoIoTPreferredConnection1); while (WiFi.waitForConnectResult() != WL_CONNECTED) { delay(2500); ArduinoCloud.update(); if (WiFi.waitForConnectResult() == WL_CONNECTED) break; setDebugMessageLevel(4); ArduinoCloud.printDebugInfo(); if (++tries == 5) break; } } if (WiFi.waitForConnectResult() != WL_CONNECTED) { both.println("Trying connection 2..."); tries = 0; ArduinoCloud.begin(ArduinoIoTPreferredConnection2); while (WiFi.waitForConnectResult() != WL_CONNECTED) { delay(2500); ArduinoCloud.update(); if (WiFi.waitForConnectResult() == WL_CONNECTED) break; setDebugMessageLevel(4); ArduinoCloud.printDebugInfo(); if (++tries == 5) break; } } if (WiFi.waitForConnectResult() != WL_CONNECTED) { both.println("Trying connection 3..."); tries = 0; ArduinoCloud.begin(ArduinoIoTPreferredConnection3); while (WiFi.waitForConnectResult() != WL_CONNECTED) { delay(2500); ArduinoCloud.update(); if (WiFi.waitForConnectResult() == WL_CONNECTED) break; setDebugMessageLevel(4); ArduinoCloud.printDebugInfo(); if (++tries == 5) break; } } if (WiFi.waitForConnectResult() != WL_CONNECTED) { both.println("No wifi available, reset to retry..."); while (true) {} }
Note that "both.println()" is a function of my Heltec board's library. It prints the same message to the serial port and the onboard display on the processor.
My only concern was with the const char[] SSID and PASS variables. They are initialized in the header file and obviously can't be changed. I thought it might be possible that the device would try to reconnect with those values after a dropped connection. But it turns out that after a dropped connection, the device reconnects with the correct credentials - the working ones that had been connected before.
This probably isn't the best code possible, but it does work. It is the result of a lot of experimentation and quite a few failures and partial successes.
For some reason that I can't explain, there is a very long delay (about 60 seconds) during the first and second attempt to connect. But it doesn't prevent the process from working. It just leaves us waiting for about two minutes while it does whatever it is doing at the start.
Now that I have this working, I have some other issues to figure out. I'll start a new thread for those.
@jimgilliland Also, you need to see what happens if you make changes to the cloud environment like add another 'widget'. In my experience, it will overwrite your manual code changes.
Also note this is not your original objective, you wanted an infinite number of connections, but now you are settling for n. BTW, I did show you the library for that (n) did I not?
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
No, this was my original objective. N is enough, any finite number. My example of 3 could just as easily be 20, though I suspect that I could optimize the code to work much more efficiently if I needed that many networks and/or locations supported. But this gives me what I was after. I don't need an unlimited number.
I saw the code fragment that you posted, but as far as I could tell, it didn't have anything to do with the IoT cloud. It was just a method of choosing a working SSID from a list. That's the right idea, but unless I missed something, it wouldn't work in this environment.
Your point about the cloud environment overwriting my code is a good one. I haven't looked into that. It seems to me that the IoT sketch should probably have one or more blocks of code that are marked "Do not edit because your changes may be overwritten". And if that were the case, it is entirely possible that my changes would have touched a "forbidden" area. At present there are no such warnings. But that doesn't mean that my code won't get replaced. I'll have to try it and see what happens.