diff --git a/boards.txt b/boards.txt index d89c412aa..b6815e8d9 100644 --- a/boards.txt +++ b/boards.txt @@ -12,7 +12,7 @@ portenta_c33.build.fpu=-mfpu=fpv5-sp-d16 portenta_c33.build.float-abi=-mfloat-abi=hard portenta_c33.build.board=PORTENTA_C33 -portenta_c33.build.defines=-DF_CPU=200000000 +portenta_c33.build.defines=-DF_CPU=200000000 -DPROVIDE_FREERTOS_HOOK portenta_c33.vid.0=0x2341 portenta_c33.pid.0=0x0068 portenta_c33.vid.1=0x2341 diff --git a/cores/arduino/Serial.cpp b/cores/arduino/Serial.cpp index d905edd90..e82d76796 100644 --- a/cores/arduino/Serial.cpp +++ b/cores/arduino/Serial.cpp @@ -58,12 +58,14 @@ void UART::WrapperCallback(uart_callback_args_t *p_args) { { break; } - case UART_EVENT_TX_COMPLETE: - case UART_EVENT_TX_DATA_EMPTY: + case UART_EVENT_TX_COMPLETE: // This is call when the transmission is complete { - //uint8_t to_enqueue = uart_ptr->txBuffer.available() < uart_ptr->uart_ctrl.fifo_depth ? uart_ptr->txBuffer.available() : uart_ptr->uart_ctrl.fifo_depth; - //while (to_enqueue) { - uart_ptr->tx_done = true; + uart_ptr->tx_complete = true; + break; + } + case UART_EVENT_TX_DATA_EMPTY: // This is called when the buffer is empty + { // Last byte is transmitting, but ready for more data + uart_ptr->tx_empty = true; break; } case UART_EVENT_RX_CHAR: @@ -87,6 +89,8 @@ UART::UART(int _pin_tx, int _pin_rx, int _pin_rts, int _pin_cts): rx_pin(_pin_rx), rts_pin(_pin_rts), cts_pin(_pin_cts), + tx_empty(true), + tx_complete(true), init_ok(false) { /* -------------------------------------------------------------------------- */ uart_cfg.txi_irq = FSP_INVALID_VECTOR; @@ -109,9 +113,10 @@ bool UART::setUpUartIrqs(uart_cfg_t &cfg) { size_t UART::write(uint8_t c) { /* -------------------------------------------------------------------------- */ if(init_ok) { - tx_done = false; + tx_empty = false; + tx_complete = false; R_SCI_UART_Write(&uart_ctrl, &c, 1); - while (!tx_done) {} + while (!tx_empty) {} return 1; } else { @@ -121,9 +126,10 @@ size_t UART::write(uint8_t c) { size_t UART::write(uint8_t* c, size_t len) { if(init_ok) { - tx_done = false; + tx_empty = false; + tx_complete = false; R_SCI_UART_Write(&uart_ctrl, c, len); - while (!tx_done) {} + while (!tx_empty) {} return len; } else { @@ -322,7 +328,7 @@ int UART::read() { /* -------------------------------------------------------------------------- */ void UART::flush() { /* -------------------------------------------------------------------------- */ - while(txBuffer.available()); + while(!tx_complete); } /* -------------------------------------------------------------------------- */ @@ -335,4 +341,4 @@ size_t UART::write_raw(uint8_t* c, size_t len) { i++; } return len; -} \ No newline at end of file +} diff --git a/cores/arduino/Serial.h b/cores/arduino/Serial.h index cc818d466..29a41d2c8 100644 --- a/cores/arduino/Serial.h +++ b/cores/arduino/Serial.h @@ -78,7 +78,8 @@ class UART : public arduino::HardwareSerial { arduino::SafeRingBufferN rxBuffer; arduino::SafeRingBufferN txBuffer; - volatile bool tx_done; + volatile bool tx_empty; + volatile bool tx_complete; sci_uart_instance_ctrl_t uart_ctrl; uart_cfg_t uart_cfg; diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 85e228081..24dfa3ec8 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -64,6 +64,7 @@ void unsecure_registers() { #define str(s) #s extern "C" void Stacktrace_Handler(void); +extern "C" __attribute__((weak)) void start_freertos_on_header_inclusion() {} void arduino_main(void) { @@ -112,6 +113,9 @@ void arduino_main(void) #endif startAgt(); setup(); +#ifdef PROVIDE_FREERTOS_HOOK + start_freertos_on_header_inclusion(); +#endif while (1) { loop(); diff --git a/libraries/Arduino_FreeRTOS/src/portable/FSP/port.c b/libraries/Arduino_FreeRTOS/src/portable/FSP/port.c index c0b5938d0..3fd8c53c9 100644 --- a/libraries/Arduino_FreeRTOS/src/portable/FSP/port.c +++ b/libraries/Arduino_FreeRTOS/src/portable/FSP/port.c @@ -225,6 +225,29 @@ static void prvTaskExitError(void); #endif +#ifdef PROVIDE_FREERTOS_HOOK +void loop_thread_func(void* arg) { + while (1) + { + loop(); + } +} + +static TaskHandle_t loop_task; +void start_freertos_on_header_inclusion() { + xTaskCreate( + (TaskFunction_t)loop_thread_func, + "Loop Thread", + 4096 / 4, /* usStackDepth in words */ + NULL, /* pvParameters */ + 4, /* uxPriority */ + &loop_task /* pxCreatedTask */ + ); + + vTaskStartScheduler(); +} +#endif + /* Arduino specific overrides */ void delay(uint32_t ms) { if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { diff --git a/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphics/TextWithArduinoGraphics.ino b/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphics/TextWithArduinoGraphics.ino index 906e85714..a40fad2f4 100644 --- a/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphics/TextWithArduinoGraphics.ino +++ b/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphics/TextWithArduinoGraphics.ino @@ -1,3 +1,6 @@ +// TextAnimation works only when ArduinoGraphics is installed and used. +// ArduinoGraphics is an external library and needs to be installed using +// Library Manager. // To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix #include "ArduinoGraphics.h" #include "Arduino_LED_Matrix.h" diff --git a/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphicsAsynchronous/TextWithArduinoGraphicsAsynchronous.ino b/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphicsAsynchronous/TextWithArduinoGraphicsAsynchronous.ino index d2d48101f..7a6d7239e 100644 --- a/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphicsAsynchronous/TextWithArduinoGraphicsAsynchronous.ino +++ b/libraries/Arduino_LED_Matrix/examples/TextWithArduinoGraphicsAsynchronous/TextWithArduinoGraphicsAsynchronous.ino @@ -1,3 +1,6 @@ +// TextAnimation works only when ArduinoGraphics is installed and used. +// ArduinoGraphics is an external library and needs to be installed using +// Library Manager. // To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix and TextAnimation #include "ArduinoGraphics.h" #include "Arduino_LED_Matrix.h" diff --git a/libraries/ESPhost/examples/ESP32_TEST/ESP32_TEST.ino b/libraries/ESPhost/examples/ESP32_TEST/ESP32_TEST.ino index 579085b35..b0c17ecb5 100644 --- a/libraries/ESPhost/examples/ESP32_TEST/ESP32_TEST.ino +++ b/libraries/ESPhost/examples/ESP32_TEST/ESP32_TEST.ino @@ -297,7 +297,7 @@ void connectAccessPoint() { int i = stoi(ap_str); Serial.println(">>> [APP]: Connecting to Access Point"); - WifiApCfg_t ap; + WifiApCfg_t ap{}; memcpy(ap.ssid,access_point_list[i].ssid,SSID_LENGTH); memcpy(ap.pwd,pwd.c_str(),pwd.size()); memcpy(ap.bssid,access_point_list[i].bssid,BSSID_LENGTH); diff --git a/libraries/OTAUpdate/examples/OTANonBlocking/OTANonBlocking.ino b/libraries/OTAUpdate/examples/OTANonBlocking/OTANonBlocking.ino new file mode 100644 index 000000000..534f77bbe --- /dev/null +++ b/libraries/OTAUpdate/examples/OTANonBlocking/OTANonBlocking.ino @@ -0,0 +1,139 @@ +/* + OTANonBlocking + + This sketch demonstrates how to make an OTA Update on the UNO R4 WiFi. + Upload the sketch and wait for the invasion! + + It requires at least version 0.5.0 of USB Wifi bridge firmware + +*/ + + +#include "WiFiS3.h" +#include "OTAUpdate.h" +#include "root_ca.h" +#include "arduino_secrets.h" + +char ssid[] = SECRET_SSID; // your network SSID (name) +char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) + +int status = WL_IDLE_STATUS; + +OTAUpdate ota; +static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/UNOR4WIFI_Animation.ota"; + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // check for the Wi-Fi module: + if (WiFi.status() == WL_NO_MODULE) { + Serial.println("Communication with Wi-Fi module failed!"); + // don't continue + while (true); + } + + String fv = WiFi.firmwareVersion(); + if (fv < WIFI_FIRMWARE_LATEST_VERSION) { + Serial.println("Please upgrade the firmware"); + } + + // attempt to connect to Wi-Fi network: + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + status = WiFi.begin(ssid, pass); + + // wait 1 seconds for connection: + delay(1000); + } + + printWiFiStatus(); + + Serial.println("ota.begin()"); + int ret = ota.begin("/update.bin"); + if(ret != OTAUpdate::OTA_ERROR_NONE) { + Serial.println("ota.begin() error: "); + Serial.println((int)ret); + return; + } + + Serial.println("ota.setCACert()"); + ret = ota.setCACert(root_ca); + if(ret != OTAUpdate::OTA_ERROR_NONE) { + Serial.println("ota.setCACert() error: "); + Serial.println((int)ret); + return; + } + + Serial.println("ota.startDownload()"); + int ota_size = ota.startDownload(OTA_FILE_LOCATION, "/update.bin"); + if(ota_size <= 0) { + Serial.println("ota.startDownload() error: "); + Serial.println(ota_size); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + return; + } + + Serial.println("ota.downloadProgress()"); + while((ret = ota.downloadProgress()) < ota_size) { + Serial.print("Progress "); + Serial.print(ret); + Serial.print("/"); + Serial.println(ota_size); + delay(100); + } + + if(ret < 0){ + Serial.println("ota.downloadProgress() error: "); + Serial.println((int)ret); + return; + } + + Serial.println("ota.verify()"); + ret = ota.verify(); + if(ret != OTAUpdate::OTA_ERROR_NONE) { + Serial.println("ota.verify() error: "); + Serial.println((int)ret); + return; + } +\ + Serial.println("ota.update()"); + ret = ota.update("/update.bin"); + if(ret != OTAUpdate::OTA_ERROR_NONE) { + Serial.println("ota.update() error: "); + Serial.println((int)ret); + return; + } +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + delay(1000); +} + +/* -------------------------------------------------------------------------- */ +void printWiFiStatus() { +/* -------------------------------------------------------------------------- */ + // print the SSID of the network you're attached to: + Serial.print("SSID: "); + Serial.println(WiFi.SSID()); + + // print your board's 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"); +} diff --git a/libraries/OTAUpdate/examples/OTANonBlocking/arduino_secrets.h b/libraries/OTAUpdate/examples/OTANonBlocking/arduino_secrets.h new file mode 100644 index 000000000..0c9fdd556 --- /dev/null +++ b/libraries/OTAUpdate/examples/OTANonBlocking/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/OTAUpdate/examples/OTANonBlocking/root_ca.h b/libraries/OTAUpdate/examples/OTANonBlocking/root_ca.h new file mode 100644 index 000000000..57e61f92f --- /dev/null +++ b/libraries/OTAUpdate/examples/OTANonBlocking/root_ca.h @@ -0,0 +1,106 @@ +const char* root_ca = \ +/* GTS Root R1 */ +"-----BEGIN CERTIFICATE-----\n" \ +"MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" \ +"CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" \ +"MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" \ +"MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" \ +"Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" \ +"A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" \ +"27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" \ +"Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" \ +"TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" \ +"qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" \ +"szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" \ +"Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" \ +"MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" \ +"wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" \ +"aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" \ +"VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" \ +"AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" \ +"FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" \ +"C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" \ +"QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" \ +"h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" \ +"7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" \ +"ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" \ +"MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" \ +"Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" \ +"6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" \ +"0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" \ +"2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" \ +"bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" \ +"-----END CERTIFICATE-----\n" \ +/* GTS Root R2 */ +"-----BEGIN CERTIFICATE-----\n" \ +"MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw\n" \ +"CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" \ +"MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" \ +"MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" \ +"Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA\n" \ +"A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt\n" \ +"nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY\n" \ +"6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu\n" \ +"MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k\n" \ +"RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg\n" \ +"f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV\n" \ +"+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo\n" \ +"dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW\n" \ +"Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa\n" \ +"G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq\n" \ +"gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID\n" \ +"AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" \ +"FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H\n" \ +"vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8\n" \ +"0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC\n" \ +"B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u\n" \ +"NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg\n" \ +"yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev\n" \ +"HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6\n" \ +"xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR\n" \ +"TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg\n" \ +"JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV\n" \ +"7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl\n" \ +"6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL\n" \ +"-----END CERTIFICATE-----\n" \ +/* GTS Root R3 */ +"-----BEGIN CERTIFICATE-----\n" \ +"MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD\n" \ +"VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n" \ +"A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n" \ +"WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n" \ +"IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n" \ +"AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G\n" \ +"jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2\n" \ +"4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n" \ +"BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7\n" \ +"VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm\n" \ +"ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X\n" \ +"-----END CERTIFICATE-----\n" \ +/* GTS Root R4 */ +"-----BEGIN CERTIFICATE-----\n" \ +"MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD\n" \ +"VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n" \ +"A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n" \ +"WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n" \ +"IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n" \ +"AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi\n" \ +"QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR\n" \ +"HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n" \ +"BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D\n" \ +"9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8\n" \ +"p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD\n" \ +"-----END CERTIFICATE-----\n" \ +/* GlobalSign R4 */ +"-----BEGIN CERTIFICATE-----\n" \ +"MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD\n" \ +"VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh\n" \ +"bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw\n" \ +"MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g\n" \ +"UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT\n" \ +"BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx\n" \ +"uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV\n" \ +"HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/\n" \ +"+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147\n" \ +"bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm\n" \ +"-----END CERTIFICATE-----\n"; diff --git a/libraries/OTAUpdate/src/OTAUpdate.cpp b/libraries/OTAUpdate/src/OTAUpdate.cpp index 50ce57233..b6ff08335 100644 --- a/libraries/OTAUpdate/src/OTAUpdate.cpp +++ b/libraries/OTAUpdate/src/OTAUpdate.cpp @@ -87,6 +87,49 @@ int OTAUpdate::download(const char* url, const char* file_path) { return ret; } +int OTAUpdate::startDownload(const char* url) { + string res = ""; + int ret = -1; + if ( url != nullptr && strlen(url) > 0) { + modem.timeout(EXTENDED_MODEM_TIMEOUT); + if(modem.write(string(PROMPT(_OTA_DOWNLOAD_START)), res, "%s%s\r\n", CMD_WRITE(_OTA_DOWNLOAD_START), url)) { + ret = atoi(res.c_str()); + } else { + ret = static_cast(Error::Modem); + } + } else { + ret = static_cast(Error::Library); + } + modem.timeout(MODEM_TIMEOUT); + return ret; +} + +int OTAUpdate::startDownload(const char* url, const char* file_path) { + string res = ""; + int ret = -1; + + if ( url != nullptr && strlen(url) > 0 && file_path != nullptr && strlen(file_path) >0) { + modem.timeout(EXTENDED_MODEM_TIMEOUT); + if(modem.write(string(PROMPT(_OTA_DOWNLOAD_START)), res, "%s%s,%s\r\n", CMD_WRITE(_OTA_DOWNLOAD_START), url, file_path)) { + ret = atoi(res.c_str()); + } else { + ret = static_cast(Error::Modem); + } + } else { + ret = static_cast(Error::Library); + } + modem.timeout(MODEM_TIMEOUT); + return ret; +} + +int OTAUpdate::downloadProgress() { + string res = ""; + if (modem.write(string(PROMPT(_OTA_DOWNLOAD_PROGRESS)), res, "%s", CMD(_OTA_DOWNLOAD_PROGRESS))) { + return atoi(res.c_str()); + } + return static_cast(Error::Modem); +} + int OTAUpdate::verify() { string res = ""; if (modem.write(string(PROMPT(_OTA_VERIFY)), res, "%s", CMD(_OTA_VERIFY))) { diff --git a/libraries/OTAUpdate/src/OTAUpdate.h b/libraries/OTAUpdate/src/OTAUpdate.h index 9b1b171c0..69266a9e3 100644 --- a/libraries/OTAUpdate/src/OTAUpdate.h +++ b/libraries/OTAUpdate/src/OTAUpdate.h @@ -42,6 +42,12 @@ class OTAUpdate { int begin(const char* file_path); int download(const char* url); int download(const char* url, const char* file_path); + + int startDownload(const char* url); + int startDownload(const char* url, const char* file_path); + + int downloadProgress(); + int verify(); int update(); int update(const char* file_path); diff --git a/libraries/Preferences/examples/TypesCheck/TypesCheck.ino b/libraries/Preferences/examples/TypesCheck/TypesCheck.ino new file mode 100644 index 000000000..3ba07014d --- /dev/null +++ b/libraries/Preferences/examples/TypesCheck/TypesCheck.ino @@ -0,0 +1,400 @@ +/* + This example checks all possible types that can be stored with Preferences library +*/ +#include +#include +Preferences prefs; + +void setup() { + Serial.begin(115200); + + if (!prefs.begin("types")) { // use "types" namespace + Serial.println("Cannot initialize preferences"); + Serial.println("Make sure your WiFi firmware version is greater than 0.3.0"); + while(1) {}; + } + + if (!testChar()) { + return; + } + + if (!testUChar()) { + return; + } + + if (!testShort()) { + return; + } + + if (!testUShort()) { + return; + } + + if (!testInt()) { + return; + } + + if (!testUInt()) { + return; + } + + if (!testLong64()) { + return; + } + + if (!testULong64()) { + return; + } + + if (!testFloat()) { + return; + } + + if (!testDouble()) { + return; + } + + if (!testBytes()) { + return; + } + + if (!testString()) { + return; + } +} + +void loop() { + Serial.println(prefs.freeEntries()); + prefs.clear(); + Serial.println(prefs.freeEntries()); + prefs.end(); + + while(1) {}; +} + +int testChar() { + int8_t data; + int8_t value; + + data = INT8_MAX; + prefs.putChar("char", data); + value = prefs.getChar("char", 0); + if (value != 127) { + Serial.println("getChar MAX Error"); + return 0; + } else { + Serial.print("getChar MAX: "); + Serial.println(value); + } + + data = INT8_MIN; + prefs.putChar("char", data); + value = prefs.getChar("char", 0); + if (value != -128) { + Serial.println("getChar MIN Error"); + return 0; + } else { + Serial.print("getChar MIN: "); + Serial.println(value); + } + + return 1; +} + +int testUChar() { + uint8_t data; + uint8_t value; + + data = UINT8_MAX; + prefs.putUChar("uchar", data); + value = prefs.getUChar("uchar", 0); + if (value != 255) { + Serial.println("getUChar MAX Error"); + return 0; + } else { + Serial.print("getUChar MAX: "); + Serial.println(value); + } + + prefs.remove("uchar"); + + data = 0; + prefs.putUChar("uchar", data); + value = prefs.getUChar("uchar", 1); + if (value != 0) { + Serial.println("getUChar MIN Error"); + return 0; + } else { + Serial.print("getUChar MIN: "); + Serial.println(value); + } + + return 1; +} + +int testShort() { + int16_t data; + int16_t value; + + data = INT16_MAX; + prefs.putShort("short", data); + value = prefs.getShort("short", 0); + if (value != 32767) { + Serial.println("getShort MAX Error"); + return 0; + } else { + Serial.print("getShort MAX: "); + Serial.println(value); + } + + data = INT16_MIN; + prefs.putShort("short", data); + value = prefs.getShort("short", 0); + if (value != -32768) { + Serial.println("getShort MIN Error"); + return 0; + } else { + Serial.print("getShort MIN: "); + Serial.println(value); + } + + return 1; +} + +int testUShort() { + uint16_t data; + uint16_t value; + + data = UINT16_MAX; + prefs.putUShort("ushort", data); + value = prefs.getUShort("ushort", 0); + if (value != 65535U) { + Serial.println("getUShort MAX Error"); + return 0; + } else { + Serial.print("getUShort MAX: "); + Serial.println(value); + } + + data = 0; + prefs.putUShort("ushort", data); + value = prefs.getUShort("ushort", 1); + if (value != 0) { + Serial.println("getUShort MIN Error"); + return 0; + } else { + Serial.print("getUShort MIN: "); + Serial.println(value); + } + + return 1; +} + +int testInt() { + int32_t data; + int32_t value; + + data = INT32_MAX; + prefs.putInt("int", data); + value = prefs.getInt("int", 0); + if (value != 2147483647) { + Serial.println("getInt MAX Error"); + return 0; + } else { + Serial.print("getInt MAX: "); + Serial.println(value); + } + + data = INT32_MIN; + prefs.putInt("int", data); + value = prefs.getInt("int", 0); + if (value != (-2147483647 - 1)) { + Serial.println("getInt MIN Error"); + return 0; + } else { + Serial.print("getInt MIN: "); + Serial.println(value); + } + + return 1; +} + +int testUInt() { + uint32_t data; + uint32_t value; + + data = UINT32_MAX; + prefs.putUInt("uint", data); + value = prefs.getUInt("uint", 0); + if (value != 4294967295U) { + Serial.println("getUInt MAX Error"); + return 0; + } else { + Serial.print("getUInt MAX: "); + Serial.println(value); + } + + data = 0; + prefs.putUInt("uint", data); + value = prefs.getUInt("uint", 1); + if (value != 0) { + Serial.println("getUInt MIN Error"); + return 0; + } else { + Serial.print("getUInt MIN: "); + Serial.println(value); + } + + return 1; +} + +int testLong64() { + int64_t data; + int64_t value; + + data = INT64_MAX; + prefs.putLong64("long", data); + value = prefs.getLong64("long", 0); + if (value != 9223372036854775807LL) { + Serial.println("getLong MAX Error"); + return 0; + } else { + Serial.print("getLong MAX: "); + Serial.println(value); + } + + data = INT64_MIN; + prefs.putLong64("long", data); + value = prefs.getLong64("long", 0); + if (value != (-9223372036854775807LL - 1)) { + Serial.println("getLong MIN Error"); + return 0; + } else { + Serial.print("getLong MIN: "); + Serial.println(value); + } + + return 1; +} + +int testULong64() { + uint64_t data; + uint64_t value; + + data = UINT64_MAX; + prefs.putULong64("ulong", data); + value = prefs.getULong64("ulong", 0); + if (value != 18446744073709551615ULL) { + Serial.println("getULong64 MAX Error"); + return 0; + } else { + Serial.print("getULong64 MAX: "); + Serial.println(value); + } + + data = 0; + prefs.putULong64("ulong", data); + value = prefs.getULong64("ulong", 1); + if (value != 0) { + Serial.println("getULong64 MIN Error"); + return 0; + } else { + Serial.print("getULong64 MIN: "); + Serial.println(value); + } + + return 1; +} + +int testFloat() { + float data; + float value; + + data = FLT_MAX; + prefs.putFloat("float", data); + value = prefs.getFloat("float", 0); + if (value != FLT_MAX) { + Serial.println("getFloat MAX Error"); + return 0; + } else { + Serial.print("getFloat MAX: "); + Serial.println(value); + } + + data = FLT_MIN; + prefs.putFloat("float", data); + value = prefs.getFloat("float", 0); + if (value != FLT_MIN) { + Serial.println("getFloat MIN Error"); + return 0; + } else { + Serial.print("getFloat MIN: "); + Serial.println(value); + } + + return 1; +} + +int testDouble() { + double data; + double value; + + data = DBL_MAX; + prefs.putDouble("double", data); + value = prefs.getDouble("double", 0); + if (value != DBL_MAX) { + Serial.println("getDouble MAX Error"); + return 0; + } else { + Serial.print("getDouble MAX: "); + Serial.println(value); + } + + data = DBL_MIN; + prefs.putDouble("double", data); + value = prefs.getDouble("double", 0); + if (value != DBL_MIN) { + Serial.println("getDouble MIN Error"); + return 0; + } else { + Serial.print("getDouble MIN: "); + Serial.println(value); + } + + return 1; +} + +int testBytes() { + uint8_t data[] = {9, 30, 235, 255, 20, 15, 0, 1, 9, 30, 235, 255, 20, 15, 0, 1, 9, 30, 235, 255, 20, 15, 0, 1, 9, 30, 235, 255, 20, 15, 0, 1}; + size_t len; + + prefs.putBytes("bytes", data, sizeof(data)); + len = prefs.getBytesLength("bytes"); + uint8_t value[len]; + prefs.getBytes("bytes", value, len); + if (memcmp(data, value, len) != 0) { + Serial.println("getBytes Error"); + return 0; + } else { + Serial.println("getBytes OK"); + } + + return 1; +} + +int testString() { + const char* data = "Lorem ipsum dolor sit amet consectetur adipiscing elit."; + String value = "default"; + + prefs.putString("string", data); + value = prefs.getString("string", value); + if (strcmp(data, value.c_str()) != 0) { + Serial.println("getString Error"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + return 0; + } else { + Serial.println("getString OK"); + } + + return 1; +} diff --git a/libraries/Preferences/src/Preferences.cpp b/libraries/Preferences/src/Preferences.cpp index 9bdac4887..bf731d8e6 100644 --- a/libraries/Preferences/src/Preferences.cpp +++ b/libraries/Preferences/src/Preferences.cpp @@ -162,8 +162,9 @@ size_t Preferences::putBool(const char* key, const bool value) { size_t Preferences::putString(const char* key, const char* value) { string res = ""; if (key != nullptr && strlen(key) > 0 && value != nullptr && strlen(value) > 0) { - if (modem.write(string(PROMPT(_PREF_PUT)), res, "%s%s,%d,%s\r\n", CMD_WRITE(_PREF_PUT), key, PT_STR, value)) { - return atoi(res.c_str()); + modem.write_nowait(string(PROMPT(_PREF_PUT)), res, "%s%s,%d,%d\r\n", CMD_WRITE(_PREF_PUT), key, PT_STR, strlen(value)); + if(modem.passthrough((uint8_t *)value, strlen(value))) { + return strlen(value); } } return 0; @@ -187,7 +188,7 @@ size_t Preferences::putBytes(const char* key, const void* value, size_t len) { PreferenceType Preferences::getType(const char* key) { string res = ""; if (key != nullptr && strlen(key) > 0) { - if (modem.write(string(PROMPT(_PREF_PUT)), res, "%s%s\r\n", CMD_WRITE(_PREF_PUT), key)) { + if (modem.write(string(PROMPT(_PREF_TYPE)), res, "%s%s\r\n", CMD_WRITE(_PREF_TYPE), key)) { return static_cast(atoi(res.c_str())); } } @@ -307,9 +308,11 @@ bool Preferences::getBool(const char* key, const bool defaultValue) { size_t Preferences::getString(const char* key, char* value, const size_t maxLen) { string res = ""; if (key != nullptr && strlen(key) > 0 && value != nullptr) { + modem.read_using_size(); if (modem.write(string(PROMPT(_PREF_GET)), res, "%s%s,%d\r\n", CMD_WRITE(_PREF_GET), key, PT_STR)) { - if (res.length() < maxLen) { + if (res.length()+1 < maxLen) { // take into account \0 at the end strncpy(value, res.c_str(), res.length()); + value[res.length()] = '\0'; return res.length(); } } @@ -320,6 +323,7 @@ size_t Preferences::getString(const char* key, char* value, const size_t maxLen) String Preferences::getString(const char* key, const String defaultValue) { string res = ""; if (key != nullptr && strlen(key) > 0) { + modem.read_using_size(); if (modem.write(string(PROMPT(_PREF_GET)), res, "%s%s,%d,%s\r\n", CMD_WRITE(_PREF_GET), key, PT_STR, defaultValue.c_str())) { return String(res.c_str()); } @@ -346,6 +350,8 @@ size_t Preferences::getBytes(const char* key, void * buf, size_t maxLen) { if (modem.write(string(PROMPT(_PREF_GET)), res, "%s%s,%d\r\n", CMD_WRITE(_PREF_GET), key, PT_BLOB)) { if (res.size() >= len && len <= maxLen) { memcpy(buf, (uint8_t*)&res[0], len); + + return len; } } } diff --git a/libraries/RTC/docs/api.md b/libraries/RTC/docs/api.md new file mode 100644 index 000000000..06da4907d --- /dev/null +++ b/libraries/RTC/docs/api.md @@ -0,0 +1,915 @@ +# Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +`class` [`AlarmMatch`](#class_alarm_match) | Class representing the alarm match system. +`class` [`RTClock`](#class_r_t_clock) | Class for interfacing with a real-time clock (RTC). +`class` [`RTCTime`](#class_r_t_c_time) | A class representing time in the context of an RTC (Real-Time Clock). +`struct` [`timeval`](#structtimeval) | + +# class `AlarmMatch` + +Class representing the alarm match system. + +This class is used to define how an alarm matches a set of conditions or criteria to trigger an action, such as a timer or event. + +## Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +| [`AlarmMatch`](#class_alarm_match_1a2d54ef9ddc542da32fe103b4e7ab28b3) | Default constructor for the [AlarmMatch](#class_alarm_match) class. | +| [`~AlarmMatch`](#class_alarm_match_1a5afd0d3d3f96c641ecbd3450ca775863) | Destructor for the [AlarmMatch](#class_alarm_match) class. | +| [`addMatchSecond`](#class_alarm_match_1aecccdfaf4a13b856ea39b3563c0047c9) | Increments the match time by one second. | +| [`addMatchMinute`](#class_alarm_match_1aa6c7ff0591e656dde418b47221b03f98) | Increments the match time by one minute. | +| [`addMatchHour`](#class_alarm_match_1aaaa7278c42a02c157f19d7adf630efeb) | Increments the match time by one hour. | +| [`addMatchDay`](#class_alarm_match_1a7750e8bd7fa3d9e8aba05d18549f9e4a) | Increments the match time by one day. | +| [`addMatchMonth`](#class_alarm_match_1a535672e2cf4435a2ef3c194359995813) | Increments the match time by one month. | +| [`addMatchYear`](#class_alarm_match_1a29be33fca9a0993be0e0c53b1f056a89) | Increments the match time by one year. | +| [`addMatchDayOfWeek`](#class_alarm_match_1a2c824482a6096fb8d7d156558dfa017b) | Increments the match time by one day of the week. | +| [`removeMatchSecond`](#class_alarm_match_1a2acb110c3cf78858addfd47b973d384b) | Decrements the match time by one second. | +| [`removeMatchMinute`](#class_alarm_match_1ad07250d87328a2fb737af1aae77cbf6b) | Decrements the match time by one minute. | +| [`removeMatchHour`](#class_alarm_match_1ad2d0f7580893e3fa816f557d48b14dde) | Decrements the match time by one hour. | +| [`removeMatchDay`](#class_alarm_match_1af5fd4dadc4adcae8ede004f66eaa12f6) | Decrements the match time by one day. | +| [`removeMatchMonth`](#class_alarm_match_1a37b940e78e62fc2d3e508b192be2eb68) | Decrements the match time by one month. | +| [`removeMatchYear`](#class_alarm_match_1ac90e5a925727f34b659a41f0c3a4d426) | Decrements the match time by one year. | +| [`removeMatchDayOfWeek`](#class_alarm_match_1ae681f0ee94875bc410a92327dd204b03) | Removes the match criteria for the day of the week. | +| [`isMatchingSecond`](#class_alarm_match_1a52de136a3d64383fb758eea86fcf3946) | Checks if the current second matches the set criteria. | +| [`isMatchingMinute`](#class_alarm_match_1ad4d0dfe998cd89c9a9682737a7aee338) | Checks if the current minute matches the set criteria. | +| [`isMatchingHour`](#class_alarm_match_1a73eab2cb02cd8bb12479022cc52ce54f) | Checks if the current hour matches the set criteria. | +| [`isMatchingDay`](#class_alarm_match_1a9f26a4bdc6febad854218bf9c142651e) | Checks if the current day matches the set criteria. | +| [`isMatchingMonth`](#class_alarm_match_1a536093cce64b2e1c4a351815e1313193) | Checks if the current month matches the set criteria. | +| [`isMatchingYear`](#class_alarm_match_1a0b8748eecf57c8c7f2dffcfba944407e) | Checks if the current year matches the set criteria. | +| [`isMatchingDayOfWeek`](#class_alarm_match_1ac8c8ab1655f28c78c5ec648beeb52ba0) | Checks if the current day of the week matches the set criteria. | + +## Members + +### `AlarmMatch` + +```cpp +AlarmMatch() +``` + +Default constructor for the [AlarmMatch](#class_alarm_match) class. + +
+ +### `~AlarmMatch` + +```cpp +~AlarmMatch() +``` + +Destructor for the [AlarmMatch](#class_alarm_match) class. + +
+ +### `addMatchSecond` + +```cpp +void addMatchSecond() +``` + +Increments the match time by one second. + +This function updates the internal match time by adding one second to the current value. +
+ +### `addMatchMinute` + +```cpp +void addMatchMinute() +``` + +Increments the match time by one minute. + +This function updates the internal match time by adding one minute to the current value. +
+ +### `addMatchHour` + +```cpp +void addMatchHour() +``` + +Increments the match time by one hour. + +This function updates the internal match time by adding one hour to the current value. +
+ +### `addMatchDay` + +```cpp +void addMatchDay() +``` + +Increments the match time by one day. + +This function updates the internal match time by adding one day to the current value. +
+ +### `addMatchMonth` + +```cpp +void addMatchMonth() +``` + +Increments the match time by one month. + +This function updates the internal match time by adding one month to the current value. +
+ +### `addMatchYear` + +```cpp +void addMatchYear() +``` + +Increments the match time by one year. + +This function updates the internal match time by adding one year to the current value. +
+ +### `addMatchDayOfWeek` + +```cpp +void addMatchDayOfWeek() +``` + +Increments the match time by one day of the week. + +This function updates the internal match time by adding one day to the current day of the week. +
+ +### `removeMatchSecond` + +```cpp +void removeMatchSecond() +``` + +Decrements the match time by one second. + +This function updates the internal match time by subtracting one second from the current second. +
+ +### `removeMatchMinute` + +```cpp +void removeMatchMinute() +``` + +Decrements the match time by one minute. + +This function updates the internal match time by subtracting one minute from the current minute. +
+ +### `removeMatchHour` + +```cpp +void removeMatchHour() +``` + +Decrements the match time by one hour. + +This function updates the internal match time by subtracting one hour from the current hour. +
+ +### `removeMatchDay` + +```cpp +void removeMatchDay() +``` + +Decrements the match time by one day. + +This function updates the internal match time by subtracting one day from the current day. +
+ +### `removeMatchMonth` + +```cpp +void removeMatchMonth() +``` + +Decrements the match time by one month. + +This function updates the internal match time by subtracting one month from the current month. +
+ +### `removeMatchYear` + +```cpp +void removeMatchYear() +``` + +Decrements the match time by one year. + +This function updates the internal match time by subtracting one year from the current year. +
+ +### `removeMatchDayOfWeek` + +```cpp +void removeMatchDayOfWeek() +``` + +Removes the match criteria for the day of the week. + +This function updates the internal match time by removing the day of the week from the matching criteria. +
+ +### `isMatchingSecond` + +```cpp +bool isMatchingSecond() +``` + +Checks if the current second matches the set criteria. + +This function compares the current second with the set match criteria (if any) and returns true if there is a match, false otherwise. + +#### Returns +`True` if the current second matches the criteria, `false` otherwise. +
+ +### `isMatchingMinute` + +```cpp +bool isMatchingMinute() +``` + +Checks if the current minute matches the set criteria. + +This function compares the current minute with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current minute matches the criteria, `false` otherwise. +
+ +### `isMatchingHour` + +```cpp +bool isMatchingHour() +``` + +Checks if the current hour matches the set criteria. + +This function compares the current hour with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current hour matches the criteria, `false` otherwise. +
+ +### `isMatchingDay` + +```cpp +bool isMatchingDay() +``` + +Checks if the current day matches the set criteria. + +This function compares the current day with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current day matches the criteria, `false` otherwise. +
+ +### `isMatchingMonth` + +```cpp +bool isMatchingMonth() +``` + +Checks if the current month matches the set criteria. + +This function compares the current month with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current month matches the criteria, `false` otherwise. +
+ +### `isMatchingYear` + +```cpp +bool isMatchingYear() +``` + +Checks if the current year matches the set criteria. + +This function compares the current year with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current year matches the criteria, `false` otherwise. +
+ +### `isMatchingDayOfWeek` + +```cpp +bool isMatchingDayOfWeek() +``` + +Checks if the current day of the week matches the set criteria. + +This function compares the current day of the week with the set match criteria (if any) and returns `true` if there is a match, `false` otherwise. + +#### Returns +`True` if the current day of the week matches the criteria, `false` otherwise. +
+ +# class `RTClock` + +Class for interfacing with a real-time clock (RTC). + +The [RTClock](#class_r_t_clock) class provides functionality to get and set the time, date, and other time-related operations, such as day of the week, alarm management, and more. + +## Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +| [`RTClock`](#class_r_t_clock_1a1fefceddd93d040e3f4296c573e0fe34) | Constructor to initialize the real-time clock (RTC). | +| [`~RTClock`](#class_r_t_clock_1a8e569b9095a0a7545278ebf132564492) | Destructor for the real-time clock (RTC). | +| [`begin`](#class_r_t_clock_1ad753f953539b7ec0e56a9f15c358c2c5) | Initializes the real-time clock (RTC). | +| [`getTime`](#class_r_t_clock_1a4c335640f3f62f42dd5ed3fad314e3e7) | Retrieves the current time from the real-time clock (RTC). | +| [`setPeriodicCallback`](#class_r_t_clock_1a47258e8554ded2f597fdb4f6e6c77548) | Sets a periodic callback function triggered by the real-time clock (RTC). | +| [`setAlarmCallback`](#class_r_t_clock_1a7e24b8f5727297ab4974a40fb506d961) | Sets an alarm callback function triggered when the specified conditions are met. | +| [`setAlarm`](#class_r_t_clock_1a04ef8ba0c3ce454ea3b7868f582fae48) | Configures an alarm based on the specified time and matching criteria. | +| [`isRunning`](#class_r_t_clock_1a09d0a22117e98e449dee1d5a74649eb5) | Checks if the RTC (Real-Time Clock) is currently running. | +| [`setTime`](#class_r_t_clock_1a64b98ad69891a6e9b1b85b27f4df7ca3) | Sets the current time of the RTC (Real-Time Clock). | +| [`setTimeIfNotRunning`](#class_r_t_clock_1a4168c5950e860aa7ff1af7b24fed2a94) | Sets the RTC time only if the clock is not currently running. | + +## Members + +### `RTClock` + +```cpp +RTClock() +``` + +Constructor to initialize the real-time clock (RTC). + +
+ +### `~RTClock` + +```cpp +~RTClock() +``` + +Destructor for the real-time clock (RTC). + +
+ +### `begin` + +```cpp +bool begin() +``` + +Initializes the real-time clock (RTC). + +#### Returns +`True` if the initialization was successful, `false` otherwise. +
+ +### `getTime` + +```cpp +bool getTime( RTCTime & t) +``` + +Retrieves the current time from the real-time clock (RTC). + +This function retrieves the current time from the RTC and stores it in the provided [RTCTime](#class_r_t_c_time) object. The [RTCTime](#class_r_t_c_time) object will be updated with the latest time and date information from the RTC module. + +#### Parameters +* `t` A reference to an [RTCTime](#class_r_t_c_time) object where the current time will be stored. + +#### Returns +`True` if the time was successfully retrieved and stored in the [RTCTime](#class_r_t_c_time) object, `false` if there was an error during the operation. +
+ +### `setPeriodicCallback` + +```cpp +bool setPeriodicCallback(rtc_cbk_t fnc, Period p) +``` + +Sets a periodic callback function triggered by the real-time clock (RTC). + +This function configures a callback function to be executed at a specific periodic interval, as defined by the `Period` parameter. The callback function will be invoked automatically by the RTC at the specified rate. + +#### Parameters +* `fnc` The callback function to be executed periodically. The function must match the `rtc_cbk_t` type signature. + +* `p` The period at which the callback function should be triggered. This is specified as a value from the `Period` enumeration. + +#### Returns +`True` if the callback was successfully set, `false` otherwise. +
+ +### `setAlarmCallback` + +```cpp +bool setAlarmCallback(rtc_cbk_t fnc, RTCTime & t, AlarmMatch & m) +``` + +Sets an alarm callback function triggered when the specified conditions are met. + +This function configures a callback function to be executed when the real-time clock (RTC) matches the specified date and time conditions defined in the [RTCTime](#class_r_t_c_time) and [AlarmMatch](#class_alarm_match) parameters. + +#### Parameters +* `fnc` The callback function to be executed when the alarm triggers. The function must match the `rtc_cbk_t` type signature. + +* `t` The target time for the alarm, specified as an [RTCTime](#class_r_t_c_time) object. + +* `m` The alarm match conditions, specified using the [AlarmMatch](#class_alarm_match) object. This determines which components of the [RTCTime](#class_r_t_c_time) must match (e.g., year, month, day). + +#### Returns +`True` if the alarm callback was successfully set, `false` otherwise. +
+ +### `setAlarm` + +```cpp +bool setAlarm( RTCTime & t, AlarmMatch & m) +``` + +Configures an alarm based on the specified time and matching criteria. + +This function sets an alarm on the real-time clock (RTC). The alarm will be triggered when the RTC's current time matches the conditions specified by the [RTCTime](#class_r_t_c_time) and [AlarmMatch](#class_alarm_match) parameters. + +#### Parameters +* `t` The target time for the alarm, specified as an [RTCTime](#class_r_t_c_time) object. + +* `m` The alarm match conditions, specified using the [AlarmMatch](#class_alarm_match) object. This determines which components of the [RTCTime](#class_r_t_c_time) must match. + +#### Returns +`True` if the alarm was successfully set, `false` otherwise. +
+ +### `isRunning` + +```cpp +bool isRunning() +``` + +Checks if the RTC (Real-Time Clock) is currently running. + +This function verifies whether the RTC module is operational and maintaining time. + +#### Returns +`True` if the RTC is running, `false` otherwise. +
+ +### `setTime` + +```cpp +bool setTime( RTCTime & t) +``` + +Sets the current time of the RTC (Real-Time Clock). + +This function updates the RTC with the provided time. + +#### Parameters +* `t` A reference to an [RTCTime](#class_r_t_c_time) object containing the desired time to set. + +#### Returns +`True` if the time was successfully updated, `false` otherwise. +
+ +### `setTimeIfNotRunning` + +```cpp +bool setTimeIfNotRunning( RTCTime & t) +``` + +Sets the RTC time only if the clock is not currently running. + +This function checks if the RTC is stopped and updates its time with the provided [RTCTime](#class_r_t_c_time) object if the clock is not running. + +#### Parameters +* `t` A reference to an [RTCTime](#class_r_t_c_time) object containing the desired time to set. + +#### Returns +`True` if the time was successfully updated, `false` otherwise. +
+ +# class `RTCTime` + +A class representing time in the context of an RTC (Real-Time Clock). + +The [RTCTime](#class_r_t_c_time) class encapsulates time-related information and provides utility methods to interact with and manipulate RTC time. + +## Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +| [`RTCTime`](#class_r_t_c_time_1a924ea08fcfda4cd7bba69d27e6044d8c) | Default constructor for the [RTCTime](#class_r_t_c_time) class. | +| [`RTCTime`](#class_r_t_c_time_1a1845bc8c5cc390e771a8569961821681) | Constructor for the [RTCTime](#class_r_t_c_time) class with a given time. | +| [`RTCTime`](#class_r_t_c_time_1adce8b95b38afbd4c83c95a55ef3199c9) | Constructor for the [RTCTime](#class_r_t_c_time) class with a given `tm` structure. | +| [`RTCTime`](#class_r_t_c_time_1af650d794e8dc4b68e2f7edf8904290c8) | Constructor for the [RTCTime](#class_r_t_c_time) class with specific date and time parameters. | +| [`~RTCTime`](#class_r_t_c_time_1ab8bee04da843e1f4d573b8dc8456045c) | Destructor for the [RTCTime](#class_r_t_c_time) class. | +| [`setDayOfMonth`](#class_r_t_c_time_1af9abac029cfc446635d0418cb026cb05) | Sets the day of the month. | +| [`setMonthOfYear`](#class_r_t_c_time_1ae9b91fdd5ac696f476bca77ab00d3924) | Sets the month of the year. | +| [`setYear`](#class_r_t_c_time_1a03f3a280099446d866dd410c6c0e37ea) | Sets the year. | +| [`setHour`](#class_r_t_c_time_1a314592b177aa3647f52b151b397c615c) | Sets the hour of the day. | +| [`setMinute`](#class_r_t_c_time_1afaa2c25a40be5ad217147fac3b59156a) | Sets the minute of the hour. | +| [`setSecond`](#class_r_t_c_time_1a00b5a03046370aa1d1895863a9a17464) | Sets the second of the minute. | +| [`setDayOfWeek`](#class_r_t_c_time_1aea6e5bd41959cb1eaf4cf3ba81f4f27f) | Sets the day of the week. | +| [`setSaveLight`](#class_r_t_c_time_1a46667e749264e0487193495e9f84b740) | Sets whether daylight saving time is active. | +| [`setUnixTime`](#class_r_t_c_time_1a8d50fa1ee9a132a037500f39845bdabb) | Sets the time using a Unix timestamp. | +| [`setTM`](#class_r_t_c_time_1a8a63142d7699025c78cbbf252b9dbe62) | Sets the time from a struct tm. | +| [`getDayOfMonth`](#class_r_t_c_time_1a42bfdfc2ae6d2cf81ddc0a6f5814f65a) | Gets the day of the month. | +| [`getMonth`](#class_r_t_c_time_1a43aed822be5e9e26efce91050de7aca8) | Gets the month of the year. | +| [`getYear`](#class_r_t_c_time_1ab7ad8a017d1972c4a80f3c63e6140f80) | Gets the year. | +| [`getHour`](#class_r_t_c_time_1a226aec3347c7d2406162af6ddf35ebf6) | Gets the hour of the day. | +| [`getMinutes`](#class_r_t_c_time_1a4569498a7960c995e266b7d23eac98ba) | Gets the minutes of the hour. | +| [`getSeconds`](#class_r_t_c_time_1a86e8e5984d1c0d954836f25d010c9f46) | Gets the seconds of the minute. | +| [`getDayOfWeek`](#class_r_t_c_time_1a72f06ebb1c1368134f6616bc905ca526) | Gets the day of the week. | +| [`getUnixTime`](#class_r_t_c_time_1a7215c300c30e6423c62cac39443871bd) | Gets the Unix timestamp. | +| [`getTmTime`](#class_r_t_c_time_1a7830e079cff08391ef28899e910e79bd) | Gets the time as a struct `tm`. | +| [`toString`](#class_r_t_c_time_1afc343321d5caee657655f7c7d998f4c0) | Returns the ISO 8601 string representation of the date and time. | +| [`operator arduino::String`](#class_r_t_c_time_1a03bf4e2ba6aaab9e829be5b17be55f36) | Returns the ISO 8601 string representation of the date and time by calling the [toString()](#class_r_t_c_time_1afc343321d5caee657655f7c7d998f4c0) method. | + +## Members + +### `RTCTime` + +```cpp +RTCTime() +``` + +Default constructor for the [RTCTime](#class_r_t_c_time) class. + +
+ +### `RTCTime` + +```cpp +RTCTime(time_t t) +``` + +Constructor for the [RTCTime](#class_r_t_c_time) class with a given time. + +Initializes the [RTCTime](#class_r_t_c_time) object with the specified time. + +#### Parameters +* `t` A time_t value representing the time to initialize the [RTCTime](#class_r_t_c_time) object with. +
+ +### `RTCTime` + +```cpp +RTCTime(struct tm & t) +``` + +Constructor for the [RTCTime](#class_r_t_c_time) class with a given `tm` structure. + +#### Parameters +* `t` A reference to a struct `tm` that contains the broken-down time to initialize the [RTCTime](#class_r_t_c_time) object with. +
+ +### `RTCTime` + +```cpp +RTCTime(int _day, Month _m, int _year, int _hours, int _minutes, int _seconds, DayOfWeek _dof, SaveLight _sl) +``` + +Constructor for the [RTCTime](#class_r_t_c_time) class with specific date and time parameters. + +Initializes the [RTCTime](#class_r_t_c_time) object with the specified date, time, day of the week, and daylight saving time status. + +#### Parameters +* `_day` The day of the month. + +* `_m` The month of the year (using the Month enum, e.g., JANUARY, FEBRUARY, etc.). + +* `_year` The year (e.g., 2024). + +* `_hours` The hour of the day (0-23). + +* `_minutes` The minute of the hour (0-59). + +* `_seconds` The second of the minute (0-59). + +* `_dof` The day of the week (using the DayOfWeek enum, e.g., MONDAY, TUESDAY, etc.). + +* `_sl` The daylight saving time status (using the SaveLight enum, e.g., DST_ON, DST_OFF). +
+ +### `~RTCTime` + +```cpp +~RTCTime() +``` + +Destructor for the [RTCTime](#class_r_t_c_time) class. + +
+ +### `setDayOfMonth` + +```cpp +bool setDayOfMonth(int day) +``` + +Sets the day of the month. + +#### Parameters +* `day` The day of the month. + +#### Returns +`true` if the day is set successfully, `false` if the day is out of range. +
+ +### `setMonthOfYear` + +```cpp +bool setMonthOfYear(Month m) +``` + +Sets the month of the year. + +#### Parameters +* `m` The month. + +#### Returns +`true` if the month is set successfully, `false` if the month is out of range. +
+ +### `setYear` + +```cpp +bool setYear(int year) +``` + +Sets the year. + +#### Parameters +* `year` The year (e.g., 1989 or 2022). + +#### Returns +`true` if the year is set successfully, `false` if the year is invalid. +
+ +### `setHour` + +```cpp +bool setHour(int hour) +``` + +Sets the hour of the day. + +#### Parameters +* `hour` The hour. + +#### Returns +`true` if the hour is set successfully, `false` if the hour is out of range. +
+ +### `setMinute` + +```cpp +bool setMinute(int minute) +``` + +Sets the minute of the hour. + +#### Parameters +* `minute` The minute. + +#### Returns +`true` if the minute is set successfully, `false` if the minute is out of range. +
+ +### `setSecond` + +```cpp +bool setSecond(int second) +``` + +Sets the second of the minute. + +#### Parameters +* `second` The second. + +#### Returns +`true` if the second is set successfully, `false` if the second is out of range. +
+ +### `setDayOfWeek` + +```cpp +bool setDayOfWeek(DayOfWeek d) +``` + +Sets the day of the week. + +#### Parameters +* `d` The day of the week (from the DayOfWeek enumeration). + +#### Returns +`true` if the day of the week is set successfully, `false` if the value is invalid. +
+ +### `setSaveLight` + +```cpp +bool setSaveLight(SaveLight sl) +``` + +Sets whether daylight saving time is active. + +#### Parameters +* `sl` The SaveLight enumeration value. + +#### Returns +`true` if the daylight saving time setting is applied successfully, `false` otherwise. +
+ +### `setUnixTime` + +```cpp +bool setUnixTime(time_t time) +``` + +Sets the time using a Unix timestamp. + +#### Parameters +* `time` The Unix timestamp (seconds since January 1, 1970). + +#### Returns +`true` if the Unix timestamp is set successfully, `false` otherwise. +
+ +### `setTM` + +```cpp +void setTM(struct tm & t) +``` + +Sets the time from a struct tm. + +#### Parameters +* `t` A reference to a struct tm that contains the time values. +
+ +### `getDayOfMonth` + +```cpp +int getDayOfMonth() const +``` + +Gets the day of the month. + +#### Returns +The day of the month. +
+ +### `getMonth` + +```cpp +Month getMonth() const +``` + +Gets the month of the year. + +#### Returns +The month. +
+ +### `getYear` + +```cpp +int getYear() const +``` + +Gets the year. + +#### Returns +The year. +
+ +### `getHour` + +```cpp +int getHour() const +``` + +Gets the hour of the day. + +#### Returns +The hour. +
+ +### `getMinutes` + +```cpp +int getMinutes() const +``` + +Gets the minutes of the hour. + +#### Returns +The minutes. +
+ +### `getSeconds` + +```cpp +int getSeconds() const +``` + +Gets the seconds of the minute. + +#### Returns +The seconds. +
+ +### `getDayOfWeek` + +```cpp +DayOfWeek getDayOfWeek() const +``` + +Gets the day of the week. + +#### Returns +The day of the week. +
+ +### `getUnixTime` + +```cpp +time_t getUnixTime() +``` + +Gets the Unix timestamp. + +#### Returns +The Unix timestamp. +
+ +### `getTmTime` + +```cpp +struct tm getTmTime() +``` + +Gets the time as a struct `tm`. + +#### Returns +A struct `tm` that contains the time values. +
+ +### `toString` + +```cpp +arduino::String toString() const +``` + +Returns the ISO 8601 string representation of the date and time. + +#### Returns +String The date and time in the format YYYY-MM-DDTHH:MM:SS. +
+ +### `operator arduino::String` + +```cpp +operator arduino::String() const +``` + +Returns the ISO 8601 string representation of the date and time by calling the [toString()](#class_r_t_c_time_1afc343321d5caee657655f7c7d998f4c0) method. + +#### Returns +String The date and time in the format YYYY-MM-DDTHH:MM:SS. +
+ +# struct `timeval` + +## Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +| [`tv_sec`](#structtimeval_1aef6ddab1064c430758f9f913b7e4a21e) | | +| [`tv_usec`](#structtimeval_1a60486501e203aa76351aae5afee09b98) | | + +## Members + +### `tv_sec` + +```cpp +time_t tv_sec +``` + +
+ +### `tv_usec` + +```cpp +useconds_t tv_usec +``` + +
+ diff --git a/libraries/RTC/src/RTC.h b/libraries/RTC/src/RTC.h index c0b3f431d..6ef0d6af4 100644 --- a/libraries/RTC/src/RTC.h +++ b/libraries/RTC/src/RTC.h @@ -5,29 +5,97 @@ #include "r_rtc_api.h" #include -struct timeval { - time_t tv_sec; - useconds_t tv_usec; +struct timeval +{ + time_t tv_sec; + useconds_t tv_usec; }; #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -void set_time(time_t t); -void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init_rtc)(void), int (*isenabled_rtc)(void)); -int gettimeofday(struct timeval *tv, void *tz); -int settimeofday(const struct timeval *tv, const struct timezone *tz); + /** + * @brief Sets the system time. + * + * This function sets the system time to the specified value. + * The time is provided as a `time_t` object, representing the + * number of seconds since the Unix epoch (January 1, 1970). + * + * @param `t` The time to set, expressed as a `time_t` object. + * This value represents the number of seconds since + * the Unix epoch. + */ + void set_time(time_t t); + + /** + * @brief Attaches RTC (Real-Time Clock) handling functions. + * + * This function attaches custom handlers for reading, writing, initializing, + * and checking the status of the RTC. These handlers allow integration with + * an external RTC module or custom RTC implementation. + * + * @param `read_rtc` A pointer to a function that reads the current RTC time + * and returns it as a `time_t` value. + * @param `write_rtc` A pointer to a function that sets the RTC time to the + * specified `time_t` value. + * @param `init_rtc` A pointer to a function that initializes the RTC hardware. + * @param `isenabled_rtc` A pointer to a function that checks whether the RTC + * is enabled, returning an integer (e.g., 1 for enabled, 0 for disabled). + */ + void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init_rtc)(void), int (*isenabled_rtc)(void)); + + /** + * @brief Retrieves the current time of day. + * + * This function gets the current time, expressed as seconds and microseconds + * since the Unix epoch (00:00:00 UTC, January 1, 1970). The time is stored in + * a `timeval` structure. + * + * @param `tv` A pointer to a `timeval` structure where the current time will be stored. + * The structure contains two fields: + * - `tv_sec`: Seconds since the Unix epoch. + * - `tv_usec`: Microseconds since the last second. + * @param `tz` A pointer to a timezone structure (optional). It is usually set to `nullptr` + * as timezone information is not handled by this function on most systems. + * + * @return Returns `0` on success, or `-1` on failure (e.g., if `tv` is `nullptr`). + */ + int gettimeofday(struct timeval *tv, void *tz); + + /** + * @brief Sets the current time of day and timezone. + * + * This function sets the system's current time and optionally the timezone. + * The new time is specified in a `timeval` structure, which contains the + * number of seconds and microseconds since the Unix epoch (00:00:00 UTC, + * January 1, 1970). + * + * @param `tv` A pointer to a `timeval` structure specifying the new time. + * The structure contains two fields: + * - `tv_sec`: Seconds since the Unix epoch. + * - `tv_usec`: Microseconds since the last second. + * @param `tz` A pointer to a `timezone` structure specifying the timezone (optional). + * + * @return Returns `0` on success, or `-1` on failure (e.g., if `tv` is `nullptr` or the operation is not permitted). + */ + int settimeofday(const struct timeval *tv, const struct timezone *tz); #ifdef __cplusplus } #endif - using stime_t = struct tm; using rtc_cbk_t = void (*)(); -enum class Month : uint8_t { +/** + * @brief Enumeration representing the months of the year. + * + * This enumeration maps the months of the year to numeric values, starting from 0 for January and ending at 11 for December. + */ +enum class Month : uint8_t +{ JANUARY = 0, FEBRUARY, MARCH, @@ -42,10 +110,24 @@ enum class Month : uint8_t { DECEMBER }; +/** + * @brief Converts a `Month` enumeration value to its corresponding integer representation. + * + * This function takes a `Month` enumeration value and returns its integer equivalent. + * + * @param `m` The `Month` enumeration value to convert. + * + * @return The integer representation of the given month. + */ int Month2int(Month m); - -enum class DayOfWeek : uint8_t { +/** + * @brief Enumeration representing the days of the week. + * + * This enumeration maps the days of the week to numeric values. + */ +enum class DayOfWeek : uint8_t +{ MONDAY = 1, TUESDAY = 2, WEDNESDAY = 3, @@ -55,18 +137,50 @@ enum class DayOfWeek : uint8_t { SUNDAY = 0 }; +/** + * @brief Converts a `DayOfWeek` enumeration value to its corresponding integer representation. + * + * This function maps a `DayOfWeek` enumeration value to an integer representation based on + * whether Sunday or Monday is considered the first day of the week. + * + * @param `dow` The `DayOfWeek` enumeration value to convert. + * @param `sunday_first` A boolean flag that determines the starting day of the week: + * - `true`: Sunday is the first day of the week (Sunday = 0, Monday = 1, ...). + * - `false`: Monday is the first day of the week (Monday = 0, Tuesday = 1, ...). + * + * @return The integer representation of the given day of the week, adjusted based on + * the value of `sunday_first`. + */ int DayOfWeek2int(DayOfWeek dow, bool sunday_first); -enum class SaveLight : uint8_t { +enum class SaveLight : uint8_t +{ SAVING_TIME_INACTIVE = 0, SAVING_TIME_ACTIVE }; +/** + * @brief Converts a `SaveLight` enumeration value to its corresponding boolean representation. + * + * This function maps a `SaveLight` enumeration value to a boolean, used to indicate + * whether it is daylight savings time (`true`) or not (`false`). + * + * @param `sl` The `SaveLight` enumeration value to convert. + * + * @return `true` if it is daylight savings time, `false` otherwise. + */ bool SaveLigth2bool(SaveLight sl); -class RTCTime { - private: +/** + * @brief A class representing time in the context of an RTC (Real-Time Clock). + * + * The `RTCTime` class encapsulates time-related information and provides utility methods + * to interact with and manipulate RTC time. + */ +class RTCTime +{ +private: stime_t stime; int day; @@ -78,34 +192,200 @@ class RTCTime { DayOfWeek day_of_week; SaveLight save_light; - public: +public: + /** + * @brief Default constructor for the RTCTime class. + */ RTCTime(); + + /** + * @brief Constructor for the RTCTime class with a given time. + * + * Initializes the RTCTime object with the specified time. + * + * @param `t` A time_t value representing the time to initialize the RTCTime object with. + */ RTCTime(time_t t); + + /** + * @brief Constructor for the RTCTime class with a given `tm` structure. + * + * @param `t` A reference to a struct `tm` that contains the broken-down time to initialize the RTCTime object with. + */ RTCTime(struct tm &t); + + /** + * @brief Constructor for the RTCTime class with specific date and time parameters. + * + * Initializes the RTCTime object with the specified date, time, day of the week, and daylight saving time status. + * + * @param `_day` The day of the month. + * @param `_m` The month of the year (using the Month enum, e.g., JANUARY, FEBRUARY, etc.). + * @param `_year` The year (e.g., 2024). + * @param `_hours` The hour of the day (0-23). + * @param `_minutes` The minute of the hour (0-59). + * @param `_seconds` The second of the minute (0-59). + * @param `_dof` The day of the week (using the DayOfWeek enum, e.g., MONDAY, TUESDAY, etc.). + * @param `_sl` The daylight saving time status (using the SaveLight enum, e.g., DST_ON, DST_OFF). + */ RTCTime(int _day, Month _m, int _year, int _hours, int _minutes, int _seconds, DayOfWeek _dof, SaveLight _sl); + + /** + * @brief Destructor for the RTCTime class. + */ ~RTCTime(); /* setters */ - bool setDayOfMonth(int day); /* day from 1 to 31 */ - bool setMonthOfYear(Month m); /* month from 1 (January) to 12 (December) */ - bool setYear(int year); /* the year 1989 or 2022 */ - bool setHour(int hour); /* from 0 (midnight) to 23 */ - bool setMinute(int minute); /* from 0 to 59 */ - bool setSecond(int second); /* from 0 to 59 */ + /** + * @brief Sets the day of the month. + * + * @param `day` The day of the month. + * + * @return `true` if the day is set successfully, `false` if the day is out of range. + */ + bool setDayOfMonth(int day); + + /** + * @brief Sets the month of the year. + * + * @param `m` The month. + * + * @return `true` if the month is set successfully, `false` if the month is out of range. + */ + bool setMonthOfYear(Month m); + + /** + * @brief Sets the year. + * + * @param `year` The year (e.g., 1989 or 2022). + * + * @return `true` if the year is set successfully, `false` if the year is invalid. + */ + bool setYear(int year); + + /** + * @brief Sets the hour of the day. + * + * @param `hour` The hour. + * + * @return `true` if the hour is set successfully, `false` if the hour is out of range. + */ + bool setHour(int hour); + + /** + * @brief Sets the minute of the hour. + * + * @param `minute` The minute. + * + * @return `true` if the minute is set successfully, `false` if the minute is out of range. + */ + bool setMinute(int minute); + + /** + * @brief Sets the second of the minute. + * + * @param `second` The second. + * + * @return `true` if the second is set successfully, `false` if the second is out of range. + */ + bool setSecond(int second); + + /** + * @brief Sets the day of the week. + * + * @param `d` The day of the week (from the DayOfWeek enumeration). + * + * @return `true` if the day of the week is set successfully, `false` if the value is invalid. + */ bool setDayOfWeek(DayOfWeek d); + + /** + * @brief Sets whether daylight saving time is active. + * + * @param `sl` The SaveLight enumeration value. + * + * @return `true` if the daylight saving time setting is applied successfully, `false` otherwise. + */ bool setSaveLight(SaveLight sl); + + /** + * @brief Sets the time using a Unix timestamp. + * + * @param `time` The Unix timestamp (seconds since January 1, 1970). + * + * @return `true` if the Unix timestamp is set successfully, `false` otherwise. + */ bool setUnixTime(time_t time); + + /** + * @brief Sets the time from a struct tm. + * + * @param `t` A reference to a struct tm that contains the time values. + */ void setTM(struct tm &t); /* Getters */ + /** + * @brief Gets the day of the month. + * + * @return The day of the month. + */ int getDayOfMonth() const; + + /** + * @brief Gets the month of the year. + * + * @return The month. + */ Month getMonth() const; + + /** + * @brief Gets the year. + * + * @return The year. + */ int getYear() const; + + /** + * @brief Gets the hour of the day. + * + * @return The hour. + */ int getHour() const; + + /** + * @brief Gets the minutes of the hour. + * + * @return The minutes. + */ int getMinutes() const; + + /** + * @brief Gets the seconds of the minute. + * + * @return The seconds. + */ int getSeconds() const; + + /** + * @brief Gets the day of the week. + * + * @return The day of the week. + */ DayOfWeek getDayOfWeek() const; + + /** + * @brief Gets the Unix timestamp. + * + * @return The Unix timestamp. + */ time_t getUnixTime(); + + /** + * @brief Gets the time as a struct `tm`. + * + * @return A struct `tm` that contains the time values. + */ struct tm getTmTime(); /** @@ -123,7 +403,14 @@ class RTCTime { operator arduino::String() const; }; -enum class Period { +/** + * @brief Enum class representing different time periods for periodic events. + * + * This enum defines various periods, which represent how often an event occurs in a given second. + * Each value indicates a multiplier for how many times an event occurs in a second. + */ +enum class Period +{ ONCE_EVERY_2_SEC, ONCE_EVERY_1_SEC, N2_TIMES_EVERY_SEC, @@ -136,57 +423,332 @@ enum class Period { N256_TIMES_EVERY_SEC }; -class AlarmMatch { - private: +/** + * @brief Class representing the alarm match system. + * + * This class is used to define how an alarm matches a set of conditions or criteria + * to trigger an action, such as a timer or event. + */ +class AlarmMatch +{ +private: unsigned int match; - public: +public: + /** + * @brief Default constructor for the AlarmMatch class. + */ AlarmMatch(); + + /** + * @brief Destructor for the AlarmMatch class. + */ ~AlarmMatch(); + + /** + * @brief Increments the match time by one second. + * + * This function updates the internal match time by adding one second to the + * current value. + */ void addMatchSecond(); + + /** + * @brief Increments the match time by one minute. + * + * This function updates the internal match time by adding one minute to the + * current value. + */ void addMatchMinute(); + + /** + * @brief Increments the match time by one hour. + * + * This function updates the internal match time by adding one hour to the + * current value. + */ void addMatchHour(); + + /** + * @brief Increments the match time by one day. + * + * This function updates the internal match time by adding one day to the + * current value. + */ void addMatchDay(); + + /** + * @brief Increments the match time by one month. + * + * This function updates the internal match time by adding one month to the + * current value. + */ void addMatchMonth(); + + /** + * @brief Increments the match time by one year. + * + * This function updates the internal match time by adding one year to the + * current value. + */ void addMatchYear(); + + /** + * @brief Increments the match time by one day of the week. + * + * This function updates the internal match time by adding one day to the + * current day of the week. + */ void addMatchDayOfWeek(); + + /** + * @brief Decrements the match time by one second. + * + * This function updates the internal match time by subtracting one second + * from the current second. + */ void removeMatchSecond(); + + /** + * @brief Decrements the match time by one minute. + * + * This function updates the internal match time by subtracting one minute + * from the current minute. + */ void removeMatchMinute(); + + /** + * @brief Decrements the match time by one hour. + * + * This function updates the internal match time by subtracting one hour + * from the current hour. + */ void removeMatchHour(); + + /** + * @brief Decrements the match time by one day. + * + * This function updates the internal match time by subtracting one day + * from the current day. + */ void removeMatchDay(); + + /** + * @brief Decrements the match time by one month. + * + * This function updates the internal match time by subtracting one month + * from the current month. + */ void removeMatchMonth(); + + /** + * @brief Decrements the match time by one year. + * + * This function updates the internal match time by subtracting one year + * from the current year. + */ void removeMatchYear(); + + /** + * @brief Removes the match criteria for the day of the week. + * + * This function updates the internal match time by removing the day of the week + * from the matching criteria. + */ void removeMatchDayOfWeek(); + + /** + * @brief Checks if the current second matches the set criteria. + * + * This function compares the current second with the set match criteria (if any) + * and returns true if there is a match, false otherwise. + * + * @return `True` if the current second matches the criteria, `false` otherwise. + */ bool isMatchingSecond(); + + /** + * @brief Checks if the current minute matches the set criteria. + * + * This function compares the current minute with the set match criteria (if any) + * and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current minute matches the criteria, `false` otherwise. + */ bool isMatchingMinute(); + + /** + * @brief Checks if the current hour matches the set criteria. + * + * This function compares the current hour with the set match criteria (if any) + * and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current hour matches the criteria, `false` otherwise. + */ bool isMatchingHour(); + + /** + * @brief Checks if the current day matches the set criteria. + * + * This function compares the current day with the set match criteria (if any) + * and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current day matches the criteria, `false` otherwise. + */ bool isMatchingDay(); + + /** + * @brief Checks if the current month matches the set criteria. + * + * This function compares the current month with the set match criteria (if any) + * and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current month matches the criteria, `false` otherwise. + */ bool isMatchingMonth(); + + /** + * @brief Checks if the current year matches the set criteria. + * + * This function compares the current year with the set match criteria (if any) + * and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current year matches the criteria, `false` otherwise. + */ bool isMatchingYear(); - bool isMatchingDayOfWeek(); + /** + * @brief Checks if the current day of the week matches the set criteria. + * + * This function compares the current day of the week with the set match criteria + * (if any) and returns `true` if there is a match, `false` otherwise. + * + * @return `True` if the current day of the week matches the criteria, `false` otherwise. + */ + bool isMatchingDayOfWeek(); }; -class RTClock { - private: +/** + * @brief Class for interfacing with a real-time clock (RTC). + * + * The RTClock class provides functionality to get and set the time, date, and other time-related + * operations, such as day of the week, alarm management, and more. + */ +class RTClock +{ +private: bool is_initialized; - public: +public: + /** + * @brief Constructor to initialize the real-time clock (RTC). + */ RTClock(); + + /** + * @brief Destructor for the real-time clock (RTC). + */ ~RTClock(); + /** + * @brief Initializes the real-time clock (RTC). + * + * @return `True` if the initialization was successful, `false` otherwise. + */ bool begin(); + /** + * @brief Retrieves the current time from the real-time clock (RTC). + * + * This function retrieves the current time from the RTC and stores it in the provided + * RTCTime object. The RTCTime object will be updated with the latest time and date + * information from the RTC module. + * + * @param `t` A reference to an RTCTime object where the current time will be stored. + * + * @return `True` if the time was successfully retrieved and stored in the RTCTime object, + * `false` if there was an error during the operation. + */ bool getTime(RTCTime &t); + /** + * @brief Sets a periodic callback function triggered by the real-time clock (RTC). + * + * This function configures a callback function to be executed at a specific periodic interval, + * as defined by the `Period` parameter. The callback function will be invoked automatically + * by the RTC at the specified rate. + * + * @param `fnc` The callback function to be executed periodically. The function must match + * the `rtc_cbk_t` type signature. + * @param `p` The period at which the callback function should be triggered. This is specified + * as a value from the `Period` enumeration. + * + * @return `True` if the callback was successfully set, `false` otherwise. + */ bool setPeriodicCallback(rtc_cbk_t fnc, Period p); + + /** + * @brief Sets an alarm callback function triggered when the specified conditions are met. + * + * This function configures a callback function to be executed when the real-time clock (RTC) + * matches the specified date and time conditions defined in the `RTCTime` and `AlarmMatch` parameters. + * + * @param `fnc` The callback function to be executed when the alarm triggers. The function must + * match the `rtc_cbk_t` type signature. + * @param `t` The target time for the alarm, specified as an RTCTime object. + * @param `m` The alarm match conditions, specified using the AlarmMatch object. This determines + * which components of the RTCTime must match (e.g., year, month, day). + * + * @return `True` if the alarm callback was successfully set, `false` otherwise. + */ bool setAlarmCallback(rtc_cbk_t fnc, RTCTime &t, AlarmMatch &m); + + /** + * @brief Configures an alarm based on the specified time and matching criteria. + * + * This function sets an alarm on the real-time clock (RTC). The alarm will be triggered + * when the RTC's current time matches the conditions specified by the `RTCTime` and + * `AlarmMatch` parameters. + * + * @param `t` The target time for the alarm, specified as an RTCTime object. + * @param `m` The alarm match conditions, specified using the AlarmMatch object. This determines + * which components of the RTCTime must match. + * + * @return `True` if the alarm was successfully set, `false` otherwise. + */ bool setAlarm(RTCTime &t, AlarmMatch &m); + /** + * @brief Checks if the RTC (Real-Time Clock) is currently running. + * + * This function verifies whether the RTC module is operational and maintaining time. + * + * @return `True` if the RTC is running, `false` otherwise. + */ bool isRunning(); + + /** + * @brief Sets the current time of the RTC (Real-Time Clock). + * + * This function updates the RTC with the provided time. + * + * @param `t` A reference to an RTCTime object containing the desired time to set. + * + * @return `True` if the time was successfully updated, `false` otherwise. + */ bool setTime(RTCTime &t); - bool setTimeIfNotRunning(RTCTime &t); + /** + * @brief Sets the RTC time only if the clock is not currently running. + * + * This function checks if the RTC is stopped and updates its time with the provided + * RTCTime object if the clock is not running. + * + * @param `t` A reference to an RTCTime object containing the desired time to set. + * + * @return `True` if the time was successfully updated, `false` otherwise. + */ + bool setTimeIfNotRunning(RTCTime &t); }; extern RTClock RTC; diff --git a/libraries/WiFiS3/examples/WiFiPing/WiFiPing.ino b/libraries/WiFiS3/examples/WiFiPing/WiFiPing.ino new file mode 100755 index 000000000..62ff33916 --- /dev/null +++ b/libraries/WiFiS3/examples/WiFiPing/WiFiPing.ino @@ -0,0 +1,119 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the WiFi module. By default the attempt is performed 5 times, but can + be changed to max. 255 + + It requires at least version 0.5.0 of USB Wifi bridge firmware and WiFiS3 library. + + This example is written for a network using WPA encryption. For + WEP or WPA, change the WiFi.begin() call accordingly. + + created 14 February 2024 + by paulvha + + */ + +#include "WiFiS3.h" +#include "arduino_secrets.h" + +///////please enter your sensitive data in the Secret tab/arduino_secrets.h +char ssid[] = SECRET_SSID; // your network SSID (name) +char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) +int keyIndex = 0; // your network key index number (needed only for WEP) + +int status = WL_IDLE_STATUS; + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // check for the WiFi module: + if (WiFi.status() == WL_NO_MODULE) { + Serial.println("Communication with WiFi module failed."); + // don't continue + while (true); + } + + // attempt to connect to WiFi network: + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + status = WiFi.begin(ssid, pass); + + // wait 10 seconds for connection: + delay(10000); + } + + printWifiStatus(); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = WiFi.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + // setting ttl to 128 and ping count to 10 + int res1 = WiFi.ping(remote_host, 128, 10); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + } + + Serial.println(); + delay(1000); +} + +/* -------------------------------------------------------------------------- */ +void printWifiStatus() { +/* -------------------------------------------------------------------------- */ + // print the SSID of the network you're attached to: + Serial.print("SSID: "); + Serial.println(WiFi.SSID()); + + // print your board's 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"); +} diff --git a/libraries/WiFiS3/examples/WiFiPing/arduino_secrets.h b/libraries/WiFiS3/examples/WiFiPing/arduino_secrets.h new file mode 100755 index 000000000..0c9fdd556 --- /dev/null +++ b/libraries/WiFiS3/examples/WiFiPing/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/WiFiS3/examples/WiFiTime/WiFiTime.ino b/libraries/WiFiS3/examples/WiFiTime/WiFiTime.ino index 22ab7495a..f027aad34 100644 --- a/libraries/WiFiS3/examples/WiFiTime/WiFiTime.ino +++ b/libraries/WiFiS3/examples/WiFiTime/WiFiTime.ino @@ -73,7 +73,7 @@ void loop() { } else { Serial.println("Error during reading epoch time."); - Serial.println("Make sure your WiFi firmware version is greater than 0.5.0"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); } Serial.println(); diff --git a/libraries/WiFiS3/src/Modem.cpp b/libraries/WiFiS3/src/Modem.cpp index 3dd1a87cc..7aa34391a 100644 --- a/libraries/WiFiS3/src/Modem.cpp +++ b/libraries/WiFiS3/src/Modem.cpp @@ -1,104 +1,94 @@ #include "Modem.h" -#define RESULT_OK "OK\r\n" -#define RESULT_ERROR "ERROR\r\n" -#define RESULT_DATA "DATA\r\n" +#define OK_TOKEN "OK" +#define ERROR_TOKEN "ERROR" +#define TERM_TOKEN "\r\n" +#define RESULT_OK OK_TOKEN TERM_TOKEN +#define RESULT_ERROR OK_TOKEN TERM_TOKEN +#define RESULT_DATA "DATA" TERM_TOKEN using namespace std; /* -------------------------------------------------------------------------- */ -ModemClass::ModemClass(int tx, int rx) : beginned(false), delete_serial(false), _timeout(MODEM_TIMEOUT), trim_results(true), read_by_size(false) { +ModemClass::ModemClass(int tx, int rx) : beginned(false), delete_serial(false), _timeout(MODEM_TIMEOUT), trim_results(true) { /* -------------------------------------------------------------------------- */ - _serial = new UART(tx,rx); + _serial = new UART(tx,rx); } /* -------------------------------------------------------------------------- */ -ModemClass::ModemClass(UART * serial) : beginned(false) , delete_serial(true) , _serial(serial), _timeout(MODEM_TIMEOUT), trim_results(true), read_by_size(false) { -/* -------------------------------------------------------------------------- */ +ModemClass::ModemClass(UART * serial) : beginned(false) , delete_serial(true) , _serial(serial), _timeout(MODEM_TIMEOUT), trim_results(true) { +/* -------------------------------------------------------------------------- */ } /* -------------------------------------------------------------------------- */ ModemClass::~ModemClass() { -/* -------------------------------------------------------------------------- */ - if(_serial != nullptr && !delete_serial){ +/* -------------------------------------------------------------------------- */ + if(_serial != nullptr && !delete_serial){ delete _serial; _serial = nullptr; - } + } } /* -------------------------------------------------------------------------- */ void ModemClass::begin(int badurate){ -/* -------------------------------------------------------------------------- */ - if(_serial != nullptr && !beginned) { +/* -------------------------------------------------------------------------- */ + if(_serial != nullptr && !beginned) { _serial->begin(badurate); beginned = true; string res = ""; _serial->flush(); modem.write(string(PROMPT(_SOFTRESETWIFI)),res, "%s" , CMD(_SOFTRESETWIFI)); - } + } } /* -------------------------------------------------------------------------- */ void ModemClass::end(){ -/* -------------------------------------------------------------------------- */ - _serial->end(); +/* -------------------------------------------------------------------------- */ + _serial->end(); } /* -------------------------------------------------------------------------- */ bool ModemClass::passthrough(const uint8_t *data, size_t size) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ _serial->write(data,size); - bool res = false; - bool found = false; - string data_res = ""; - - unsigned long start_time = millis(); - while(millis() - start_time < _timeout && !found){ - while(_serial->available()){ - char c = _serial->read(); - data_res += c; - - if(string::npos != data_res.rfind(RESULT_OK)){ - found = true; - res = true; - break; - } - else if (string::npos != data_res.rfind(RESULT_ERROR)) { - found = true; - res = false; - break; - } - } - } - - if(_serial_debug && _debug_level >= 2) { + + std::string prompt = DO_NOT_CHECK_CMD, data_res; + auto res = buf_read(prompt, data_res); + + if(_serial_debug && _debug_level >= 2) { _serial_debug->print(" ANSWER (passthrough): "); _serial_debug->println(data_res.c_str()); - if(res) { + if(res == Ok) { _serial_debug->println(" Result: OK"); + } else if(res == Error) { + _serial_debug->println(" Result: ERROR"); + } else if(res == Timeout) { + _serial_debug->println(" Result: TIMEOUT"); + } else { + _serial_debug->println(" Result: ParseError"); } - else { - _serial_debug->println(" Result: FAILED"); - } - } - - return res; + } + + return res == Ok; } /* -------------------------------------------------------------------------- */ void ModemClass::write_nowait(const string &cmd, string &str, const char * fmt, ...) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + (void)cmd; + (void)str; + va_list va; va_start (va, fmt); vsnprintf((char *)tx_buff, MAX_BUFF_SIZE, fmt, va); va_end (va); - - if(_serial_debug && _debug_level >= 2) { + + if(_serial_debug && _debug_level >= 2) { _serial_debug->print("REQUEST (passthrough): "); _serial_debug->write(tx_buff,strlen((char *)tx_buff)); _serial_debug->println(); } - + _serial->write(tx_buff,strlen((char *)tx_buff)); return; } @@ -106,13 +96,13 @@ void ModemClass::write_nowait(const string &cmd, string &str, const char * fmt, /* -------------------------------------------------------------------------- */ bool ModemClass::write(const string &prompt, string &data_res, const char * fmt, ...){ -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ data_res.clear(); va_list va; va_start (va, fmt); vsnprintf((char *)tx_buff, MAX_BUFF_SIZE, fmt, va); va_end (va); - + if(_serial_debug) { _serial_debug->println(); _serial_debug->print("REQUEST: "); @@ -121,183 +111,310 @@ bool ModemClass::write(const string &prompt, string &data_res, const char * fmt, } _serial->write(tx_buff,strlen((char *)tx_buff)); - return buf_read(prompt,data_res);; -} + auto res = buf_read(prompt, data_res); + if(_serial_debug) { + _serial_debug->print(" ANSWER: "); + _serial_debug->println(data_res.c_str()); + if(res == Ok) { + _serial_debug->println(" Result: OK"); + } else if(res == Error) { + _serial_debug->println(" Result: ERROR"); + } else if(res == Timeout) { + _serial_debug->println(" Result: TIMEOUT"); + } else { + _serial_debug->println(" Result: ParseError"); + } + } -typedef enum { - IDLE, - WAIT_FOR_SIZE, - WAIT_FOR_DATA -} ReadBySizeSt_t; + return res == Ok; +} /* -------------------------------------------------------------------------- */ -bool ModemClass::read_by_size_finished(string &rx) { -/* -------------------------------------------------------------------------- */ - bool rv = false; - static bool first_call = true; - static ReadBySizeSt_t st = IDLE; - static int data_to_be_received = 0; - static int data_received = 0; - if(first_call) { - first_call = false; - st = WAIT_FOR_SIZE; - } +ModemClass::ParseResult ModemClass::buf_read(const string &prompt, string &data_res) { +/* -------------------------------------------------------------------------- */ + /* + * This function implements as FSM that parses basic AT command responses + * The expected syntax should match the following regex + * - (?:\+(\w+)[:=][ ]?(\w*))?(?:\r\n)?(ERROR\r\n|OK\r\n) + * + "ERROR" "OK" + * + "+COMMAND: OK" + * + "+COMMAND: ERROR" + * + "+COMMAND: 1231231OK" (NOTE only one parameter supported) + * + "+COMMAND: 1231231ERROR" (NOTE only one parameter supported) + * - custom sized response: + * + "+COMMAND: 4| 123OK" + */ + enum class at_parse_state_t { + Begin = 0, + Cmd = 1, + Data = 2, + Sized = 3, + ResWaitLF = 4, + Res = 5, + Error = 6, + ParseError = 7, + Ok = 8, + Completed = 9, + }; - switch(st) { - case IDLE: - - break; - case WAIT_FOR_SIZE: { - int pos = rx.find("|"); - int pos_space = rx.find(" "); - if(pos != string::npos && pos_space != string::npos) { - string n = rx.substr(pos_space,pos); - int to_be_rx = atoi(n.c_str()); - if(to_be_rx <= 0) { - while( _serial->available() ){ - _serial->read(); - } - rv = true; - first_call = true; - st = IDLE; - } - else { - /* add 4 because OK\r\n is always added at the end of data */ - data_to_be_received = to_be_rx + 4; - data_received = 0; - st = WAIT_FOR_DATA; - } - rx.clear(); - } - } - break; - - case WAIT_FOR_DATA: - data_received++; - if(data_received == data_to_be_received) { - rv = true; - first_call = true; - st = IDLE; - } - break; + at_parse_state_t state = at_parse_state_t::Begin; + std::string commandName; - default: - st = IDLE; - break; - } - return rv; -} + ModemClass::ParseResult res = Error; + unsigned int sized_read_size = 0; + unsigned int sized_read_count = 0; + unsigned int result_parse = 0; + bool restart = false, + consume_char = true; // This flag is used to indicate to consume another character from the stream + char c; + // I expect the answer to be in this form: "ERROR" "OK" + // if prompt == DO_NOT_CHECK_CMD + const bool check_prompt = (prompt != DO_NOT_CHECK_CMD); -/* -------------------------------------------------------------------------- */ -bool ModemClass::buf_read(const string &prompt, string &data_res) { -/* -------------------------------------------------------------------------- */ - bool res = false; - bool found = false; - if(_serial_debug && _debug_level >= 1) { _serial_debug->print("RAW: "); } unsigned long start_time = millis(); - while((millis() - start_time < _timeout) && !found){ - while( _serial->available() ){ - char c = _serial->read(); - data_res += c; - - if(_serial_debug && _debug_level >= 1) { + while(state != at_parse_state_t::Completed) { + + if(millis() - start_time > _timeout) { + res = Timeout; + break; + } + + if(consume_char && !_serial->available()) { + // if there is nothing available, go to the beginning of the cycle + continue; + } else if(consume_char) { // available is true + c = _serial->read(); + } else if(!consume_char) { + // reset consume_char to true + consume_char = true; + } + + if(_serial_debug && _debug_level >= 1 && consume_char) { + if(c == '\n') { + _serial_debug->print(""); + } else if (c == '\r') { + _serial_debug->print(""); + } else if (c == ' ') { + _serial_debug->print(""); + } else if(c < ' ') { + _serial_debug->print("<"); + _serial_debug->print((unsigned int)c); + _serial_debug->print(">"); + } else { _serial_debug->print(c); } - - - if(read_by_size) { - if(read_by_size_finished(data_res)) { - found = true; - read_by_size = false; - res = true; - if(data_res.size() > 0) { - data_res = data_res.substr(0, data_res.length() - (sizeof(RESULT_OK) - 1)); - } - else { - break; - } - } + } + if(_serial_debug && _debug_level >= 3) { + _serial_debug->print(" State "); + _serial_debug->println((int)state); + } + + switch(state) { + case at_parse_state_t::Begin: + /* + * In this state we wait for a '+' character, which will mark the beginning of a response + * or the status response code "ERROR" or "OK" + * we need to consume the available buffer if it doesn't match the expected response, + * in order to avoiding dealing with previous responses which were not parsed successfully + */ + + if(c == '+') { + // This line allow to strenghten the checks on the response prompt, + // it is required that passthrough() function is able to know the command prompt, + // provided in the previous call of write_nowait() + // the answer doesn't match the expected form, thus the response received + // is not related to the sent command we need to restart + // restart = !check_prompt; + + commandName += c; // prompt includes also '+' + state = at_parse_state_t::Cmd; + } else if(c == RESULT_OK[result_parse]) { + // the answer doesn't match the expected form, we need to restart + restart = check_prompt; + + state = at_parse_state_t::Ok; + result_parse++; + } else if(c == RESULT_ERROR[result_parse]) { + // the answer doesn't match the expected form, we need to restart + restart = check_prompt; + + state = at_parse_state_t::Error; + result_parse++; } - else { - if(string::npos != data_res.rfind(RESULT_DATA)) { - data_res = data_res.substr(0, data_res.length() - (sizeof(RESULT_DATA) - 1)); - if(prompt != DO_NOT_CHECK_CMD) { - if(removeAtBegin(data_res, prompt)) { - res = true; - found = true; - } else { - data_res.clear(); - continue; - } - } - else { - res = true; - found = true; - } - break; - } - else if(string::npos != data_res.rfind(RESULT_OK)){ - data_res = data_res.substr(0, data_res.length() - (sizeof(RESULT_OK) - 1) ); - if(prompt != DO_NOT_CHECK_CMD) { - if(removeAtBegin(data_res, prompt)) { - res = true; - found = true; - } else { - data_res.clear(); - continue; - } - } - else { - res = true; - found = true; - } - break; - } - else if (string::npos != data_res.rfind(RESULT_ERROR)) { - found = true; - data_res.substr(0, data_res.length() - (sizeof(RESULT_ERROR) - 1)); - res = false; - break; + // if we uncomment this we can force strict response matching + // else { + // state = at_parse_state_t::ParseError; + // } + + break; + case at_parse_state_t::Cmd: + /* + * In this state we parse the command prompt and wait for either ':' or '=' characters + * in order to go the next state + */ + + if(c == ':' || c == '=') { + commandName += c; // prompt includes also ':' + + if (check_prompt && commandName != prompt) { + // the response we got is not the one we were expecting, parse the wrong response till the end + // and start the parse of the next response + restart = true; + commandName = ""; } + state = at_parse_state_t::Data; + + data_res = ""; + // state = at_parse_state_t::Data; + } else { // no space should be present in the prompt response + commandName += c; + } + + break; + case at_parse_state_t::Data: + /* + * In this state we parse response parameters and push them into data_res + * in case multiple parameters separated by ',' are sent, they will be present in data_res + * - if we encounter we need to wait for + * - if we encounter we need to parse the response status + * - if we encounter '|', the next token will contain binary sized data, the current value in + * in data_res contains the length of the next token + */ + + if(c == '|') { // sized read, the previous parameter is the length + state = at_parse_state_t::Sized; + + sized_read_size = atoi(data_res.c_str()); + data_res.clear(); + } else if(c == '\r') { + state = at_parse_state_t::ResWaitLF; + } else if(c == '\n') { + state = at_parse_state_t::Res; + } else if(trim_results && c != ' ') { + data_res += c; // in case trim_result is true, avoid adding spaces + } else if(!trim_results) { + data_res += c; + } + + break; + case at_parse_state_t::Sized: + /* + * In this state we collect exactly sized_read_size characters into data_res + * when we consume all of them we go into Result parse state, where we supposedly + * wait for 'OK' + */ + data_res += c; + + if(++sized_read_count == sized_read_size) { + state = at_parse_state_t::Res; } + break; + case at_parse_state_t::ResWaitLF: + if(c == '\n') { + state = at_parse_state_t::Res; + } + /* fall through */ + + /* + * break is volountary not present, to cover for cases where the response status is in the + * following form: '...OK' 'ERROR' + */ + case at_parse_state_t::Res: + /* + * In this state we wait for either an 'O' or an 'E', in order to get an 'OK' + * or 'ERROR' + * The first two cases is when there is no parameter in the response, but just the OK and ERROR tokens + */ + + if(data_res == OK_TOKEN) { + res = Ok; + state = at_parse_state_t::Completed; + } else if(data_res == ERROR_TOKEN) { + res = Error; + state = at_parse_state_t::Completed; + } if(c == RESULT_OK[0]) { // OK response + state = at_parse_state_t::Ok; + result_parse = 1; + } else if(c == RESULT_ERROR[0]) { // Error response + state = at_parse_state_t::Error; + result_parse = 1; + } + // if we uncomment this we can force strict response matching + // else { + // state = at_parse_state_t::ParseError; + // } + break; + case at_parse_state_t::Ok: + /* + * In this state we want to match the exact 'K' response + */ + if(c != RESULT_OK[result_parse++]) { + state = at_parse_state_t::ParseError; + } + + if(result_parse == strlen(RESULT_OK)) { + res = Ok; + state = at_parse_state_t::Completed; + } + break; + case at_parse_state_t::Error: + /* + * In this state we want to match the exact 'RROR' response + */ + + if(c != RESULT_ERROR[result_parse++]) { + state = at_parse_state_t::ParseError; + } + + if(result_parse == strlen(RESULT_ERROR)) { + res = Error; + state = at_parse_state_t::Completed; + } + break; + case at_parse_state_t::ParseError: + res = ParseError; + // if we get a parseError, we go back from the beginning and try again to parse, unitl the timeout expires + state = at_parse_state_t::Begin; + restart = false; + consume_char = false; + break; + case at_parse_state_t::Completed: + break; + } + + if(restart && state == at_parse_state_t::Completed) { + state = at_parse_state_t::Begin; + restart = false; } } - if(trim_results) { - trim(data_res); + + if(_serial_debug && _debug_level >= 3) { + _serial_debug->print("Final State "); + _serial_debug->print((int)state); + _serial_debug->print(" res "); + _serial_debug->println((int)res); } + trim_results = true; - read_by_size = false; if(_serial_debug && _debug_level >= 1) { _serial_debug->print("<-RAW END"); _serial_debug->println(); } - if(_serial_debug) { - _serial_debug->print(" ANSWER: "); - _serial_debug->println(data_res.c_str()); - if(res) { - _serial_debug->println(" Result: OK"); - } - else { - _serial_debug->println(" Result: FAILED"); - } - } - - return res; } #ifdef ARDUINO_UNOWIFIR4 - ModemClass modem = ModemClass(&Serial2); + ModemClass modem = ModemClass(&Serial2); #else - ModemClass modem = ModemClass(D24,D25); + ModemClass modem = ModemClass(D24,D25); #endif diff --git a/libraries/WiFiS3/src/Modem.h b/libraries/WiFiS3/src/Modem.h index 78539e7e3..3f785bc9d 100644 --- a/libraries/WiFiS3/src/Modem.h +++ b/libraries/WiFiS3/src/Modem.h @@ -35,21 +35,21 @@ class ModemClass { } void read_using_size() { - read_by_size = true; - } + // read_by_size = true; // deprecated + } bool beginned; /* calling this function with no argument will enable debug message to be printed on Serial - use first parameter UART *u to redirect debug output to a different serial + use first parameter UART *u to redirect debug output to a different serial level from 0 defaul to 2 (maximum) */ void debug(Stream &u, uint8_t level = 0) { _serial_debug = &u; - - if(level > 2) { - level = 2; + + if(level > 3) { + level = 3; } _debug_level = level; } @@ -66,14 +66,19 @@ class ModemClass { void timeout(size_t timeout_ms) {_timeout = timeout_ms;} private: - bool buf_read(const std::string &cmd, std::string &data_res); + enum ParseResult { + Ok, + Error, + ParseError, + Timeout + }; + + ParseResult buf_read(const std::string &cmd, std::string &data_res); bool delete_serial; UART * _serial; unsigned long _timeout; uint8_t tx_buff[MAX_BUFF_SIZE]; bool trim_results; - bool read_by_size; - bool read_by_size_finished(std::string &rx); Stream * _serial_debug; uint8_t _debug_level = 0; }; diff --git a/libraries/WiFiS3/src/WiFi.cpp b/libraries/WiFiS3/src/WiFi.cpp index 0717f6731..7e73b94f1 100644 --- a/libraries/WiFiS3/src/WiFi.cpp +++ b/libraries/WiFiS3/src/WiFi.cpp @@ -20,9 +20,18 @@ const char* CWifi::firmwareVersion() { return fw_version; } return "99.99.99"; - } +/* -------------------------------------------------------------------------- */ +uint32_t CWifi::firmwareVersionU32() { +/* -------------------------------------------------------------------------- */ + string res = ""; + modem.begin(); + if(modem.write(string(PROMPT(_FWVERSION_U32)), res, CMD_READ(_FWVERSION_U32))) { + return res[0] << 16| res[1] << 8 | res[2]; + } + return 0x636363; +} /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid) { @@ -54,7 +63,7 @@ int CWifi::begin(const char* ssid, const char *passphrase) { return WL_CONNECTED; } } - return WL_CONNECT_FAILED; + return WL_CONNECT_FAILED; } /* passphrase is needed so a default one will be set */ @@ -78,7 +87,7 @@ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ string res = ""; modem.begin(); modem.write(string(PROMPT(_MODE)),res, "%s%d\r\n" , CMD_WRITE(_MODE), 2); @@ -97,10 +106,10 @@ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip) { /* -------------------------------------------------------------------------- */ - IPAddress _gw(local_ip[0],local_ip[1], local_ip[2], 1); - IPAddress _sm(255,255,255,0); - IPAddress dns(0,0,0,0); - return _config(local_ip, _gw, _sm, _gw, dns); + IPAddress _gw(local_ip[0],local_ip[1], local_ip[2], 1); + IPAddress _sm(255,255,255,0); + IPAddress dns(0,0,0,0); + return _config(local_ip, _gw, _sm, _gw, dns); } /* -------------------------------------------------------------------------- */ @@ -116,7 +125,7 @@ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPA string gw = to_string(gateway[0]) + "."; gw += to_string(gateway[1]) + "."; gw += to_string(gateway[2]) + "."; - gw += to_string(gateway[3]); + gw += to_string(gateway[3]); string nm = to_string(subnet[0]) + "."; nm += to_string(subnet[1]) + "."; @@ -127,18 +136,18 @@ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPA _dns1 += to_string(dns1[1]) + "."; _dns1 += to_string(dns1[2]) + "."; _dns1 += to_string(dns1[3]); - + string _dns2 = to_string(dns2[0]) + "."; _dns2 += to_string(dns2[1]) + "."; _dns2 += to_string(dns2[2]) + "."; - _dns2 += to_string(dns2[3]); + _dns2 += to_string(dns2[3]); ip_ap = local_ip; gw_ap = gateway; nm_ap = subnet; modem.write(PROMPT(_SOFTAPCONFIG),res, "%s%s,%s,%s\r\n" , CMD_WRITE(_SOFTAPCONFIG), ip.c_str(), ip.c_str(), nm.c_str()); - modem.write(string(PROMPT(_SETIP)),res, "%s%s,%s,%s,%s,%s\r\n" , CMD_WRITE(_SETIP), ip.c_str(), gw.c_str(), nm.c_str(),_dns1.c_str(),_dns2.c_str()); + modem.write(string(PROMPT(_SETIP)),res, "%s%s,%s,%s,%s,%s\r\n" , CMD_WRITE(_SETIP), ip.c_str(), gw.c_str(), nm.c_str(),_dns1.c_str(),_dns2.c_str()); } /* -------------------------------------------------------------------------- */ @@ -152,32 +161,32 @@ void CWifi::config(IPAddress local_ip, IPAddress dns_server) { /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -/* -------------------------------------------------------------------------- */ - +/* -------------------------------------------------------------------------- */ + IPAddress _sm(255,255,255,0); IPAddress dns(0,0,0,0); - return _config(local_ip, gateway, _sm,dns_server,dns); + return _config(local_ip, gateway, _sm,dns_server,dns); } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { /* -------------------------------------------------------------------------- */ - + IPAddress dns(0,0,0,0); - return _config(local_ip, gateway, subnet,dns_server,dns); + return _config(local_ip, gateway, subnet,dns_server,dns); } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1) { /* -------------------------------------------------------------------------- */ IPAddress dns(0,0,0,0); - return _config(localIP(), gatewayIP(), subnetMask(),dns_server1,dns); + return _config(localIP(), gatewayIP(), subnetMask(),dns_server1,dns); } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { /* -------------------------------------------------------------------------- */ - return _config(localIP(), gatewayIP(), subnetMask(),dns_server1,dns_server2); + return _config(localIP(), gatewayIP(), subnetMask(),dns_server1,dns_server2); } /* -------------------------------------------------------------------------- */ @@ -189,29 +198,28 @@ void CWifi::setHostname(const char* name) { /* -------------------------------------------------------------------------- */ int CWifi::disconnect() { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ string res = ""; modem.begin(); if(modem.write(string(PROMPT(_DISCONNECT)),res,CMD(_DISCONNECT))) { return 1; - } + } return 0; } /* -------------------------------------------------------------------------- */ void CWifi::end(void) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ string res = ""; modem.begin(); modem.write(string(PROMPT(_SOFTRESETWIFI)),res, "%s" , CMD(_SOFTRESETWIFI)); } - static bool macStr2macArray(uint8_t *mac_out, const char *mac_in) { - if(mac_in[2] != ':' || + if(mac_in[2] != ':' || mac_in[5] != ':' || mac_in[8] != ':' || mac_in[11] != ':' || @@ -227,13 +235,12 @@ static bool macStr2macArray(uint8_t *mac_out, const char *mac_in) { return true; } - /* -------------------------------------------------------------------------- */ uint8_t* CWifi::macAddress(uint8_t* _mac) { -/* -------------------------------------------------------------------------- */ - string res = ""; - modem.begin(); - if(modem.write(string(PROMPT(_MODE)),res, "%s" , CMD_READ(_MODE))) { +/* -------------------------------------------------------------------------- */ + string res = ""; + modem.begin(); + if(modem.write(string(PROMPT(_MODE)),res, "%s" , CMD_READ(_MODE))) { if(atoi(res.c_str()) == 1) { if(modem.write(string(PROMPT(_MACSTA)),res, "%s" , CMD_READ(_MACSTA))) { macStr2macArray(_mac, res.c_str()); @@ -249,9 +256,6 @@ uint8_t* CWifi::macAddress(uint8_t* _mac) { return _mac; } - - - /* -------------------------------------------------------------------------- */ int8_t CWifi::scanNetworks() { /* -------------------------------------------------------------------------- */ @@ -280,7 +284,7 @@ int8_t CWifi::scanNetworks() { ap.encryption_mode = tokens[4]; access_points.push_back(ap); } - } + } } return (int8_t)access_points.size(); @@ -317,10 +321,9 @@ IPAddress CWifi::dnsIP(int n) { return dns_IP; } } - return IPAddress(0,0,0,0); + return IPAddress(0,0,0,0); } - /* -------------------------------------------------------------------------- */ IPAddress CWifi::localIP() { /* -------------------------------------------------------------------------- */ @@ -334,14 +337,14 @@ IPAddress CWifi::localIP() { if(modem.write(string(PROMPT(_MODE)),res, "%s" , CMD_READ(_MODE))) { if(atoi(res.c_str()) == 1) { if(modem.write(string(PROMPT(_IPSTA)),res, "%s%d\r\n" , CMD_WRITE(_IPSTA), IP_ADDR)) { - + local_IP.fromString(res.c_str()); - + } } else if(atoi(res.c_str()) == 2) { if(modem.write(string(PROMPT(_IPSOFTAP)),res, CMD(_IPSOFTAP))) { - + local_IP.fromString(res.c_str()); } } @@ -376,27 +379,26 @@ IPAddress CWifi::gatewayIP() { gateway_IP.fromString(res.c_str()); return gateway_IP; } - return IPAddress(0,0,0,0); + return IPAddress(0,0,0,0); } /* -------------------------------------------------------------------------- */ const char* CWifi::SSID(uint8_t networkItem) { /* -------------------------------------------------------------------------- */ - if(networkItem < access_points.size()) { - return access_points[networkItem].ssid.c_str(); - } - return nullptr; + if(networkItem < access_points.size()) { + return access_points[networkItem].ssid.c_str(); + } + return nullptr; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int32_t CWifi::RSSI(uint8_t networkItem) { - if(networkItem < access_points.size()) { - return atoi(access_points[networkItem].rssi.c_str()); - } - return -1000; +/* -------------------------------------------------------------------------- */ + if(networkItem < access_points.size()) { + return atoi(access_points[networkItem].rssi.c_str()); + } + return -1000; } -/* -------------------------------------------------------------------------- */ static uint8_t Encr2wl_enc(string e) { if (e == string("open")) { @@ -418,54 +420,52 @@ static uint8_t Encr2wl_enc(string e) { } else { return ENC_TYPE_UNKNOWN; } - } - +} /* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType() { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ scanNetworks(); string myssid(SSID()); for(unsigned int i = 0; i < access_points.size(); i++) { if(myssid == access_points[i].ssid) { - return Encr2wl_enc(access_points[i].encryption_mode); + return Encr2wl_enc(access_points[i].encryption_mode); } } return ENC_TYPE_UNKNOWN; } - /* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType(uint8_t networkItem) { - if(networkItem < access_points.size()) { - return Encr2wl_enc(access_points[networkItem].encryption_mode); - } - return 0; +/* -------------------------------------------------------------------------- */ + if(networkItem < access_points.size()) { + return Encr2wl_enc(access_points[networkItem].encryption_mode); + } + return 0; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { +/* -------------------------------------------------------------------------- */ if(networkItem < access_points.size()) { for(int i = 0; i < 6; i++) { *(bssid + i) = access_points[networkItem].uint_bssid[i]; } - return bssid; + return bssid; } - return nullptr; + return nullptr; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t CWifi::channel(uint8_t networkItem) { +uint8_t CWifi::channel(uint8_t networkItem) { +/* -------------------------------------------------------------------------- */ if(networkItem < access_points.size()) { - return atoi(access_points[networkItem].channel.c_str()); + return atoi(access_points[networkItem].channel.c_str()); } return 0; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ const char* CWifi::SSID() { /* -------------------------------------------------------------------------- */ string res = ""; @@ -486,9 +486,9 @@ const char* CWifi::SSID() { return ""; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ uint8_t* CWifi::BSSID(uint8_t* bssid) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ string res = ""; if(modem.write(string(PROMPT(_GETBSSID)), res, CMD_READ(_GETBSSID))) { macStr2macArray(bssid, res.c_str()); @@ -497,7 +497,7 @@ uint8_t* CWifi::BSSID(uint8_t* bssid) { return nullptr; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ int32_t CWifi::RSSI() { /* -------------------------------------------------------------------------- */ string res = ""; @@ -507,9 +507,9 @@ int32_t CWifi::RSSI() { return 0; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ const char* CWifi::softAPSSID() { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ string res = ""; if(modem.write(string(PROMPT(_GETSOFTAPSSID)), res, CMD_READ(_GETSOFTAPSSID))) { apssid = res; @@ -520,7 +520,7 @@ const char* CWifi::softAPSSID() { /* -------------------------------------------------------------------------- */ uint8_t CWifi::status() { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ modem.begin(); string res = ""; if(modem.write(string(PROMPT(_GETSTATUS)), res, CMD_READ(_GETSTATUS))) { @@ -532,7 +532,7 @@ uint8_t CWifi::status() { /* -------------------------------------------------------------------------- */ int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ modem.begin(); string res = ""; if(modem.write(string(PROMPT(_GETHOSTBYNAME)),res, "%s%s\r\n" , CMD_WRITE(_GETHOSTBYNAME), aHostname)) { @@ -542,13 +542,15 @@ int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { return 0; } +/* -------------------------------------------------------------------------- */ uint8_t CWifi::reasonCode() { - return 0; +/* -------------------------------------------------------------------------- */ + return 0; } -/* ----------------------------------------------*/ +/* -------------------------------------------------------------------------- */ unsigned long CWifi::getTime() { -/* ----------------------------------------------*/ +/* -------------------------------------------------------------------------- */ modem.begin(); string res = ""; if(modem.write(string(PROMPT(_GETTIME)),res,"%s\r\n", CMD_WRITE(_GETTIME))) { @@ -557,10 +559,39 @@ unsigned long CWifi::getTime() { return 0; } +/* -------------------------------------------------------------------------- */ void CWifi::setTimeout(unsigned long timeout) { +/* -------------------------------------------------------------------------- */ _timeout = timeout; } +/* -------------------------------------------------------------------------- */ +int CWifi::ping(IPAddress ip, uint8_t ttl, uint8_t count) { +/* -------------------------------------------------------------------------- */ + return ping(ip.toString().c_str(), ttl, count); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const String &hostname, uint8_t ttl, uint8_t count) +/* -------------------------------------------------------------------------- */ +{ + return ping(hostname.c_str(), ttl, count); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const char* host, uint8_t ttl, uint8_t count) { +/* -------------------------------------------------------------------------- */ + int ret = WL_PING_ERROR; + modem.begin(); + /* ping timeout is 1s and interval another 1s */ + modem.timeout((count * 2000) + MODEM_TIMEOUT); + string res = ""; + if (modem.write(string(PROMPT(_PING)), res, "%s,%s,%d,%d\r\n", CMD_WRITE(_PING), host, ttl, count)) { + ret = atoi(res.c_str()); + } + modem.timeout(MODEM_TIMEOUT); + return ret; +} CWifi WiFi; diff --git a/libraries/WiFiS3/src/WiFi.h b/libraries/WiFiS3/src/WiFi.h index 8a50f4178..2b733cfab 100644 --- a/libraries/WiFiS3/src/WiFi.h +++ b/libraries/WiFiS3/src/WiFi.h @@ -22,30 +22,30 @@ #define WL_MAC_ADDR_LENGTH 6 class CAccessPoint { - public: - std::string ssid; - std::string bssid; - uint8_t uint_bssid[6]; - std::string rssi; - std::string channel; - std::string encryption_mode; +public: + std::string ssid; + std::string bssid; + uint8_t uint_bssid[6]; + std::string rssi; + std::string channel; + std::string encryption_mode; }; class CWifi { -private: - void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2); - unsigned long _timeout; - std::vector access_points; - std::string ssid; - std::string apssid; - +private: + void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2); + unsigned long _timeout; + std::vector access_points; + std::string ssid; + std::string apssid; + - IPAddress ip_ap = DEFAULT_IP_AP_ADDRESS; - IPAddress gw_ap = DEFAULT_GW_AP_ADDRESS; - IPAddress nm_ap = DEFAULT_NM_AP_ADDRESS; + IPAddress ip_ap = DEFAULT_IP_AP_ADDRESS; + IPAddress gw_ap = DEFAULT_GW_AP_ADDRESS; + IPAddress nm_ap = DEFAULT_NM_AP_ADDRESS; @@ -57,15 +57,29 @@ class CWifi { * Get firmware version */ static const char* firmwareVersion(); + /* + * Get firmware version U32 + * + * Since version is made in a semver fashion, thus in an integer it will be represented as + * byte 1 (MSB) | byte 2 | byte 3 | byte 4 + * 0 | MAJOR | MINOR | PATCH + */ + uint32_t firmwareVersionU32(); + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128, uint8_t count = 1); + int ping(const String &hostname, uint8_t ttl = 128, uint8_t count = 1); + int ping(const char* host, uint8_t ttl = 128, uint8_t count = 1); - /* - * Start WiFi connection for OPEN networks + /* + * Start WiFi connection for OPEN networks * param ssid: Pointer to the SSID string. */ int begin(const char* ssid); - + /* Start WiFi connection with passphrase * the most secure supported mode will be automatically selected @@ -112,7 +126,7 @@ class CWifi { * param subnet: Static Subnet mask */ void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); - + /* Change DNS IP configuration * * param dns_server1: IP configuration for DNS server 1 @@ -148,8 +162,8 @@ class CWifi { * Get the interface MAC address. * * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - * - * the value returned by this function is meaningfull only if called + * + * the value returned by this function is meaningfull only if called * afert a begin (both begin or beginAP) or a ScanNetwork function * otherwise an empty mac address is returned */ @@ -174,9 +188,9 @@ class CWifi { * * return: gateway IP address value */ - IPAddress gatewayIP(); + IPAddress gatewayIP(); - IPAddress dnsIP(int n = 0); + IPAddress dnsIP(int n = 0); /* * Get the interface the AP IP address. @@ -238,8 +252,8 @@ class CWifi { * * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list - - + + */ uint8_t encryptionType(uint8_t networkItem); uint8_t encryptionType(); @@ -283,7 +297,7 @@ class CWifi { void setTimeout(unsigned long timeout); - + }; extern CWifi WiFi; diff --git a/libraries/WiFiS3/src/WiFiClient.cpp b/libraries/WiFiS3/src/WiFiClient.cpp index 143f92dae..9e6d09261 100644 --- a/libraries/WiFiS3/src/WiFiClient.cpp +++ b/libraries/WiFiS3/src/WiFiClient.cpp @@ -128,7 +128,7 @@ int WiFiClient::_read() { if(modem.write(string(PROMPT(_CLIENTRECEIVE)),res, "%s%d,%d\r\n" , CMD_WRITE(_CLIENTRECEIVE), _sock, size)) { if(res.size() > 0) { - for(int i = 0, rv = 0; i < size && i < res.size(); i++) { + for(uint32_t i = 0, rv = 0; i < size && i < res.size(); i++) { rx_buffer->store((uint8_t)res[i]); rv++; } @@ -168,7 +168,7 @@ int WiFiClient::read(uint8_t *buf, size_t size) { int rv = 0; bool go_on = true; if(_sock >= 0 && rx_buffer != nullptr) { - for(int i = 0; i < size && go_on; i++) { + for(size_t i = 0; i < size && go_on; i++) { bool is_read = false; *(buf+i) = rx_buffer->read(&is_read); if(is_read) { diff --git a/libraries/WiFiS3/src/WiFiClient.h b/libraries/WiFiS3/src/WiFiClient.h index 81f5afae6..63b019c32 100644 --- a/libraries/WiFiS3/src/WiFiClient.h +++ b/libraries/WiFiS3/src/WiFiClient.h @@ -70,14 +70,13 @@ class WiFiClient : public Client { protected: int _sock; + bool destroy_at_distructor; int _connectionTimeout = 0; void getSocket(); static constexpr uint32_t RX_BUFFER_DIM = 1024; std::shared_ptr> rx_buffer; int _read(); void read_if_needed(size_t s); - bool destroy_at_distructor; - }; diff --git a/libraries/WiFiS3/src/WiFiFileSystem.cpp b/libraries/WiFiS3/src/WiFiFileSystem.cpp index 938f2d8b5..8dc7fa8b5 100644 --- a/libraries/WiFiS3/src/WiFiFileSystem.cpp +++ b/libraries/WiFiS3/src/WiFiFileSystem.cpp @@ -20,6 +20,7 @@ size_t WiFiFileSystem::writefile(const char* name, const char* data, size_t size if(modem.passthrough((uint8_t *)data, size)) { return size; } + return 0; } /* -------------------------------------------------------------------------- */ diff --git a/libraries/WiFiS3/src/WiFiSSLClient.cpp b/libraries/WiFiS3/src/WiFiSSLClient.cpp index 91b6951e5..bfe7c488d 100644 --- a/libraries/WiFiS3/src/WiFiSSLClient.cpp +++ b/libraries/WiFiS3/src/WiFiSSLClient.cpp @@ -148,7 +148,7 @@ int WiFiSSLClient::_read() { modem.read_using_size(); if(modem.write(string(PROMPT(_SSLCLIENTRECEIVE)),res, "%s%d,%d\r\n" , CMD_WRITE(_SSLCLIENTRECEIVE), _sock, size)) { if(res.size() > 0) { - for(int i = 0, rv = 0; i < size && i < res.size(); i++) { + for(uint32_t i = 0, rv = 0; i < size && i < res.size(); i++) { rx_buffer->store((uint8_t)res[i]); rv++; } @@ -185,7 +185,7 @@ int WiFiSSLClient::read(uint8_t *buf, size_t size) { read_if_needed(size); int rv = 0; bool go_on = true; - for(int i = 0; i < size && go_on; i++) { + for(size_t i = 0; i < size && go_on; i++) { bool is_read = false; *(buf+i) = rx_buffer->read(&is_read); if(is_read) { diff --git a/libraries/WiFiS3/src/WiFiTypes.h b/libraries/WiFiS3/src/WiFiTypes.h index 70be019a5..d72acd95a 100644 --- a/libraries/WiFiS3/src/WiFiTypes.h +++ b/libraries/WiFiS3/src/WiFiTypes.h @@ -31,4 +31,11 @@ enum wl_enc_type { ENC_TYPE_UNKNOWN = 255 }; +typedef enum { + WL_PING_DEST_UNREACHABLE = -1, + WL_PING_TIMEOUT = -2, + WL_PING_UNKNOWN_HOST = -3, + WL_PING_ERROR = -4 +} wl_ping_result_t; + #endif \ No newline at end of file diff --git a/libraries/WiFiS3/src/WiFiUdp.cpp b/libraries/WiFiS3/src/WiFiUdp.cpp index 5337c8360..f229485c6 100644 --- a/libraries/WiFiS3/src/WiFiUdp.cpp +++ b/libraries/WiFiS3/src/WiFiUdp.cpp @@ -181,7 +181,7 @@ int WiFiUDP::_read() { modem.read_using_size(); if(modem.write(string(PROMPT(_UDPREAD)),res, "%s%d,%d\r\n" , CMD_WRITE(_UDPREAD), _sock, size)) { if(res.size() > 0) { - for(int i = 0, rv = 0; i < size && i < res.size(); i++) { + for(uint32_t i = 0, rv = 0; i < size && i < res.size(); i++) { rx_buffer.store((uint8_t)res[i]); rv++; } @@ -218,7 +218,7 @@ int WiFiUDP::read(unsigned char* buf, size_t size) { read_if_needed(size); int rv = 0; bool go_on = true; - for(int i = 0; i < size && go_on; i++) { + for(size_t i = 0; i < size && go_on; i++) { bool is_read = false; *(buf+i) = rx_buffer.read(&is_read); if(is_read) { diff --git a/platform.txt b/platform.txt index 87cb0603d..38f7aee8e 100644 --- a/platform.txt +++ b/platform.txt @@ -3,7 +3,7 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification name=Arduino Renesas fsp Boards -version=1.2.2 +version=1.3.1 # Compile variables # ------------------------