I have spent many hours now trying to come to a solution that I feel should be simple however I am not familiar with C++ programming. The goal I have is the following:
- Publish event that triggers webhook to get weather data from api.
- Receive weather data from api and merge it with current DHT22 temperature/humidity reading.
- Send a formatted JSON string with the combined weather data via webhook to MongoDB.
I have the webhook call to the weather api recieving data. I have the webhook call to MongoDB sending data in the correct manner. The issue I currently have is getting the values from the weather api webhook response into the combined result needed to send to MongoDB.
The "outside_humidity" value doesn't get set in the final bit:
{"outside_temperature": 45.54, "outside_humidity": , "inside_temperature": -4.00, "inside_humidity": -4.00}
Also, both "inside_" values return -4.00 for a while after I update the firmware but then eventually register what I would expect from the DHT22 sensor. Not sure why.
Here is my code. DISCLAIMER: I used ChatGPT to get some of the key:value parsing since I am unfamiliar with C++.
#include <PietteTech_DHT.h>
#define DHTTYPE DHT22
#define DHTPIN D4
// sensor sending interval (seconds)
#define SEND_INTERVAL 600
PietteTech_DHT DHT(DHTPIN, DHTTYPE);
float humidity;
float temperature;
char humidityString[10];
char temperatureString[10];
char temperatureBuffer[10];
char humidityBuffer[10];
int failed = 0;
// last time since we sent sensor readings
int lastUpdate = 0;
void parseKeyValue(const char *inputString, char delimiter, std::function<void(const char *, const char *)> callback) {
char token[40]; // Adjust the size based on your needs
char key[20]; // Adjust the size based on your needs
char value[20]; // Adjust the size based on your needs
int tokenIndex = 0;
for (int i = 0; i < strlen(inputString); i++) {
char currentChar = inputString[i];
if (currentChar == delimiter || currentChar == '\0') {
// Null-terminate the token
token[tokenIndex] = '\0';
// Extract key and value from the token
int colonIndex = -1;
for (int j = 0; j < tokenIndex; j++) {
if (token[j] == ':') {
colonIndex = j;
break;
}
}
if (colonIndex != -1) {
// Null-terminate the key and value
strncpy(key, token, colonIndex);
key[colonIndex] = '\0';
strncpy(value, token + colonIndex + 1, tokenIndex - colonIndex - 1);
value[tokenIndex - colonIndex - 1] = '\0';
// Invoke the callback function with key and value
callback(key, value);
}
// Reset the token index for the next token
tokenIndex = 0;
} else {
// Build the token
token[tokenIndex++] = currentChar;
}
}
}
void keyValueCallback(const char *key, const char *value) {
// Store the parsed values in variables
if (strcmp(key, "temp") == 0) {
strncpy(temperatureBuffer, value, sizeof(temperatureBuffer));
} else if (strcmp(key, "hum") == 0) {
strncpy(humidityBuffer, value, sizeof(humidityBuffer));
}
}
void setup()
{
Serial.begin(9600);
DHT.begin();
// configure Particle variables - float isn't accepted, so we have to use string versions
Particle.variable("temperature", &temperatureString[0], STRING);
Particle.variable("humidity", &humidityString[0], STRING);
// Subscribe to the integration response event
Particle.subscribe("hook-response/currentWeather", myHandler, MY_DEVICES);
// run the first measurement
loop();
}
void myHandler(const char *event, const char *data)
{
const char *inputString = data;
char delimiter = ',';
// Parse the input string
parseKeyValue(data, delimiter, keyValueCallback);
// Create a JSON-formatted string
char jsonString[150]; // Adjust the size based on your needs
snprintf(jsonString, sizeof(jsonString), "{\"outside_temperature\": %s, \"outside_humidity\": %s, \"inside_temperature\": %s, \"inside_humidity\": %s}", temperatureBuffer, humidityBuffer, temperatureString, humidityString);
// Publish the JSON-formatted string
Particle.publish("weatherMongoDB", jsonString, PRIVATE);
}
void loop()
{
int now = Time.now();
// only run every SEND_INTERVAL seconds
if (now - lastUpdate < SEND_INTERVAL) {
return;
}
lastUpdate = now;
int result = DHT.acquireAndWait(2000);
temperature = DHT.getFahrenheit();
humidity = DHT.getHumidity();
// // convert floats to strings for Particle variables
sprintf(temperatureString, "%.2f", temperature);
sprintf(humidityString, "%.2f", humidity);
// Particle.publish("temperature", temperatureString, PRIVATE);
// Particle.publish("humidity", humidityString, PRIVATE);
// weather API webhook
// Get some data
String data = String(10);
Particle.publish("currentWeather", data, PRIVATE);
// Wait 60 seconds
delay(60000);
}