Discussion Forums

Using iOS/Android App to setup WiFi on a New DUO

#1

@guohui Two Questions (related)
Question #1:
The on-line get-started out of the box experience seems to indicate that an Android version for setting up an out of the box DUO with a new SSID and Password is still in the works.
Please update if it is already released? If not when?

Question #2:
If I want to use BLE to setup WiFi Credentials (using the WiFi.setCred…)
the application code stalls running BLE until it can find WiFi that has been pre-programmed.
For example
(a) I setup DUO with WiFi as SSID: myWiFi, Password: My Password,
(b) then take the DUO to a physically different location where myWiFi is no longer available, but a different WiFi such as SSID: CoffeeShopWiFi
Password: Coffee,
© On powering up DUO at new location CoffeeShopWiFi, the LED blinks green searching for WiFi and the rest of the code does not proceed. This happens even if I set the system to MANUAL.
So the question #2:
If I need to use the DUO in a product with my developed firmware, how do I get the user to update the product with an APP (Android) to access and set the DUO’s WiFi via BLE? ( I cannot ask the end user to press the setup and reset buttons and hold them till white blink etc etc – as the DUO would be inside an enclosure).

#2

Yes please guohui, when will Android version be ready?

#3
  1. We try our best to release the Android version within this month.

  2. [quote=“hk101, post:1, topic:1188”]
    On powering up DUO at new location CoffeeShopWiFi, the LED blinks green searching for WiFi and the rest of the code does not proceed. This happens even if I set the system to MANUAL.
    [/quote]

Did you mean the Duo keep trying to connect to AP even if after you setting the SYSTEM_MODE(MANUAL); in your sketch and uploading it to the Duo? Could you post the sketch or code snip of it?

You can implement a BLE service for setting WiFi credentials in your sketch.

#4

This example BLE2WiFi.ino
tests the DUO’s capability to
connect to the WiFi.

/*
 * Copyright (c) 2016 RedBear
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
 * IN THE SOFTWARE.
 */
 
/*
 * Download RedBear "BLE Controller" APP from APP store(IOS)/Play Store(Android) to play with this sketch
 */
 
/******************************************************
 *                      Macros
 ******************************************************/
/*
 * SYSTEM_MODE:
 *     - AUTOMATIC: Automatically try to connect to Wi-Fi and the Particle Cloud and handle the cloud messages.
 *     - SEMI_AUTOMATIC: Manually connect to Wi-Fi and the Particle Cloud, but automatically handle the cloud messages.
 *     - MANUAL: Manually connect to Wi-Fi and the Particle Cloud and handle the cloud messages.
 *     
 * SYSTEM_MODE(AUTOMATIC) does not need to be called, because it is the default state. 
 * However the user can invoke this method to make the mode explicit.
 * Learn more about system modes: https://docs.particle.io/reference/firmware/photon/#system-modes .
 */

#include "Arduino.h"
#include "spark_wiring_wifi.h"
#include "spark_wiring_client.h"
 
#if defined(ARDUINO) 
SYSTEM_MODE(MANUAL); 
#endif


/* 
 * BLE peripheral preferred connection parameters:
 *     - Minimum connection interval = MIN_CONN_INTERVAL * 1.25 ms, where MIN_CONN_INTERVAL ranges from 0x0006 to 0x0C80
 *     - Maximum connection interval = MAX_CONN_INTERVAL * 1.25 ms,  where MAX_CONN_INTERVAL ranges from 0x0006 to 0x0C80
 *     - The SLAVE_LATENCY ranges from 0x0000 to 0x03E8
 *     - Connection supervision timeout = CONN_SUPERVISION_TIMEOUT * 10 ms, where CONN_SUPERVISION_TIMEOUT ranges from 0x000A to 0x0C80
 */
#define MIN_CONN_INTERVAL          0x0028 // 50ms.
#define MAX_CONN_INTERVAL          0x0190 // 500ms.
#define SLAVE_LATENCY              0x0000 // No slave latency.
#define CONN_SUPERVISION_TIMEOUT   0x03E8 // 10s.

// Learn about appearance: http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
#define BLE_PERIPHERAL_APPEARANCE  BLE_APPEARANCE_UNKNOWN

#define BLE_DEVICE_NAME            "Simple Chat"

#define CHARACTERISTIC1_MAX_LEN    20
#define CHARACTERISTIC2_MAX_LEN    20
#define TXRX_BUF_LEN               20

/******************************************************
 *               Variable Definitions
 ******************************************************/
static uint8_t service1_uuid[16]    = { 0x71,0x3d,0x00,0x00,0x50,0x3e,0x4c,0x75,0xba,0x94,0x31,0x48,0xf1,0x8d,0x94,0x1e };
static uint8_t service1_tx_uuid[16] = { 0x71,0x3d,0x00,0x03,0x50,0x3e,0x4c,0x75,0xba,0x94,0x31,0x48,0xf1,0x8d,0x94,0x1e };
static uint8_t service1_rx_uuid[16] = { 0x71,0x3d,0x00,0x02,0x50,0x3e,0x4c,0x75,0xba,0x94,0x31,0x48,0xf1,0x8d,0x94,0x1e };

// GAP and GATT characteristics value
static uint8_t  appearance[2] = { 
  LOW_BYTE(BLE_PERIPHERAL_APPEARANCE), 
  HIGH_BYTE(BLE_PERIPHERAL_APPEARANCE) 
};

static uint8_t  change[4] = {
  0x00, 0x00, 0xFF, 0xFF
};

static uint8_t  conn_param[8] = {
  LOW_BYTE(MIN_CONN_INTERVAL), HIGH_BYTE(MIN_CONN_INTERVAL), 
  LOW_BYTE(MAX_CONN_INTERVAL), HIGH_BYTE(MAX_CONN_INTERVAL), 
  LOW_BYTE(SLAVE_LATENCY), HIGH_BYTE(SLAVE_LATENCY), 
  LOW_BYTE(CONN_SUPERVISION_TIMEOUT), HIGH_BYTE(CONN_SUPERVISION_TIMEOUT)
};

/* 
 * BLE peripheral advertising parameters:
 *     - advertising_interval_min: [0x0020, 0x4000], default: 0x0800, unit: 0.625 msec
 *     - advertising_interval_max: [0x0020, 0x4000], default: 0x0800, unit: 0.625 msec
 *     - advertising_type: 
 *           BLE_GAP_ADV_TYPE_ADV_IND 
 *           BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 
 *           BLE_GAP_ADV_TYPE_ADV_SCAN_IND 
 *           BLE_GAP_ADV_TYPE_ADV_NONCONN_IND
 *     - own_address_type: 
 *           BLE_GAP_ADDR_TYPE_PUBLIC 
 *           BLE_GAP_ADDR_TYPE_RANDOM
 *     - advertising_channel_map: 
 *           BLE_GAP_ADV_CHANNEL_MAP_37 
 *           BLE_GAP_ADV_CHANNEL_MAP_38 
 *           BLE_GAP_ADV_CHANNEL_MAP_39 
 *           BLE_GAP_ADV_CHANNEL_MAP_ALL
 *     - filter policies: 
 *           BLE_GAP_ADV_FP_ANY 
 *           BLE_GAP_ADV_FP_FILTER_SCANREQ 
 *           BLE_GAP_ADV_FP_FILTER_CONNREQ 
 *           BLE_GAP_ADV_FP_FILTER_BOTH
 *     
 * Note:  If the advertising_type is set to BLE_GAP_ADV_TYPE_ADV_SCAN_IND or BLE_GAP_ADV_TYPE_ADV_NONCONN_IND, 
 *        the advertising_interval_min and advertising_interval_max should not be set to less than 0x00A0.
 */
static advParams_t adv_params = {
  .adv_int_min   = 0x0030,
  .adv_int_max   = 0x0030,
  .adv_type      = BLE_GAP_ADV_TYPE_ADV_IND,
  .dir_addr_type = BLE_GAP_ADDR_TYPE_PUBLIC,
  .dir_addr      = {0,0,0,0,0,0},
  .channel_map   = BLE_GAP_ADV_CHANNEL_MAP_ALL,
  .filter_policy = BLE_GAP_ADV_FP_ANY
};

static uint8_t adv_data[] = {
  0x02,
  BLE_GAP_AD_TYPE_FLAGS,
  BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE,
  
  0x08,
  BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME,
  'D','U','O','2','W','i','F',
  
  0x11,
  BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
  0x1e,0x94,0x8d,0xf1,0x48,0x31,0x94,0xba,0x75,0x4c,0x3e,0x50,0x00,0x00,0x3d,0x71
};

static uint16_t character1_handle = 0x0000;
static uint16_t character2_handle = 0x0000;
static uint16_t character3_handle = 0x0000;

static uint8_t BLEin[CHARACTERISTIC1_MAX_LEN] = { 0x01 };
static uint8_t characteristic2_data[CHARACTERISTIC2_MAX_LEN] = { 0x00 };

//static btstack_timer_source_t characteristic2;

char rx_buf[TXRX_BUF_LEN];
static uint8_t rx_buf_num;
static uint8_t rx_state = 0;

static boolean New_BLE2WiFi_SSID_Recd = false;
static boolean New_BLE2WiFi_PWD_Recd = false;
static boolean New_BLE2WiFi_Creds_Recd = false;
int led=D7;
char BLESSID[CHARACTERISTIC1_MAX_LEN] = { 0x00 };
char BLEPWD[CHARACTERISTIC1_MAX_LEN] = { 0x00 };

// your network name also called SSID
String ssid = "";
// your network password (key)
String password = "";

/******************************************************
 *               Function Definitions
 ******************************************************/
void deviceConnectedCallback(BLEStatus_t status, uint16_t handle) {
  switch (status) {
    case BLE_STATUS_OK:
      Serial.println("Device connected!");
      break;
    default: break;
  }
}

void deviceDisconnectedCallback(uint16_t handle){
  Serial.println("Disconnected.");
}

int gattWriteCallback(uint16_t value_handle, uint8_t *buffer, uint16_t size) {
  uint8_t index = 0;
  char input[20];
  int inpsize =0;
  for (int i = 0;i<20;i++) { input[i] = 0; }
  inpsize = min(size,CHARACTERISTIC1_MAX_LEN); 
  memcpy(BLEin, buffer, inpsize);
  if (character1_handle == value_handle) {
    memcpy(BLEin, buffer, inpsize);
    Serial.print("Received BLEmsg: "); 
    for (uint8_t index = 0; index < inpsize; index++) {
      Serial.print((char)BLEin[index]);
    }
    Serial.print(" size: ");
    Serial.print(inpsize);
    Serial.println(" ");
    // Enter the string "SS you_rssid" on Android App, note the space between SS and your_ssid
    if ((BLEin[0]=='S')&&(BLEin[1]=='S'))  {
        // record SSID starting at index = 0
        for (index = 0; index < inpsize-3; index++) {
          input[index] = BLEin[index+3];
        }
        ssid = input;
        //Serial.print("BLE SSID:[");
        //Serial.print(ssid);
        //Serial.println("]");
        for (int i = 0;i<20;i++) { input[i] = 0; }
        New_BLE2WiFi_SSID_Recd = true;
    }
    // Enter the string "PS your_password" : Note the third char is space
    if ((BLEin[0]=='P')&&(BLEin[1]=='W')) {
        // record Passwd starting at index 0
        for (index = 0; index < inpsize-3; index++) {
          input[index] = BLEin[index+3];
        }
        password=input;
        //Serial.print("BLE PSWD:[");
        //Serial.print(password);
        //Serial.println("]");
        New_BLE2WiFi_PWD_Recd = true; // assume SSID has been received before
        for (int i = 0;i<20;i++) { input[i] = 0; }
    }
    // no need for multiple booleans , but SSID and PWD may be input out of order
    if( New_BLE2WiFi_SSID_Recd  && New_BLE2WiFi_PWD_Recd ) {
      New_BLE2WiFi_SSID_Recd = false;
      New_BLE2WiFi_PWD_Recd = false;
      New_BLE2WiFi_Creds_Recd = true;
    }
    // Clear out received buffer
    for(uint8_t k=0;k<CHARACTERISTIC1_MAX_LEN;k++) {
       buffer[k]='\0';
    }
  }
  return 0;
}
/*
void m_uart_rx_handle() {   //update characteristic data
  ble.sendNotify(character2_handle, rx_buf, CHARACTERISTIC2_MAX_LEN);
  memset(rx_buf, 0x00,20);
  rx_state = 0;
}
*/
static void  characteristic2_notify(btstack_timer_source_t *ts) {   
  if (Serial.available()) {
    //read the serial command into a buffer
    uint8_t rx_len = min(Serial.available(), CHARACTERISTIC2_MAX_LEN);
    Serial.readBytes(rx_buf, rx_len);
    //send the serial command to the server
    Serial.print("Sent: ");
    Serial.println(rx_buf);
    rx_state = 1;
  }
  if (rx_state != 0) {
    //Serial.print("Sending");
    //Serial.println(rx_buf);
    ble.sendNotify(character2_handle, (uint8_t*)rx_buf, CHARACTERISTIC2_MAX_LEN);
    memset(rx_buf, 0x00, 20);
    rx_state = 0;
  }
  // reset
  //ble.setTimer(ts, 200);
  //ble.addTimer(ts);
}

void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("Network Name: ");
Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

void TurnONWiFi() {
    WiFi.disconnect();
    WiFi.off();
    WiFi.clearCredentials(); delay(100);
    Serial.println("Cleared WiFi Credentials");
    Serial.print("Will connect to: ");
    Serial.print(ssid);
    Serial.print(" ");
    Serial.println(password); 
    WiFi.on(); delay(1000);
    WiFi.setCredentials(ssid,password);
    WiFi.connect(); 
    delay(2000);Serial.println("Connecting to WiFi");
    //Serial.print("Waiting for WiFi");delay(5000);
    while (WiFi.connecting()) {
      // print dots while we wait to connect
      Serial.print(".");
      delay(300);
    }
    Serial.println("\nYou're connected to the network");
    Serial.println("Waiting for an ip address");
    IPAddress localIP = WiFi.localIP();
    while (localIP[0] == 0) {
      localIP = WiFi.localIP();
      Serial.println("waiting for an IP address");
      delay(1000);
  }
    while(!WiFi.ready()) delay(1000);
    // Reset ssid and pwd for next BLE msg to give new ssid & pwd 
    ssid = ""; 
    password = "";
    // Print what is the current ssid and ip and rssi
    printWifiStatus();  
}

void WiFiOnCheckCreds() {
    WiFi.on(); 
    WiFi.connect(); 
    delay(2000);Serial.println("Connecting to WiFi");
    while (WiFi.connecting()) {
      // print dots while we wait to connect
      Serial.print(".");
      delay(300);
    }
    Serial.println("\nYou're connected to the network");
    Serial.println("Waiting for an ip address");
    IPAddress localIP = WiFi.localIP();
    while (localIP[0] == 0) {
      localIP = WiFi.localIP();
      Serial.println("waiting for an IP address");
      delay(1000);
    }
    while(!WiFi.ready()) delay(1000);
    printWifiStatus(); 
}

void BLE_setup() {
  
  // Register BLE callback functions
  ble.onConnectedCallback(deviceConnectedCallback);
  ble.onDisconnectedCallback(deviceDisconnectedCallback);
  ble.onDataWriteCallback(gattWriteCallback);

  // Add GAP service and characteristics
  ble.addService(BLE_UUID_GAP);
  ble.addCharacteristic(BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME, ATT_PROPERTY_READ|ATT_PROPERTY_WRITE, (uint8_t*)BLE_DEVICE_NAME, sizeof(BLE_DEVICE_NAME));
  ble.addCharacteristic(BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE, ATT_PROPERTY_READ, appearance, sizeof(appearance));
  ble.addCharacteristic(BLE_UUID_GAP_CHARACTERISTIC_PPCP, ATT_PROPERTY_READ, conn_param, sizeof(conn_param));

  // Add GATT service and characteristics
  ble.addService(BLE_UUID_GATT);
  ble.addCharacteristic(BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED, ATT_PROPERTY_INDICATE, change, sizeof(change));

  // Add user defined service and characteristics
  ble.addService(service1_uuid);
  character1_handle = ble.addCharacteristicDynamic(service1_tx_uuid, ATT_PROPERTY_NOTIFY|ATT_PROPERTY_WRITE|ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, BLEin, CHARACTERISTIC1_MAX_LEN);
  character2_handle = ble.addCharacteristicDynamic(service1_rx_uuid, ATT_PROPERTY_NOTIFY, characteristic2_data, CHARACTERISTIC2_MAX_LEN);

  // Set BLE advertising parameters
  ble.setAdvertisementParams(&adv_params);

  // // Set BLE advertising data
  ble.setAdvertisementData(sizeof(adv_data), adv_data);

  // BLE peripheral starts advertising now.
  ble.startAdvertising();

  // set one-shot timer
  //characteristic2.process = &characteristic2_notify;
  //ble.setTimer(&characteristic2, 500);//100ms
  //ble.addTimer(&characteristic2);
}

void setup() {
  Serial.begin(115200);
  delay(3000);
  ssid = "";
  password = "";
  Serial.println("Using BLE to Setup WiFi.");
  ble.init();
  BLE_setup();
  Serial.println("BLE start advertising.");
}

void loop() {
  int n = 0;
  int cmdsz =0;
  if (Serial.available()) {
    //read the serial command into a buffer
    uint8_t rx_len = min(Serial.available(), CHARACTERISTIC2_MAX_LEN);
    Serial.readBytes(rx_buf, rx_len);
    //send the serial command to the server
    Serial.print("Sent: ");
    Serial.println(rx_buf);
    ble.sendNotify(character2_handle, (uint8_t*)rx_buf, CHARACTERISTIC2_MAX_LEN);
    memset(rx_buf, 0x00, 20);
  }
  if (New_BLE2WiFi_Creds_Recd) {
           Serial.print("New WiFi Credentials recd: ");
           Serial.print("[");
           Serial.print(ssid); 
           Serial.print(",");
           Serial.print(password); 
           Serial.println("]");
           TurnONWiFi();
           New_BLE2WiFi_Creds_Recd = false; // Reset BLE message 
 } else if ((BLEin[0]=='W') && (BLEin[1]=='N')) { // What is current WiFi Network?
          Serial.println("Turning On WiFi and check for ip ");
          // If not connected try to re-connect before printin status 
          WiFiOnCheckCreds();
          BLEin[0] = '\0'; BLEin[1]='\0';
 } else if ((BLEin[0]=='W') && (BLEin[1]=='S')) { // What is current WiFi Status?
          Serial.println("Examining WiFi Status:"); 
          // Just print status 
          printWifiStatus();
          BLEin[0] = '\0'; BLEin[1]='\0';
 }
} // loop

The setup is a DUO connected to
the PC via USB and the arduino IDE
with the Arduino Serial Monitor.

(My WiFi ssid and password temporarily
changed to illustrate the use cases)

The Simple Chat app on Android is used
as follows:

Send two char commands from simple chat
with optional command line arguments:

WS => Print current WiFi status

WN => Connect to WiFi & print Status

SS your_ssid => Store WiFi SSID
(Complete message should be less than
20 chars including the SS and space
after SS)

PW your_password => store WiFi password
and connect to the WiFi network.

Running the BLE2WiF.ino on DUO,


Test 1: Blank DUO
Set+Reset-> White, Then power off by
removing USB, power back on, blinking blue
then load compile app via USB

Below are Serial Monitor output

BLE start advertising.
Device connected!
Received BLEmsg: WS
size: 4
Examining WiFi Status:
Network Name:
IP Address: 0.0.0.0
signal strength (RSSI):0 dBm
Received BLEmsg: WN
size: 4
Turning On WiFi and check for ip
Disconnected.

Comments for above results:
Because this was a blank DUO, i.e.
no WiFi previously stored, The DUO went
into a “search” for WiFi
Blue LED blink approx 1 sec blink.

Once the command WN is sent from
chat to DUO, the “Disconnected”
is printed and the BLE is no longer
active.
\\\\\Question\\\\\
Why should the BLE be turned OFF
if there is no WiFi?
////////////////////////////


Test 2: Blank DUO, but load WiFi
credentials via terminal (“W”)

SSID: hkguest
Security 0=unsecured, 1=WEP, 2=WPA, 3=WPA2: 3
Password: WelcomeAll
Thanks! Wait while I save those credentials…

Awesome. Now we’ll connect!

If you see a pulsing cyan light, your device
has connected to the Cloud and is ready to go!

If your LED flashes red or you encounter any other problems,
visit https://www.particle.io/support to debug.

Particle <3 you!

===========================
Below are Serial Monitor output

BLE start advertising.
Device connected!
Received BLEmsg: WS
size: 4
Examining WiFi Status:
Network Name:
IP Address: 0.0.0.0
signal strength (RSSI):0 dBm
Received BLEmsg: WN
size: 4
Turning On WiFi and check for ip
Connecting to WiFi

You’re connected to the network
Waiting for an ip address
Network Name: hkguest
IP Address: 192.168.1.68
signal strength (RSSI):-56 dBm
Received BLEmsg: SS hkatt
size: 10
Received BLEmsg: PW WonderfulDay
size: 17
New WiFi Credentials recd: [hkatt
,WonderfulDay
]
Cleared WiFi Credentials
Will connect to: hkatt
WonderfulDay

Disconnected.


Comments for above results:
Once again, the command WS
shows no-connect because the system
is in MANUAL mode.
Then the command WN connects to a WiFi
network that has been previously stored
in the DUO
Following that I send the “SS hkatt”
which is registered internal to the DUO,
and the “PW WonderfulDaY” as ssid and password.

The app code goes through and echos the
ssid and password, and fails to connect.

Initially I thought it was due to a “NULL”
char in the ssid and password, but the behaviour
is same regardless of termination of ssid
and password strings.

And again BLE stops responding at “Disconnected”.
\\\\\Question\\\\\
Why should the BLE disconnect
if DUO is searching for WiFi?
///////////////////////////

#5

Hi @hk101,

You would reach the truth after reading this guide: https://github.com/redbear/Duo/blob/master/docs/listening_mode_setup_protocol.md

Please pay attention to the Note paragraph. :wink:

#6

Hi @guohui,

Thanks for the information. You indicate that the Note gives more information:
------------------------------------ Note Begin ----------------
"Note : When the Duo is in the Listening Mode, if multithreading is not used, neither the system event loop running backstage nor user application will continue, untill exiting from the Listening Mode. If multithreading is enabled, the system event loop running backstage will be blocked untill exiting from the Listening Mode, while the user application executes as usual. But in the case that user application has implemented the BLE functionality and multithreading is enbaled, since the Duo will de-init and re-init the BLE functionality in the Listening Mode, the BLE functionality implemented by user application won’t work any more, even that it might make the BLE functionality in the Listening Mode broken.

To exit Listening Mode, one of the following conditions must be satisfied:

  1. WiFi credentials is configured via using USB serial.

  2. “Connect to AP” command is received via WiFi or BLE

  3. “Finish Firmware Update” command is recieved via WiFi (Duo only)

  4. WiFi.listen(false) is called in user application only if multithreading is enabled"
    --------------------------------------------Note End

First: I have not yet tested the multithreading as the note says, but I want your feedback, before I put in more time. Hope you can help.

The indication in the note is that even if I turn on the multi threading, the “Duo will de-init and re-init the BLE” and "user application won’t work ".

Of the conditions to be met , #1 and #3 are not available to the end user, so cannot be used. #4 can be included in the code ( I have not yet tried)

But how to implement #2 via BLE, if the BLE “wont work” as the note says.

Can you please post a code snippet that I can use?

Much appreciated, thank you

#7

No matter multithreading is used or not, the DUo will deinit and reinit the BLE data base and HCI when entering the Listening Mode. If multithreading is not used, then the user application is totally blocked and we don’t worry about that the BLE functionality in user application if implemented will corrupt the BLE functionality in the Listening Mode. While if multithreading is used, user application keep going and if BLE functionality is implemented, some BLE APIs invoked in user application would put the HCI in a wrong state, which might corrupt the BLE functionality in the Listening Mode.

Not “won’t work”, “might not work” instead. It depends on the BLE APIs you invoke in application if multithreading is used. The BLE callbacks in user application won’t work since they are overridden by Listening Mode, so don’t worry about them. Only the proactive BLE APIs might put the database and HCI in a wrong state.

What kind of code snippet do you want? App side or the Duo side? BTW, you should dig deep in that guide and you’ll see the format of the “Connect to AP” command via WiFi and BLE.

Cheers!

#8

@guohui.
OK. “might not work” is still not a good product strategy. For example
Redbear DUO “might not work” but still pay me $25 for the DUO – who will buy?
Sorry I do not mean to be rude, but just pointing out that “might not work”
is not acceptable.

“What kind of code snippet do you want?”
In my posted code above, how do I invoke multithreading (Yes, I will
dig deep in the guide, but…) if you have a couple lines of code that will
invoke multi threading ?
In my code above, will the BLE inputs to ssid and password work if I just
invoke multithreading? How to be certain, once the product has shipped to the end user?

Thank you for the help

#9

The system firmware is under developing, any new features would be improved by fixing bugs and applying patches.

Please refer to this guide: https://docs.particle.io/reference/firmware/photon/#system-thread.

Of course it will, as the multithreading won’t impact the BLE functionality.