//20240107改成使用sd卡来记录温湿度信息,因为腾讯的云服务器1年到,续费太贵。
//20220830路由器重启导致无法上传不知卡住何处,故在loop和upload之前都判断下wifi,不通就重连,之前if显然不合适,必须while,下一步如果不行,遇到网络不通的直接esp restart
/*
2024017 2332
实现了从dht11读取数据,并从网上取得网络时间,然后把两个温度湿度加时间写入到sd卡里面,
每隔三秒写一次基,基本已经实现了,下一步要实现的就是把8266做成一个服务器,
然后直接可以从服务器下载了这个文。
*/
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Wire.h>
#include <DHT.h>
#include <SPI.h>
#include <SD.h>
// 引入 wifi 模块,并实例化,不同的芯片这里的依赖可能不同
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
WiFiClient espClient; //新添加
HTTPClient http;
WiFiClient client; //新添加
// 设置 wifi 信息
#define WIFI_SSID "xxx"//(这里面连你自己家的WiFi,注意要是2.4G频段的,5G的不行)
#define WIFI_PASSWD "xxxx"//(你自己家的WiFi密码)
const char* host = "server";
#define DHTPIN 3 // Digital pin connected to the DHT sensor
//配置spi信息
#define MOSI 13
#define MISO 12
#define CLK 14
#define CS 15
static bool hasSD = false;
File myFile;
File uploadFile;
ESP8266WebServer server(80);
// Uncomment the type of sensor in use:
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
String GetUrl;
String Sdtime;
int sta;
String response;
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
if (!SD.begin(12)) {
Serial.println("sd failed!");
return;
}
Serial.println("sd done.");
// 初始化 wifi
wifiInit(WIFI_SSID, WIFI_PASSWD);
//初始化 iot,需传入 wifi 的 client,和设备产品信息
Serial.println(F("start"));
dht.begin();
if (MDNS.begin(host)) {
MDNS.addService("http", "tcp", 80);
Serial.println("MDNS responder started");
Serial.println("You can now connect to http://192.168.4.1");
}
server.on("/list", HTTP_GET, printDirectory);
server.on("/edit", HTTP_DELETE, handleDelete);
server.on("/edit", HTTP_PUT, handleCreate);
server.on("/edit", HTTP_POST, []() {
returnOK();
}, handleFileUpload);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
// put your main code here, to run repeatedly:
}
void loop() {
checkwifi();
server.handleClient();
MDNS.update();
delay(10000);
Serial.println(F("开始获取网络时间"));
gettime();
upload2();
}
// 初始化 wifi 连接
void wifiInit(const char *ssid, const char *passphrase)
{
//静态地址、网关、子网掩码
IPAddress local_IP(192, 168, 0, 200);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns1(192,168,0,1); //太恶心的,不设置dns能连接wifi不能上网。
//设置
WiFi.config(local_IP, gateway, subnet,dns1);//设置静态IP
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWD);//路由器的WiFi名称和密码
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("=init 0x01 WiFi not Connect led red ");
}
Serial.println("Connected to AP");
Serial.println("WIFI SmartConfig Success");
Serial.printf("SSID:%s", WiFi.SSID().c_str());
Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());
Serial.print("LocalIP:");
Serial.print(WiFi.localIP());
Serial.print(" ,GateIP:");
Serial.println(WiFi.gatewayIP());
}
void checkwifi()
{
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("=0x02 WiFi not Connect led red ");
wifiInit(WIFI_SSID, WIFI_PASSWD);
++sta;
if (sta>=60){
sta=0;
ESP.restart();
}
}
}
void gettime(){
String GetUrl = "http://quan.suning.com/getSysTime.do";
//WiFiClient client; //新添加
Serial.println(F("开始获取网络时间函数内部"));
http.setTimeout(5000);
http.begin(client,GetUrl);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
//读取响应内容
String response = http.getString();
Serial.println(response);
Sdtime="";
Sdtime=response.substring(13, 32);
Serial.println(Sdtime);
}
}else {Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());} http.end();
}
//只是读取dht11 写入sd卡。
void upload2(){
float h = dht.readHumidity();
float t = dht.readTemperature();
//read temperature and humidity
if (isnan(h) || isnan(t)) {
Serial.println("upload2=Failed to read from DHT sensor!");
}
swritesd(String(t),String(h),Sdtime);
Serial.println("sd=sd写入成功!");
}
void upload(){
float h = dht.readHumidity();
float t = dht.readTemperature();
//read temperature and humidity
if (isnan(h) || isnan(t)) {
Serial.println("upload=Failed to read from DHT sensor!");
}
swritesd(String(t),String(h),"2024/01/07 22:22:22");
Serial.println("sd=sd写入成功!");
//写入httpserser
WiFiClient client;
const int httpPort = 8000;
if (!client.connect("49.234.33.166", httpPort)) {
Serial.println("upload=connection failed");
//ESP.reset();
return;
}
//String data = "pst=temperature>" + String(random(0,100)) +"||humidity>" + String(random(0,100)) + "||data>text";
String data="t1="+String(t)+"&t2="+String(h);
//String data="t1="+String(t)+"&t2="+String(h)+"&t3="+String(WiFi.gatewayIP());
//Serial.print("Requesting POST: ");
// Send request to the server:
client.println("POST / HTTP/1.1");
client.println("Host:49.234.33.166");
client.println("Accept: */*");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(data.length());
client.println();
client.print(data);
delay(500); // Can be changed
Serial.println("upload=send to httpserver success ");
if (client.connected()) {
client.stop(); // DISCONNECT FROM THE SERVER
}
}
void swritesd(String stt, String shh,String sdatetime)
{
myFile = SD.open("wenshidu.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to wenshidu.txt...");
myFile.println(stt+", "+shh+", "+sdatetime);
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
/*读取sd卡信息。
//* re-open the file for reading:
myFile = SD.open("wenshidu.txt");
if (myFile) {
Serial.println("wenshidu.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
*/
}
void returnOK() {
server.send(200, "text/plain", "");
}
void returnFail(String msg) {
server.send(500, "text/plain", msg + "\r\n");
}
bool loadFromSdCard(String path) {
String dataType = "text/plain";
if (path.endsWith("/")) {
path += "index.html";
}
if (path.endsWith(".src")) {
path = path.substring(0, path.lastIndexOf("."));
} else if (path.endsWith(".htm") || path.endsWith(".html")) {
dataType = "text/html";
} else if (path.endsWith(".css")) {
dataType = "text/css";
} else if (path.endsWith(".js")) {
dataType = "application/javascript";
} else if (path.endsWith(".png")) {
dataType = "image/png";
} else if (path.endsWith(".gif")) {
dataType = "image/gif";
} else if (path.endsWith(".jpg")) {
dataType = "image/jpeg";
} else if (path.endsWith(".ico")) {
dataType = "image/x-icon";
} else if (path.endsWith(".xml")) {
dataType = "text/xml";
} else if (path.endsWith(".pdf")) {
dataType = "application/pdf";
} else if (path.endsWith(".zip")) {
dataType = "application/zip";
} else if (path.endsWith(".json")) {
dataType = "application/json";
}
File dataFile = SD.open(path.c_str());
if (dataFile.isDirectory()) {
path += "/index.htm";
dataType = "text/html";
dataFile = SD.open(path.c_str());
}
if (!dataFile) {
return false;
}
if (server.hasArg("download")) {
dataType = "application/octet-stream";
}
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
Serial.println("Sent less data than expected!");
}
dataFile.close();
return true;
}
void deleteRecursive(String path) {
File file = SD.open((char *)path.c_str());
if (!file.isDirectory()) {
file.close();
SD.remove((char *)path.c_str());
return;
}
file.rewindDirectory();
while (true) {
File entry = file.openNextFile();
if (!entry) {
break;
}
String entryPath = path + "/" + entry.name();
if (entry.isDirectory()) {
entry.close();
deleteRecursive(entryPath);
} else {
entry.close();
SD.remove((char *)entryPath.c_str());
}
yield();
}
SD.rmdir((char *)path.c_str());
file.close();
}
void handleCreate() {
if (server.args() == 0) {
return returnFail("BAD ARGS");
}
String path = server.arg(0);
if (path == "/" || SD.exists((char *)path.c_str())) {
returnFail("BAD PATH");
return;
}
if (path.indexOf('.') > 0) {
File file = SD.open((char *)path.c_str(), FILE_WRITE);
if (file) {
file.write((const char *)0);
file.close();
}
} else {
SD.mkdir((char *)path.c_str());
}
returnOK();
}
void handleDelete() {
if (server.args() == 0) {
return returnFail("BAD ARGS");
}
String path = server.arg(0);
if (path == "/" || !SD.exists((char *)path.c_str())) {
returnFail("BAD PATH");
return;
}
deleteRecursive(path);
returnOK();
}
void handleFileUpload() {
if (server.uri() != "/edit") {
return;
}
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
if (SD.exists((char *)upload.filename.c_str())) {
SD.remove((char *)upload.filename.c_str());
}
uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
Serial.print("Upload: START, filename: "); Serial.println(upload.filename);
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (uploadFile) {
uploadFile.write(upload.buf, upload.currentSize);
}
Serial.print("Upload: WRITE, Bytes: "); Serial.println(upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
if (uploadFile) {
uploadFile.close();
}
Serial.print("Upload: END, Size: "); Serial.println(upload.totalSize);
}
}
void printDirectory() {
if (!server.hasArg("dir")) {
return returnFail("BAD ARGS");
}
String path = server.arg("dir");
if (path != "/" && !SD.exists((char *)path.c_str())) {
return returnFail("BAD PATH");
}
File dir = SD.open((char *)path.c_str());
path.clear();
if (!dir.isDirectory()) {
dir.close();
return returnFail("NOT DIR");
}
dir.rewindDirectory();
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/json", "");
WiFiClient client = server.client();
server.sendContent("[");
for (int cnt = 0; true; ++cnt) {
File entry = dir.openNextFile();
if (!entry) {
break;
}
String output;
if (cnt > 0) {
output = ',';
}
output += "{\"type\":\"";
output += (entry.isDirectory()) ? "dir" : "file";
output += "\",\"name\":\"";
output += entry.name();
output += "\"";
output += "}";
server.sendContent(output);
entry.close();
}
server.sendContent("]");
server.sendContent(""); // Terminate the HTTP chunked transmission with a 0-length chunk
dir.close();
}
void handleNotFound() {
if (hasSD && loadFromSdCard(server.uri())) {
return;
}
String message = "SDCARD Not Detected\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " NAME:" + server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
Serial.print(message);
}
http://192.168.0.200/list?dir=/
通过以上路径访问文件夹,访问文件,文件一大就超时,没啥用。setup说好的只执行一次,好像也不是那么稳定,静态ip设置后能访问wifi无法访问ntp,需要指定dns。
=========以下函数有严重的问题。会导致8266 wdt reset,无法解决,=========
void myDelay(int milliseconds) {
unsigned long startTime = millis(); // 记录函数开始时间
while (millis() - startTime < milliseconds) {
// 等待延时时间过去
}}
//我们定义了一个`blinkLED`函数来实现LED灯的闪烁。该函数接受一个参数,表示延时的毫秒数。通过调用自定义的延时函数`myDelay`
//,我们可以实现不同的延时时间,从而实现LED灯的不同闪烁频率。
void blinkLED(int milliseconds) {
digitalWrite(LED_BUILTIN, HIGH); // 点亮LED灯
myDelay(milliseconds); // 延时指定的时间
digitalWrite(LED_BUILTIN, LOW); // 熄灭LED灯
myDelay(milliseconds); // 延时指定的时间
}