阿杜伊诺。将文本文件从SD卡发送到web服务器

阿杜伊诺。将文本文件从SD卡发送到web服务器,web,post,arduino,text-files,Web,Post,Arduino,Text Files,我有一个Arduino草图,每10分钟,将温度数据写入SD文本文件,并将数据发布到web服务器 如果internet连接丢失,草图将继续将数据保存到SD文本文件(但不会将其发布到web)。 当互联网连接恢复时,我需要 从SD卡读取整个文本文件并将其发布到web服务器(php脚本接收发布的内容) 使用以下代码,我可以发布到php脚本。但是现在我需要postdata变量包含文本文件 if (client.connect("192.168.1.100", 80))

我有一个Arduino草图,每10分钟,将温度数据写入SD文本文件,并将数据发布到web服务器

如果internet连接丢失,草图将继续将数据保存到SD文本文件(但不会将其发布到web)。 当互联网连接恢复时,我需要 从SD卡读取整个文本文件并将其发布到web服务器(php脚本接收发布的内容)

使用以下代码,我可以发布到php脚本。但是现在我需要postdata变量包含文本文件

          if (client.connect("192.168.1.100", 80))
          {
            client.println("POST /readfile.php HTTP/1.1");
            client.println("Host: 192.168.1.100");
            client.println("User-Agent: Arduino/1.0");
            client.println("Connection: close");            
            client.println("Content-Type: application/x-www-form-urlencoded");
            client.print("Content-Length: ");
            client.println(postdata.length());
            client.println("");
            client.println(postdata);
            delay(1);
            client.stop();
所以我需要一种方法来读取字符串(或任何)变量中的文本文件

我可以使用Arduino UNO、MEGA或ESP32
提前谢谢

这是一个完整的代码,可在ArduineIDE 1.8.12上使用ESP8266(核心1.6.3)或ESP32(核心1.0.4),并使用内置SD卡。
由于您没有提供数据文件结构的详细信息,因此假设是

  • 每个数据项都在一行中
  • 行内的数据结构在服务器上处理
  • 服务器期望并处理每个传输的一个数据条目(=行)
代码已注释,请阅读这些代码以了解详细信息:

#include "FS.h"
#include "SD.h"
#include "SPI.h"
#ifdef ESP32
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif

// function declaration
void postFileContent(const char * path );

#define FILE_LINE_LENGTH        81  // a line has 80 chars 
char txtLine[FILE_LINE_LENGTH];
char postdata [FILE_LINE_LENGTH];
bool readCondition = true;  // Has to be defined somewhere to trigger SD read

#ifdef ESP8266
const uint8_t chipSelect = 4;  //CS pin of the sd card reader
#endif
WiFiClient client;

void setup() {
  Serial.begin(115200);
#ifdef ESP32
  if (!SD.begin()) {
#elif defined(ESP8266)
  if (!SD.begin(chipSelect)) {
#endif
    Serial.println("Card reader mount failed");
    return;
  }
#ifdef ESP32
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
#endif
}

void loop() {
  //...... Your program structure
  if (client.connect("192.168.1.100", 80)) {
    if (readCondition == true) {
      postFileContent("/data_log.txt"); // Read file data_log.txt in Root directory
      readCondition = false; // reset condition
    }
    else {
      client.println("POST /readfile.php HTTP/1.1");
      client.println("Host: 192.168.1.100");
      client.println("User-Agent: Arduino/1.0");
      client.println("Connection: close");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(strlen(postdata));
      client.println("");
      client.println(postdata);
    }
    delay(1);
    client.stop();
  }
  //...... Your program structure

}

void postFileContent(const char* path) {
  Serial.print(F(" -- Reading entries from file = "));
  Serial.print(path);
  if (!SD.exists(path)) {
    Serial.println("ERROR: The required file does not exist.");
    return;
  }
#ifdef ESP32
  File file = SD.open(path);
#elif defined(ESP8266)
  File file = SD.open(path, FILE_READ); // FILE_READ is default so not realy needed but if you like to use this technique for e.g. write you need FILE_WRITE
#endif
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
  char c;
  uint8_t i = 0;

  while (file.available()) {
    c = file.read();
    if (c == '\n') { //Checks forline break
      txtLine[i] = '\0';
      Serial.print(F(" * "));
      Serial.println(txtLine); //This is where you get one line of file at a time.
      client.println("POST /readfile.php HTTP/1.1");
      client.println("Host: 192.168.1.100");
      client.println("User-Agent: Arduino/1.0");
      client.println("Connection: close");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(strlen(txtLine));
      client.println("");
      client.println(txtLine);
    }
    else if (c >= 32) {
      txtLine[i] = c;
      i++;
    }
  }
  file.close();
  Serial.println(F("DONE Reading"));
}
#包括“FS.h”
#包括“SD.h”
#包括“SPI.h”
#ifdef ESP32
#包括
#定义的elif(ESP8266)
#包括
#恩迪夫
//函数声明
void postFileContent(const char*path);
#定义文件行长度81//一行有80个字符
char txtLine[文件行长度];
char postdata[文件行长度];
bool readCondition=true;//必须在某个地方定义以触发SD读取
#ifdef ESP8266
const uint8\u t chipSelect=4//sd卡读卡器的CS pin码
#恩迪夫
无线客户端;
无效设置(){
序列号开始(115200);
#ifdef ESP32
如果(!SD.begin()){
#定义的elif(ESP8266)
如果(!SD.begin(芯片选择)){
#恩迪夫
Serial.println(“读卡器安装失败”);
返回;
}
#ifdef ESP32
uint8_t cardType=SD.cardType();
如果(cardType==卡\u无){
Serial.println(“未附SD卡”);
返回;
}
#恩迪夫
}
void循环(){
//……您的课程结构
if(客户端连接(“192.168.1.100”,80)){
if(readCondition==true){
postFileContent(“/data_log.txt”);//读取根目录中的文件数据_log.txt
readCondition=false;//重置条件
}
否则{
println(“POST/readfile.php HTTP/1.1”);
client.println(“主机:192.168.1.100”);
client.println(“用户代理:Arduino/1.0”);
client.println(“连接:关闭”);
client.println(“内容类型:application/x-www-form-urlencoded”);
client.print(“内容长度:”);
client.println(strlen(postdata));
客户。println(“”);
client.println(postdata);
}
延迟(1);
client.stop();
}
//……您的课程结构
}
无效postFileContent(常量字符*路径){
Serial.print(F(“--readingentriefromfile=”);
串行打印(路径);
如果(!SD.存在(路径)){
Serial.println(“错误:所需文件不存在。”);
返回;
}
#ifdef ESP32
File File=SD.open(路径);
#定义的elif(ESP8266)
File File=SD.open(path,File_READ);//File_READ是默认值,因此不需要,但如果您想使用此技术进行写入,则需要使用File_write
#恩迪夫
如果(!文件){
Serial.println(“打开文件读取失败”);
返回;
}
字符c;
uint8_t i=0;
while(file.available()){
c=file.read();
如果(c=='\n'){//检查换行符
txtLine[i]='\0';
连续打印(F(“*”);
Serial.println(txtLine);//这是一次获取一行文件的地方。
println(“POST/readfile.php HTTP/1.1”);
client.println(“主机:192.168.1.100”);
client.println(“用户代理:Arduino/1.0”);
client.println(“连接:关闭”);
client.println(“内容类型:application/x-www-form-urlencoded”);
client.print(“内容长度:”);
client.println(strlen(txtLine));
客户。println(“”);
client.println(txtLine);
}
如果(c>=32),则为else{
txtLine[i]=c;
i++;
}
}
file.close();
序列号。打印号(F(“完成读取”);
}

希望这能帮助您入门

这里有一个完整的代码,可以在ArduineIDE 1.8.12上使用ESP8266(core 1.6.3)或ESP32(core 1.0.4),并使用内置SD卡。
由于您没有提供数据文件结构的详细信息,因此假设是

  • 每个数据项都在一行中
  • 行内的数据结构在服务器上处理
  • 服务器期望并处理每个传输的一个数据条目(=行)
代码已注释,请阅读这些代码以了解详细信息:

#include "FS.h"
#include "SD.h"
#include "SPI.h"
#ifdef ESP32
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif

// function declaration
void postFileContent(const char * path );

#define FILE_LINE_LENGTH        81  // a line has 80 chars 
char txtLine[FILE_LINE_LENGTH];
char postdata [FILE_LINE_LENGTH];
bool readCondition = true;  // Has to be defined somewhere to trigger SD read

#ifdef ESP8266
const uint8_t chipSelect = 4;  //CS pin of the sd card reader
#endif
WiFiClient client;

void setup() {
  Serial.begin(115200);
#ifdef ESP32
  if (!SD.begin()) {
#elif defined(ESP8266)
  if (!SD.begin(chipSelect)) {
#endif
    Serial.println("Card reader mount failed");
    return;
  }
#ifdef ESP32
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
#endif
}

void loop() {
  //...... Your program structure
  if (client.connect("192.168.1.100", 80)) {
    if (readCondition == true) {
      postFileContent("/data_log.txt"); // Read file data_log.txt in Root directory
      readCondition = false; // reset condition
    }
    else {
      client.println("POST /readfile.php HTTP/1.1");
      client.println("Host: 192.168.1.100");
      client.println("User-Agent: Arduino/1.0");
      client.println("Connection: close");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(strlen(postdata));
      client.println("");
      client.println(postdata);
    }
    delay(1);
    client.stop();
  }
  //...... Your program structure

}

void postFileContent(const char* path) {
  Serial.print(F(" -- Reading entries from file = "));
  Serial.print(path);
  if (!SD.exists(path)) {
    Serial.println("ERROR: The required file does not exist.");
    return;
  }
#ifdef ESP32
  File file = SD.open(path);
#elif defined(ESP8266)
  File file = SD.open(path, FILE_READ); // FILE_READ is default so not realy needed but if you like to use this technique for e.g. write you need FILE_WRITE
#endif
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
  char c;
  uint8_t i = 0;

  while (file.available()) {
    c = file.read();
    if (c == '\n') { //Checks forline break
      txtLine[i] = '\0';
      Serial.print(F(" * "));
      Serial.println(txtLine); //This is where you get one line of file at a time.
      client.println("POST /readfile.php HTTP/1.1");
      client.println("Host: 192.168.1.100");
      client.println("User-Agent: Arduino/1.0");
      client.println("Connection: close");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(strlen(txtLine));
      client.println("");
      client.println(txtLine);
    }
    else if (c >= 32) {
      txtLine[i] = c;
      i++;
    }
  }
  file.close();
  Serial.println(F("DONE Reading"));
}
#包括“FS.h”
#包括“SD.h”
#包括“SPI.h”
#ifdef ESP32
#包括
#定义的elif(ESP8266)
#包括
#恩迪夫
//函数声明
void postFileContent(const char*path);
#定义文件行长度81//一行有80个字符
char txtLine[文件行长度];
char postdata[文件行长度];
bool readCondition=true;//必须在某个地方定义以触发SD读取
#ifdef ESP8266
const uint8\u t chipSelect=4;//sd卡读卡器的CS pin
#恩迪夫
无线客户端;
无效设置(){
序列号开始(115200);
#ifdef ESP32
如果(!SD.begin()){
#定义的elif(ESP8266)
如果(!SD.begin(芯片选择)){
#恩迪夫
Serial.println(“读卡器安装失败”);
返回;
}
#ifdef ESP32
uint8_t cardType=SD.cardType();
如果(cardType==卡\u无){
Serial.println(“未附SD卡”);
返回;
}
#恩迪夫
}
void循环(){
//……您的课程结构
if(客户端连接(“192.168.1.100”,80)){
if(readCondition==true){
postFileContent(“/data_log.txt”);//读取根目录中的文件数据_log.txt
readCondition=false;//重置条件
}
否则{
println(“POST/readfile.php HTTP/1.1”);
client.println(“主机:192.168.1.100”);
client.println(“用户代理:Arduino/1.0”);
client.println(“连接:关闭”);
client.println(“内容类型:application/x-www-form-urle