Manage the Pairing Code

Ci sono due modi per attivare il modulo miuPanel su un nuovo smartphone.
La prima procedura, presentata nella sezione getting starded, richiede che lo smartphone sia vicino al modulo.
La seconda procedura, utilizzata in questo esempio, consente di attivare il modulo su un nuovo smartphone remoto senza la necessità che lo smartphone sia vicino al modulo durante questa procedura. In altre parole, puoi condividere il controllo del sistema collegato al modulo WiFi con un amico che si trova  dall’altra parte del mondo.

Quello che devi comunicare al nuovo utente affinchè possa aggiungere il modulo sulla sua App è una password, chiamata pairing code. L’app mostra la finestra per inserire il pairing code pochi secondi dopo aver cliccato sul pulsante “Add New Module”, come mostra la figura seguente:

Il pairing code viene gestito attraverso due comandi seriali inviati al modulo WiFi interessato:

Come si può leggere nella descrizione completa del comando, il comando PCODE: SET richiede due parametri: il “seed” (che diventerà la seconda parte del pairing code) ed il numero di volte in cui è possibile utilizzare quel pairing code.

Nel caso in cui si vuole abilitare e fissare un pairing code fisso per tutta la vita utile del progetto, è sufficiente inviare questi comandi al modulo una volta soltanto, in fase di progetto, senza prevedere una specifica gestione nel firmware.

Nel caso in cui si vuole gestire il pairing code del modulo successivamente alla fase di progetto, è bene pensare ad una sua gestione nel firmware  (per esempio tramite un comodo pannello grafico sull’App accessibile solo agli amministratori del sistema).
Qui proponiamo un esempio di pannello che è possibile integrare nell’applicazione per gestire il codice di associazione diretto dall’app. Il layout del pannello che proponiamo è:

Usando l’Online Panel Simulator abbiamo costruito la seguente stringa HCTML:

D!EEE;-0{!356^m%100,y8T*20:Remote Pairing Code;}{m^%100,y8!FFF#356M1:Display Log;}{%95,y5}{^{<%80,y5#666T:SEED: Enter a number of 12-Digit;|>M2#f00:;}_{E1!FFF%80,8*12fb:;}_{%95,y2}{<%80,y5T#666:N: Enter number of uses [1-100];|>M3#f00:;}_{E2!FFF%80,8*12fb:;}_{%95,y5}_{mB1%50,y6!FFF,888:SET PCODE;}}/20{%100,y1!FFF}/20{mB2%50,y6!FFF,888:GET STATUS;}/20{%100,y1!FFF}/20{mB3%50,y6!FFF,888:DISABLE PCODE;}/20{%100,y1!FFF}

Arduino UNO sketch

Copia ed incolla lo sketch per provarlo sul tuo modulo.

Poichè è il CLOUD µPanel che gestisce il pairing code, è necessario che il modulo WiFi sia connesso al cloud mentre si usano i seguente comandi PCODE:SET e PCODE:GET.

String Msg;
String seed_str = "";
String n_uses_str = "";
String str_tmp = "";     // generic string variable for temporary use
unsigned char flag_seed_ok = 0;
unsigned char flag_n_uses_ok = 0;

void setup(){
  Serial.begin(57600); // Initialise serial
  delay(5000);                
  SendPanel();        // Send The Panel calling a function
}

void loop(){
  int c;
  int int1 = 0;

  while ((c = Serial.read()) > '\n') Msg += (char) c;  // Read incoming chars, if any, until new line
  if (c == '\n'){                                      // is the message complete?    
    // -------------------------------------------
    if (Msg.substring(0, 4).equals("#E1:")){ // SEED
      seed_str = Msg.substring(4);      
      if (seed_str.length() == 12 && IsNumber(seed_str) == true){ // Check number length (must be 12 digit)  
          Serial.println(F("#M2OK"));
          flag_seed_ok = 1;
      }
      else{
          Serial.println(F("#M2Error"));
          flag_seed_ok = 0; 
      }
    }
    // -------------------------------------------
    else if (Msg.substring(0, 4).equals("#E2:")){ // NUMBER OF USES
      n_uses_str = Msg.substring(4);
      if (IsNumber(n_uses_str) == true && n_uses_str.toInt() > 0 && n_uses_str.toInt() < 1000){ 
        Serial.println(F("#M3OK"));
        flag_n_uses_ok = 1;
      }
      else{ // error seed
        Serial.println(F("#M3Error"));
        flag_n_uses_ok = 0;
      }
    }
    // -------------------------------------------
    else if (Msg.equals("#B1P")){ // Pressed "SET PCODE"
      if (flag_seed_ok == 1 && flag_n_uses_ok == 1){
        Serial.print(F("$CLOUD PCODE:SET:"));
        Serial.print(seed_str);
        Serial.write(':');
        Serial.println(n_uses_str);
      }
    }
    // -------------------------------------------    
    else if (Msg.equals("#B2P")) // Pressed "GET STATUS"
    {
      Serial.println(F("$CLOUD PCODE:GET:"));
    }
    // -------------------------------------------    
    else if (Msg.equals("#B3P")){ // Pressed "GET STATUS"
      Serial.println(F("$CLOUD PCODE:SET:")); // Disable code
    }
    // -------------------------------------------    
    else if (Msg.substring(0, 17).equals("$CLOUD:PCODE-SET:")){ // Reply from cloud
      int1 = Msg.indexOf("(Pairing-Pin"); 
      if (int1 >= 0){ // String found
        Serial.print("#M1");
        Serial.println(Msg.substring(int1)); 
      }  
      else{
        Serial.println("#M1CLOUD:PCODE-SET: -Unknown Reply-");
      }   
    }
    // -------------------------------------------    
    else if (Msg.substring(0, 17).equals("$CLOUD:PCODE-GET:")){ // Reply from cloud
      if (Msg.substring(17) == "::0:0"){
       Serial.println("#M1 None pairing code"); 
      }
      else{
        //Serial.print("#M1");
        //Serial.println(Msg);

        Serial.print("#M1Status: ACTIVE --- Num. valid uses: ");

        int start_i = Msg.indexOf(':', 29); 
        int stop_i = Msg.indexOf(':', 30);        
        Serial.print(Msg.substring(start_i +1, stop_i));

        Serial.print(" --- Errors: ");       
        start_i = Msg.indexOf(':',stop_i);       
        Serial.println(Msg.substring(start_i +1));
      }
    }
    // -------------------------------------------
    // WiFi Module unwanted RESET >>>>> send panel again
    else if (Msg.equals("$ERR-CLOUD")){
      Serial.println("#M1ERROR CLOUD: Connect via CLOUD!");
    }    
    // -------------------------------------------
    // WiFi Module unwanted RESET >>>>> send panel again
    else if (Msg.equals("$RES")){
      SendPanel();
    }
    Msg = "";
  }
} // END Loop
//----------------------------------------------------------------
//---------------------------  FUNCTIONS -------------------------
//----------------------------------------------------------------
void SendPanel(void){

  // Discharge old partial messages and send panel
  Serial.println("");

  //Send Panel slit in more serial print
  Serial.print  (F("$P:D!EEE;-0{!356^m%100,y8T*20:Remote Pairing Code;}{m^%100,y8!FFF#356M1:;}{%95,y5}"));
  Serial.print  (F("{^{<%80,y5#666T:SEED: Enter a number of 12-Digit;|>M2#f00:;}_{E1!FFF%80,8*12fb:;}_{%95,y2}"));
  Serial.print  (F("{<%80,y5T#666:N: Enter number of uses [1-100];|>M3#f00:;}_{E2!FFF%80,8*12fb:;}_{%95,y5}_"));
  Serial.print  (F("{mB1%50,y6!FFF,888:SET PCODE;}}/20{%100,y1!FFF}/20{mB2%50,y6!FFF,888:GET STATUS;}/20{%100,y1!FFF}"));
  Serial.println(F("/20{mB3%50,y6!FFF,888:DISABLE PCODE;}/20{%100,y1!FFF}"));
}
//----------------------------------------------------------------

// Check if a string contains a number

boolean IsNumber(String str){
  boolean result = true;
  int str_length = str.length();   
   for(int i=0; i <str_length;  i++)
   {
      if(!isDigit(str.charAt(i))) result = false;
   }
   return result;
}