使用 Arduino 或 ESP8266 进行批量更新
此示例展示如何使用 Arduino® MKR1000 开发板或 ESP8266 开发板连接到 Wi-Fi® 网络,以持续收集 Wi-Fi 信号强度并批量更新 ThingSpeak™ 通道。
您可以使用Bulk-Write JSON Data API 批量收集数据并将其发送到 ThingSpeak 通道。此策略可降低设备的耗电量。在此示例中,您使用 Arduino MKR1000 开发板每 15 秒收集一次数据,每 2 分钟更新一次通道。由于 Arduino MKR1000 和 ESP8266 开发板没有实时时钟,因此您可以使用相对时间戳来发送批量更新消息。
设置
创建一个通道,如图 通过新通道收集数据 所示。
如果您使用的是 Arduino MKR1000 开发板,请将库
WiFi101.h和SPI.h包含到您的 Arduino 草图中。如果您使用的是 ESP8266 开发板,请将库EthernetClient.h和ESP8266WiFi.h添加到您的 Arduino 草图中
代码
1)首先包含适合您的硬件的库。
// #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
2) 初始化 jsonBuffer 来保存 JSON 数据。
char jsonBuffer[500] = "["; // Initialize the jsonBuffer to hold data
3) 定义 Wi-Fi 凭证以将您的 Arduino 板连接到网络,并初始化 Wi-Fi 客户端库。
char ssid[] = "YOUR-NETWORK-SSID"; // Your network SSID (name) char pass[] = "YOUR-NETWORK-PWD"; // Your network password WiFiClient client; // Initialize the Wi-Fi client library
4) 定义 ThingSpeak 服务器。
char server[] = "api.thingspeak.com"; // ThingSpeak Server
5) 定义跟踪上次连接时间和上次更新时间的其他全局变量。另外,定义更新数据的时间间隔,并将数据发布到 ThingSpeak。
/* 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
6) 使用 setup 方法初始化串口数据传输并连接 Wi-Fi 网络。
void setup() {
Serial.begin(9600);
// Attempt to connect to Wi-Fi 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 Wi-Fi");
printWiFiStatus(); // Print Wi-Fi connection information
}
7) 在 loop 方法中,调用 updatesJson 方法每秒更新一次 jsonBuffer 数据。
void loop() {
// If update time has reached 1 second, then update the jsonBuffer
if (millis() - lastUpdateTime >= updateInterval) {
updatesJson(jsonBuffer);
}
}
8) 定义 updatesJson 方法,不断用数据更新 jsonBuffer。由于 Arduino MKR1000 没有实时时钟,您可以使用 'delta_t' 参数来定义连续消息之间的相对时间戳(以秒为单位)。如果您的设备有实时时钟,则可以使用绝对时间戳。用 'delta_t' 参数替换 'created_at' 参数。将消息格式化为 Bulk-Write JSON Data 中提到的格式的 JSON。调用 httpRequest 方法每 2 分钟向 ThingSpeak 发送一次数据。
// Updates the josnBuffer with data
void updatesJson(char* jsonBuffer){
/* JSON format for updates parameter in the API
* This example uses the relative timestamp as it uses the "delta_t".
* You can also provide the absolute timestamp using the "created_at" parameter instead of "delta_t".
* "[{\"delta_t\":0,\"field1\":-70},{\"delta_t\":3,\"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();
strcat(jsonBuffer, "\"field1\":");
lengthT = String(rssi).length();
String(rssi).toCharArray(temp,lengthT+1);
strcat(jsonBuffer,temp);
strcat(jsonBuffer,"},");
// If posting interval time has reached 2 minutes, 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
}
9) 定义 httpRequest 方法向 ThingSpeak 发送数据,并打印服务器的响应代码。响应代码 202 表示服务器已接受处理请求。
// 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".
* 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\":\"YOUR-CHANNEL-WRITEAPIKEY\",\"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/YOUR-CHANNEL-ID/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 conenction time
}
10) 定义 printWiFiStatus 函数来打印您的设备 IP 地址和信号强度。
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");
}