How to display all char with string format in split string method
Posted: 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
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
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;
}
}
"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