Plug&play software to send WIFI name and password to the core

Hey,

I made some boards with the Core inside and I want to send them to some people. I want them to be able to connect the Core to the internet via their WIFI, but I don’t want them to install too much stuff or clam the core.
Do you have a simple app (not the smartconfig) for smartphones or a plug&play software (via USB, like the Particle Dev, but just the part of “setup device’s WIFI”) for that?

BTW, if it’s easier with the photon I can switch it when I’ll get that…

Thanks,
Itay

Just an idea to think about

You could preset a SSID/PWD combination on the device which allows the user to connect to the cloud by just temporarily adjusting the router (or even more convenient mobile phone AP) to allow the device to connect via the preset credentials and after that you could let them send in their credentials via a Spark.function() that feeds the info to WiFi.setCredentials()

On the other hand what is too much stuff to install?
If your users don’t happen to be on Windows there is hardly anything you need to install for serial connection and for Windows it’s only the serial driver. A little program you could provide for your users (which tells them how to put the device into listening mode and then just sends ‘w’ to the Core and provides a UI for the rest) wouldn’t need to be installed but could run out the box.

1 Like

@ScruffR, I'm looking for something like that. Do we have something like that?

I don’t know of anything like it off the Particle shelf, but in C# for Windows it’s something like a 10-liner :wink:

On the other hand any standalone (non-setup) serial terminal would do too.
e.g.
http://www.compuphase.com/software_termite.htm (no waranty the EXE it’s safe to use).
or a spin-off with source code
http://www.codeproject.com/Articles/23656/Termie-A-Simple-RS-Terminal

Hey @ScruffR,

I’m not a C# programer and I would like to do it in the program.
Let’s say, when the Core go inside WIFI.LISTENING() mode, it will ask you what is your wifi SSID and wifi PASS and change them with WIFI.SETCREDENTIALS() (I tried, but the connection with the serial monitor disconnected when I press 3 secs on the mode button and moving to “listening mode”) or maybe when you press ‘W’ it will ask you if you want to change it. I tried this too but I can’t make it work.
Do you have any idea?

Try it without listening mode like this.
For convenience I’ve used Serial.readBytesUntil(), but you have to be quick to enter your data and don’t press ENTER!


SYSTEM_MODE(SEMI_AUTOMATIC)

char input[256];
int  idx;

char ssid[64] = { '\0' };
char pwd[64] = { '\0' };
int  auth = -1;

void setup()
{
    WiFi.on();
    
    Serial.begin(115200);

    while(!Serial.available())
    {
        Serial.println("PRESS ANY KEY TO PROCEEDE (ESC to terminate)");
        delay(1000);
    }
    
    
    if (Serial.read() != 0x1B)
    {
        while(Serial.read() >= 0); // flush any remaining bytes
        
        WiFi.clearCredentials();   // if you only want one set of credentials stored
        
        Serial.println("be quick to enter before timeout - don't press ENTER!");
        Serial.println("Enter SSID : ");
        while (!ssid[0])
            Serial.readBytesUntil('\n', ssid, 63);
        Serial.println(ssid);
            
        // Auth options are WLAN_SEC_UNSEC (0), 
        //                  WLAN_SEC_WPA (1), 
        //                  WLAN_SEC_WEP (2) and
        //                  WLAN_SEC_WPA2 (3)
        // plus 1 for atoi()
        Serial.println("be quick to enter before timeout - don't press ENTER!");
        Serial.println("Enter encryption open (1), WEP (2), WPA (3), WPA2 (4)  : ");
        input[0] = '\0';
        while (WLAN_SEC_UNSEC > auth || auth > WLAN_SEC_WPA2)
        {
            Serial.readBytesUntil('\n', input, 63);
            auth = atoi(input) - 1;  // atoi returns 0 on fail, but 
        }
        Serial.println(auth + 1);
        
        if (auth > 0)
        {
            Serial.println("be quick to enter before timeout - don't press ENTER!");
            Serial.println("Enter PWD:  ");
            while (!pwd[0])
                Serial.readBytesUntil('\n', pwd, 63);
            Serial.println(pwd);
        }        
        
        WiFi.setCredentials(ssid, pwd, auth);
        
    }
    
    Spark.connect();
}

void loop()
{

}

1 Like

@ScruffR, Thank you!!

Yes, you right, I need to be really quick or copy -->past (BTW, why is it so short time or why can’t we wait for the enter?)
I’ll try to combine it as a function that I could call from the loop.

Normally I’d do it in a loop character by character - but that would have blown up the code even more :wink:

The implementation of readByteUntil() has a timeout of (I think) one second and if you press ENTER, it includes it in the string - which we don’t want.
But if you want, I can also whip up an input function, but I also guess you can :+1:

1 Like

Hey @ScruffR,
I added a check for the wifi. If the wifi is working skip the “while” and the menu.

    SYSTEM_MODE(SEMI_AUTOMATIC)
    
    char input[256];
    int  idx;
    
    char ssid[64] = { '\0' };
    char pwd[64] = { '\0' };
    int  auth = -1;
    
    void setup()
    {
        WiFi.on();
        WiFi.connect();
        Serial.begin(115200);
        Serial.println("checking wifi");
        delay(15*1000); //give it a long time to connect to the wifi
        if (!WiFi.ready()){ //connected good?
            while(!Serial.available())
            {
                Serial.println("PRESS ANY KEY TO PROCEEDE (ESC to terminate)");
                delay(1000);
            }
            
            
            if (Serial.read() != 0x1B)
            {
                while(Serial.read() >= 0); // flush any remaining bytes
                
                
                
                Serial.println("be quick to enter before timeout - don't press ENTER!");
                Serial.println("Enter SSID : ");
                while (!ssid[0])
                //delay(5000);
                    Serial.readBytesUntil('\n', ssid, 63);
                Serial.println(ssid);
                    
                // Auth options are WLAN_SEC_UNSEC (0), 
                //                  WLAN_SEC_WPA (1), 
                //                  WLAN_SEC_WEP (2) and
                //                  WLAN_SEC_WPA2 (3)
                // plus 1 for atoi()
                Serial.println("be quick to enter before timeout - don't press ENTER!");
                Serial.println("Enter encryption open (1), WEP (2), WPA (3), WPA2 (4)  : ");
                input[0] = '\0';
                while (WLAN_SEC_UNSEC > auth || auth > WLAN_SEC_WPA2)
                {
                    Serial.readBytesUntil('\n', input, 63);
                    auth = atoi(input) - 1;  // atoi returns 0 on fail, but 
                }
                Serial.println(auth + 1);
                
                if (auth > 0)
                {
                    Serial.println("be quick to enter before timeout - don't press ENTER!");
                    Serial.println("Enter PWD:  ");
                    while (!pwd[0])
                        Serial.readBytesUntil('\n', pwd, 63);
                    Serial.println(pwd);
                }        
                WiFi.clearCredentials();   // if you only want one set of credentials stored
                WiFi.setCredentials(ssid, pwd, auth);
                
            }
            
            Spark.connect();
        }
    Spark.connect();
    }
    
    void loop()
    {
    
    Serial.println("in loop");
    delay(3000);
    }

Now it’s good enough and easy to connect CoolTerm terminal to send the WIFI credentials.
Thanks again.

1 Like

If you're interested, in this thread I've whiped up some char-by-char serial read even with echo.

1 Like

Hey,

I built out a windows app to change the wifi configuration. It is really rough at the moment but you can take a look at it here https://github.com/jlkalberer/Particle.WifiSetup

@ScruffR - Can you check out the WifiSetup.h to make sure I’m not doing anything unnecessary?

2 Likes

As much as I can say, that seems very decent.
There might be some bits and bobs that could be left out, but for the sake of readability and portability (Spark.connect() on Photon used to not connect WiFi reliably) I’d stick with the verbosity :+1:

I’m just not sure about the SYSTEM_MODE(SEMI_AUTOMATIC) inside a header. I’d rather instruct the user to pay attention to choose the mode carefully and make your code work with all possible modes.
And maybe provide .cpp and .h files.

Alright, that sounds good. I’ll try to clean things up tonight if I have time.

I fried my Spark Core so I can only test on a Photon at the moment but I have another one coming so I’ll test soon.

The next thing I want to get working is installing the correct driver if a user doesn’t have it installed. I also need to detect which com port to use when the photon/core is connected but that is trivial.

Thanks again.

1 Like

have you had a chance to work on this project any more?

No… I decided to use SoftAP instead. I decided against an installer since it’s just more friction for the user.

The code posted by @scruffr and @itayd100 from this post works quite well. However, I need to keep the WiFi disconnected and connect it only when needed. When I reboot my Photon after once storing the WiFi credentials in it and try to reconnect using the (hopefully!!) saved WiFi credentials using WiFi.on(), the Photon blinks blue indicating that WiFi is not setup. When I setup the WiFi again using this code - disconnect and reconnect the Wifi, it works - as long as I don’t reboot.

Any ideas?

It seems the credentials are not getting permanently stored. I also tried by eliminating the WiFi.clearCredentials(); from the code.

That’s quite a while ago :wink:
Can you post your current code (with any alterations you’ve done)?
And a short description what does work and what doesn’t (again)?