Alternative to SoftAp - Photon Wifi setup using PC or Mac

One more addendum – reliability of SoftAP can also be affected by the firmware running on the Wi-Fi device. Running the latest version of system firmware is always best practice, as is limiting possible firmware interactions that might interfere with the SoftAP setup libraries during configuration.

3 Likes

:thumbsup:
Thanks for the reminder... We need to include regular testing our latest device firmware with the Particle firmware updates and push those out...

Very good point as we have not really focused on that during our development. Often times it means more work getting our libraries back in line with the Particle improvements and changes! :frowning:

1 Like

What are you guys building? Love to see the different stuff being built.

Believe me when I say… we really wish we could be telling people what we are doing by now!!

:wink:

1 Like

How about simulating an USB storage after startup?
For example, in the beginning of power up it’s in usb-serial mode. If there is no input within 5 seconds, it switches to usb-storage mode. There we can save a config file containing wifi ssid and password.

If you need the usb-serial back, just reboot and break from serial, like the uboot auto booting.
Or you can write a function to switch through network.

1 Like

I’m not aware of a USB Mass Storage endpoint on the Particle devices.
It was proposed aeons ago but more pressing features need to be incorporated first.
on hold https://github.com/spark/firmware/issues/166

But an alternative would be a SD slot to provide a config file via that.

Great discussion on this thread. I just wanted to share our experience from using P1’s for our consumer products over the past two years. Even though SoftAP is very well supported by Particle and works most of the time, connecting to WiFi still remains the #1 support issue for us. And its not all Particle to blame, we could do a better job with our App and support documentation that accompanies the product.

We have developed multiple ways for a consumer to connect the device to WiFi. The recommended way is our App. It works for 75% of the cases.

The next option is our web app - its similar to setup.particle.io, however requires that the ethernet cable be unplugged on the PC/Mac. This resolves about 10% of cases for us.

The third option is the Particle App. We request the customer to log into the Particle App with the supplied public credentials. Once the device is online, we ask the user to initiate the ‘transfer’ process in our App, which unclaims the device from the ‘support’ Particle account, claims it to the ‘production’ particle account and associates it with the user. The whole process takes less than 1 min and we do realize there are issues with this approach but its used less than 5% of times.

The final resort is over serial and only advanced users have shown willingness to go down this route. We looked into creating a desktop App for this but gave up after the new Windows 10 signed driver restrictions. We also don’t have any expertise developing for Mac and it didn’t make sense to develop just for PC. If we do revisit this effort, does anyone know if you can package Particle Drivers with our own windows application? The ideal implementation would be to download a single .exe file from our website and install it to configure the device to wifi. An example is the DJI Assistant for windows.

Anyway, this is a hard problem and Particle has done a great job tackling new issues as they come. One of the ongoing challenges we are having, in case you folks aren’t already aware, is with mesh wifi routers, like Google wifi. These routers beam both 2.4GHz and 5GHz channels with the same name and this causes our device to not connect at all. On the Google Wifi, there is no way to assign different channel names - its a much asked feature and Google is still working on it. Not a complaint, but if anyone has experienced this before, let us know.

2 Likes

Wow, what terrific feedback! It is nice to see your product out there doing well.

I’m wondering if we could (while the device is in SoftAP mode) allow a Serial message to be handled. In that case all we would have to do is ask the user to run the terminal program on a Mac (I don’t know enough about PC’s to know if this is feasible) and enter a string (SSID and Password), based on their type of Router’s security.

Maybe an AppleScript guru out there could develop something for us to pull the credentials automatically… I have to research.

I’m sure that the community could get a good share of the most common routers together for testing.

Anyone see this as a viable approach?

2 Likes

So, inserting this***:

void loop(void)
{
  if (WiFi.listening())
  {
    // In listening mode, running SoftAP
    if (const char* newMessg = checkForNewMessage(Serial, '\n'))
    {
      if (strstr(newMessg, "CLEARWIFI"))
      {
        WiFi.clearCredentials();
        delay(1000);
        System.reset();
      }
      Serial.println(newMessg);
      char message[strlen(newMessg) + 1];
      strcpy(message, newMessg);
      char SSID[33];
      strcpy(SSID, strtok(message, ":"));
      Serial.println(SSID);
      char PASSWORD[33];
      strcpy(PASSWORD, strtok(NULL, ":"));
      Serial.println(PASSWORD);
      WiFi.setCredentials(SSID, PASSWORD);
      delay(1000);
      System.reset();
    }
    wifiUp = false;
    return;
  }

into the standard SoftAP example to clear and set the wifi via Serial terminal and my mac terminal…

now trying to develop an Applescript to do this automatically.

***along with this function:

const char* checkForNewMessage(Stream& stream, const char endMarker)
{
  static char incomingMessage[MAX_MESSAGE_LENGTH] = "";
  static byte idx = 0;
  if(stream.available())
  {
    incomingMessage[idx] = stream.read();
    if(incomingMessage[idx] == endMarker)
    {
      incomingMessage[idx] = '\0';
      idx = 0;
      return incomingMessage;
    }
    else
    {
      idx++;
      if(idx > MAX_MESSAGE_LENGTH - 1)
      {
        //stream.print(F("{\"error\":\"message too long\"}\n"));  //you can send an error to sender here
        idx = 0;
        incomingMessage[idx] = '\0';
      }
    }
  }
  return nullptr;
}
2 Likes

@rahilj, with Windows 10 you don't need to supply serial drivers for the Particle devices anymore. The stock MS drivers do work fine (enough) with Particle devices.


@BulldogLowell, in reply to

This should be possible, but for completness: Only with SYSTEM_THREAD(ENABLED) to have loop() run while in Listening/SoftAP Mode

1 Like

Thanks. We built on a great platform.

@rahilj, with Windows 10 you don't need to supply serial drivers for the Particle devices anymore. The stock MS drivers do work fine (enough) with Particle devices

Ah, that's correct. I forgot thats not the case anymore. Is the MS driver behavior dependent on the firmware version? Our last reel of P1 chips has 0.49 firmware version.

That's possible - depending to the VID/PID used. But since you'll flash your own firmware anyway you'll be updating the system at the same time, or not?

we hacked together a quick applescript that (for now during our testing) worked for us:

tell application "Terminal"
	quit
end tell

tell application "System Preferences"
	quit
end tell


set voice to (display dialog "Would you like to uses Voice Asist?" with title "TITLE!" buttons {"yes", "no"} default button 1)
set usingVoiceAssist to button returned of voice

if usingVoiceAssist is equal to "yes" then
	set volume output volume 50 -- percent
end if

tell application "System Preferences"
	activate
	set current pane to pane id "com.apple.preference.network"
	--click button "Advanced..." of window "Network"
end tell

if usingVoiceAssist is equal to "yes" then
	say "Please look at your Network Settings to determine your Why Fy Network Name, also called S S I D"
end if

delay 5

if usingVoiceAssist is equal to "yes" then
	say "Now Click Advanced and determine what type of security your why fy is using. You may have double U eee pee, double U pee A or double U pee A 2"
end if

delay 5

if usingVoiceAssist is equal to "yes" then
	say "Now press OK and then Close the System Preferences Window"
end if

if usingVoiceAssist is equal to "yes" then
	say "Now select your wifi security type"
end if

set wifiSelected to display dialog "Select your WiFi Type, (WPA2 is most common)" with title "TITLE!" buttons {"WPA2/WPA2 Personal", "WPA", "WEP"}
set WiFiType to button returned of wifiSelected

if usingVoiceAssist is equal to "yes" then
	say "Now enter your Why Fy ess ess eye dee"
end if

set WifiSSID to text returned of (display dialog "WiFi SSID:" with title "TITLE!" default answer "" buttons {"Cancel", "next"} default button 2)

if usingVoiceAssist is equal to "yes" then
	say "Now Enter your Why Fy password"
end if

if WiFiType is equal to "WEP" then
	set numBytes to 0
	repeat while ((numBytes is not equal to 5) and (numBytes is not equal to 11))
		set WiFiPassword to text returned of (display dialog "WiFi Password:" with title "TITLE!" default answer "" buttons {"Cancel", "next"} default button 2)
		log WiFiPassword
		set numBytes to (length of WiFiPassword) / 2
	end repeat
	if usingVoiceAssist is equal to "yes" then
		say "Since your why fy is W E P, you have to enter a why fy key position, it is usually position one, but you may have to try others if that position fails"
	end if
	set optionList to {"01", "02", "03", "04"}
	set keySelection to choose from list optionList with prompt "Select Key Position (usually 01)" default items "01"
	set keyPosition to (keySelection as integer) - 1
	log keyPosition
else
	set WiFiPassword to text returned of (display dialog "WiFi Password:" with title "TITLE!" default answer "" buttons {"Cancel", "next"} default button 2)
end if

if usingVoiceAssist is equal to "yes" then
	say "Please look at the Terminal and identify your device USB modem eye dee, then enter that eye dee into the window that pops up"
end if

tell application "Terminal"
	activate
	delay 5
end tell
tell application "System Events"
	keystroke "ls /dev/tty.usbmodem*"
	keystroke return
end tell
set ttyAddress to text returned of (display dialog "Enter the complete TTY address as seen in the terminal window (i.e. /dev/tty.usbmodem1411)" with title "TITLE!" default answer "/dev/tty.usbmodem" buttons {"Cancel", "next"} default button 2)
tell application "Terminal"
	activate
	delay 3
end tell
tell application "System Events"
	keystroke "screen "
	keystroke ttyAddress
	keystroke return
	delay 3
	if WiFiType is equal to "WEP" then
		keystroke WifiSSID
		keystroke ":0"
		keystroke keyPosition
		if numBytes is equal to 5 then
			keystroke "05"
		else if numBytes is equal to 11 then
			keystroke "0D"
		end if
		
		keystroke WiFiPassword
		keystroke ":WEP:"
	else if WiFiType = "WPA" then
		keystroke WifiSSID
		keystroke ":"
		keystroke WiFiPassword
		keystroke ":WPA:"
	else
		keystroke WifiSSID
		keystroke ":"
		keystroke WiFiPassword
		keystroke ":"
	end if
	keystroke return
end tell

tell application "Terminal"
	quit
end tell

if usingVoiceAssist is equal to "yes" then
	say "After a few moments, your device's L E D should be breathing a cyan color, your setup is now complete"
end if

with this revision to the SoftAP code:

void loop(void)
{
  if (WiFi.listening())
  {
    // In listening mode, running SoftAP
    if (const char* newMessg = checkForNewMessage(Serial, '\r'))
    {
      Serial.println(newMessg);
      if (strstr(newMessg, "CLEARWIFI"))
      {
        WiFi.clearCredentials();
        delay(1000);
        System.reset();
      }
      enum{
        WPA2,
        WEP,
        WPA,
      } wifiSetup = WPA2;
      if(strstr(newMessg, "WEP"))
      {
        wifiSetup = WEP;
      }
      else if(strstr(newMessg, "WPA"))
      {
        wifiSetup = WPA;
      }
      char message[strlen(newMessg) + 1];
      strcpy(message, newMessg);
      char SSID[33];
      strcpy(SSID, strtok(message, ":"));
      Serial.println(SSID);
      char PASSWORD[33];
      strcpy(PASSWORD, strtok(NULL, ":"));
      Serial.println(PASSWORD);
      switch(wifiSetup)
      {
        case WPA2:
          WiFi.setCredentials(SSID, PASSWORD);
          break;
        case WEP:
          WiFi.setCredentials(SSID, PASSWORD, WEP);
          break;
        case WPA:
          WiFi.setCredentials(SSID, PASSWORD, WPA);
          break;
      }
      delay(1000);
      System.reset();
    }
    wifiUp = false;
    return;
  }
1 Like

No, our firmware is flashed when the client first connects the device. We haven't yet implemented a way to flash the devices prior to shipping.

The script and FW changes works great! Kudos!
A very basic question (I am naive at MAC development) - is there a way for the Apple script to print out the device ID? I could try to piece it together but if you already know that could save some effort.

Thanks

I think that could be done . We could have the Particle device echo the deviceID on request via Serial. Gotta look at that.