Read substring via wifi

Hi there, I created an app to command via wifi a servo. I just did it via Bluetooth. I decided to switch to have more stability. I used more textboxes to set some special parameters remotely. at this point my problem was born. I thought to see my currentLine something like this : http://192.168.3.1/C###. I was wrong because my output is this even if I attached on the URL calling the text that I would put in textbox. I print the current line to have a debug. You can see it from the pic

In the end, how can I set Ext_thr as ### attached after C for example?

//SET EXT THR
     else  if (currentLine.endsWith("GET /C")) {
           DEBUG_SERIAL.print("currentline:");
           DEBUG_SERIAL.println(currentLine);
           String thr= currentLine.substring(3);
           DEBUG_SERIAL.print("thr:");
           DEBUG_SERIAL.println(thr);
           String thr1= currentLine.substring(6);
           DEBUG_SERIAL.print("thr1:");
           DEBUG_SERIAL.println(thr1);
           EXT_thr = thr.toFloat();
           DEBUG_SERIAL.print("EXT_thr = ");   DEBUG_SERIAL.println(EXT_thr);
           client.print("EXT_thr = ");   client.println(EXT_thr);
           delay(500);
     }

I don't know what device you are using, in this example with ESP32 I use the function if (req.indexOf("on2") != -1) to check the information received.

1 Like

hey, @Juan_Antonio thank you so much for your tip. I have to ask you for additional help because, after looking at your examples, I didn't find anything that can be similar to my situation, I guess. Indeed from my first message, I can see that currentLine is not what I was expected: GET/C### where ### is the number written in textbox. Furthermore, I noticed that I am using only a webviewer in the app and not the web tool. Could be there some differences. Can you guide me over the solution please?
By the way, I am using an android smartphone and a portenta h7 pro

@DjangoTango

I have not used the Portenta H7 Pro (+100 €).

Try the Web component, try to show the entire currentLine in the Serial Monitor.

Try using the functions... readStringUntil('\r') and .indexOf("..")

String req = client.readStringUntil('\r');
Serial.println(req);

// Make the client's request.
if (req.indexOf("on12") != -1)

Try doing this example in Portenta to see if it works, if it works I think it will be easy to adapt it to your project.

1 Like

Hi @Juan_Antonio following yours tips I was able to achieve my goal. Thank You!
By the way I used the "webviewer" and not the "web" to do my final task. I think that req.indexOf was the real solution. I keep off the client.stop() otherwise I read the imu only for some seconds.
At the same time, I want to share with u this my code and the shortcut of my apps done with web and webviewer component. This is because, although I can use both apps, they don't work properly:

  • with "webviewer" app I can't see the client.print
  • with web app Each time that I push a button the result on the screen is: error 1101, unable to get a response with the specific URL: HTTP://....... and I can't see again the client.print.

Where I am wrong? WHat is better to change in your opinion?
Gracias

#include <WiFi.h>
#include "arduino_secrets.h"
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
int Value;
int lettura;
float q0,q1,q2,q3,gx,gy,gz,norm,phi;
float radtodeg = 57296/1000;

WiFiServer server(80);

void setup() {
// put your setup code here, to run once:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Wire.begin();
/* Initialise the sensor /
if(!bno.begin())
{
/ There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while(1);
}

delay(1000);
/* Crystal must be configured AFTER loading calibration data into BNO055. */

  bno.setExtCrystalUse(true);
Serial.println("Access Point Web Server");

pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
digitalWrite(LEDR,HIGH);
digitalWrite(LEDG,HIGH);
digitalWrite(LEDB,HIGH);

// by default the local IP address of will be 192.168.3.1
// you can override it with the following:
// WiFi.config(IPAddress(10, 0, 0, 1));

// The AP needs the password be at least 8 characters long
if(strlen(pass) < 8){
Serial.println("Creating access point failed");
Serial.println("The WiFi password must be at least 8 characters long");
// don't continue
while(true);
}

// print the network name (SSID);
Serial.print("Creating access point named: ");
Serial.println(ssid);

//Create the Access point
status = WiFi.beginAP(ssid, pass);
if (status != WL_AP_LISTENING) {
Serial.println("Creating access point failed");
// don't continue
while (true);
}

// wait 10 seconds for connection:
delay(10000);

// start the web server on port 80
server.begin();

// you're connected now, so print out the status
printWiFiStatus();

}

void loop() {

// compare the previous status to the current status
if (status != WiFi.status()) {
// it has changed update the variable
status = WiFi.status();

if (status == WL_AP_CONNECTED) {
  // a device has connected to the AP
  Serial.println("Device connected to AP");
} else {
  // a device has disconnected from the AP, and we are back in listening mode
  Serial.println("Device disconnected from AP");
}
}

WiFiClient client = server.available(); // listen for incoming clients

if (client) { // if you get a client,

String estado = "";                // make a String to hold incoming data from the client
  while (client.connected()) {            // loop while the client's connected

  if (client.available()) {             // if there's bytes to read from the client,
String req = client.readStringUntil('\r');

// Make the client's request.
if (req.indexOf("ROFF") != -1) {
lettura=1;digitalWrite(LEDR, HIGH); 
Serial.print("Req: ");
Serial.println(req); 
estado = "LEDR OFF";
Serial.print("Estado: "); 
Serial.println(estado);
 client.println(estado);
 } // Return status.

if (req.indexOf("RON") != -1){
lettura=0;
digitalWrite(LEDR, LOW); 
Serial.print("Req: ");
Serial.println(req);
estado = "LEDR ON";
Serial.print("Estado: ");
Serial.println(estado);
client.println(estado);
}

if (req.indexOf("SET") != -1){
Serial.print("Req: ");
Serial.println(req); 
estado = "SET";
Serial.print("Estado: ");
Serial.println(estado);
client.println(estado);
String thr= req.substring(8);
Value = thr.toInt();
Serial.print("Value: ");
Serial.println(Value);
}

 //client.stop();

  } // end if (client.available()) 
   
         if (lettura == 1) {
                              imu::Quaternion quat = bno.getQuat();

                              q0= quat.w();
                              q1=quat.x();
                              q2= quat.y();
                              q3=quat.z();
                              gx = q1 * q3 - q0 * q2;
                              gy = q0 * q1 + q2 * q3;
                              gz = q0 * q0 + q3 * q3 -0.5f;
                              norm = sqrt(gx * gx + gy * gy + gz * gz);                                                             
                              norm = 1.0 / norm;
                              gx *= norm; gy *= norm; gz *= norm;
                              phi = acos(gy); phi = phi*radtodeg;
                              Serial.println(phi);
  }
  
} // end while (client.connected())
} //end (client)

} // end loop()

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

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

// print where to go in a browser:
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
}


Check my example:

Here return value:
//////////////////////////////////////////////
// Página WEB. ////////////////////////////
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // Comillas importantes.
client.println(estado); // Return status.

client.flush();
client.stop();
Serial.println("Client disconnected.");
}

Hey @Juan_Antonio thank you again for your disponibility! By the way, even if I tried your solution, It doesn't work properly for my aim.
I need that when I send a string with OFF for example, the imu starts to read continuously. With client.stop() I can read the imu only for 5 seconds and then I can't send other strings then the error 1101 appears again.
This is my loop. You can see the setup and the apps in the previous messages.
What do you think about it?

WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,

String estado = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected

if (client.available()) { // if there's bytes to read from the client,
String req = client.readStringUntil('\r');

// Make the client's request.
if (req.indexOf("ROFF") != -1) {lettura=1;digitalWrite(LEDR, HIGH);estado = "LEDR OFF, IMU Started";}
if (req.indexOf("RON") != -1){lettura=0;digitalWrite(LEDR, LOW);estado = "LEDR ON, IMU Finished";client.stop();}
if (req.indexOf("SET") != -1){estado = "SET-UP";
String thr= req.substring(8);Value = thr.toInt();client.print("Value: ");client.println(Value);client.stop();}

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // Comillas importantes.
Serial.println(estado);
client.println(estado); // Return status.

client.flush();
//client.stop();

} // end if (client.available())

     if (lettura == 1) {
                          imu::Quaternion quat = bno.getQuat();

                          q0= quat.w();
                          q1=quat.x();
                          q2= quat.y();
                          q3=quat.z();
                          gx = q1 * q3 - q0 * q2;
                          gy = q0 * q1 + q2 * q3;
                          gz = q0 * q0 + q3 * q3 -0.5f;
                          norm = sqrt(gx * gx + gy * gy + gz * gz);                                                             
                          norm = 1.0 / norm;
                          gx *= norm; gy *= norm; gz *= norm;
                          phi = acos(gy); phi = phi*radtodeg;
                          Serial.println(phi);
}

} // end while (client.connected())
} //end (client)

} // end loop()

I have not made a code to "maintain" the connection. The codes I have made create the connection and exit.

What you are doing looks more like MQTT.

If you are using an imu you have to study if the frequency of sending data can be achieved by the connection, perhaps the Wi-Fi connection cannot work with a high data speed.

Another idea would be to put a Clock in the app and connect with the IP every so often, maybe 2 seconds.

Another idea would be to put a / meta http-equiv = ”refresh” content = ”2" /

to automatically refresh every 2 seconds.

1 Like

Yes i understood @Juan_Antonio thank you. I Guess that the wifi frequency Is more thank compatible with the Imu updating. Indeed your code works fine for me if i keep out the client.stop() but at the same time and in that way the code isn t able to print the output in the client. Considering this, Will your answer be the same? I want only to be sure because i feel myseof still a rookie about appinventor environment

@Juan_Antonio Anyway I am continuing to not understand why in this way, all it works good except for the client.print. The output is perfect in the serial monitor but I don't see anything in the app. The app is built using WEBviewer component. And the loop in the code is this one. All should work properly, but not the client.print. Why??

  if (req.indexOf("ROFF") != -1) {lettura=1;digitalWrite(LEDR, HIGH);estado = "LEDR OFF, IMU Started";Serial.println(estado);client.println(estado);} 

if (req.indexOf("RON") != -1){lettura=0; digitalWrite(LEDR, LOW);estado = "LEDR ON, IMU Finished";Serial.println(estado);client.println(estado); }

if (req.indexOf("SET") != -1){lettura=0;estado = "SET-UP"; String thr= req.substring(8);Value = thr.toInt();client.println(estado); client.print("Value: ");client.println(Value);Serial.println(estado); Serial.print("Value: ");Serial.println(Value);}

@DjangoTango

Try simpler code first.

In this example an Access Point is created.
From the app you can turn on/off an LED using the WebViewer component.
The mobile must be on the same network.
It is preferable to install it in the app, not in Companion.
It is made with ESP32, I do not know if your device will work the same libraries.

http://kio4.com/arduino/119_Wemos_PuntoAcceso_BotonLED.htm

In this topic I have put related information:

Hi @Juan_Antonio Thank you so much for your help, I m sorry for my late reply. Right now my system works better. I would like to ask you the last question. Lokking at Webviewer I thought that the section I created and that I attach below, shall mix the SET and Text (in my head) but it doesn't do it indeedthe currentLine doesn't show the text but only GET /SET. Why? How can I solve it?

if (currentLine.endsWith("GET /SET")) {
           digitalWrite(LEDB, HIGH);
           client.println("Setting a number ");// GET /Lr turns the Red LED off
          _UART_USB_.println("Setting a number");
          String thr= currentLine.substring(9);Value = thr.toInt();
          _UART_USB_.print("Thr: ");_UART_USB_.println(thr);
          _UART_USB_.print("Value: ");_UART_USB_.println(Value);
          _UART_USB_.print("currentLine: ");_UART_USB_.println(currentLine);
         } 

Try

if (currentLine.indexOf("SET") != -1){

mmm yes, better! But now the output is all this:
Setting a number
Thr:
Value: 0
currentLine: GET /SET
Setting a number
Thr:
Value: 0
currentLine: GET /SET1
Setting a number
Thr: 2
Value: 2
currentLine: GET /SET12
Setting a number
Thr: 2
Value: 2
currentLine: GET /SET12
Setting a number
Thr: 2 H
Value: 2
currentLine: GET /SET12 H
Setting a number
Thr: 2 HT
Value: 2
currentLine: GET /SET12 HT
Setting a number
Thr: 2 HTT
Value: 2
currentLine: GET /SET12 HTT
Setting a number
Thr: 2 HTTP
Value: 2
currentLine: GET /SET12 HTTP
Setting a number
Thr: 2 HTTP/
Value: 2
currentLine: GET /SET12 HTTP/
Setting a number
Thr: 2 HTTP/1
Value: 2
currentLine: GET /SET12 HTTP/1
Setting a number
Thr: 2 HTTP/1.
Value: 2
currentLine: GET /SET12 HTTP/1.
Setting a number
Thr: 2 HTTP/1.1
Value: 2
currentLine: GET /SET12 HTTP/1.1
Setting a number
Thr: 2 HTTP/1.1
Value: 2
currentLine: GET /SET12 HTTP/1.1
Setting a number
Thr: http://192.168.3.1/SET
Value: 0
currentLine: Referer: http://192.168.3.1/SET
Setting a number
Thr: http://192.168.3.1/SET1
Value: 0
currentLine: Referer: http://192.168.3.1/SET1
Setting a number
Thr: http://192.168.3.1/SET12
Value: 0
currentLine: Referer: http://192.168.3.1/SET12
Setting a number
Thr: http://192.168.3.1/SET12
Value: 0
currentLine: Referer: http://192.168.3.1/SET12

if (currentLine.indexOf("SET1") != -1){
if (currentLine.indexOf("SET2") != -1){
if (currentLine.indexOf("SET3") != -1){

Blocks

http://192.168.3.1/SET1
http://192.168.3.1/SET2
http://192.168.3.1/SET3

Sorry @Juan_Antonio what do you mean? I shall text any number in text. Thus after SET could be any number from 1 to 500 let s say.

Thank you

Try with SET1, SET2,... in code ESP and Blocks.

I tried but if I text 4 for example It doesn't work. Maybe I am wrong because I didn't understand what do you mean with code ESP and Blocks. In Blocks of app I have to put firstly SET because after that I have to put the number. About the ESP honestly I am not using any external module, but only a portenta as access-point. I hope you can have a little more of patience.

Thank you.

If you put this code, what do you get?

if (currentLine.indexOf("SET") != -1){
UART_USB.print("currentLine: ");UART_USB.println(currentLine);