ESP32 connection to Google cloud, Error : Settings incorrect or missing a cyper for SSL Connect with mqtt.2030.ltsapis.goog:8883 - google-cloud-platform

i am trying to connect ESP32 with google cloude
but i am getting this error
Settings incorrect or missing a cyper for SSL
Connect with mqtt.2030.ltsapis.goog:8883
ClientId: projects/nomadic-armor-279716/locations/asia-east1/registries/iot-sample-registry/devices/esp32newD
Waiting 60 seconds, retry will likely fail
my code is divided over 4 files :
esp32main :
#include "esp32-mqtt.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
setupCloudIoT();
}
void loop() {
mqttClient->loop();
delay(10); // <- fixes some issues with WiFi stability
if (!mqttClient->connected()) {
connect();
}
}
ciotic_config.h
// This file contains your configuration used to connect to Cloud IoT Core
#include "credentials.h"
// Wifi newtork details.
const char *ssid = WIFI_SSID;
const char *password = WIFI_PASSWD;
// Cloud iot details.
const char *project_id = PROJECT_ID;
const char *location = REGION;
const char *registry_id = REGISTRY;
const char *device_id = DEVICE;
// Configuration for NTP
const char* ntp_primary = "pool.ntp.org";
const char* ntp_secondary = "time.nist.gov";
#ifndef LED_BUILTIN
#define LED_BUILTIN 5
#endif
// To get the private key run (where private-key.pem is the ec private key
// used to create the certificate uploaded to google cloud iot):
// openssl ec -in <private-key.pem> -noout -text
// and copy priv: part.
// The key length should be exactly the same as the key length bellow (32 pairs
// of hex digits). If it's bigger and it starts with "00:" delete the "00:". If
// it's smaller add "00:" to the start. If it's too big or too small something
// is probably wrong with your key.
const char *private_key_str =
// Replace this below string with your own, in the same format
// The below key is dummy, so using it will not help you in any way
"f3:36:fe:81:72:36:77:60:29:1d:4a:fc:21:c7:6c:"
"96:75:2c:7f:6e:52:2f:c8:cb:7d:03:c8:25:ef:28:"
"61:0b";
// Time (seconds) to expire token += 20 minutes for drift
const int jwt_exp_secs = 3600; // Maximum 24H (3600*24)
// To get the certificate for your region run:
// openssl s_client -showcerts -connect mqtt.googleapis.com:8883
// for standard mqtt or for LTS:
// openssl s_client -showcerts -connect mqtt.2030.ltsapis.goog:8883
// Copy the certificate (all lines between and including ---BEGIN CERTIFICATE---
// and --END CERTIFICATE--) to root.cert and put here on the root_cert variable.
const char *root_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIDfDCCAmSgAwIBAgIJAJB2iRjpM5OgMA0GCSqGSIb3DQEBCwUAME4xMTAvBgNV\n"
"BAsMKE5vIFNOSSBwcm92aWRlZDsgcGxlYXNlIGZpeCB5b3VyIGNsaWVudC4xGTAX\n"
"BgNVBAMTEGludmFsaWQyLmludmFsaWQwHhcNMTUwMTAxMDAwMDAwWhcNMzAwMTAx\n"
"MDAwMDAwWjBOMTEwLwYDVQQLDChObyBTTkkgcHJvdmlkZWQ7IHBsZWFzZSBmaXgg\n"
"eW91ciBjbGllbnQuMRkwFwYDVQQDExBpbnZhbGlkMi5pbnZhbGlkMIIBIjANBgkq\n"
"hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWJP5cMThJgMBeTvRKKl7N6ZcZAbKDVA\n"
"tNBNnRhIgSitXxCzKtt9rp2RHkLn76oZjdNO25EPp+QgMiWU/rkkB00Y18Oahw5f\n"
"i8s+K9dRv6i+gSOiv2jlIeW/S0hOswUUDH0JXFkEPKILzpl5ML7wdp5kt93vHxa7\n"
"HswOtAxEz2WtxMdezm/3CgO3sls20wl3W03iI+kCt7HyvhGy2aRPLhJfeABpQr0U\n"
"ku3q6mtomy2cgFawekN/X/aH8KknX799MPcuWutM2q88mtUEBsuZmy2nsjK9J7/y\n"
"hhCRDzOV/yY8c5+l/u/rWuwwkZ2lgzGp4xBBfhXdr6+m9kmwWCUm9QIDAQABo10w\n"
"WzAOBgNVHQ8BAf8EBAMCAqQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\n"
"MA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEELsPOJZvPr5PK0bQQWrUrLUwDQYJ\n"
"KoZIhvcNAQELBQADggEBALnZ4lRc9WHtafO4Y+0DWp4qgSdaGygzS/wtcRP+S2V+\n"
"HFOCeYDmeZ9qs0WpNlrtyeBKzBH8hOt9y8aUbZBw2M1F2Mi23Q+dhAEUfQCOKbIT\n"
"tunBuVfDTTbAHUuNl/eyr78v8Egi133z7zVgydVG1KA0AOSCB+B65glbpx+xMCpg\n"
"ZLux9THydwg3tPo/LfYbRCof+Mb8I3ZCY9O6FfZGjuxJn+0ux3SDora3NX/FmJ+i\n"
"kTCTsMtIFWhH3hoyYAamOOuITpPZHD7yP0lfbuncGDEqAQu2YWbYxRixfq2VSxgv\n"
"gWbFcmkgBLYpE8iDWT3Kdluo1+6PHaDaLg2SacOY6Go=\n"
"-----END CERTIFICATE-----\n";
// In case we ever need extra topics
const int ex_num_topics = 0;
const char* ex_topics[ex_num_topics];
//const int ex_num_topics = 1;
//const char* ex_topics[ex_num_topics] = {
// "/devices/my-device/tbd/#"
//};
credentials.h
#define WIFI_SSID "Taha"
#define WIFI_PASSWD "mkt193540"
#define PROJECT_ID "nomadic-armor-279716"
#define REGION "asia-east1"
#define REGISTRY "iot-sample-registry"
#define DEVICE "esp32newD"
esp32-mqtt.h
// This file contains static methods for API requests using Wifi / MQTT
#ifndef __ESP32_MQTT_H__
#define __ESP32_MQTT_H__
#include <Client.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>
#include <CloudIoTCore.h>
#include <CloudIoTCoreMqtt.h>
#include "ciotc_config.h" // Update this file with your configuration
// The MQTT callback function for commands and configuration updates
// Place your message handler code here.
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
int ledonpos=payload.indexOf("ledon");
if (ledonpos != -1) {
// If yes, switch ON the ESP32 internal led
Serial.println("Switch led on");
digitalWrite(LED_BUILTIN, HIGH);
} else {
// If no, switch off the ESP32 internal led
Serial.println("Switch led off");
digitalWrite(LED_BUILTIN, LOW);
}
}
/////////////////////////////////////////////
// Initialize WiFi and MQTT for this board //
Client *netClient;
CloudIoTCoreDevice *device;
CloudIoTCoreMqtt *mqtt;
MQTTClient *mqttClient;
unsigned long iss = 0;
String jwt;
/*
///////////////////////////////
// Helpers specific to this board
///////////////////////////////
String getDefaultSensor() {
return "Wifi: " + String(WiFi.RSSI()) + "db";
}
*/
String getJwt() {
iss = time(nullptr);
Serial.println("Refreshing JWT");
jwt = device->createJWT(iss, jwt_exp_secs);
return jwt;
}
void setupWifi() {
Serial.println("Starting wifi");
WiFi.mode(WIFI_STA);
// WiFi.setSleep(false); // May help with disconnect? Seems to have been removed from WiFi
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
configTime(0, 0, ntp_primary, ntp_secondary);
Serial.println("Waiting on time sync...");
while (time(nullptr) < 1592336214) {
delay(10);
}
}
void connectWifi() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
}
void connect() {
connectWifi();
mqtt->mqttConnect();
}
void setupCloudIoT() {
device = new CloudIoTCoreDevice(
project_id, location, registry_id, device_id,
private_key_str);
setupWifi();
netClient = new WiFiClientSecure();
mqttClient = new MQTTClient(512);//1024
mqttClient->setOptions(180, true, 1000); // keepAlive, cleanSession, timeout
mqtt = new CloudIoTCoreMqtt(mqttClient, netClient, device);
mqtt->setUseLts(true);
mqtt->startMQTT();
}
#endif //__ESP32_MQTT_H__
this code suppose to communicate with cloud and receive "ledon" or "ledoff" and implement the command.

First post in here. I was trying the same thing here and just got comm between my ESP8266 and GCP. I've learned three major things:
ESP32 and ESP8266 share a few libraries that are not compatible. You need to select the right one.
On root_cert you need to put the RSA_key
On private key (on firmware) you put the EC_private, while in the IoT Core you put the ec_public.
Good luck.

Related

How to insert data to MySQL database with C++ language for Arduino sensor

I am trying to update my Arduino sensor data in my cloud MySQL database. I successfully connected it with my cloud database, but it gives me syntax error, which is
Error: 235 = You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a.acceleration.x, a.acceleration.y, a.acceleration.z, g.gyro.x, g.gyro.y,' at line 1"
I meant a.acceleration.x = x axis acceleration, a.acceleration.y = y axis acceleration, a.acceleration.z = z axis acceleration, g.gyro.x = x axis gyro, and so on from my Arduino MPU6050 sensor. How am I supposed to edit my code? Here is my code.
#include <SPI.h>
#include <WiFi101.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
Adafruit_MPU6050 mpu;
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server_addr(XX,XX,XX,XX); // IP of the MySQL *server* here
char user[] = "XXXXXX"; // MySQL user login username
char password[] = "XXXXXXXX"; // MySQL user login password
// WiFi card example
char ssid[] = "XXXXXXX"; // your SSID
char pass[] = "XXXXXXX"; // your SSID Password
char INSERT_SQL[] = "INSERT INTO sensor_data.Arduino_RawData (X_Axis_Acceleration, Y_axis_Acceleration, Z_Axis_Acceleration, X_Axis_Gyro, Y_Axis_Gyro, Z_Axis_Gyro) VALUES (a.acceleration.x, a.acceleration.y, a.acceleration.z, g.gyro.x, g.gyro.y, g.gyro.z)";
WiFiClient client;
MySQL_Connection conn((Client *)&client);
void setup() {
Serial.begin(115200);
while (!Serial); // wait for serial port to connect
// Begin WiFi section
int status = WiFi.begin(ssid, pass);
if ( status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// print out info about the connection:
else {
Serial.println("Connected to network");
IPAddress ip = WiFi.localIP();
Serial.print("My IP address is: ");
Serial.println(ip);
}
// End WiFi section
Serial.println("Connecting...");
if (conn.connect(server_addr, 3306, user, password)) {
delay(1000);
}
else
Serial.println("Connection failed.");
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
// set accelerometer range to +-8G
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
// set gyro range to +- 500 deg/s
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
// set filter bandwidth to 21 Hz
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(100);
}
void loop() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
delay(3000);
Serial.println("Recording data.");
// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
// Execute the query
cur_mem->execute(INSERT_SQL);
// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
delete cur_mem;
}
I expect this code to update Google Cloud SQL database following my columns. Please let me know what to edit.

Splitting BLE findings and sending out to MQTT line by line using an ESP32

So I have two ESP32s for this project, one sending BLE scanned device info and the other ESP32 sending the scan results to an MQTT broker. I am currently facing the issue where I cannot break the results up into multiple JSON lines and send them out to the MQTT broker line by line. Please do let me know if you have any solutions. Thank you!!
#include <WiFi.h> //Remove when not MQTT-ing using WiFi
#include <PubSubClient.h>
const char* ssid = "--------";
const char* password = "+++++++++++";
#define RXD2 16
#define TXD2 17
WiFiClient espClient;
PubSubClient client(espClient);
// MQTT Broker
const char* mqtt_broker = "broker.hivemq.com";
const char* topic = "**********";
const int mqtt_port = 1883;
void setup() {
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
//connecting to a mqtt broker
client.setServer(mqtt_broker, mqtt_port);
while (!client.connected()) {
String client_id = "esp32-client-";
client_id += String(WiFi.macAddress());
Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
if (client.connect(client_id.c_str())) {
Serial.println("Public hivemq broker connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
String msg = "";
msg = Serial2.readString();
//String msg = "test MQTT";
// publish
int index = msg.lastIndexOf('}');
int length = msg.length();
String subMsg = msg.substring(index, length);
client.publish(topic,subMsg.c_str());
Serial.println("Message has been sent is: ");
Serial.println(subMsg.c_str();
delay(5000);
}
This is the output that I have:
{"Device Name":"GXHGA22CF3B9","EDID":"d4:0b:dd:2c:f3:b9","RTID":"FF005802600001F","RSSI":"-77"}
{"Device Name":"","EDID":"d7:9c:0e:1d:e6:a2","RTID":"FF005802600001F","RSSI":"-71"}
{"Device Name":"Buds2","EDID":"d8:4d:72:1f:80:15","RTID":"FF005802600001F","RSSI":"-75"}
{"Device Name":"KBPro_185309","EDID":"dd:34:02:06:33:a8","RTID":"FF005802600001F","RSSI":"-87"}
{"Device Name":"GXHGA2DAEC2A","EDID":"de:1e:da:da:ec:2a","RTID":"FF005802600001F","RSSI":"-86"}
{"Device Name":"","EDID":"e9:c7:1b:79:e1:41","RTID":"FF005802600001F","RSSI":"-76"}
{"Device Name":"","EDID":"e9:f5:80:7f:c8:ea","RTID":"FF005802600001F","RSSI":"-89"}
{"Device Name":"","EDID":"ef:e0:22:b2:c6:d0","RTID":"FF005802600001F","RSSI":"-84"}
{"Device Name":"GXHGA20A5D4A","EDID":"f6:4e:4d:0a:5d:4a","RTID":"FF005802600001F","RSSI":"-84"}
{"Device Name":"","EDID":"ff:65:fa:78:7f:c1","RTID":"FF005802600001F","RSSI":"-93"}
{"Device Name":"","EDID":"00:64:0f:26:92:09","RTID":"FF005802600001F","RSSI":"-90"}
Your current code finds the last } in the message and then takes that as the starting point for a substring to the end of the message. So you will always get a } character. You need to loop through the messages in a single read and find the start and end braces, pulling out each message.
Something like this:
void loop() {
// put your main code here, to run repeatedly:
String msg = "";
msg = Serial2.readString();
int start_idx = 0 ;
while( start_idx >= 0 )
{
start_idx = msg.indexOf('{',start_idx);
if ( start_idx >= 0 )
{
int end_idx = msg.indexOf('}',start_idx+1);
String subMsg = msg.substring(start_idx, end_idx+1);
client.publish(topic,subMsg.c_str());
Serial.println("Message has been sent is: ");
Serial.println(subMsg.c_str();
start_idx = end_idx + 1;
}
}
}
Note - this assumes that the JSON doesn't contain any objects - since the internal braces will also be separated. It also assumes you get complete JSON messages with each Serial read (i.e. they're not truncated). So you may need to handle these cases - but this should give you a start.
I've also removed the delay - I don't know why you'd want to delay for 5 seconds between reads - unless this was just for testing.

Google iot MQTT - ESP32 Connects the first time and only reconnects after 30m

I'm working with google Iot cloud with ESP32, I am sending fake values just to make a test with the MQTT data PUB/SUB, Apparently I'm succeeding in publishing the values, sometimes, I can't reconnect to google iot.
I don't know why it keeps checking wifi...publising and doest check for the JWT key.
I have noticed that if I connect once to the google iot and then I unplug the esp32 from my pc (disconnect no power), and plug it back again and try to connect, I will enter in this "checking wifi" for about 30m, until I can connect back to google iot. How can fix this? I beleived there was something to deal with this:
// Time (seconds) to expire token += 20 minutes for drift
const int jwt_exp_secs = 3600; // Maximum 24H (3600*24)
When I manage to get a good response that send info to the servers, i get this+:
entry 0x400806b8
Setup.....
Starting wifi
Connecting to WiFi
Connected
Waiting on time sync...
checking wifi...
connecting...Refreshing JWT
connected
Library connected!
incoming: /devices/esp32-device/config -
incoming: /devices/esp32-device/config -
Publishing value
Publishing value
Publishing value
Publishing value
Publishing value
There is times that I get a bad response for about 30m, using the same code, it seems to be sending constant data, which shouldn't be constant.(wasn't suppose to happen):
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Setup.....
Starting wifi
Connecting to WiFi
Connected
Waiting on time sync...
checking wifi...Publishing value
checking wifi...checking wifi...checking wifi...Publishing value
(Just keeps repeating)
This is the main connection to MQTT code, with the attempts to fix problems, but didn't work:
// This file contains static methods for API requests using Wifi / MQTT
#ifndef __ESP32_MQTT_H__
#define __ESP32_MQTT_H__
#include <Client.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>
#include <CloudIoTCore.h>
#include <CloudIoTCoreMqtt.h>
#include "ciotc_config.h" // Update this file with your configuration
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
// Initialize WiFi and MQTT for this board
Client *netClient;
CloudIoTCoreDevice *device;
CloudIoTCoreMqtt *mqtt;
MQTTClient *mqttClient;
unsigned long iat = 0;
String jwt;
String getDefaultSensor() {
return "Wifi: " + String(WiFi.RSSI()) + "db";
}
String getJwt() {
Serial.println("Entered JWT");
delay(5000);
iat = time(nullptr);
Serial.println("Refreshing JWT");
jwt = device->createJWT(iat, jwt_exp_secs);
return jwt;
}
void setupWifi() {
Serial.println("Starting wifi");
Serial.print("WIFI status = ");
Serial.println(WiFi.getMode());
WiFi.disconnect(true);
delay(3000);
WiFi.mode(WIFI_STA);
delay(3000);
Serial.print("WIFI status = ");
Serial.println(WiFi.getMode());
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.println("Connected");
delay(5000);
configTime(0, 0, ntp_primary, ntp_secondary);
Serial.println("Waiting on time sync...");
while (time(nullptr) < 1510644967) {
delay(10);
}
}
void connectWifi() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
}
delay(5000);
}
bool publishTelemetry(String data) {
return mqtt->publishTelemetry(data);
}
bool publishTelemetry(const char* data, int length) {
return mqtt->publishTelemetry(data, length);
}
bool publishTelemetry(String subfolder, String data) {
return mqtt->publishTelemetry(subfolder, data);
}
bool publishTelemetry(String subfolder, const char* data, int length) {
return mqtt->publishTelemetry(subfolder, data, length);
}
void connect() {
connectWifi();
mqtt->mqttConnect();
delay(5000);
}
void setupCloudIoT() {
device = new CloudIoTCoreDevice(
project_id, location, registry_id, device_id,
private_key_str);
setupWifi();
netClient = new WiFiClientSecure();
mqttClient = new MQTTClient(512);
mqttClient->setOptions(180, true, 1000); // keepAlive, cleanSession, timeout
mqtt = new CloudIoTCoreMqtt(mqttClient, netClient, device);
mqtt->setUseLts(true);
mqtt->startMQTT();
delay(5000);
}
#endif //__ESP32_MQTT_H__
This is the main.cpp:
#include <Arduino.h>
#include <WiFiClientSecure.h>
#include "esp32-mqtt.h"
#include <ArduinoJson.h>
#define led 14
char buffer[100];
float counter = 0;
float counter1 = 0;
void setup() {
Serial.begin(115200);
Serial.println("Setup.....");
pinMode(led, OUTPUT);
setupCloudIoT();
}
unsigned long lastMillis = 0;
void loop() {
mqtt->loop();
delay(10); // <- fixes some issues with WiFi stability
if (!mqttClient->connected()) {
connect();
}
counter++;
counter1++;
if (millis() - lastMillis > 1000) {
Serial.println("Publishing value");
lastMillis = millis();
float temp = counter;
float hum = counter1;
StaticJsonDocument<100> doc;
doc["temp"] = temp;
doc["humidity"] = hum;
serializeJson(doc, buffer);
publishTelemetry(buffer);
}
}
Does someone know if there is any other module that doesn't have this same issue?
The issue you face is IMHO not a problem of your code or the MQTT-lib you use. There seems to be a problem in the ESP32 core package (1.04 has it still). See this collection of issues from github and some proposed work around, which in the end delay the problem but do not solve it.
Issue with MQTT collection of problems from 2018 till today
These are open issues regarding WiFi re/connection problems
A test case for provoking an error is linked from one of the post.I use for identifying ESP32 specific problems the identical programm on an esp8266 with MQTT connection and there it runs for months.The ESP32 people have the bad habit to leave issues uncommented open for month hopeing the stale bot closes them. So I just cited the open issues, if you search for closed issues you'll find some more) closed by stale bot and not by solution!

'dustDensity' is not captured

I'm trying to merge some code from another Arduino project into my current project. What i'm try to do is post the readings that I get from my current project to a web server, so that I can access it from my laptop or mobile device.
When I try to merge server code, I get the error 'dustDensity' is not captured. Not really sure as to why this is happening, and would appreciate some help to get around this issue.
Trying to compile this code in Arduino IDE but it won't.
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#define USE_AVG
#define LED_BUILTIN 13
// Replace with your network credentials
const char* ssid = "ssid";
const char* password = "password";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Arduino pin numbers.
const int sharpLEDPin = 18; // Arduino digital pin 7 connect to sensor LED.
const int sharpVoPin = 25; // Arduino analog pin 5 connect to sensor Vo.
// For averaging last N raw voltage readings.
#ifdef USE_AVG
#define N 100
static unsigned long VoRawTotal = 0;
static int VoRawCount = 0;
#endif // USE_AVG
// Set the typical output voltage in Volts when there is zero dust.
static float Voc = 0.6;
// Use the typical sensitivity in units of V per 100ug/m3.
const float K = 0.5;
/////////////////////////////////////////////////////////////////////////////
// Helper functions to print a data value to the serial monitor.
void printValue(String text, unsigned int value, bool isLast = false) {
Serial.print(text);
Serial.print("=");
Serial.print(value);
if (!isLast) {
Serial.print(", ");
}
}
void printFValue(String text, float value, String units, bool isLast = false) {
Serial.print(text);
Serial.print("=");
Serial.print(value);
Serial.print(units);
if (!isLast) {
Serial.print(", ");
}
}
/////////////////////////////////////////////////////////////////////////////
// Arduino setup function.
void setup() {
// Set LED pin for output.
pinMode(sharpLEDPin, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// Start the hardware serial port for the serial monitor.
Serial.begin(9600);
// Wait two seconds for startup.
delay(2000);
Serial.println("");
Serial.println("GP2Y1014AU0F Demo");
Serial.println("=================");
}
// Arduino main loop.
void loop() {
// Turn on the dust sensor LED by setting digital pin LOW.
digitalWrite(sharpLEDPin, LOW);
// Wait 0.28ms before taking a reading of the output voltage as per spec.
delayMicroseconds(280);
// Record the output voltage. This operation takes around 100 microseconds.
int VoRaw = analogRead(sharpVoPin);
// Turn the dust sensor LED off by setting digital pin HIGH.
digitalWrite(sharpLEDPin, HIGH);
// Wait for remainder of the 10ms cycle = 10000 - 280 - 100 microseconds.
delayMicroseconds(9620);
// Print raw voltage value (number from 0 to 1023).
#ifdef PRINT_RAW_DATA
printValue("VoRaw", VoRaw, true);
Serial.println("");
#endif // PRINT_RAW_DATA
// Use averaging if needed.
float Vo = VoRaw;
#ifdef USE_AVG
VoRawTotal += VoRaw;
VoRawCount++;
if ( VoRawCount >= N ) {
Vo = 1.0 * VoRawTotal / N;
VoRawCount = 0;
VoRawTotal = 0;
} else {
return;
}
#endif // USE_AVG
// Compute the output voltage in Volts.
Vo = Vo / 1024.0 * 5.0;
printFValue("Vo", Vo*1000.0, "mV");
// Convert to Dust Density in units of ug/m3.
float dV = Vo - Voc;
if ( dV < 0 ) {
dV = 0;
Voc = Vo;
}
float dustDensity = dV / K * 100.0;
printFValue("DustDensity", dustDensity, "ug/m3", true);
Serial.println("");
if (dustDensity > 85.0) {
digitalWrite(LED_BUILTIN,HIGH);
}
else {
digitalWrite(LED_BUILTIN,LOW);
}
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html");
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", VoRaw().c_str());
});
// Start server
server.begin();
} // END PROGRAM
So not sure, why it won't compile. I'm trying to send dustDensity to a website from my ESP32.
Your code is currently
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
});
This code:
[](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", dustDensity().c_str());
}
is a "lambda expression". It's a function that won't be evaluated until request->send_P() is called. That means that dustDensity won't be defined at that point. For it to be available to the function it has to be "captured", which means that you must tell the lambda expression explicitly to make it available.
You'll also need to turn it into a C-string or String since the method wants a string argument.
So you need to rewrite this code to look more like this:
server.on("/temperature", HTTP_GET, [dustDensity](AsyncWebServerRequest *request){
request->send(200, "text/plain", String(dustDensity()));
});
The changes here are:
- add dustDensity to the brackets in the lambda so that it's captured and available inside the function
- change send_P to send because send_P is meant for sending strings stored in PROGMEM
- make a String from dustDensity so that send() has some text to send
ESPAsyncWebServer is extensively documented with lots of examples. I highly recommend reading the documentation if you're using it.

How to store response from html request in char array on arduino?

I have an Arudino Uno with an Adafruit CC3000 wifi shield attached.
I am trying to send multiple http requests and store the results from the GET requests. I can make and receive the requests successfully, but space on the arduino (in the buffer?) runs out when I try to store more than one of the responses.
I'm happy to store one string at a time so I figured that instead of using the arduino String class if I use a char array instead and allocate memory, I can then free the memory afterwards. That way I could use the memory as required, hopefully not cause any issues in running the rest of the code. I know this also depends on how long the incoming response is, but let's assume the response size is small enough. Feel free to shoot me down if there are flaws in my logic... (likely)
I tried variations of creating the char array without having to define the size beforehand and then using strcpy or strcat to append the new characters, but with no success.
I want to do something in the process of: create char array, fill it, use it, free it from memory.
In the past I've used this method in such a form:
char *array = new char[size_wanted];
strcpy(array,some_char_array);
strcat(array,some_other_char_array);
This of course works well when you know what size_wanted is. I don't until I read the buffer, but once I've read the buffer I've read it, so cannot read it again. Am I missing a trick here?! Is there a simpler way to do this using the Arduino String class? Am I missing the obvious or just not understanding how this works? Any ideas would be greatly appreciated.
My code:
/***************************************************
Adafruit CC3000 Wifi Breakout & Shield Example
****************************************************/
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 2 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed
#define WLAN_SSID "wifi"
#define WLAN_PASS "passoword"
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3000
// What page to grab!
#define WEBSITE "www.adafruit.com"
#define WEBPAGE "/testwifi/index.html"
uint32_t ip;
int n = 1;
char* result;
void setup(void)
{
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
/* Initialise the module */
Serial.println(F("\nInitializing..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.println(F("Connected!"));
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
ip = 0;
// Try looking up the website's IP address
Serial.print(WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);
String r1, r2, r3, r4, r5;
r1 = connect_to_webclient();
r2 = connect_to_webclient();
r3 = connect_to_webclient();
r4 = connect_to_webclient();
r5 = connect_to_webclient();
/*
Serial.println("RESULTS:");
Serial.println("r1:"); Serial.println(r1);
Serial.println("r2:"); Serial.println(r2);
Serial.println("r3:"); Serial.println(r3);
Serial.println("r4:"); Serial.println(r4);
Serial.println("r5:"); Serial.println(r5);
*/
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time your try to connect ... */
Serial.println(F("\n\nDisconnecting"));
cc3000.disconnect();
}
void loop(void)
{
delay(1000);
}
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
String connect_to_webclient() {
/* Try connecting to the website.
Note: HTTP/1.1 protocol is used to keep the server from closing the connection before all data is read.
*/
Serial.print("\nConnection number: ");
Serial.println(n);
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
Serial.println("Connected succeeded");
www.fastrprint(F("GET "));
www.fastrprint(WEBPAGE);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("-------------------------------------"));
/* Read data until either the connection is closed, or the idle timeout is reached. */
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
Serial.print(c);
//strcat(result, c);
lastRead = millis();
}
}
www.close();
Serial.println(F("-------------------------------------"));
n++;
return result;
}