Paso 6: código:
Abajo está el código de Arduino (también se puede descargar el mismo archivo)
Prestar atención al uso intensivo de la cadena en este programa. Me enfrenté a muchos problemas porque si esta ya podríamos resolver par de ellos con las siguientes observaciones:
- Utilice la función 'String.reserve()' de la memoria dinámica para la instancia de string, esto permite mejor manipulación en las asignaciones de memoria en el montón. Pero todavía no es suficiente, no garantiza nada.
- Uso de la macro 'F()': que permite el almacenamiento de cadenas en memoria flash en lugar de RAM. Funciona sólo con cadenas estáticas dentro de las operaciones de impresión/println. Esto es muy útil pero no suficiente (no funciona con cuerdas dinámicas)
- disminuir el número de cuerdas reservados: no pide encontrar hasta 10 dispositivos, si esto no es realmente lo que quieres,. 3 sería suficiente por ejemplo.
El problema que el programa ejecutar y cargar en cualquier caso, que funcionará de forma inesperada, respondiendo a las diferentes consultas que la escribió y no mostrar algunas cadenas y cosas así.
La manera de resolverlo es usar arrays char (o char *) en lugar de cadenas. Este es mi siguiente paso pero ahora no tengo tiempo para hacerlo ;)
/* * AT_AT_mode.ino - a wizard for HC-05 bluetooth modules * Copyright (c) 2016 Rami Baddour. All right reserved. * http://ramibaddour.com/ https://ch.linkedin.com/in/ramibaddour * * A program to view, set, modify and use the HC-05 bluetooth with an interactive textural menus * over serial monitore * * You can include parts of the code that does specific functionality (e.g. search for devices) * to your own program * * Note that this code uses intensively the String class, which has some unpredictable behaviour * when virtual memory is not possible to researve. IT is tested to work perfectly when restricting * number of recorded searched devices to 3. above this can have some problems with displyed strings. * * Newer version will use char arrays instead, hopefully with better stability. * * */ #include SoftwareSerial mySerial(5, 4);// RX, TX where the HC-05 is connected #define pinRe 3 // the Reset pin, connected to HC-05 pin No. 11 #define pinEn 6 // the Enable pin, connected to HC-05 pin No. 34 #define INQ1 1 // Inquire Acces mode: 0-standard 1-RSSI(default) #define INQ2 100 // Maximum number of devices responce: 0-to-32000 #define INQ3 30 // Inquire timeout: 1-to-48 sec #define MAXDEV 1 // Maximum number of devices to record. #define PAIRTO "25" // Pairing timout in seconds #define MAXSTRLEN 50 // maximum buffer researved for string variables. #define ATSTART "#start" // The token string to start AT command input #define ATEND "#end" // The token string to end AT command or Operational menu input #define ATOP "#op" // The token string to start the operation menu. // column widths in character count for the discovred BT devices' list #define colW1 6 #define colW2 45 #define colW3 20 #define colW4 7 int8_t currIn = -1; // The current input, records the user selection and used within the program state machine int8_t currSt = -1; // the current state, defines the current status in regards to the menu selections int8_t deviceCount = 0; // the Reset pin, connected to HC-05 pin No. 13 int devCount = 0; // how many devices in total have been discovered in the last device inquiry int devLoc = 0; // the location of the selected device within the list of discovered devices. String serialStr, tmpName, tmpRes; //some string variables to be used later //define a data structure for each descovered device. It inlcudes basic information like the name, address, RRSI and Service class typedef struct inqDevices{ String Name; String Address; String RSSI; String Class; inqDevices(int defSize=MAXSTRLEN){ Name.reserve(defSize); Name = ""; Address.reserve(20); Address = ""; RSSI.reserve(20); RSSI = ""; Class.reserve(40); Class = ""; } }inqDevice; inqDevice lstDevices[MAXDEV];
// This function takes a string of any length 'strIn' and outputs a the same string but with fixed length 'strLen' // which is a substring of the input if length(strIn)>strLen, is the same as 'strIn' with the remaining characters // filled with 'strFillChar' character. // if 'strFill' is set to true, the input string is appended to the end of the result string as well. String strFixed (String strIn, int strLen, boolean strFill = false, String strFillChar = " "){ String tmpStr1 = strIn.substring(0,strLen); int tmpLen = tmpStr1.length(); for (int i=0; i< (strLen - tmpLen); i++) tmpStr1 = tmpStr1 + strFillChar; if (strFill) tmpStr1 = tmpStr1 + strIn; return (tmpStr1); } // A function to clear the contents of the Device List array strings. void clearDeviceList(){ for (int i = 0; i
// Use the 'discardOK' setting if you want the function to discard the 'OK' result on the AT command return. // Use the 'charsToCutFrom' and 'charsToCutTo' if you want to get only a substring of the AT command return. e.g. if you want to discard // the '+INQ:' initial part in the 'AT+INQ' command responce and get directly the address and signal information of the descovered device. String getFromMySerial(String strToWrite = "", bool discardOK=true, int charsToCutFrom = 0, int charsToCutTo = 150){ if (strToWrite != "") { mySerial.println(strToWrite); delay(50); // these delays may be not necessary, it just to accomodate slow responding HC-05 modules. } String tmpStr = (mySerial.readStringUntil('\n')); tmpStr.trim(); delay(50); if (discardOK) mySerial.readStringUntil('\n'); return tmpStr.substring(charsToCutFrom, charsToCutTo); } // This function is similar to the previous 'getFromMySerial'. But this one is used when the answer // is not guarenteed after a fixed delay. e.g. if you wait to get remote BT device address or name in // discovery process. also, it is used if you are not expecting a return value at all. String getFromMySerialSimple(String strToWrite = "", int charsToCutFrom = 0, int charsToCutTo = 150){ if (strToWrite != "") { mySerial.println(strToWrite); delay(100); return ""; } else { while (!mySerial.available()){delay(10);} String tmpStr = (mySerial.readStringUntil('\n')); return tmpStr.substring(charsToCutFrom, charsToCutTo); } }
void setup() { Serial.begin(57600); mySerial.begin(38400); // default HC-05 baud rate at AT-mode Serial.print(F("to enter AT mode please type '")); Serial.print(ATSTART); Serial.print(F("', to exist type ")); Serial.print(ATEND); Serial.print(F(", or type '")); Serial.print(ATOP); Serial.println(F(" for the menu")); pinMode(pinRe, OUTPUT); pinMode(pinEn, OUTPUT); serialStr = ""; serialStr.reserve(MAXSTRLEN); tmpName.reserve(MAXSTRLEN); tmpRes.reserve(MAXSTRLEN); }
void loop(){ if (Serial.available()) { serialStr = (Serial.readStringUntil('\n')); serialStr.trim(); // Entering AT mode, you set EN pin to HIGH, and generate a 100ms negative pulse on the reset pin if (serialStr.equalsIgnoreCase(ATSTART)) { Serial.println(F(ATSTART)); Serial.println(F("You are now in AT mode, Enter AT commands:")); currIn = -1; currSt = -5; digitalWrite(pinEn,HIGH); // Set the Enable pin (no.34) to HIGH, and keep it during the AT command operation digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to HIGH, the module restarts in AT Command mode. serialStr = ""; } // Exiting AT mode into data transmission mode, you set EN pin to LOW, and generate a 100ms negative pulse on the reset pin else if (serialStr.equalsIgnoreCase(ATEND)){ currIn = -1; currSt = -1; Serial.println(F(ATEND)); Serial.println(F("You have quit AT mode.")); digitalWrite(pinEn,LOW); // Set the Enable pin (no.34) to LOW, and keep it during the data transmission mode digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to LOW, the module restarts in Data transmission mode. } // To enter the operational menu mode, you do the same as initiating AT mode, but with the state variablle state to 0 so you enable the menu state machine else if (serialStr.equalsIgnoreCase(ATOP)){ currIn = 0; currSt = 0; Serial.println(F(ATOP)); digitalWrite(pinEn,HIGH); digitalWrite(pinRe,LOW); delay(100); digitalWrite(pinRe,HIGH); } // For any other input, this is basically a selection of an item in the menu, or a command in AT mode. else{ Serial.println(serialStr); currIn = serialStr.toInt(); //any non-numerical input results in '0' } // This is when we start the AT mode , all inputs are sent to the bluetooth module. if (currSt == -5){ mySerial.println(serialStr); } } // In case of responce or input from the bluetooth module itself if (mySerial.available()){ while (mySerial.available()){ tmpName = (mySerial.readStringUntil('\n')); tmpName.trim(); Serial.println(tmpName); delay(50); }
} if (currIn >= 0){ // enter the state machine only if we get a valid input switch (currSt){ // the menu display selection case 0:{ // this is the main menu switch (currIn){ // based on the user input, selects the corresponding operation and therefore the next state case 0: Serial.println(F("----------------------------------------------------------")); Serial.println(F("Please select from the following operations:")); Serial.println(F(" 1- Display the module settings")); Serial.println(F(" 2- Modify current settings")); Serial.println(F(" 3- Reset to original settings")); Serial.println(F(" 4- Master-only operations")); Serial.println(F(" 5 -")); Serial.print(F("(Option No.) ")); currIn = -1; // we set to -1 to avoid entering into the state machine indefinately. break; case 1: currSt = 1; break; case 2: currSt = 2; currIn = 0; break; case 3: currSt = 3; break; case 4: currSt = 4; currIn = 0; break; default: Serial.println (F("not a valid input, please select from the list")); currSt = 0; currIn = 0; } break; } case 1:{ // display the module main settings. for each, send the command and wait for the result and display it Serial.println(F("----------------------------------------------------------")); Serial.println(F("The current module settings are:")); Serial.print(F(" -- Name : ")); Serial.println(getFromMySerial("AT+NAME", true, 6)); Serial.print(F(" -- Baudrate : ")); Serial.println(getFromMySerial("AT+UART", true, 6)); Serial.print(F(" -- Role : ")); if (getFromMySerial("AT+ROLE", true, 6) == "1") Serial.println(F("Master")); else Serial.println(F("Slave")); Serial.print(F(" -- Conn. Mode : ")); tmpRes = getFromMySerial("AT+CMODE", true, 6); if ( tmpRes == "0") Serial.println(F("Single remote connection")); else if ( tmpRes == "1") Serial.println(F("Any remote connection")); else Serial.println(F("Test mode")); Serial.print(F(" -- Passowrd : ")); Serial.println(getFromMySerial("AT+PSWD", true, 6)); currSt = 0; currIn = 0; break; } case 2:{ // The menu to modify the BT module settings switch (currIn){ case 0: Serial.println(F("----------------------------------------------------------")); Serial.println(F("Please select from the following operations:")); Serial.println(F(" 1- Modify the module name")); Serial.println(F(" 2- Modify UART settings")); Serial.println(F(" 3- Modify the pairing code/PW")); Serial.println(F(" 4- Switch the role (Master/Slave)")); Serial.println(F(" 5- Change connection mode")); Serial.println(F(" 6- Back...")); Serial.print(F("(Option No.) ")); currIn = -1; break; case 1: currSt = 21; currIn = 0; break; case 2: currSt = 22; currIn = 0; break; case 3: currSt = 23; currIn = 0; break; case 4: currSt = 24; currIn = 0; break; case 5: currSt = 25; currIn = 0; break; case 6: currSt = 0; currIn = 0; break; default: Serial.println (F("not a valid input, please select from the list")); currSt = 2; // stay in the same menu if wrong input is entered currIn = 0; break; } break; } case 21:{ // Modify the module's name Serial.println(F("----------------------------------------------------------")); Serial.print(F("The curent module name is : ")); Serial.println(getFromMySerial("AT+NAME", true, 6)); Serial.println(F("Please enter a new name, or leave blank to keep the current setting.")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") Serial.println(F("Name is left unchanged")); else{ tmpName = "AT+NAME=" + tmpName; tmpRes = getFromMySerial(tmpName, true); if (tmpRes == "OK") Serial.println (F("Name change successful")); else Serial.println (F("Faild to change the name, please check the name and try again")); } currSt = 2; currIn = 0; break; } case 22:{ // Modify the serial UART port settings (Baudrate, Stop bit and Parity bits) Serial.println(F("----------------------------------------------------------")); Serial.print(F("The curent UART (Baudrate) settings are : ")); tmpName = getFromMySerial("AT+UART", true, 6); String tmpBR = tmpName.substring(0,tmpName.indexOf(',')); // Baud rate String tmpSB = tmpName.substring(tmpName.indexOf(',')+1,tmpName.indexOf(',')+2);// Stop Bit String tmpPB = tmpName.substring(tmpName.indexOf(',')+3,tmpName.indexOf(',')+4);// Parity bit Serial.println(tmpName); Serial.println(F("Choose new Baudrate, or leave it blank to keep unchanged. Possible options:")); Serial.println(F("(1) 4800 (2) 9600 (3) 19200 (4) 38400 (5) 57600")); Serial.println(F("(6) 115200 (7) 234000 (8) 460800 (9) 921600 (10) 1382400")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") { Serial.print(F("Baudrate is left unchanged: ")); Serial.println(tmpBR); } else { int tmpInt = tmpName.toInt(); //Baudrate if ((tmpInt > 0)&&(tmpInt < 11)) Serial.print(F("Baudrate channged successfully, the new baudrate is: ")); switch (tmpInt) { case 1: case 2: case 3: case 4: tmpBR = String(2400 * pow(2,tmpInt),0); Serial.println(tmpBR); break; case 5: case 6: case 7: case 8: case 9: tmpBR = String(1800 * pow(2,tmpInt),0); Serial.println(tmpBR); break; case 10: tmpBR = "1382400"; Serial.println(tmpBR); break; default: Serial.println(F("Incorrect input, baudrate is left unchanged")); } } Serial.println(); // Stop Bits Serial.println(F("Choose the number of Stop bits, or leave it blank to keep unchanged. Possible options:")); Serial.println(F("(a) 0:1 bit (b) 1:2 bits")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") { Serial.print(F("Stop bit number is left unchanged: ")); Serial.println(tmpSB); } else if ((tmpName == "a")||(tmpName == "A")) { tmpSB = "0"; Serial.print(F("Stop bit number is channged successfully, the new setting is: ")); Serial.println(tmpSB); } else if ((tmpName == "b")||(tmpName == "B")) { tmpSB = "1"; Serial.print(F("Stop bit number is channged successfully, the new setting is: ")); Serial.println(tmpSB); } else Serial.println(F("Incorrect input, Stop bit number is left unchanged")); Serial.println(); //Parity bits Serial.println(F("Choose parity bits setting, or leave it blank to keep unchanged. Possible options:")); Serial.println(F("(1) no parity (2) odd parity (3) even parity")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); int tmpInt = tmpName.toInt(); if (tmpName == "") { Serial.print(F("Parity bits setting is left unchanged: ")); Serial.println(tmpPB); } else if ((tmpInt >0)&&(tmpInt <4)) { tmpPB = tmpName; Serial.print(F("Parity bits setting is channged successfully, the new setting is: ")); Serial.println(tmpPB); } else Serial.println(F("Incorrect input, Parity bits setting is left unchanged")); tmpName = "AT+UART=" + tmpBR + "," + tmpSB + "," + tmpPB; // The overal UART settings command String tmpRes = getFromMySerial(tmpName, true); if (tmpRes == "OK") Serial.println (F("UART settings change successful")); else Serial.println (F("Faild to change the UART settings, please try again")); currSt = 2; currIn = 0; break; } case 23:{ // Modify the password (Pairing code) Serial.println(F("----------------------------------------------------------")); Serial.print(F("The curent pairing code is : ")); Serial.println(getFromMySerial("AT+PSWD", true, 6)); Serial.println(F("Please enter a new pairing passkey, or leave blank to keep the current code.")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") Serial.println(F("Pairing passkey is left unchanged")); else { tmpName = "AT+PSWD=" + tmpName; String tmpRes = getFromMySerial(tmpName, true); if (tmpRes == "OK") Serial.println (F("Pairing passkey change successful")); else Serial.println (F("Faild to change the Pairing passkey , please check the code and try again")); } currSt = 2; currIn = 0; break; } case 24:{ // Modify the role (Master/Slave/Slave-loop) Serial.println(F("----------------------------------------------------------")); Serial.print(F("The curent role setting is : ")); tmpName = getFromMySerial("AT+ROLE", true, 6); tmpName.trim(); Serial.print(tmpName); if (tmpName == "0") Serial.println(F(" [Slave]")); else if (tmpName == "1") Serial.println(F(" [Master]")); else if (tmpName == "2") Serial.println(F(" [Slave-loop]")); Serial.println(F("Choose a new role, or leave it blank to keep unchanged. Possible options:")); Serial.println(F("(0) 0:Slave (1) 1:Master (2) 2:Slave-loop")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") { Serial.print(F("Role is left unchanged: ")); } else { int tmpInt = tmpName.toInt(); switch (tmpInt) { case 0: case 1: case 2: tmpName = "AT+ROLE=" + tmpName; tmpRes = getFromMySerial(tmpName, true); if (tmpRes == "OK") Serial.println (F("Role change successful")); else Serial.println (F("Faild to change the role, please try again")); break; default: Serial.println(F("Incorrect input, role is left unchanged")); break; } } currSt = 2; currIn = 0; break; } case 25:{ // Change the connection mode Serial.println(F("----------------------------------------------------------")); Serial.print(F("The curent connection mode is : ")); tmpName = getFromMySerial("AT+CMODE", true, 6); tmpName.trim(); Serial.print(tmpName); if (tmpName == "0") Serial.println(F(" [Single remote connection]")); else if (tmpName == "1") Serial.println(F(" [Any remote connection]")); else if (tmpName == "2") Serial.println(F(" [Test mode]")); Serial.println(F("Choose a new connection mode, or leave it blank to keep unchanged. Possible options:")); Serial.println(F("(0) 0:Single remote connection (1) 1:Any remote connection (2) 2:Test mode")); while (!Serial.available()); tmpName = (Serial.readStringUntil('\n')); tmpName.trim(); if (tmpName == "") { Serial.print(F("Connection mode is left unchanged: ")); } else { int tmpInt = tmpName.toInt(); switch (tmpInt) { case 0: case 1: case 2: tmpName = "AT+CMODE=" + tmpName; tmpRes = getFromMySerial(tmpName, true); if (tmpRes == "OK") Serial.println (F("Connection mode change successful")); else Serial.println (F("Faild to change the connection mode, please try again")); break; default: Serial.println(F("Incorrect input, connection mode is left unchanged")); break; } } currSt = 2; currIn = 0; break; } case 3:{ // Reset the module to the original settings Serial.println(F("----------------------------------------------------------")); Serial.println(F("The module settings are reset to original")); getFromMySerial("AT+ORGL", false, 6); Serial.print(F(" -- Name : ")); Serial.println(getFromMySerial("AT+NAME", true, 6)); Serial.print(F(" -- Baudrate : ")); Serial.println(getFromMySerial("AT+UART", true, 6)); Serial.print(F(" -- Role : ")); if (getFromMySerial("AT+ROLE", true, 6) == "1") Serial.println(F("Master")); else Serial.println(F("Slave")); Serial.print(F(" -- Passowrd : ")); Serial.println(getFromMySerial("AT+PSWD", true, 6)); currSt = 0; currIn = 0; break; } case 4:{ // The menu to perform the Master module operations. if (getFromMySerial("AT+ROLE", true, 6) != "1") { // Check if the module role=1 which mean the module is master. Serial.println(F("The module should be in Master role to perform these operations, please change the role.")); currSt = 2; currIn = 0; } else{ switch (currIn){ case 0: Serial.println(F("----------------------------------------------------------")); Serial.println(F("Please select from the following operations:")); Serial.println(F(" 1- Discover nearby devices")); Serial.println(F(" 2- Pair with a device")); Serial.println(F(" 3- Connect to a device")); Serial.println(F(" 4- Remove devices from pairing list")); Serial.println(F(" 5- Bind with a device")); Serial.println(F(" 6- Back...")); Serial.print(F("(Option No.) ")); currIn = -1; break; case 1: currSt = 41; currIn = 0; break; case 2: currSt = 42; currIn = 0; break; case 3: currSt = 43; currIn = 0; break; case 4: currSt = 44; currIn = 0; break; case 5: currSt = 45; currIn = 0; break; case 6: currSt = 0; currIn = 0; break; default: Serial.println (F("not a valid input, please select from the list")); currSt = 4; currIn = 0; break; } } break; } case 41:{ // Inquire nearby devices (addresses + names) Serial.println(F("----------------------------------------------------------")); Serial.println(F("List of nearby devices:")); getFromMySerial("AT+INIT", true); // Discard the result, it may result in error if the SPP profile is already opened tmpName = String("AT+INQM=" + String(INQ1) + "," + String(INQ2) + "," + String(INQ3)); tmpRes = getFromMySerial(tmpName, true); if (tmpRes != "OK") Serial.println (F("Inquire mode setting failed")); else { getFromMySerialSimple("AT+INQ"); // As multiple devices might be discovered, only execute the command then wait on serial for each new line until "OK" is received clearDeviceList(); tmpName = getFromMySerialSimple("", 5); // at least, we have on result even if no devices were discovered, which is the "OK" output at the end of the inquire process while ((tmpName !="")) // As "OK" is less than 5 characters long, the result will be empty string when OK is received. { int ind1st = tmpName.indexOf(','); // the index of the first comma int ind2nd = tmpName.indexOf(',',ind1st + 1); // the index of the second comma String devAddr = tmpName.substring(0,ind1st); // The device's address String devClas = tmpName.substring(ind1st+1,ind2nd); // The device's service class String devRSSI = tmpName.substring(ind2nd+1); // The device's RSSI devLoc = searchDeviceList(devAddr); // check ifthe device address is already discovered, As in most cases the same deie can be discovered multiple times with different RSSI and/or different service classes if ((devLoc < 0)&& devCount < MAXDEV) // a new device, not found in the list, but there is still empty slot in the list (did not exceed the maximum number of stored devices) { lstDevices[devCount].Address = devAddr; // we store the new device data lstDevices[devCount].Class = devClas; lstDevices[devCount].RSSI = devRSSI; devCount++; } delay(10); tmpName = getFromMySerialSimple("", 5); // get the next input from MySerial (i.e. BT device) } Serial.println (strFixed("+",colW1 + colW2 + colW3 + colW4 + 3,true,"-")); // draw a table with the results Serial.println ("| " + strFixed("Ind.",colW1)+ strFixed("BT Device Name:",colW2) + strFixed("BT Device Address",colW3) + strFixed("Paired",colW4)+ " |"); Serial.println ("| " + strFixed("-----",colW1)+ strFixed("----------------",colW2) + strFixed("------------------",colW3) + strFixed("-------",colW4)+ " |"); for (int i=0; i devCount){ // if a numerical input exceeds the number of stored/discovered devices Serial.println(F("----------------------------------------------------------")); Serial.println(F("The selected index is out of bounds, please select within the list of available devices")); Serial.print(F("(Option No.) ")); currIn = -3; // stay in the same menu, until a correct index is entered or 'q' for exitting to previous menu } else{ devLoc = currIn - 1; // the index starts with 0 tmpName = lstDevices[devLoc].Address; tmpName.replace(":",","); tmpName = String("AT+PAIR=" + tmpName+","+PAIRTO); tmpRes = getFromMySerialSimple(tmpName); tmpRes = getFromMySerialSimple(""); // we do this as the pairing process can take longer, so we cannot rely on the timeout in the readstringuntil() tmpRes.trim(); if (tmpRes == "OK") { Serial.println (("You are now paired with the device " + lstDevices[devLoc].Name +" [" + lstDevices[devLoc].Address + "]")); } else { Serial.println (tmpName); Serial.println (tmpRes); Serial.println (F("Could not pair with the device, try again or initiat another search for devices")); } currSt = 4; currIn = 0; } break; } case 43:{ // Connect with one of the discovered devices if (currIn == 0){ if (serialStr.equalsIgnoreCase("q")){ //'q' to quite to previous menu currSt = 4; currIn = 0; } else{ Serial.println(F("----------------------------------------------------------")); Serial.println(F("Select the device index that you want to connect to, q to abort ")); Serial.print(F("(Option No.) ")); currIn = -3; } } else if (currIn > devCount){ // if a numerical input exceeds the number of stored/discovered devices Serial.println(F("----------------------------------------------------------")); Serial.println(F("The selected index is out of bounds, please select within the list of available devices")); Serial.print(F("(Option No.) ")); currIn = -3; } else{ devLoc = currIn - 1; // the index starts with 0 tmpName = lstDevices[devLoc].Address; tmpName.replace(":",","); tmpName = String("AT+LINK=" + tmpName); tmpRes = getFromMySerialSimple(tmpName); tmpRes = getFromMySerialSimple(""); // we do this as the linking/connecting process can take longer, so we cannot rely on the timeout in the readstringuntil() tmpRes.trim(); if (tmpRes == "OK"){ Serial.println (("You are now connected with the device " + lstDevices[devLoc].Name +" [" + lstDevices[devLoc].Address + "], type '#end' to disconnect and reset.")); currSt = 6; currIn = 0; } else{ Serial.println (tmpName); Serial.println (tmpRes); Serial.println (F("Could not connect with the device, try again or initiat another search for devices")); } currSt = 4; currIn = 0; } break; serialStr = ""; } case 44:{ if (currIn == 0) { if (serialStr.equalsIgnoreCase("q")) { currSt = 4; currIn = 0; } else if (serialStr.equalsIgnoreCase("a")) { tmpRes = getFromMySerial(String("AT+ADCN"), true, 6); tmpRes.trim(); int tmpCount = tmpRes.toInt(); for (int i=0; i devCount) { Serial.println(F("----------------------------------------------------------")); Serial.println(F("The selected index is out of bounds, please select within the list of available devices")); Serial.print(F("(Option No.) ")); currIn = -4; } else { devLoc = currIn - 1; tmpName = lstDevices[devLoc].Address; tmpName.replace(":",","); tmpRes = getFromMySerial(String("AT+FSAD=")+ tmpName, true); tmpRes.trim(); if (tmpRes == "OK") { tmpRes = getFromMySerial(String("AT+RMSAD=")+ tmpName, true); tmpRes.trim(); if (tmpRes == "OK") { Serial.println(("The device " + lstDevices[devLoc].Name +" [" + lstDevices[devLoc].Address + "] is removed from the paired devices list")); } } else { Serial.println (F("The device is not within the paired devices list.")); } currIn = 0; } break; } case 45:{ if (currIn == 0) { if (serialStr.equalsIgnoreCase("q")) { currSt = 4; currIn = 0; } else { Serial.println(F("----------------------------------------------------------")); Serial.println(F("Select the device index that you want to bind with, q to abort ")); Serial.print(F("(Option No.) ")); currIn = -3; } } else if (currIn > devCount) { Serial.println(F("----------------------------------------------------------")); Serial.println(F("The selected index is out of bounds, please select within the list of available devices")); Serial.print(F("(Option No.) ")); currIn = -3; } else { devLoc = currIn - 1; tmpName = lstDevices[devLoc].Address; tmpName.replace(":",","); tmpName = String("AT+BIND=" + tmpName); tmpRes = getFromMySerialSimple(tmpName); tmpRes = getFromMySerialSimple(""); tmpRes.trim(); if (tmpRes == "OK") { Serial.println (("You are now binded with the device " + lstDevices[devLoc].Name +" [" + lstDevices[devLoc].Address + "], type '#end' to disconnect and reset.")); } else { Serial.println (F("Could not bind with the device, try again or initiat another search for devices")); } currSt = 4; currIn = 0; } break; } case 6:{ for (int i=0; i< serialStr.length(); i++) mySerial.write(serialStr[i]); break; } } } serialStr = ""; }