• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь ESP8266 Thingspeak накопление и передача - съедает память.

Gecooo

New member
Приветствую.
Есть пример кода с Thingspeak - накапливает данные каждые 15 сек и затем передает каждые 2 минуты на сервер. Но с каждой передачей уменьшается freeheap и в конце зависает ESP8266.
Как побороть эту проблему?
Оригинал кода здесь. Я изменил только вывод данных.
Мой код:
Код:
/* This example shows how to bulk update a ThingSpeak channel using an Arduino MKR1000 or an ESP8266*/

#include<EthernetClient.h> //Uncomment this library to work with ESP8266
#include<ESP8266WiFi.h> //Uncomment this library to work with ESP8266

//#include<SPI.h> // Comment this to work with ESP8266 board
//#include<WiFi101.h> // Comment this to work with ESP8266 board

char jsonBuffer[500] = "["; // Initialize the jsonBuffer to hold data

char ssid[] = "XXXXXXXXXXXXX"; //  Your network SSID (name)
char pass[] = "XXXXXXXXXXXX"; // Your network password
WiFiClient client; // Initialize the WiFi client library

char server[] = "api.thingspeak.com"; // ThingSpeak Server

/* 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 = 120L * 1000L; // Post data every 2 minutes
const unsigned long updateInterval = 15L * 1000L; // Update once every 15 seconds

void setup() {
  Serial.begin(9600);
  // Attempt to connect to WiFi network
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
    delay(10000);  // Wait 10 seconds to connect
  }
  Serial.println("Connected to wifi");
  printWiFiStatus(); // Print WiFi connection information
}

void loop() {
  // If update time has reached 15 seconds, then update the jsonBuffer
  if (millis() - lastUpdateTime >=  updateInterval) {
    updatesJson(jsonBuffer);
    Serial.println(jsonBuffer);
    Serial.println(sizeof(jsonBuffer));
   
  }
   
}

// Updates the jsonBuffer with data
void updatesJson(char* jsonBuffer){
  /* JSON format for updates paramter in the API
   *  This example uses the relative timestamp as it uses the "delta_t". If your device has a real-time clock, you can provide the absolute timestamp using the "created_at" parameter
  *  instead of "delta_t".
   *  "[{\"delta_t\":0,\"field1\":-70},{\"delta_t\":15,\"field1\":-66}]"
   */
  // Format the jsonBuffer as noted above
  strcat(jsonBuffer,"{\"delta_t\":");
  unsigned long deltaT = (millis() - lastUpdateTime)/1000;
  size_t lengthT = String(deltaT).length();
  char temp[4];
  String(deltaT).toCharArray(temp,lengthT+1);
  strcat(jsonBuffer,temp);
  strcat(jsonBuffer,",");
  //long rssi = WiFi.RSSI();
  long freeheap = ESP.getFreeHeap();
  strcat(jsonBuffer, "\"field1\":");
  //lengthT = String(rssi).length();
  lengthT = String(freeheap).length();
  //String(rssi).toCharArray(temp,lengthT+1);
  String(freeheap).toCharArray(temp,lengthT+1);
  strcat(jsonBuffer,temp);
//    strcat(jsonBuffer,",");
//  long freeheap = ESP.getFreeHeap();
//  strcat(jsonBuffer, "\"field2\":");
//  lengthT = String(freeheap).length();
//  String(freeheap).toCharArray(temp,lengthT+1);
//  strcat(jsonBuffer,temp);
  strcat(jsonBuffer,"},");
  // If posting interval time has reached 2 minutes, then update the ThingSpeak channel with your data
  if (millis() - lastConnectionTime >=  postingInterval) {
        size_t len = strlen(jsonBuffer);
        jsonBuffer[len-1] = ']';
        httpRequest(jsonBuffer);
  }
  lastUpdateTime = millis(); // Update the last update time
  Serial.println(sizeof(temp));
}

// Updates the ThingSpeakchannel with data
void httpRequest(char* jsonBuffer) {
  /* JSON format for data buffer in the API
   *  This example uses the relative timestamp as it uses the "delta_t". If your device has a real-time clock, you can also provide the absolute timestamp using the "created_at" parameter
   *  instead of "delta_t".
   *   "{\"write_api_key\":\"YOUR-CHANNEL-WRITEAPIKEY\",\"updates\":[{\"delta_t\":0,\"field1\":-60},{\"delta_t\":15,\"field1\":200},{\"delta_t\":15,\"field1\":-66}]
   */
  // Format the data buffer as noted above
  char data[500] = "{\"write_api_key\":\"XXXXXXXXXX\",\"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
  // POST data to ThingSpeak
  if (client.connect(server, 80)) {
    client.println("POST /channels/XXXXXX/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 (Arduino ESP8266)");
    client.println("Connection: close");
    client.println("Content-Type: application/json");
    client.println("Content-Length: "+data_length);
    client.println();
    client.println(data);
  }
//  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 connection time
}

void printWiFiStatus() {
  // Print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // Print your device IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // Print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
 

Gecooo

New member
попробуйте
после 81 строки написать
*jsonBuffer=0;
проходит только первый пакет данных на сервер, далее ошибка. А память с каждым пакетом уменьшается все-равно.

причем тут динамический?
Это на СИ косвенное присваивание нулевому элементу
если в дурине этого нет то напишите
jsonBuffer[0]=0;
то же самое. вот вывод в сериал:Screenshot_26.png
 
Последнее редактирование:

Юрий Ботов

Moderator
Команда форума
Попробуйте так:

Код:
// Updates the jsonBuffer with data
void updatesJson(char* jsonBuffer){
  /* JSON format for updates paramter in the API
   *  This example uses the relative timestamp as it uses the "delta_t". If your device has a real-time clock, you can provide the absolute timestamp using the "created_at" parameter
  *  instead of "delta_t".
   *  "[{\"delta_t\":0,\"field1\":-70},{\"delta_t\":15,\"field1\":-66}]"
   */
 String temps = String("");
  // Format the jsonBuffer as noted above
  strcat(jsonBuffer,"{\"delta_t\":");
  unsigned long deltaT = (millis() - lastUpdateTime)/1000;
  size_t lengthT = String(deltaT).length();
  char temp[4];
  temps = String(deltaT);
  temps.toCharArray(temp,lengthT+1);
  strcat(jsonBuffer,temp);
  strcat(jsonBuffer,",");
  //long rssi = WiFi.RSSI();
  long freeheap = ESP.getFreeHeap();
  strcat(jsonBuffer, "\"field1\":");
  //lengthT = String(rssi).length();
  lengthT = String(freeheap).length();
  //String(rssi).toCharArray(temp,lengthT+1);
  temps = String(freeheap);
  temps.toCharArray(temp,lengthT+1);
  strcat(jsonBuffer,temp);
//    strcat(jsonBuffer,",");
//  long freeheap = ESP.getFreeHeap();
//  strcat(jsonBuffer, "\"field2\":");
//  lengthT = String(freeheap).length();
//  String(freeheap).toCharArray(temp,lengthT+1);
//  strcat(jsonBuffer,temp);
  strcat(jsonBuffer,"},");
  // If posting interval time has reached 2 minutes, then update the ThingSpeak channel with your data
  if (millis() - lastConnectionTime >=  postingInterval) {
        size_t len = strlen(jsonBuffer);
        jsonBuffer[len-1] = ']';
        httpRequest(jsonBuffer);
  }
  lastUpdateTime = millis(); // Update the last update time
  Serial.println(sizeof(temp));
}
Возможно компилятор не отрабатывает деструктор необъявленного элемента...
 

Gecooo

New member
Все манипуляции были на версии SDK 2.4.1.
Попробовал поставил 2.4.0 - всё заработало, память не кушает.

Всем спасибо, что откликнулись на просьбу о помощи.
Screenshot_7.png
 
Сверху Снизу