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

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!

Related

How to use RTCM data to achieve RTK?

I'm using this example from the Sparkfun Arduino Library
/*
Use ESP32 WiFi to get RTCM data from RTK2Go (caster) as a Client
By: SparkFun Electronics / Nathan Seidle
Date: November 18th, 2021
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example shows how to obtain RTCM data from a NTRIP Caster over WiFi
and push it over I2C to a ZED-F9x.
It's confusing, but the Arduino is acting as a 'client' to a 'caster'. In this case we will
use RTK2Go.com as our caster because it is free. See the NTRIPServer example to see how
to push RTCM data to the caster.
You will need to have a valid mountpoint available. To see available mountpoints go here: http://rtk2go.com:2101/
This is a proof of concept to show how to connect to a caster via HTTP. Using WiFi for a rover
is generally a bad idea because of limited WiFi range in the field.
For more information about NTRIP Clients and the differences between Rev1 and Rev2 of the protocol
please see: https://www.use-snip.com/kb/knowledge-base/ntrip-rev1-versus-rev2-formats/
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
RTK Surveyor: https://www.sparkfun.com/products/18443
RTK Express: https://www.sparkfun.com/products/18442
Hardware Connections:
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <WiFi.h>
#include "secrets.h"
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;
//The ESP32 core has a built in base64 library but not every platform does
//We'll use an external lib if necessary.
#if defined(ARDUINO_ARCH_ESP32)
#include "base64.h" //Built-in ESP32 library
#else
#include <Base64.h> //nfriendly library from https://github.com/adamvr/arduino-base64, will work with any platform
#endif
//Global variables
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long lastReceivedRTCM_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps
int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void setup()
{
Serial.begin(115200);
Serial.println(F("NTRIP testing"));
Wire.begin(); //Start I2C
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1);
}
Serial.println(F("u-blox module connected"));
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state.
myGNSS.setNavigationFrequency(1); //Set output in Hz.
Serial.print(F("Connecting to local WiFi"));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(F("."));
}
Serial.println();
Serial.print(F("WiFi connected with IP: "));
Serial.println(WiFi.localIP());
while (Serial.available()) Serial.read();
}
void loop()
{
if (Serial.available())
{
beginClient();
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
}
Serial.println(F("Press any key to start NTRIP Client."));
delay(1000);
}
//Connect to NTRIP Caster, receive RTCM, and push to ZED module over I2C
void beginClient()
{
WiFiClient ntripClient;
long rtcmCount = 0;
Serial.println(F("Subscribing to Caster. Press key to stop"));
delay(10); //Wait for any serial to arrive
while (Serial.available()) Serial.read(); //Flush
while (Serial.available() == 0)
{
//Connect if we are not already. Limit to 5s between attempts.
if (ntripClient.connected() == false)
{
Serial.print(F("Opening socket to "));
Serial.println(casterHost);
if (ntripClient.connect(casterHost, casterPort) == false) //Attempt connection
{
Serial.println(F("Connection to caster failed"));
return;
}
else
{
Serial.print(F("Connected to "));
Serial.print(casterHost);
Serial.print(F(": "));
Serial.println(casterPort);
Serial.print(F("Requesting NTRIP Data from mount point "));
Serial.println(mountPoint);
const int SERVER_BUFFER_SIZE = 512;
char serverRequest[SERVER_BUFFER_SIZE];
snprintf(serverRequest, SERVER_BUFFER_SIZE, "GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n",
mountPoint);
char credentials[512];
if (strlen(casterUser) == 0)
{
strncpy(credentials, "Accept: */*\r\nConnection: close\r\n", sizeof(credentials));
}
else
{
//Pass base64 encoded user:pw
char userCredentials[sizeof(casterUser) + sizeof(casterUserPW) + 1]; //The ':' takes up a spot
snprintf(userCredentials, sizeof(userCredentials), "%s:%s", casterUser, casterUserPW);
Serial.print(F("Sending credentials: "));
Serial.println(userCredentials);
#if defined(ARDUINO_ARCH_ESP32)
//Encode with ESP32 built-in library
base64 b;
String strEncodedCredentials = b.encode(userCredentials);
char encodedCredentials[strEncodedCredentials.length() + 1];
strEncodedCredentials.toCharArray(encodedCredentials, sizeof(encodedCredentials)); //Convert String to char array
snprintf(credentials, sizeof(credentials), "Authorization: Basic %s\r\n", encodedCredentials);
#else
//Encode with nfriendly library
int encodedLen = base64_enc_len(strlen(userCredentials));
char encodedCredentials[encodedLen]; //Create array large enough to house encoded data
base64_encode(encodedCredentials, userCredentials, strlen(userCredentials)); //Note: Input array is consumed
#endif
}
strncat(serverRequest, credentials, SERVER_BUFFER_SIZE);
strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE);
Serial.print(F("serverRequest size: "));
Serial.print(strlen(serverRequest));
Serial.print(F(" of "));
Serial.print(sizeof(serverRequest));
Serial.println(F(" bytes available"));
Serial.println(F("Sending server request:"));
Serial.println(serverRequest);
ntripClient.write(serverRequest, strlen(serverRequest));
//Wait for response
unsigned long timeout = millis();
while (ntripClient.available() == 0)
{
if (millis() - timeout > 5000)
{
Serial.println(F("Caster timed out!"));
ntripClient.stop();
return;
}
delay(10);
}
//Check reply
bool connectionSuccess = false;
char response[512];
int responseSpot = 0;
while (ntripClient.available())
{
if (responseSpot == sizeof(response) - 1) break;
response[responseSpot++] = ntripClient.read();
if (strstr(response, "200") > 0) //Look for 'ICY 200 OK'
connectionSuccess = true;
if (strstr(response, "401") > 0) //Look for '401 Unauthorized'
{
Serial.println(F("Hey - your credentials look bad! Check you caster username and password."));
connectionSuccess = false;
}
}
response[responseSpot] = '\0';
Serial.print(F("Caster responded with: "));
Serial.println(response);
if (connectionSuccess == false)
{
Serial.print(F("Failed to connect to "));
Serial.print(casterHost);
Serial.print(F(": "));
Serial.println(response);
return;
}
else
{
Serial.print(F("Connected to "));
Serial.println(casterHost);
lastReceivedRTCM_ms = millis(); //Reset timeout
}
} //End attempt to connect
} //End connected == false
if (ntripClient.connected() == true)
{
uint8_t rtcmData[512 * 4]; //Most incoming data is around 500 bytes but may be larger
rtcmCount = 0;
//Print any available RTCM data
while (ntripClient.available())
{
//Serial.write(ntripClient.read()); //Pipe to serial port is fine but beware, it's a lot of binary data
rtcmData[rtcmCount++] = ntripClient.read();
if (rtcmCount == sizeof(rtcmData)) break;
}
if (rtcmCount > 0)
{
lastReceivedRTCM_ms = millis();
//Push RTCM to GNSS module over I2C
myGNSS.pushRawData(rtcmData, rtcmCount, false);
Serial.print(F("RTCM pushed to ZED: "));
Serial.println(rtcmCount);
}
}
//Close socket if we don't have new data for 10s
if (millis() - lastReceivedRTCM_ms > maxTimeBeforeHangup_ms)
{
Serial.println(F("RTCM timeout. Disconnecting..."));
if (ntripClient.connected() == true)
ntripClient.stop();
return;
}
delay(10);
}
Serial.println(F("User pressed a key"));
Serial.println(F("Disconnecting..."));
ntripClient.stop();
}
on an ESP32 Thing Plus C with a ZED-F9P and it's working fine, but it only outputs RTCM data. How do I apply the RTCM data to the GPS data and achieve RTK? My goal is to have the ESP32 Thing Plus C output RTK Latitude and Longitude to the serial monitor.
Example output:
RTCM pushed to ZED: 163
RTCM pushed to ZED: 311
RTCM pushed to ZED: 1694
RTCM pushed to ZED: 1332
Any ideas would be appeciated! Thanks
Answered by PaulZC on Sparkfun Forum
Hi Jacob,
It sounds like everything is working OK. But, correct, there is
nothing in that example to actually print out the position.
Please try Example17. It is better-structured and uses callbacks to:
display your position; and push NMEA GGA data to the server. Some
NTRIP servers require the GGA data, others don't. If the GGA data
causes problems, you can comment this line to disable the push:
https://github.com/sparkfun/SparkFun_u- ... ck.ino#L81
Have fun! Paul

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.

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

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.

Google cloud MQTT with Esp32 Reusing JWT error

I am trying to send fake temperature data from an ESP32 to Google Cloud with Arduino IDE and using this library https://github.com/GoogleCloudPlatform/google-cloud-iot-arduino. I created a registry and a device on google iot core. On my side I manually put the csa certificate on the ESP32 and correctly set all parameters and private key string in 'ciotc_config.h'. When I try to connect I get in the Serial Monitor the following output repeting itself:
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Setup.....
Starting wifi
Connecting to WiFi
Connected
Waiting on time sync...
Esp32-mqtt:
void setupWifi() {
Serial.println("Starting wifi");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.println("Connected");
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(1000);
}
}
I made a change in the main.cpp just because I will not be working with those sensors:
unsigned long lastMillis = 0;
void loop() {
mqtt->loop();
delay(10); // <- fixes some issues with WiFi stability
if (!mqttClient->connected()) {
connect();
}
if (millis() - lastMillis > 60000) {
Serial.println("Publishing value");
lastMillis = millis();
float temp = 33;
float hum = 50;
StaticJsonDocument<100> doc;
doc["temp"] = temp;
doc["humidity"] = hum;
serializeJson(doc, buffer);
//publishTelemetry(mqttClient, "/sensors", getDefaultSensor());
publishTelemetry( buffer);
}
}
Image from PUB:
I guess it is just a debug information. It could be in the line where you write the JWT tag information.
I wrote a tutorial about how to connect the ESP32 to Google Cloud IoT with full source code that is very similar to your code but It didn't repeat that info. You can give a look https://www.survivingwithandroid.com/cloud-iot-core-esp32/ and you can reuse the code. Let me know if I can help you somehow.
It doesn't look like you're ever successfully connecting.
In your output, I see connecting... so it's in the mqttConnect() call, but it never outputs connected! so it's stuck in the while loop where it's calling getJwt()
Now, why it's not outputting the mqtt errors may mean your errors are related to something else, and the mqtt client is totally fine, which is why you aren't seeing any other output. As a debugging check, I'd put a Serial.println("fubar") in the mqttConnect() call above the delay(1000) and see if you get other output there, pointing at some other connection error other than an mqtt connection problem.

Arduino simple timed loop without delay() - millis() doesn't work?

Have some arduino code for temp loggers that is VERY NEARLY working....!
I've built an OTA routine so I can update them remotely, however the delay() loop I had to ensure it only logged temperatures every 15 mins is now causing problems as it effectively freezes the arduino by design for 15mins, meaning OTA wouldn't work whilst it is in this state.
Some suggestions say just to flip to millis() instead, but I can't seem to get this working and it's logging ~20 records every second at the moment.
Ideally I just want delay_counter counting up to the value in DELAY_TIME, then running the rest of the code and resetting the counter.
Can anyone help me and point out what I'm doing daft in my code???
// v2 Temp sensor
// Connecting to Home NAS
#include <DHT.h>
#include <DHT_U.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <InfluxDbClient.h>
#define SSID "xxx" //your network name
#define PASS "xxx" //your network password
#define VersionID "v3"
#define SensorName "ServerUnit" //name of sensor used for InfluxDB and Home Assistant
// Temp Sensor 1 - GardenTropical
// Temp Sensor 2 - GardenRoom
// Temp Sensor 3 - Greenhouse
// Temp Sensor 4 - OutsideGreenhouse
// Temp Sensor 5 - ServerUnit
// Connection Parameters for Jupiter InfluxDB
#define INFLUXDB_URL "http://192.168.1.5:8086"
#define INFLUXDB_DB_NAME "home_assistant"
#define INFLUXDB_USER "xxx"
#define INFLUXDB_PASSWORD "xxx"
// Single InfluxDB instance
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);
// Define data point with measurement name 'DaveTest`
Point sensor("BrynyneuaddSensors");
#define PORT 80
#define DHTPIN 4 // what pin the DHT sensor is connected to
#define DHTTYPE DHT22 // Change to DHT22 if that's what you have
#define BAUD_RATE 115200 //Another common value is 9600
#define DELAY_TIME 900000 //time in ms between posting data to Home Server
unsigned long delay_counter = 0;
DHT dht(DHTPIN, DHTTYPE);
//this runs once
void setup()
{
Serial.begin(BAUD_RATE);
// Connect to WIFI
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print("*");
}
// Initialise OTA Routine
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//initalize DHT sensor
dht.begin();
// set InfluxDB database connection parameters
client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME, INFLUXDB_USER, INFLUXDB_PASSWORD);
// Add constant tags - only once
sensor.addTag("device", SensorName);
// Check server connection
if (client.validateConnection()) {
Serial.print("Connected to InfluxDB: ");
Serial.println(client.getServerUrl());
} else {
Serial.print("InfluxDB connection failed: ");
Serial.println(client.getLastErrorMessage());
Serial.println(client.getServerUrl());
Serial.println("Exiting DB Connection");
}
}
//this runs over and over
void loop() {
ArduinoOTA.handle();
float h = dht.readHumidity();
Serial.print("Humidity: ");
Serial.println(h);
// Read temperature as Fahrenheit (isFahrenheit = true)
float c = dht.readTemperature();
Serial.print("Temperature: ");
Serial.println(c);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(c)) {
Serial.println("Reading DHT22 Failed, exiting");
return;
}
//update Influx DB channel with new values
updateTemp(c, h);
Serial.print("Writing to InfluxDB: ");
//INFLUXDB - clear temp data so it doesn't repeat
sensor.clearFields();
// Update Influx DB
sensor.addField("Temperature", c);
sensor.addField("Humidity", h);
Serial.println(sensor.toLineProtocol());
// Write data
client.writePoint(sensor);
//wait for delay time before attempting to post again
if(millis() >= DELAY_TIME){
delay_counter += 0;
}
//Increment Delay Counter
delay_counter++;
}
bool updateTemp(float tempC, float humid) {
WiFiClient client; // Create a WiFiClient to for TCP connection
Serial.println("Receiving HTTP response");
while (client.available()) {
char ch = static_cast<char>(client.read());
Serial.print(ch);
}
Serial.println();
Serial.println("Closing TCP connection");
client.stop();
return true;
}
Set a TimerObject. this seems to be what you want.
Download the Arduino TimerObject code from github and follow the installation instructions
#include "TimerObject.h"
Create the callback function
Create the TimerObject
Setup the TimerObject and periodically call update() in your loop():
// make sure to include the header
#include "TimerObject.h"
...
// setup your TimerObject
TimerObject* sensor_timer = new TimerObject(15 * 60 * 1000); // milliseconds
...
// define the stuff you want to do every 15 minutes and
// stick it in a function
// not sure what from your loop() needs to go in here
void doSensor()
{
float h = dht.readHumidity();
Serial.print("Humidity: ");
Serial.println(h);
// Read temperature as Fahrenheit (isFahrenheit = true)
float c = dht.readTemperature();
Serial.print("Temperature: ");
Serial.println(c);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(c)) {
Serial.println("Reading DHT22 Failed, exiting");
return;
}
//update Influx DB channel with new values
updateTemp(c, h);
Serial.print("Writing to InfluxDB: ");
//INFLUXDB - clear temp data so it doesn't repeat
sensor.clearFields();
// Update Influx DB
sensor.addField("Temperature", c);
sensor.addField("Humidity", h);
Serial.println(sensor.toLineProtocol());
// Write data
client.writePoint(sensor);
}
...
// add the timer setup to your setup()
// probably at the end is a good place
void setup()
{
...
// lots of stuff above here
sensor_timer->setOnTimer(&doSensor);
sensor_timer->Start();
}
// modify your loop() to check the timer on every pass
void loop()
{
ArduinoOTA.handle();
sensor_timer->Update();
}
If you don't want to wait 15 minutes for the first call of doSensor, you can explicitly call it at the end of your setup() function before you start the timer.
Here is an simple example how to use millis()
int last_report = -777;//dummy value
int REPORT_INTERVAL = 15 *60 ; // 15 minutes
void loop() {
ArduinoOTA.handle();
int interval = millis() / 1000 - last_report;
if (interval < REPORT_INTERVAL) {
return;
}
last_report = millis() / 1000;
//do some important stuff
}
Make it simole and use easy code:
const unsigned long timeIntervall = 15*60*1000; // 15 minutes
unsigned long timeStamp = 0;
void setup(){....}
void loop() {
ArduinoOTA.handle(); // is running all the time
// Code in this section only runs every timeIntervall - rollover safe
if(millis() - timeStamp > timeIntervall ){
float h = dht.readHumidity();
......
// Write data
client.writePoint(sensor);
timeStamp = millis(); // reset the timer
}
}