ThingSpeak Bulk update not running in loop.

3 views (last 30 days)
Hi, im trying to send data to Thingspeak in bulk/batches. I adopted this example <https://ww2.mathworks.cn/help/thingspeak/continuously-collect-data-and-bulk-update-a-thingspeak-channel-using-an-arduino-mkr1000-board-or-an-esp8266-board.html> .
After 1st batch of data is sent to thingspeak successfully, the code doesnot run loop to continue further buffer the data in JSON. That means it send data to server only once and then do nothing. Please guide to sort this issue.
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
const char apn[] = "***********";
const char gprsUser[] = "";
const char gprsPass[] = "";
const char simPIN[] = "";
const char server[] = "api.thingspeak.com";
const int port = 80;
char jsonBuffer[500] = "["; // Initialize the jsonBuffer to hold data
#define SerialMon Serial
#define SerialAT Serial1
#define TIMEOUT 5000
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM7600 // Modem is SIM7600
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#include <TinyGsmClient.h>
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
/* Collect data once every 15 seconds and post data to ThingSpeak channel once every 2 minutes */
unsigned long lastConnectionTime = 0; // Track the last connection time
unsigned long lastUpdateTime = 0; // Track the last update time
const unsigned long postingInterval = 20L * 1000L; // Post data every 2 minutes
const unsigned long updateInterval = 2L * 1000L; // Update once every 15 seconds
// Sensor Libraries
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHTPIN 32
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
void setup() {
SerialMon.begin(115200);
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
SerialMon.println("Initializing modem...");
modem.init();
// Configure
the wake up source as timer wake up
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
SerialMon.print("Connecting to ");
SerialMon.print(server);
if (!client.connect(server, port)) {
SerialMon.println(" Fail");
}
else {
SerialMon.println(" OK");
}
}
dht.begin();
}
void loop() {
// If update time has reached 1 second, then update the jsonBuffer
if (millis() - lastUpdateTime >= updateInterval) {
updatesJson(jsonBuffer);
}
}
// Updates the josnBuffer with data
void updatesJson(char* jsonBuffer) {
// Collect Hall effect sensor data
//int h = hallRead();
float t = dht.readTemperature();
float h = dht.readHumidity();
Serial.print("Temperature: "); Serial.println(t);
// Format a single data point as a JSON object
char temp[500]; // Temporary buffer for JSON object
//sprintf(temp, "{\"delta_t\":%lu,\"field1\":%d},", (millis() - lastUpdateTime) / 1000, t);
sprintf(temp, "{\"delta_t\":%lu,\"field1\":%.2f,\"field2\":%.2f},", (millis() - lastUpdateTime) / 1000, t, h);
// Append the JSON object to the jsonBuffer
strcat(jsonBuffer, temp);
// If 15 seconds have passed since the last update, send the data to ThingSpeak
if (millis() - lastConnectionTime >= postingInterval) {
// Close the JSON array
size_t len = strlen(jsonBuffer);
jsonBuffer[len - 1] = ']';
// Send data to ThingSpeak
httpRequest(jsonBuffer);
// Reset the jsonBuffer for the next batch of data
jsonBuffer[0] = '[';
jsonBuffer[1] = '\0';
}
lastUpdateTime = millis(); // Update the last update time
}
// Updates the ThingSpeakchannel with data
void httpRequest(char* jsonBuffer) {
// Format the data buffer as noted above
char data[500] = "{\"write_api_key\":\"MY_API_KEY\",\"updates\":"; // Replace YOUR-CHANNEL-WRITEAPIKEY with your ThingSpeak channel write API key
strcat(data,jsonBuffer);
strcat(data,"}");
// Close any connection before sending a new request
client.stop();
String data_length = String(strlen(data)+1); //Compute the data buffer length
Serial.println(data);
// POST data to ThingSpeak
if (client.connect(server, 80)) {
client.println("POST /channels/MY_CHANNEL_NUMBER/bulk_update.json HTTP/1.1"); // Replace YOUR-CHANNEL-ID with your ThingSpeak channel ID
client.println("Host: api.thingspeak.com");
client.println("User-Agent: mw.doc.bulk-update (ESP8266)");
client.println("Connection: close");
client.println("Content-Type: application/json");
client.println("Content-Length: "+data_length);
client.println();
client.println(data);
String answer=getResponse();
Serial.println( answer );
}
else {
Serial.println("Failure: Failed to connect to ThingSpeak");
}
delay(250); //Wait to receive the response
client.parseFloat();
String resp = String(client.parseInt());
Serial.println("Response code:"+resp); // Print the response code. 202 indicates that the server has accepted the response
jsonBuffer[0] = '['; //Reinitialize the jsonBuffer for next batch of data
jsonBuffer[1] = '\0';
lastConnectionTime = millis(); //Update the last conenction time
}
String getResponse(){
String response;
long startTime = millis();
delay( 200 );
while ( client.available() < 1 && (( millis() - startTime ) < TIMEOUT ) ){
delay( 5 );
}
if( client.available() > 0 ){ // Get response from server.
char charIn;
do {
charIn = client.read(); // Read a char from the buffer.
response += charIn; // Append the char to the string response.
} while ( client.available() > 0 );
}
client.stop();
return response;
}
  3 Comments
Husnain
Husnain on 30 Sep 2023
Edited: Christopher Stapels on 30 Sep 2023
I chnanged update time to 15 sec collect / 120 sec send. Problem is same. It runs the 1st round of loop, send data to thingspeak successfully, prints response code (as below), and then do nothing.
For debugging i also orinted temperature values, it prints temperature for 1st round but for 2nd round it doesnot even print temperature, that means the buffer is not restarting for second batch, there could be some problem with the JSON buffer.
Following is the serial printer output. it shows temperature readings in first batch, but after sending 1st batch it stops doing anything.
17:28:25.191 -> Temperature: 26.50
17:28:40.191 -> Temperature: 26.40
17:28:55.204 -> Temperature: 26.50
17:28:55.281 -> {"write_api_key":"xxxxxxxxxxxxxxxx","updates":[{"delta_t":15,"field1":26.50,"field2":54.70},{"delta_t":15,"field1":26.60,"field2":55.10},{"delta_t":15,"field1":26.50,"field2":55.30},{"delta_t":15,"field1":26.40,"field2":55.00},{"delta_t":15,"field1":26.60,"field2":55.10},{"delta_t":15,"field1":26.50,"field2":55.30},{"delta_t":15,"field1":26.40,"field2":54.90},{"delta_t":15,"field1":26.50,"field2":55.70}]}
17:28:56.884 -> HTTP/1.1 202 Accepted
17:28:56.884 -> Date: Sat, 30 Sep 2023 09:28:57 GMT
17:28:56.884 -> Content-Type: application/json; charset=utf-8
17:28:56.884 -> Transfer-Encoding: chunked
17:28:56.884 -> Connection: close
17:28:56.884 -> Status: 202 Accepted
17:28:56.884 -> Cache-Control: no-cache
17:28:56.884 -> Access-Control-Allow-Origin: *
17:28:56.884 -> Access-Control-Max-Age: 1800
17:28:56.884 -> X-Request-Id: cbd68b65-f44b-4124-9c09-09160e202bb9
17:28:56.884 -> Access-Control-Allow-Headers: origin, content-type, X-Requested-With
17:28:56.929 -> Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH
17:28:56.929 -> X-Frame-Options: SAMEORIGIN
17:28:56.929 ->
17:28:56.929 -> 10
17:28:56.929 -> {"success":true}
17:28:56.929 -> 0
17:28:56.929 ->
17:28:56.929 ->
Christopher Stapels
Christopher Stapels on 30 Sep 2023
Edited: Christopher Stapels on 30 Sep 2023
I think you are correct on the JSON buffer overflow. One way to test would be to prefill the buffer with data and just write the same buffer each time to ThingSpeak without recording new data.
Also have you tried initializing the JSON buffer as larger than 500?
I think its great you are getting this to work with a GSM modem. Edited out your API key in the serial output above.

Sign in to comment.

Answers (0)

Communities

More Answers in the  ThingSpeak Community

Categories

Find more on Read Data from Channel in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!