diff --git a/platformio.ini b/platformio.ini index 11b5328..b5df90c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,13 +30,14 @@ [env:esp32-s3-devkitc-1] ; platformio/espressif32@^6.4.0 -platform = espressif32 @ 6.8.0 +; platform = espressif32 +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip board = esp32-s3-devkitc-1 framework = arduino platform_packages = - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 - ; framework-arduinoespressif32 @ 2.0.6+sha.099b432 + ; toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 + ; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master ; board_upload.flash_size=4MB board_upload.flash_size=4MB board_upload.maximum_size=327680 @@ -59,10 +60,12 @@ board_build.flash_mode = dio build_flags: -DVERSION=${this.custom_prog_version} -DARDUINO_USB_CDC_ON_BOOT=1 + ; -DCONFIG_SOC_SDMMC_HOST_SUPPORTED=y, + ; -DCONFIG_TINYUSB_MSC_ENABLED=y ;-DDINBIAO extra_scripts = pre:extra_script.py -custom_prog_version = V3.1DDY +custom_prog_version = V3.2 debug_tool.upload_protocol = esp-builtin monitor_speed = 115200 ; 你当前是 921600,若改回 115200 请同时调整 monitor_filters = esp32_exception_decoder \ No newline at end of file diff --git a/src/Define.h b/src/Define.h index a3f0f83..83ce18f 100644 --- a/src/Define.h +++ b/src/Define.h @@ -3,7 +3,8 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) // #define ARDUINO_USB_MODE 0 - +#include +#include //#define DebugCalibration //#define DINBIAO @@ -14,6 +15,11 @@ #define Curentvsion TOSTRING(VERSION) #endif +#define STOP_WORK_BIT (1<<0) +#define StART_WORK_BIT (1<<1) +#define START_MSC_BIT (1<<2) + +extern EventGroupHandle_t Eventgroup; #endif \ No newline at end of file diff --git a/src/Myhttpserver.cpp b/src/Myhttpserver.cpp index fa7edf7..c58f085 100644 --- a/src/Myhttpserver.cpp +++ b/src/Myhttpserver.cpp @@ -1,7 +1,7 @@ #include"Myhttpserver.h" myHttpServer * myhttpserver; - - +#include +#include String myHttpServer::getnetData() { if (!isinit) @@ -83,7 +83,8 @@ bool myHttpServer::UpdateData(String path, char *str, size_t lenth, String Conte { return false; } - Serial.println("start put data to "+path); + // Serial.println("start put data to "+path); + write_log_def(10,"start put data to "+path); http1->beginRequest(); http1->post(path); if (Contenttype != "") @@ -97,8 +98,9 @@ bool myHttpServer::UpdateData(String path, char *str, size_t lenth, String Conte http1->endRequest(); int err = http1->write((const byte *)str, lenth); delay(100); - Serial.print("send date size"); - Serial.println(err); + // Serial.print("send date size"); + // Serial.println(err); + write_log_def(10,"send date size"+String(err)); /* for (size_t i = 0; i < lenth; i++) @@ -138,7 +140,8 @@ bool myHttpServer::UpdateData(String path, char *str, size_t lenth, String Conte } String body = http1->responseBody(); - Serial.println("body:"+body); + // Serial.println("body:"+body); + write_log_def(10,"body:"+body); if (body != "ok") { http1->stop(); @@ -160,17 +163,67 @@ void myHttpServer::ReuploadData(String path, String webpath, String content ) Vector files; String vec[20]; //每次处理20个 files.setStorage(vec); - while (!sdcard::ListDir(path.c_str(), files)) + sdcard::lock(); + bool hasmore = !sdcard::ListDir(path.c_str(), files); + sdcard::unlock(); + while (hasmore) { + sdcard::lock(); if (files.size() != 0) { - Serial.println("find " + String(files.size()) + "file"); + + + + + // Serial.println("find " + String(files.size()) + "file"); + write_log_def(10,"find " + String(files.size()) + "file"); for (size_t i = 0; i < files.size(); i++) { + //判断是否时md5文件 如果是则跳过 + if (files.at(0).endsWith(".md5")) + { + continue; + } + //判断filename.md5是否存在 如果存在则读取md5并计算文件的md5进行对比 + if (!sdcard::fileexists((files.at(i) + ".md5").c_str())) + { + continue; + + } + String md5value=sdcard::ReadFileToString((files.at(i) + ".md5").c_str()); + if (md5value=="") + { + continue; + /* code */ + } + //计算文件的md5 + + + + + + File nowfile = SD_MMC.open(files.at(i).c_str(), "rb"); size_t size = nowfile.size(); char *arr = new char[size]; nowfile.readBytes(arr, size); + MD5Builder md5my; + md5my.begin(); + md5my.add((uint8_t *)arr, size); + md5my.calculate(); + String md5string = md5my.toString(); + if (md5string != md5value) + { + // Serial.println("file md5 not match ,skip this file"+files.at(i)); + write_log_def(10,"file md5 not match ,skip this file"+files.at(i)); + delete[] arr; + sdcard::deleteFolderOrFile(files.at(i).c_str()); + continue; + /* code */ + } + + + bool flagsucc = UpdateData(webpath, arr, size, content); if (!flagsucc) { @@ -183,11 +236,16 @@ void myHttpServer::ReuploadData(String path, String webpath, String content ) /* code */ } } + hasmore = !sdcard::ListDir(path.c_str(), files); + sdcard::unlock(); vTaskDelay(1); + } if (files.size() != 0) { - Serial.println("find " + String(files.size()) + "file not enough 20"); + sdcard::lock(); + // Serial.println("find " + String(files.size()) + "file not enough 20"); + write_log_def(10,"find " + String(files.size()) + "file not enough 20"); for (size_t i = 0; i < files.size(); i++) { vTaskDelay(1); @@ -195,7 +253,9 @@ void myHttpServer::ReuploadData(String path, String webpath, String content ) size_t size = nowfile.size(); char *arr = new char[size]; nowfile.readBytes(arr, size); - Serial.println("run here now"); + + write_log_def(10,"run here now 123"); + vTaskDelay(1); bool flagsucc = UpdateData(webpath, arr, size, content); if (!flagsucc) { @@ -207,21 +267,26 @@ void myHttpServer::ReuploadData(String path, String webpath, String content ) sdcard::deleteFolderOrFile(files.at(i).c_str()); /* code */ } + sdcard::unlock(); } vTaskDelay(1); } void Reuploaddata1(void *) //重新上传数据 { + myhttpserver->ReuploadData("/down", Http_Sepctral_Path); myhttpserver->ReuploadData("/up", Http_Sepctral_Path); myhttpserver->ReuploadData("/other", Http_Wind_Path, "application/json"); + } void Reuploaddata2() //重新上传数据 { + // sdcard::lock(); myhttpserver->ReuploadData("/down", Http_Sepctral_Path); myhttpserver->ReuploadData("/up", Http_Sepctral_Path); myhttpserver->ReuploadData("/other", Http_Wind_Path, "application/json"); + // sdcard::unlock(); } void myHttpServer::setup1(Client &client,char * serveradd) @@ -232,5 +297,6 @@ void myHttpServer::setup1(Client &client,char * serveradd) isinit = true; log_path = "/httplog.txt"; myhttpserver= this; - Serial.println("start httpserver 2332213"+String(http1->iServerName)); + // Serial.println("start httpserver 2332213"+String(http1->iServerName)); + write_log_def(10,"start httpserver: "+String(http1->iServerName)); } diff --git a/src/Myhttpserver.h b/src/Myhttpserver.h index 4a23b28..b984ca0 100644 --- a/src/Myhttpserver.h +++ b/src/Myhttpserver.h @@ -7,9 +7,13 @@ #include "log.h" void Reuploaddata1(void *); void Reuploaddata2() ; -static String Http_Sepctral_Path="/DDY/weather/php/SpectralDataUp.php"; +// static String Http_Sepctral_Path="/DDY/weather/php/SpectralDataUp.php"; -static String Http_Wind_Path="/DDY/weather/php/WindsensorUp.php"; +// static String Http_Wind_Path="/DDY/weather/php/WindsensorUp.php"; + +static String Http_Sepctral_Path="/weather/php/SpectralDataUp.php"; + +static String Http_Wind_Path="/weather/php/WindsensorUp.php"; static String Http_Log_Path="/weather/php/log.php"; static String Http_Sensorinfo_UP_Path="/weather/php/SensorInfoUp.php"; static String Http_Station_GPS_INfo_Path="/weather/php/StationGPSinfo.php"; diff --git a/src/SDmanger.cpp b/src/SDmanger.cpp index f9f8b48..66020c6 100644 --- a/src/SDmanger.cpp +++ b/src/SDmanger.cpp @@ -1,10 +1,60 @@ #include"SDmanger.h" +#include "esp_vfs_fat.h" +#include "sdmmc_cmd.h" +#include File Comenfile; + SemaphoreHandle_t sd_mutex = xSemaphoreCreateMutex(); + + void sdcard::lock() { + xSemaphoreTake(sd_mutex, portMAX_DELAY); + } + + void sdcard::unlock() { + xSemaphoreGive(sd_mutex); + } + +void sdcard::formatSDCard() { +// SD_MMC.end(); // 先卸载SD卡文件系统 + Serial.println("Formatting SD card..."); + esp_vfs_fat_mount_config_t mount_config = { + .format_if_mount_failed = true, // 不自动格式化 + .max_files = 5, + .allocation_unit_size = 16 * 1024 + }; + sdmmc_card_t* card = nullptr; + + card= SD_MMC.card(); + //esp_err_t err = esp_vfs_fat_sdcard_format("/sdcard", card); + // 调用真正的格式化函数 + esp_vfs_fat_mount_config_t fmt_config = mount_config; // 也可以调整 fmt_config 参数 + esp_err_t err = esp_vfs_fat_sdcard_format_cfg("/sdcard", card, &fmt_config); + Serial.println("Formatting completed"); + if (err == ESP_OK) { + Serial.println("SD card formatted successfully"); + } else { + Serial.printf("Format failed: %s\n", esp_err_to_name(err)); + } + + +} +#define sd_cmd 7 +#define sd_clk 6 +#define sd_dat0 5 +#define sd_dat1 4 +#define sd_dat2 16 +#define sd_dat3 15 int sdcard::init_sdcard() { - SD_MMC.setPins(9,10,11,12,13,14); - int succ = SD_MMC.begin("/sdcard", true,true,150); + pinMode(48, OUTPUT); + digitalWrite(48, HIGH); + vTaskDelay(1000); + SD_MMC.setPins(9,10,11,12,13,14); + //格式化sd卡 + //SD_MMC.setPins(sd_clk,sd_cmd,sd_dat0,sd_dat1,sd_dat2,sd_dat3); + + int succ = SD_MMC.begin("/sdcard", false,true); + if (succ) { Serial.printf("SD_MMC Begin: %d\n", succ); uint8_t cardType = SD_MMC.cardType(); @@ -32,6 +82,8 @@ int sdcard::init_sdcard() return ESP_OK; } + + void sdcard::mylistDir( const char * dirname, uint8_t levels) { Serial.printf("Listing directory: %s\n", "/"); @@ -64,13 +116,27 @@ int sdcard::init_sdcard() Serial.print(" SIZE: "); Serial.println(filex.size()); } + filex.close(); filex = root.openNextFile(); } } + +bool sdcard::fileexists(const char * path) +{ + File f = SD_MMC.open(path); + if (!f) { + f.close(); + return false; + } + f.close(); + return true; +} + bool sdcard::ListDir(const char * dirname,Vector &stringlist) { stringlist.clear(); - Serial.printf("Listing directory: %s\n", dirname); + Serial.println("Listing directory: "); + String dir(dirname); File root = SD_MMC.open(dirname); if (!root) { @@ -98,9 +164,10 @@ bool sdcard::ListDir(const char * dirname,Vector &stringlist) } } + filex.close(); filex = root.openNextFile(); } - +filex.close(); return true; } @@ -241,6 +308,8 @@ bool sdcard::ListDir(const char * dirname,Vector &stringlist) return SD_MMC.mkdir(path); } + + namespace sdcard { void openFileformWirte(String Path) @@ -274,7 +343,23 @@ namespace sdcard } } - + String ReadFileToString(const char * path) + { + String ret=""; + File file=SD_MMC.open(path,"r"); + if (!file) + { + return ret; + /* code */ + } + while (file.available()) + { + ret+=char(file.read()); + /* code */ + } + file.close(); + return ret; + } void closeCommenFile() { if (Comenfile.available()) diff --git a/src/SDmanger.h b/src/SDmanger.h index f7279e0..d6d38b0 100644 --- a/src/SDmanger.h +++ b/src/SDmanger.h @@ -22,7 +22,11 @@ namespace sdcard{ void WritetoFileCommen(String Str); void WritetoFileCommen(char *data,size_t lenth); void closeCommenFile(); - +void lock(); +void unlock(); +String ReadFileToString(const char * path); + bool fileexists(const char * path); + void formatSDCard(); } #endif diff --git a/src/SensorOptoSky.cpp b/src/SensorOptoSky.cpp index cde1196..57a05b7 100644 --- a/src/SensorOptoSky.cpp +++ b/src/SensorOptoSky.cpp @@ -4,7 +4,7 @@ #include "wifidebug.h" - +#include #include "SensorOptoSky.h" bool SensorOptoSky::initSensor(int id ) { @@ -167,6 +167,7 @@ void SensorOptoSky::GetOneDate(int msc) { memcpy(DATABUFF, IS1Sensor.result + 1, SensorInfo.BandNum * 2); //memcpy(DATABUFF, IS1Sensor.result , SensorInfo.BandNum * 2); shortLittletoBiG(DATABUFF, SensorInfo.BandNum); + esp_task_wdt_reset(); //手动喂狗 } void SensorOptoSky::shortLittletoBiG(unsigned short *data, int lenth) { @@ -250,11 +251,17 @@ void SensorOptoSky::TakeOneJob() { int shutter=OptSnenser(90); shutterup=shutter; GetOneDate(shutter); + + //esp_task_wdt_reset(); //手动喂狗 + memcpy(UpData,DATABUFF,SensorInfo.BandNum*2); SetShutter(0); GetOneDate(shutter); + for (int i = 0; i < SensorInfo.BandNum; ++i) { - UpData[i]=UpData[i]-DATABUFF[i]; + int temp=UpData[i]-DATABUFF[i]; + UpData[i]=temp>0?temp:0; + // UpData[i]=UpData[i]-DATABUFF[i]; } shutterup=shutter; Serial.println("Finish Up ------Green"); @@ -282,7 +289,9 @@ void SensorOptoSky::TakeOneJob() { SetShutter(0); GetOneDate(shutter); for (int i = 0; i < SensorInfo.BandNum; ++i) { - DownData[i]=DownData[i]-DATABUFF[i]; + int temp=DownData[i]-DATABUFF[i]; + DownData[i]=temp>0?temp:0; + } shutterdown=shutter; Serial.println("Down Finish ------Blue"); diff --git a/src/log.cpp b/src/log.cpp index 1e79a3f..11f189c 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -28,8 +28,90 @@ ab+ 读写打开一个二进制文件,允许读或在文件末追加数据。 加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。 */ + +String pathforlog = "/log.txt"; +dateandtime start_offset_datetime = {2024, 1, 1, 0, 0, 0}; // 设置起始时间为2024-01-01 00:00:00 +uint64_t start_offset_mcu_time= 0; // 2024-01-01 00:00:00对应的Unix时间戳 + + +void setpathforlog(String path) +{ + pathforlog = path; +} + +bool isLeapYear(int year) { + return (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)); +} + +int daysInMonth(int year, int month) { + static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + if (month == 2 && isLeapYear(year)) return 29; + return days[month - 1]; +} + +void tmaddseconds(dateandtime &tm, long long n) { + // 先加秒 + tm.second += n; + + // 秒转分钟 + tm.minute += tm.second / 60; + tm.second %= 60; + + // 分钟转小时 + tm.hour += tm.minute / 60; + tm.minute %= 60; + + // 小时转天 + tm.day += tm.hour / 24; + tm.hour %= 24; + + // 处理日/月/年的进位 + while (true) { + int dim = daysInMonth(tm.year, tm.month); + if (tm.day <= dim) break; + tm.day -= dim; + tm.month++; + if (tm.month > 12) { + tm.month = 1; + tm.year++; + } + } +} + + +void setoffsettime(dateandtime tm) +{ + start_offset_datetime = tm; + start_offset_mcu_time = millis(); +} + + + +void write_log_def(unsigned char level,String write_data) +{ + write_log(pathforlog,level,write_data); +} +String two(int v) { + if (v < 10) return "0" + String(v); + return String(v); +} +String getlocaltime() +{ + unsigned long uptime = millis(); + long time_diff = uptime - start_offset_mcu_time; + + long seconds = time_diff / 1000; + long milliseconds = time_diff % 1000; + dateandtime tm = start_offset_datetime; + tmaddseconds(tm, seconds); + String timestr=String(tm.year) + "-"+two(tm.month) +"-" + two(tm.day) + " " + two(tm.hour) + ":" + two(tm.minute) + ":" + two(tm.second); + return timestr; +} + + void write_log(String path,unsigned char level,String write_data) { + //return; #ifdef ceshi Serial.println(write_data); #endif @@ -37,24 +119,24 @@ void write_log(String path,unsigned char level,String write_data) if(level > 10) { //保存本地,和同时上传云端,小于10只保存本地 } + unsigned long uptime = millis(); - unsigned long seconds = uptime / 1000; - unsigned long minutes = seconds / 60; - unsigned long hours = minutes / 60; - unsigned long days = hours / 24; - unsigned long years = days / 365; - seconds %= 60; - minutes %= 60; - hours %= 24; - days %= 365; + long time_diff = uptime - start_offset_mcu_time; - String timeString = String(years) + "-" + String(days) + "-" + String(hours) + ":" + String(minutes) + ":" + String(seconds); + long seconds = time_diff / 1000; + long milliseconds = time_diff % 1000; + dateandtime tm = start_offset_datetime; + tmaddseconds(tm, seconds); + + + String timeString = String(tm.year) + "-"+two(tm.month) +"-" + two(tm.day) + " " + two(tm.hour) + ":" + two(tm.minute) + ":" + two(tm.second)+ "." + String(milliseconds); write_data = timeString + ":" + write_data; - + sdcard::lock(); File file; file = SD_MMC.open(path,"ab+"); file.println(write_data); file.flush(); file.close(); + sdcard::unlock(); } diff --git a/src/log.h b/src/log.h index 054b04f..2172a69 100644 --- a/src/log.h +++ b/src/log.h @@ -4,9 +4,20 @@ #define ceshi 1 #include "SDmanger.h" +struct dateandtime +{ + int year; + int month; + int day; + int hour; + int minute; + int second; +}; void write_log(String path,unsigned char level,String write_data); - - +void setoffsettime(dateandtime tm); +void write_log_def(unsigned char level,String write_data); +void setpathforlog(String path); +String getlocaltime(); #endif diff --git a/src/main.cpp b/src/main.cpp index 4dceaa3..5e10c90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,14 @@ #include"Define.h" #include +// #include "msc.h" + #include #include "SensorOptoSky.h" #include #include #include +#include "mymsc.h" //#include "MyWebServer.h" #include "SDmanger.h" //#include "HttpsOTAUpdate.h" @@ -15,15 +18,16 @@ #define beePin 39 #define BeeChain 0 #include - +#include #define LOGGING //myPort将原来ESP8266对内通讯改为,485对内的通讯 // #define MYPORT_TX 45 // #define MYPORT_RX 46 +#define WATCHDOG_TIMEOUT_SECONDS 600 int hassend = 0; GSMMannger *gsmmanger; UpDateClassByme *ProgrameUper; - +EventGroupHandle_t Eventgroup; SensorOptoSky IS1Sensor; myHttpServer *httpserver; @@ -63,29 +67,59 @@ String fenge(String str, String fen, int index) return "-1"; return temps[index]; } +// void beebee(int timemill) +// { +// ledcAttachPin(beePin, BeeChain); +// ledcWrite(BeeChain, 125); +// vTaskDelay(timemill); + +// ledcWrite(BeeChain, 0); +// vTaskDelay(timemill); + +// ledcWrite(BeeChain, 125); +// vTaskDelay(timemill); + +// ledcWrite(BeeChain, 0); +// ledcDetachPin(beePin); +// } + void beebee(int timemill) { - ledcAttachPin(beePin, BeeChain); - ledcWrite(BeeChain, 125); + // === 替换 ledcAttachPin === + // 旧: ledcAttachPin(beePin, BeeChain); + // 新: ledcAttach(pin, freq, resolution_bits); + // 假设频率仍然是 220Hz,分辨率是 8位 (0-255) + // 注意:如果 BeeChain 被用作一个通道号,并且你希望显式地使用它, + // 新的 ledcAttach 函数并没有直接的 channel 参数。 + // 但是,你可以通过 ledcSetChannelPin(BeeChain, beePin); 来实现类似目的。 + // 最常见的用法是让 ledcAttach 自动选择通道。 + + // 如果 BeeChain 只是一个 "逻辑链" 或者通道号,现在我们直接用 beePin 和频率、分辨率 + // ledcAttach(beePin, 220, 8); // 将 beePin 关联到 LEDC,设置频率 220Hz,8位分辨率 + // 这会在内部自动分配一个空闲的 LEDC 通道给 beePin。 + // === 替换 ledcWrite === + // 旧: ledcWrite(BeeChain, 125); + // 新: ledcWrite(pin, duty); + ledcWrite(beePin, 125); // 在 beePin 上设置 125 的占空比 (~49%,因为 125/255) + vTaskDelay(timemill); // 使用实时操作系统任务延迟 + ledcWrite(beePin, 0); // 在 beePin 上设置 0 的占空比 (关闭) vTaskDelay(timemill); - - ledcWrite(BeeChain, 0); - vTaskDelay(timemill); - - ledcWrite(BeeChain, 125); - vTaskDelay(timemill); - - ledcWrite(BeeChain, 0); - ledcDetachPin(beePin); + ledcWrite(beePin, 125); // 在 beePin 上设置 125 的占空比 (打开) + vTaskDelay(timemill); + ledcWrite(beePin, 0); // 在 beePin 上设置 0 的占空比 (关闭) + // === 替换 ledcDetachPin === + // 旧: ledcDetachPin(beePin); + // 新: ledcDetach(pin); + ledcDetach(beePin); // 从 LEDC 分离 beePin } - String Datenow=""; void printbytcp(String str) { //tcpserver.SendDataToClinet(str); - Serial.println(str); +// Serial.println(str); +// write_log(log_path,0,str); str=Datenow+"#######"+str; int lennn=str.length(); char *temp = new char[lennn]; @@ -97,13 +131,16 @@ void printbytcp(String str) } + + void readmeichaung() { /////////////////////////////////now/////////////////////////// double temprature = myslave.getMLX(); - Serial.println("wendu"); - Serial.println(temprature); - Serial.println("hello word"); + // Serial.println("wendu"); + // Serial.println(temprature); + // Serial.println("hello word"); + write_log(log_path,10,"temprature:" + String(temprature)); ////////////////////////////////now//////////////////////////// myslave.getWehter(); memcpy(windret,myslave.ret,17); @@ -112,24 +149,27 @@ void readmeichaung() float TT = (windret[7] * 256 + windret[8]) * 1.0 / 100; float HH = (windret[9] * 256 + windret[10]) * 1.0 / 100; long PP = (windret[13] * 256 + windret[14]) * 256 * 256 + (windret[11] * 256 + windret[12]); - Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP)); + // Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP)); + write_log(log_path,10,"VV:" + String(VV) + " DD:" + String(DD) + " TT:" + String(TT) + " HH:" + String(HH) + " PP:" + String(PP)); } String get_GPS(void) { - Serial.println("check GPS..."); + + write_log(log_path,10,"check GPS..."); gsmmanger->modem->sendAT(GF("+CGNSPWR?")); gsmmanger->modem->waitResponse("OK"); - Serial.println("Open GPS..."); + + write_log(log_path,10,"Open GPS..."); gsmmanger->modem->sendAT(GF("+CGNSPWR=1")); gsmmanger->modem->waitResponse("OK"); gsmmanger->modem->sendAT(GF("+CGNSAID=31,1,1,1")); gsmmanger->modem->waitResponse("OK"); - Serial.println("get GNSS..."); + gsmmanger->modem->sendAT(GF("+CGNSINF")); String gpsbac; @@ -149,7 +189,8 @@ String get_GPS(void) return "-1"; } - Serial.println(gpsbac); + + write_log(log_path,10,"gpsdate:"+Date); return Date; } @@ -157,34 +198,89 @@ String get_GPS(void) // { // return gsmmanger->modem->getNetworkTime; // } -#include "esp_task_wdt.h" +// #include "esp_task_wdt.h" +// 用于存储 loop 任务的句柄(如果需要) +TaskHandle_t loopTaskHandle = NULL; +#include +#include +#include void setup() { + + + -esp_task_wdt_init(20, true); - Serial.begin(115200); + +//esp_task_wdt_init(20, true); + Serial.begin(460800); Serial.println("start"); //return; Serial.println(Curentvsion); + sdcard::lock(); + // vTaskDelay(5000); sdcard::init_sdcard(); + String hasbeenformat = sdcard::ReadFileToString("/do_not_remove_and_edit_this_file"); + if(hasbeenformat == ""){ + sdcard::formatSDCard(); + sdcard::WriteStringToFile("/do_not_remove_and_edit_this_file","do not remove and edit this file \n\ + this file is used to tell the system that the sdcard has been formated,\ + \nif you want to format the sdcard,please delete this file,\n\ + the system will format the sdcard automatically next reboot."); + //重启 + esp_restart(); + } + // vTaskDelay(5000); + //sdcard::formatSDCard(); + // while (1) + // { + // vTaskDelay(5000); + // Serial.println("restart"); + + + // /* code */ + // } + sdcard::testwriet(); sdcard::Mkdir("/up"); sdcard::Mkdir("/down"); sdcard::Mkdir("/other"); sdcard::Mkdir("/gps"); sdcard::Mkdir("/log"); - - beginWIFI(); - // sdcard::mylistDir("/",2); + sdcard::unlock(); + write_log(log_path,10,log_data); + // Serial.println(gsmmanger->GetDataAndTime()); + Eventgroup = xEventGroupCreate(); + if (Eventgroup == NULL) { + Serial.println("create eventgroup failed"); + /* code */ } + + + + + + + + + xTaskCreatePinnedToCore( + TaskSerialFS, // Function that should be called + "TaskSerialFS", // Name of the task (for debugging) + 1000*10, // Stack size (bytes) + NULL, // Parameter to pass + 1, // Task priority + NULL, // Task handle + 0); // run on core 0 + beginWIFI(); + // pinMode(21, OUTPUT); // digitalWrite(21, HIGH); pinMode(beePin, OUTPUT); - ledcSetup(BeeChain, 220, 8); - ledcAttachPin(beePin, 0); + // ledcSetup(BeeChain, 220, 8); + // ledcAttachPin(beePin, 0); + ledcAttach(beePin, 220, 8); beebee(1000); - + myslave.init(46,45); //sleep(3); readmeichaung(); @@ -202,6 +298,7 @@ esp_task_wdt_init(20, true); #endif IsNetOK = gsmmanger->setpu(); httpserver = new myHttpServer(); + gsmmanger->client->setTimeout(20*1000); //设置客户端超时20秒 if (IsNetOK) { @@ -218,6 +315,17 @@ esp_task_wdt_init(20, true); // Serial.println("start httpserver"+String(httpserver->http->iServerName)); String Date = httpserver->getnetData(); + //String "1989-03-27 00:00:01"; + dateandtime tmtemp; + tmtemp.year=Date.substring(0,4).toInt(); + tmtemp.month=Date.substring(5,7).toInt(); + tmtemp.day=Date.substring(8,10).toInt(); + tmtemp.hour=Date.substring(11,13).toInt(); + tmtemp.minute=Date.substring(14,16).toInt(); + tmtemp.second=Date.substring(17,19).toInt(); + setoffsettime(tmtemp); + + if (Date=="error") { Serial.println("getnetData failed,esp_restart"); @@ -228,6 +336,7 @@ esp_task_wdt_init(20, true); Serial.println("date is :"+Date); String tem = fenge(Date," ",0); log_path = "/log/"+tem+".log"; + setpathforlog(log_path); log_data = Date+"\r\nSystem starts working."; write_log(log_path,10,""); write_log(log_path,10,log_data); @@ -260,7 +369,7 @@ esp_task_wdt_init(20, true); vTaskDelay(1000); //////////////////////////////初始化http模块////////////////////////////////////////////// //http = new HttpClient(*gsmmanger->client, "82.156.1.111"); - if (IsNetOK) + if (IsNetOK) { ProgrameUper = new UpDateClassByme(httpserver->http1); } @@ -269,37 +378,103 @@ esp_task_wdt_init(20, true); IS1Sensor.initSensor(); String StationID = IS1Sensor.SensorInfo.serialnumber; String SensorID = IS1Sensor.SensorInfo.SensorName; + if (IsNetOK) + { + ProgrameUper->initme(Curentvsion); + ProgrameUper->StationID=StationID; + ProgrameUper->CheckAndUpdate(); + write_log(log_path,10,"Http Init Success."); + String Upheader = StationID + "##" + SensorID + "##" + String(IS1Sensor.SensorInfo.BandNum) + "##" + String(IS1Sensor.SensorInfo.a1,9) + ":" + String(IS1Sensor.SensorInfo.a2,9) + ":" + String(IS1Sensor.SensorInfo.a3,9) + ":" + String(IS1Sensor.SensorInfo.a4,9)+"##"+ProgrameUper->CurrentVersion; + Serial.println(Upheader); + httpserver->UpdateData(Http_Sensorinfo_UP_Path, (char *)Upheader.c_str(), Upheader.length()); + } - - ProgrameUper->initme(Curentvsion); - ProgrameUper->StationID=StationID; - ProgrameUper->CheckAndUpdate(); - write_log(log_path,10,"Http Init Success."); // ProgrameUper->DownloadFirmwareForurl(""); ////////////////////////////上传IS1设备信息////////////////////////////////////////////// //////////////////////////////初始化IS1/////////////////////////////////////////////////// // String Date=getnetData(); - String Upheader = StationID + "##" + SensorID + "##" + String(IS1Sensor.SensorInfo.BandNum) + "##" - + String(IS1Sensor.SensorInfo.a1,9) + ":" + String(IS1Sensor.SensorInfo.a2,9) + ":" + String(IS1Sensor.SensorInfo.a3,9) + ":" + String(IS1Sensor.SensorInfo.a4,9)+"##"+ProgrameUper->CurrentVersion; - Serial.println(Upheader); - httpserver->UpdateData(Http_Sensorinfo_UP_Path, (char *)Upheader.c_str(), Upheader.length()); + write_log(log_path,10,"IS1 Init ...."); /////////////////////////////////////////////////////////////////////////////////////// // - httpserver-> http1->stop(); - ticker.attach(60 * 60, Reuploaddata2); + //httpserver-> http1->stop(); + + // ticker.attach(10 * 60, Reuploaddata2); write_log(log_path,10,"IS1 Init Success."); /////////////////////////////////////////////////////////////////////////////////////// log_data = "System Init Success"; - write_log(log_path,10,log_data); - // Serial.println(gsmmanger->GetDataAndTime()); + write_log(log_path,10,"-------------------------------------------------system has been restart-----------------------------------------------------"); + + // --- 转换为毫秒 --- + const uint32_t WATCHDOG_TIMEOUT_MS = WATCHDOG_TIMEOUT_SECONDS * 1000; + + // ------------------- 配置 TWDT ------------------- + + // 1. 定义配置结构体 + esp_task_wdt_config_t twdt_config = { + .timeout_ms = WATCHDOG_TIMEOUT_MS, // 设置超时时间(毫秒) + + // 监控核心 0 和核心 1 的空闲任务。 + // 在 Arduino 环境中,通常 loop() 运行在核心 1 上 (如果启用了双核), + // 核心 0 处理 WiFi/蓝牙/网络栈。监控两者是系统级别的健壮做法。 + // (1 << 0) | (1 << 1) == 0b11 == 3 + .idle_core_mask = (1 << 0) | (1 << 1), + + // 当 TWDT 超时时,触发系统复位(false),而不是触发软件 panic(true)。 + .trigger_panic = false, + }; + esp_err_t err = esp_task_wdt_init(&twdt_config); + if (err != ESP_OK) { + Serial.printf("TWDT initialization failed: %s\n", esp_err_to_name(err)); + // 如果 TWDT 初始化失败,可能需要重启或报警 + return; + } + + // 3. 将当前的 loop 任务(运行你的 getDateFromHttp 的任务)添加到 TWDT 监控列表 + loopTaskHandle = xTaskGetCurrentTaskHandle(); + + if (esp_task_wdt_add(loopTaskHandle) != ESP_OK) { + Serial.println("Failed to add loop task to TWDT!"); + } else { + Serial.printf("TWDT initialized and monitoring loop task for %d ms (%d s)\n", + WATCHDOG_TIMEOUT_MS, WATCHDOG_TIMEOUT_SECONDS); + } } String lastdate=""; +dateandtime temnow = {2025, 1, 1, 0, 0, 0}; + void loop() { + if (xEventGroupGetBits(Eventgroup) & STOP_WORK_BIT) + { + Serial.println("system stop work NOW!!"); + + + xEventGroupClearBits(Eventgroup, STOP_WORK_BIT); + xEventGroupWaitBits(Eventgroup, StART_WORK_BIT, pdTRUE, pdFALSE, portMAX_DELAY); + Serial.println("system start work"); + + /* code */ + } + + if(xEventGroupGetBits(Eventgroup) & START_MSC_BIT) + { + Serial.println("start msc now"); + xEventGroupClearBits(Eventgroup, START_MSC_BIT); + setupmsc(); + while (1) + { + vTaskDelay(1000); + esp_task_wdt_reset(); //手动喂狗 + /* code */ + } + + } + + String Date; /////////////////NOW///////////////////// @@ -310,13 +485,15 @@ void loop() String yuliang = String(myslave.getYuliang()); delay(1010); - Serial.println("yuliang "+yuliang); + // Serial.println("yuliang "+yuliang); + write_log(log_path,10,"getYuliang :"+yuliang); /////////////////NOW///////////////////// String yuliangfz = String(myslave.getYuliang()); delay(1010); - Serial.println("fuzhao " + yuliangfz); + // Serial.println("fuzhao " + yuliangfz); + log_data ="fuzhao :"+yuliangfz; write_log(log_path,10,log_data); @@ -328,43 +505,57 @@ void loop() float TT = (windret[7] * 256 + windret[8]) * 1.0 / 100; float HH = (windret[9] * 256 + windret[10]) * 1.0 / 100; long PP = (windret[13] * 256 + windret[14]) * 256 * 256 + (windret[11] * 256 + windret[12]); - Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP)); + //Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP)); write_log(log_path,10,"VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP)); ////////////////////////////NOW/////////////////////////// String temprature =String(myslave.getMLX()); - Serial.println("wendu"); - Serial.println(temprature); + log_data ="wendu :"+temprature; write_log(log_path,10,log_data); ////sim 循环 write_log(log_path,10,"start gsmmanger->loop()"); - gsmmanger->loop(); + if (IsNetOK) + { + gsmmanger->loop(); + } + + #ifdef DINBIAO String Datenow1= httpserver->getnetData(); Datenow =fenge(Datenow1, " ", 0) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 0) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 1) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 2); IS1Sensor.PrintFunc=printbytcp; #endif write_log(log_path,10,"start TakeOneJob()"); + esp_task_wdt_reset(); //手动喂狗 IS1Sensor.TakeOneJob(); ////IS1采集一次 String StationID = IS1Sensor.SensorInfo.serialnumber; String SensorID = IS1Sensor.SensorInfo.SensorName; + esp_task_wdt_reset(); //手动喂狗 + ///////////////获取时间 ////////通过GPS获取时间,如果获取失败就通过4G访问网页获取。如果获取成功那就对GPS数据进行分割解析出时间。 String gpsbac; for(int i = 0 ;i < 5 ; i++) { write_log(log_path,10,"start getnetData()"); - Date = httpserver->getnetData(); + if (IsNetOK) + { + Date = httpserver->getnetData(); + }else{ + Date="error"; + } + + if(Date == "error") { write_log(log_path,10,"start get_GPS()"); Date = get_GPS(); - if(Date != "-1") + if(Date != "-1" & IsNetOK) { break; if(hassend == 0) @@ -380,7 +571,8 @@ void loop() // sdcard::WriteStringToFile(nameoffile, temp, lennn); } else{ - Serial.println("Finish Put StationGPSinfo Data"); + + write_log(log_path,10,"Finish Put StationGPSinfo Data"); } delete[] temp; @@ -392,6 +584,7 @@ void loop() } else { + Date=getlocaltime(); // break; } @@ -408,14 +601,25 @@ void loop() vTaskDelay(500); } + esp_task_wdt_reset(); //手动喂狗 + temnow.year=Date.substring(0,4).toInt(); + temnow.month=Date.substring(5,7).toInt(); + temnow.day=Date.substring(8,10).toInt(); + temnow.hour=Date.substring(11,13).toInt(); + temnow.minute=Date.substring(14,16).toInt(); + temnow.second=Date.substring(17,19).toInt(); + setoffsettime(temnow); write_log(log_path,10,"Date is : "+Date); // delay(15000); if (fenge(Date, " ", 0)!=lastdate) { lastdate=fenge(Date, " ", 0); log_path = "/log/"+lastdate+".log"; + setpathforlog(log_path); myslave.claeryuliang(); - ProgrameUper->CheckAndUpdate(); + if(IsNetOK) + { ProgrameUper->CheckAndUpdate();} + } @@ -442,31 +646,51 @@ void loop() { //temp[Upheader.length()+i]=str[i]; } - Serial.println("lenth of up data is "+String(lennn)); + // Serial.println("lenth of up data is "+String(lennn)); + write_log(log_path,10,"lenth of up data is "+String(lennn)); memcpy(temp + Upheader.length(), IS1Sensor.UpData,IS1Sensor.SensorInfo.BandNum * 2); bool flagsucc = httpserver->UpdateData(Http_Sepctral_Path, temp, lennn); //输出前100个字节 字符 +esp_task_wdt_reset(); //手动喂狗 + // Serial.println("temp is :"); + // Serial.write(temp, 100); + // write_log(log_path,10,"temp is :"); - Serial.println("temp is :"); - Serial.write(temp, 100); - + // for (int i = 0; i < 100 && i < lennn; i++) + // { + // Serial.print(temp[i], HEX); + // Serial.print(" "); + // } + String log_temp="temp is :"; for (int i = 0; i < 100 && i < lennn; i++) { - Serial.print(temp[i], HEX); - Serial.print(" "); + log_temp+=String(temp[i], HEX)+" "; } + write_log(log_path,10,log_temp); vTaskDelay(3000); if (!flagsucc) { + //计算md5并保存 为读取时判断数据是否正确 + MD5Builder md5my; + md5my.begin(); + md5my.add((uint8_t *)temp, lennn); + md5my.calculate(); + String md5string = md5my.toString(); + sdcard::lock(); sdcard::WriteStringToFile(Upname, temp, lennn); - log_data ="Up_data upload failed,save to SD."; + sdcard::WriteStringToFile(Upname + ".md5", (char *)md5string.c_str(), md5string.length()); + sdcard::unlock(); + + + log_data ="Up_data upload failed,save to SD. md5 is"+md5string; write_log(log_path,10,log_data); } else { - Serial.println("finish Put Up Data"); + + write_log(log_path,10,"finish Put Up Data"); log_data ="finish Put Up Data."; write_log(log_path,10,log_data); } @@ -475,7 +699,7 @@ void loop() //////////////////////上传Down数据////////////////// - write_log(log_path,10,"put dowm data"); + write_log(log_path,0,"put dowm data"); lennn = IS1Sensor.SensorInfo.BandNum * 2 + Downheader.length(); temp = new char[lennn]; memcpy(temp, Downheader.c_str(), Downheader.length()); @@ -485,22 +709,38 @@ void loop() { // temp[Downheader.length()+i]=str[i]; } - Serial.println("lenth of down data is "+String(lennn)); + + write_log(log_path,10,"lenth of down data is "+String(lennn)); memcpy(temp + Downheader.length(), IS1Sensor.DownData,IS1Sensor.SensorInfo.BandNum * 2); flagsucc = httpserver->UpdateData(Http_Sepctral_Path, temp, lennn); + esp_task_wdt_reset(); //手动喂狗 vTaskDelay(3000); - //输出前100个 - Serial.println("temp is :"); - Serial.write(temp, 100); + String log_temp1="down data is :"; + for (int i = 0; i < 100 && i < lennn; i++) + { + log_temp1+=String(temp[i], HEX)+" "; + } + write_log(log_path,0,log_temp1); + + if (!flagsucc) { + //计算md5并保存 为读取时判断数据是否正确 + MD5Builder md5my; + md5my.begin(); + md5my.add((uint8_t *)temp, lennn); + md5my.calculate(); + String md5string = md5my.toString(); + sdcard::lock(); sdcard::WriteStringToFile(Downname, temp, lennn); - log_data ="Down_data upload failed,save to SD."; + sdcard::unlock(); + sdcard::WriteStringToFile(Downname + ".md5", (char *)md5string.c_str(), md5string.length()); + log_data ="Down_data upload failed,save to SD. md5 is"+md5string; write_log(log_path,10,log_data); }else{ - Serial.println("finish Put Down Data"); + log_data ="finish Put Down Data."; write_log(log_path,10,log_data); } @@ -512,24 +752,73 @@ void loop() memcpy(temp, senderID.c_str(), senderID.length()); memcpy(temp + senderID.length(), windret + 3, 12); flagsucc = httpserver->UpdateData(Http_Wind_Path, temp, lennn, "application/json"); + esp_task_wdt_reset(); //手动喂狗 vTaskDelay(3000); if (!flagsucc) { + // 计算md5并保存 为读取时判断数据是否正确 + MD5Builder md5my; + md5my.begin(); + md5my.add((uint8_t *)temp, lennn); + md5my.calculate(); + String md5string = md5my.toString(); + + sdcard::lock(); sdcard::WriteStringToFile(othername, temp, lennn); - log_data ="put Other Data failed,save to SD."; + sdcard::WriteStringToFile(othername + ".md5", (char *)md5string.c_str(), md5string.length()); + sdcard::unlock(); + log_data="other_data upload failed.save to sd"; write_log(log_path,10,log_data); }else{ - Serial.println("finish Put Other Data"); log_data ="finish Put Other Data."; write_log(log_path,10,log_data); } delete[] temp; + if (0) + + { + String onelinestr=""; + onelinestr="date:"+Date+",upshutter:"+String(IS1Sensor.shutterup)+",downshutter:"+String(IS1Sensor.shutterdown)+",StationID:"+StationID+"\n"; + String fodernamer=fenge(Date, " ", 0); + sdcard::lock(); + sdcard::Mkdir("/Data"); + sdcard::Mkdir("/Data/"+fodernamer); + sdcard::unlock(); + onelinestr+="UPDN,"; + for (size_t i = 0; i < IS1Sensor.SensorInfo.BandNum; i++) + { + onelinestr+=String(IS1Sensor.UpData[i*2]*256+IS1Sensor.UpData[i*2+1]); + if (i!=IS1Sensor.SensorInfo.BandNum-1) + { + onelinestr+=","; + } + + } + onelinestr+="\n"; + onelinestr+="DOWNDN,"; + for (size_t i = 0; i < IS1Sensor.SensorInfo.BandNum; i++) + { + onelinestr+=String(IS1Sensor.DownData[i*2]*256+IS1Sensor.DownData[i*2+1]); + if (i!=IS1Sensor.SensorInfo.BandNum-1) + { + onelinestr+=","; + } + + } + onelinestr+="\n"; + sdcard::lock(); + + sdcard::WriteStringToFile("/Data/"+fodernamer+"/"+datestring+".csv", (char *)onelinestr.c_str(), onelinestr.length()); + sdcard::unlock(); + + } //结束并等待一定时间 // http->stop(); delay(100);return; - + esp_task_wdt_reset(); //手动喂狗 delay(120000); + esp_task_wdt_reset(); //手动喂狗 #ifdef DINBIAO abort(); ESP.restart(); diff --git a/src/optoskybase.h b/src/optoskybase.h index 721d072..fe8086a 100644 --- a/src/optoskybase.h +++ b/src/optoskybase.h @@ -46,7 +46,7 @@ struct STRSensorInfo #define GET_WAVELENGTH_CALIBRATION_COFF 0x55 #define GET_STAT_OF_LAMPOUT 0x60 #define SET_GPIO 0x61 -#define byte u_char +#define byte uint8_t diff --git a/src/updatebyme.cpp b/src/updatebyme.cpp index fa6d6e2..3b5cedf 100644 --- a/src/updatebyme.cpp +++ b/src/updatebyme.cpp @@ -110,6 +110,7 @@ size_t UpDateClassByme::DownloadFirmwareForurl(String version) void UpDateClassByme::initme(String Version) { + Serial.println("CurrentVersion is:"+Version); CurrentVersion=Version; } diff --git a/weatherslave/src/main.cpp b/weatherslave/src/main.cpp index 0673fdf..b0cb75e 100644 --- a/weatherslave/src/main.cpp +++ b/weatherslave/src/main.cpp @@ -115,7 +115,8 @@ void onRequest() { } void onReceive(int len) { - Serial.printf("onReceive[%d]: ", len); + //Serial.printf("onReceive[%d]: ", len); + Serial.println("onReceive:["+String(len)+"] "); while (Wire.available()) { Serial.write(Wire.read()); } @@ -124,7 +125,8 @@ void onReceive(int len) { void onReceive111(size_t len) { - Serial.printf("onReceive[%d]: "); + // Serial.printf("onReceive[%d]: "); + Serial.println("onReceive111:["+String(len)+"] "); while (Wire.available()) { Serial.write(Wire.read()); }