ota.cpp
1 #include "ota.h" 2 3 #if CERATINA_OTA_ENABLED 4 5 #include <Arduino.h> 6 #include <ArduinoOTA.h> 7 #include <WiFi.h> 8 9 static bool started = false; 10 static bool updating = false; 11 12 void networking::ota::initialize(void) { 13 if (started) return; 14 15 ArduinoOTA.setHostname(config::HOSTNAME); 16 ArduinoOTA.setPort(config::ota::PORT); 17 18 if (config::ota::PASSWORD[0] != '\0') 19 ArduinoOTA.setPassword(config::ota::PASSWORD); 20 21 ArduinoOTA 22 .onStart([]() { 23 updating = true; 24 const char *type = (ArduinoOTA.getCommand() == U_FLASH) 25 ? "firmware" : "filesystem"; 26 Serial.printf("[ota] start updating %s\n", type); 27 }) 28 .onEnd([]() { 29 updating = false; 30 Serial.println(F("\n[ota] update complete")); 31 }) 32 .onProgress([](unsigned int progress, unsigned int total) { 33 Serial.printf("[ota] %u%%\r", progress / (total / 100)); 34 }) 35 .onError([](ota_error_t error) { 36 const char *msg = "unknown"; 37 switch (error) { 38 case OTA_AUTH_ERROR: msg = "auth failed"; break; 39 case OTA_BEGIN_ERROR: msg = "begin failed"; break; 40 case OTA_CONNECT_ERROR: msg = "connect failed"; break; 41 case OTA_RECEIVE_ERROR: msg = "receive failed"; break; 42 case OTA_END_ERROR: msg = "end failed"; break; 43 } 44 Serial.printf("[ota] error: %s\n", msg); 45 }); 46 47 ArduinoOTA.begin(); 48 started = true; 49 Serial.printf("[ota] listening on port %d\n", config::ota::PORT); 50 } 51 52 void networking::ota::service(void) { 53 if (!started) return; 54 ArduinoOTA.handle(); 55 } 56 57 bool networking::ota::isInProgress(void) { 58 return updating; 59 } 60 61 #else 62 63 void networking::ota::initialize(void) {} 64 void networking::ota::service(void) {} 65 bool networking::ota::isInProgress(void) { return false; } 66 67 #endif 68 69 // ───────────────────────────────────────────────────────────────────────────── 70 // Tests 71 // ───────────────────────────────────────────────────────────────────────────── 72 #ifdef PIO_UNIT_TESTING 73 74 75 #include "ota.h" 76 #include <testing/utils.h> 77 78 namespace networking::ota { void test(void); } 79 80 #include <Arduino.h> 81 82 static void test_ota_config(void) { 83 GIVEN("OTA is configured"); 84 THEN("the configuration is valid"); 85 86 TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(0, config::ota::PORT, 87 "device: OTA port must be > 0"); 88 89 #if CERATINA_OTA_ENABLED 90 TEST_PRINTF("OTA enabled on port %d", config::ota::PORT); 91 #else 92 TEST_MESSAGE("OTA is disabled (CERATINA_OTA_ENABLED=0)"); 93 94 #endif 95 } 96 97 static void test_ota_noop_when_disabled(void) { 98 WHEN("OTA functions are called while disabled"); 99 THEN("they complete as no-ops"); 100 #if !CERATINA_OTA_ENABLED 101 networking::ota::initialize(); 102 networking::ota::service(); 103 #else 104 TEST_IGNORE_MESSAGE("OTA is enabled — test not applicable"); 105 #endif 106 } 107 108 void networking::ota::test(void) { 109 MODULE("OTA"); 110 RUN_TEST(test_ota_config); 111 RUN_TEST(test_ota_noop_when_disabled); 112 } 113 114 #endif