How to display all char with string format in split string method

farhanjaa
Posts: 2
Joined: Sun Feb 27, 2022 8:01 pm

How to display all char with string format in split string method

Postby farhanjaa » Sun Feb 27, 2022 8:06 pm

I'm making a college final project, namely esp32 cam qr code scanner but I found a problem that I can't bring up all strings in the split string method that I use, I assume that the library I use, namely "data->payload" is uin8_t and not can be converted to string, is there any solution? Sorry, I'm very new to this kind of stuff.
And this is the code

Code: Select all

/*
  ESP32-CAM QR code Reader
  Author : ChungYi Fu (Kaohsiung, Taiwan)  2021-8-13 20:00
  https://www.facebook.com/francefu

  Refer to the code
  https://github.com/alvarowolfx/ESP32QRCodeReader

  自訂指令格式 http://192.168.xxx.xxx/control?cmd=P1;P2;P3;P4;P5;P6;P7;P8;P9

  http://192.168.xxx.xxx/?ip                      //取得APIP, STAIP
  http://192.168.xxx.xxx/?mac                     //取得MAC位址
  http://192.168.xxx.xxx/?digitalwrite=pin;value  //數位輸出
  http://192.168.xxx.xxx/?analogwrite=pin;value   //類比輸出
  http://192.168.xxx.xxx/?digitalread=pin         //數位讀取
  http://192.168.xxx.xxx/?analogread=pin          //類比讀取
  http://192.168.xxx.xxx/?touchread=pin           //觸碰讀取
  http://192.168.xxx.xxx/?restart                 //重啟電源
  http://192.168.xxx.xxx/?flash=value             //閃光燈 value= 0~255
  http://192.168.xxx.xxx/?servo=pin;value         //伺服馬達 value= 0~180
  http://192.168.xxx.xxx/?relay=pin;value         //繼電器 value = 0, 1
  http://192.168.xxx.xxx/?uart=value              //序列埠
*/

//輸入WIFI連線帳號密碼
const char* ssid = "IPAN";
const char* password = "Inpres11";

//輸入AP端連線帳號密碼  http://192.168.4.1
const char* apssid = "";
const char* appassword = "";         //AP密碼至少要8個字元以上

String Feedback = ""; //回傳客戶端訊息
//指令參數值
String Command = "", cmd = "", P1 = "", P2 = "", P3 = "", P4 = "", P5 = "", P6 = "", P7 = "", P8 = "", P9 = "";
//指令拆解狀態值
byte ReceiveState = 0, cmdState = 1, strState = 1, questionstate = 0, equalstate = 0, semicolonstate = 0;

#include <WiFi.h>
#include "esp_camera.h"          //視訊函式
#include "soc/soc.h"             //用於電源不穩不重開機 
#include "soc/rtc_cntl_reg.h"    //用於電源不穩不重開機 
#include "quirc.h"

TaskHandle_t Task;

//ESP32-CAM 安信可模組腳位設定
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

struct QRCodeData
{
  bool valid;
  int dataType;
  uint8_t payload[1024];
  int payloadLen;
};

  String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;
 
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  } 
 
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

struct quirc *q = NULL;
uint8_t *image = NULL;
camera_fb_t * fb = NULL;
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
struct QRCodeData qrCodeData;
String QRCodeResult = "";

WiFiServer server(80);
WiFiClient client;

camera_config_t config;

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);  //關閉電源不穩就重開機的設定

  Serial.begin(115200);
  Serial.setDebugOutput(true);  //開啟診斷輸出
  Serial.println();

  //視訊組態設定  https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 10000000;
  config.pixel_format = PIXFORMAT_GRAYSCALE;
  config.frame_size = FRAMESIZE_QVGA;
  config.jpeg_quality = 15;
  config.fb_count = 1;

  //視訊初始化
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    ESP.restart();
  }

  sensor_t * s = esp_camera_sensor_get();
  s->set_framesize(s, FRAMESIZE_QVGA);

  //s->set_vflip(s, 1);  //垂直翻轉
  //s->set_hmirror(s, 1);  //水平鏡像

  //閃光燈(GPIO4)
  ledcAttachPin(4, 4);
  ledcSetup(4, 5000, 8);

  WiFi.mode(WIFI_AP_STA);  //其他模式 WiFi.mode(WIFI_AP); WiFi.mode(WIFI_STA);

  //指定Client端靜態IP
  //WiFi.config(IPAddress(192, 168, 201, 100), IPAddress(192, 168, 201, 2), IPAddress(255, 255, 255, 0));

  for (int i = 0; i < 2; i++) {
    WiFi.begin(ssid, password);    //執行網路連線

    delay(1000);
    Serial.println("");
    Serial.print("Connecting to ");
    Serial.println(ssid);

    long int StartTime = millis();
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      if ((StartTime + 5000) < millis()) break;  //等待10秒連線
    }

    if (WiFi.status() == WL_CONNECTED) {    //若連線成功
      WiFi.softAP((WiFi.localIP().toString() + "_" + (String)apssid).c_str(), appassword); //設定SSID顯示客戶端IP
      Serial.println("");
      Serial.println("STAIP address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");

      for (int i = 0; i < 5; i++) { //若連上WIFI設定閃光燈快速閃爍
        ledcWrite(4, 10);
        delay(200);
        ledcWrite(4, 0);
        delay(200);
      }
      break;
    }
  }

  if (WiFi.status() != WL_CONNECTED) {    //若連線失敗
    WiFi.softAP((WiFi.softAPIP().toString() + "_" + (String)apssid).c_str(), appassword);

    for (int i = 0; i < 2; i++) { //若連不上WIFI設定閃光燈慢速閃爍
      ledcWrite(4, 10);
      delay(1000);
      ledcWrite(4, 0);
      delay(1000);
    }
  }

  //指定AP端IP
  //WiFi.softAPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
  Serial.println("");
  Serial.println("APIP address: ");
  Serial.println(WiFi.softAPIP());
  Serial.println("");

  //設定閃光燈為低電位
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);

  server.begin();

  xTaskCreatePinnedToCore(
    QRCodeReader, /* Task function. */
    "Task",   /* name of task. */
    10000,     /* Stack size of task */
    NULL,      /* parameter of the task */
    1,         /* priority of the task */
    &Task,    /* Task handle to keep track of created task */
    0);        /* pin task to core 0 */

  Serial.print("listenConnection running on core ");
  Serial.println(xPortGetCoreID());
}

void loop() {
  listenConnection();
}

void QRCodeReader( void * pvParameters ) {
  Serial.print("QRCodeReader running on core ");
  Serial.println(xPortGetCoreID());

  while (1) {
    q = quirc_new();
    if (q == NULL) {
      Serial.print("can't create quirc object\r\n");
      continue;
    }

    fb = esp_camera_fb_get();
    if (!fb)
    {
      Serial.println("Camera capture failed");
      continue;
    }

    //Serial.printf("quirc_begin\r\n");
    quirc_resize(q, fb->width, fb->height);
    image = quirc_begin(q, NULL, NULL);
    //Serial.printf("Frame w h len: %d, %d, %d \r\n", fb->width, fb->height, fb->len);
    memcpy(image, fb->buf, fb->len);
    quirc_end(q);
    //Serial.printf("quirc_end\r\n");

    int count = quirc_count(q);
    if (count > 0) {
      Serial.println(count);
      quirc_extract(q, 0, &code);
      err = quirc_decode(&code, &data);

      if (err) {
        Serial.println("Decoding FAILED");
        QRCodeResult = "Decoding FAILED";
      } else {
        Serial.printf("Decoding successful:\n");
        dumpData(&data);
        /*
          qrCodeData.dataType = data.data_type;
          for (int j = 0; j < data.payload_len; j++)
          {
          qrCodeData.payload[j] = data.payload[j];
          }
          qrCodeData.valid = true;
          qrCodeData.payload[data.payload_len] = '\0';
          qrCodeData.payloadLen = data.payload_len;
        */
        //vTaskDelay(3000/portTICK_RATE_MS);
      }
      Serial.println();
    }

    esp_camera_fb_return(fb);
    fb = NULL;
    image = NULL;
    quirc_destroy(q);
  }
}

void dumpData(const struct quirc_data *data)
{

  Serial.printf("Version: %d\n", data->version);
  Serial.printf("ECC level: %c\n", "MLHQ"[data->ecc_level]);
  Serial.printf("Mask: %d\n", data->mask);
  Serial.printf("Length: %d\n", data->payload_len);
  Serial.printf("Payload: %s\n", data->payload);
     const unsigned char* str  =data->payload;
   const char tokens = *str;
//     String testtok= String(tokens);
  String stringku =String (tokens);
  Serial.print("data string: "); Serial.println(stringku);
  String substringku0 = getValue(stringku, ' ', 0);
  Serial.print("substring[0]: "); Serial.println(substringku0);
  String substringku3 = getValue(stringku, ' ', 3);
  Serial.print("substring[3]: "); Serial.println(substringku3);
  Serial.print(*str);
  
  
  //
  //   uint8_t token_idx = 0;
  QRCodeResult = (const char *)data->payload;


}

//執行自訂指令
void ExecuteCommand() {
  //Serial.println("");
  //Serial.println("Command: "+Command);
  if (cmd != "getstill") {
    Serial.println("cmd= " + cmd + " ,P1= " + P1 + " ,P2= " + P2 + " ,P3= " + P3 + " ,P4= " + P4 + " ,P5= " + P5 + " ,P6= " + P6 + " ,P7= " + P7 + " ,P8= " + P8 + " ,P9= " + P9);
    Serial.println("");
  }

  //自訂指令區塊  http://192.168.xxx.xxx?cmd=P1;P2;P3;P4;P5;P6;P7;P8;P9
  if (cmd == "your cmd") {
    // You can do anything
    // Feedback="<font color=\"red\">Hello World</font>";   //可為一般文字或HTML語法
  }
  else if (cmd == "ip") { //查詢APIP, STAIP
    Feedback = "AP IP: " + WiFi.softAPIP().toString();
    Feedback += "<br>";
    Feedback += "STA IP: " + WiFi.localIP().toString();
  }
  else if (cmd == "mac") { //查詢MAC位址
    Feedback = "STA MAC: " + WiFi.macAddress();
  }
  else if (cmd == "restart") { //重設WIFI連線
    ESP.restart();
  }
  else if (cmd == "digitalwrite") { //數位輸出
    ledcDetachPin(P1.toInt());
    pinMode(P1.toInt(), OUTPUT);
    digitalWrite(P1.toInt(), P2.toInt());
  }
  else if (cmd == "digitalread") { //數位輸入
    Feedback = String(digitalRead(P1.toInt()));
  }
  else if (cmd == "analogwrite") { //類比輸出
    if (P1 == "4") {
      ledcAttachPin(4, 4);
      ledcSetup(4, 5000, 8);
      ledcWrite(4, P2.toInt());
    }
    else {
      ledcAttachPin(P1.toInt(), 9);
      ledcSetup(9, 5000, 8);
      ledcWrite(9, P2.toInt());
    }
  }
  else if (cmd == "analogread") { //類比讀取
    Feedback = String(analogRead(P1.toInt()));
  }
  else if (cmd == "touchread") { //觸碰讀取
    Feedback = String(touchRead(P1.toInt()));
  }
  else if (cmd == "framesize") { //解析度
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_framesize(s, (framesize_t)val);
  }
  else if (cmd == "quality") { //畫質
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_quality(s, val);
  }
  else if (cmd == "contrast") { //對比
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_contrast(s, val);
  }
  else if (cmd == "brightness") { //亮度
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_brightness(s, val);
  }
  else if (cmd == "hmirror") { //水平鏡像
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_hmirror(s, val);
  }
  else if (cmd == "vflip") { //垂直翻轉
    sensor_t * s = esp_camera_sensor_get();
    int val = P1.toInt();
    s->set_vflip(s, val);
  }
  else if (cmd == "serial") { //序列埠
    Serial.print(P1);
  }
  else if (cmd == "restart") { //重啟電源
    ESP.restart();
  }
  else if (cmd == "flash") { //閃光燈
    ledcAttachPin(4, 4);
    ledcSetup(4, 5000, 8);
    int val = P1.toInt();
    ledcWrite(4, val);
  }
  else if (cmd == "servo") { //伺服馬達 (0-180)
    ledcAttachPin(P1.toInt(), 3);
    ledcSetup(3, 50, 16);

    int val = 7864 - P2.toInt() * 34.59;
    if (val > 7864)
      val = 7864;
    else if (val < 1638)
      val = 1638;
    ledcWrite(3, val);
  }
  else if (cmd == "relay") { //繼電器
    pinMode(P1.toInt(), OUTPUT);
    digitalWrite(13, P2.toInt());
  }
  else {
    Feedback = "Command is not defined.";
  }

  if (Feedback == "") Feedback = Command;
}


//自訂網頁首頁管理介面
static const char PROGMEM INDEX_HTML[] = R"rawliteral(
<!DOCTYPE html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<canvas id="canvas" width="320" height="240"></canvas><br>
Flash<input type="range" id="flash" min="0" max="255" value="0">
<input type="button" value="Get Still" onclick="getStill();"><br>
<div id="result" style="color:red"></div>
</body>
</html> 
  
<script>
  var canvas = document.getElementById('canvas'); 
  var context = canvas.getContext('2d');
  var flash = document.getElementById('flash');
  var result = document.getElementById('result');
  
  flash.onchange = function() {
    var query = document.location.origin+"/?flash="+flash.value;
    fetch(query);
  }

  function getStill() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/?getstill", true);
    xhr.responseType = "arraybuffer";
    
    xhr.onload = function (oEvent) {
      var arrayBuffer = xhr.response; // Note: not xhr.responseText
      if (arrayBuffer) {
        var byteArray = new Uint8Array(arrayBuffer);
        var imgData=context.getImageData(0,0,canvas.width,canvas.height);
        var val = 0;
        for (var i=0;i<imgData.data.length;i+=4) {
          val = parseInt(byteArray[i/4], 10);
              imgData.data[i]=val;
              imgData.data[i+1]=val;
              imgData.data[i+2]=val;
              imgData.data[i+3]=255;
          }
          context.putImageData(imgData,0,0);
          setTimeout(function(){getStill();}, 100);
        }
    };
    
    xhr.send(null);
  }
</script>   
)rawliteral";

void listenConnection() {
  Feedback="";Command="";cmd="";P1="";P2="";P3="";P4="";P5="";P6="";P7="";P8="";P9="";
  ReceiveState=0,cmdState=1,strState=1,questionstate=0,equalstate=0,semicolonstate=0;
  
  client = server.available();
  
  if (client) { 
    String currentLine = "";

    while (client.connected()) {
      if (client.available()) {
        char c = client.read(); 
        getCommand(c);   //將緩衝區取得的字元拆解出指令參數
        if (c == '\n') {
          if (currentLine.length() == 0) {
            if (cmd=="getstill") {
              getStill();            
            } else {
              mainPage();
            }         
            Feedback="";
            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }

        if ((currentLine.indexOf("?")!=-1)&&(currentLine.indexOf(" HTTP")!=-1)) {
          if (Command.indexOf("stop")!=-1) {  //若指令中含關鍵字stop立即斷線 -> http://192.168.xxx.xxx?cmd=aaa;bbb;ccc;stop
            client.println();
            client.println();
            client.stop();
          }
          currentLine="";
          Feedback="";
          ExecuteCommand();
        }
      }
    }
    delay(1);
    client.stop();
  }
}

void mainPage() {
    //回傳HTML首頁或Feedback
    client.println("HTTP/1.1 200 OK");
    client.println("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
    client.println("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS");
    client.println("Content-Type: text/html; charset=utf-8");
    client.println("Access-Control-Allow-Origin: *");
    client.println("Connection: close");
    client.println();
    
    String Data="";
    if (cmd!="")
      Data = Feedback;
    else {
      Data = String((const char *)INDEX_HTML);
    }
    int Index;
    for (Index = 0; Index < Data.length(); Index = Index+1024) {
      client.print(Data.substring(Index, Index+1024));
    }
}

void getStill() {
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();  
  if(!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  uint8_t *fbBuf = fb->buf;
  size_t fbLen = fb->len; 
  
  client.println("HTTP/1.1 200 OK");
  client.println("Access-Control-Allow-Origin: *");              
  client.println("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
  client.println("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS");
  client.println("Content-Type: application/octet-stream");
  client.println();

  for (size_t n=0;n<fbLen;n=n+1024) {
    if (n+1024<fbLen) {
      client.write(fbBuf, 1024);
      fbBuf += 1024;
    }
    else if (fbLen%1024>0) {
      size_t remainder = fbLen%1024;
      client.write(fbBuf, remainder);
    }
  }  
  esp_camera_fb_return(fb);

  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
}

//拆解命令字串置入變數
void getCommand(char c) {
  if (c=='?') ReceiveState=1;
  if ((c==' ')||(c=='\r')||(c=='\n')) ReceiveState=0;
  
  if (ReceiveState==1)
  {
    Command=Command+String(c);
    
    if (c=='=') cmdState=0;
    if (c==';') strState++;
  
    if ((cmdState==1)&&((c!='?')||(questionstate==1))) cmd=cmd+String(c);
    if ((cmdState==0)&&(strState==1)&&((c!='=')||(equalstate==1))) P1=P1+String(c);
    if ((cmdState==0)&&(strState==2)&&(c!=';')) P2=P2+String(c);
    if ((cmdState==0)&&(strState==3)&&(c!=';')) P3=P3+String(c);
    if ((cmdState==0)&&(strState==4)&&(c!=';')) P4=P4+String(c);
    if ((cmdState==0)&&(strState==5)&&(c!=';')) P5=P5+String(c);
    if ((cmdState==0)&&(strState==6)&&(c!=';')) P6=P6+String(c);
    if ((cmdState==0)&&(strState==7)&&(c!=';')) P7=P7+String(c);
    if ((cmdState==0)&&(strState==8)&&(c!=';')) P8=P8+String(c);
    if ((cmdState==0)&&(strState>=9)&&((c!=';')||(semicolonstate==1))) P9=P9+String(c);
    
    if (c=='?') questionstate=1;
    if (c=='=') equalstate=1;
    if ((strState>=9)&&(c==';')) semicolonstate=1;
  }
}
the main problem is in void dumpData(const struct quirc_data *data) And the output like this when i scan the QR Code.
"Decoding successful:
Version: 11
ECC level: M
Mask: 2
Length: 64
Payload: M1Jones/Tony EU96YHI MELSYDJQ 0528 239Y008A00001 100 WW
data string: M
substring[0]: M
substring[3]:
"
Please anyone help me why substring is not displaying every sentence in available string "payload". Thank you

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: How to display all char with string format in split string method

Postby ESP_Sprite » Mon Feb 28, 2022 1:17 am

Just to show you why your current setup does what it does:

Code: Select all

  const unsigned char* str = data->payload; //Grab the payload                                                                                                                                                       
  const char tokens = *str;                 //Grab the first character, and store it into the 8-bit variable 'tokens'                                                                                                
  String stringku =String (tokens)          //Make a string out of that first character        

farhanjaa
Posts: 2
Joined: Sun Feb 27, 2022 8:01 pm

Re: How to display all char with string format in split string method

Postby farhanjaa » Mon Feb 28, 2022 6:54 am

ESP_Sprite wrote:
Mon Feb 28, 2022 1:17 am
Just to show you why your current setup does what it does:

Code: Select all

  const unsigned char* str = data->payload; //Grab the payload                                                                                                                                                       
  const char tokens = *str;                 //Grab the first character, and store it into the 8-bit variable 'tokens'                                                                                                
  String stringku =String (tokens)          //Make a string out of that first character        
Thank you for your response. actually I want all the sentences in "data->payload" with the definition "String stringku=data->payload;" but a problem like this appears invalid conversion from 'const uint8_t* {aka const unsigned char*}' to 'const char*'. this "data->payload" can't be converted to string, I'm still confused why it can't be converted to string

Who is online

Users browsing this forum: No registered users and 92 guests