1717 */
1818
1919/*
20- Sketch uses 1108838 bytes (84%) of program storage space. Maximum is 1310720 bytes.
20+ Sketch uses 1110306 bytes (84%) of program storage space. Maximum is 1310720 bytes.
2121Global variables use 50536 bytes (15%) of dynamic memory, leaving 277144 bytes for local variables. Maximum is 327680 bytes.
2222*/
2323#include < WiFi.h>
@@ -41,7 +41,7 @@ Preferences prefs;
4141 * Software version number
4242 * Format: major.minor.patch
4343 */
44- #define SWVersion " v0.2.0 -alpha"
44+ #define SWVersion " v0.2.1 -alpha"
4545
4646const char *ssid = " SonyBraviaX400" ;
4747const char *password = " 79756622761" ;
@@ -122,6 +122,17 @@ private:
122122 timerDuration, timerActive, timerStart);
123123 }
124124
125+ /* *
126+ * @brief Safely stops any active timer
127+ */
128+ void stopTimer ()
129+ {
130+ timerActive = false ;
131+ timerStart = 0 ;
132+ timerDuration = 0 ;
133+ saveToPreferences ();
134+ }
135+
125136public:
126137 /* *
127138 * @brief Constructs a new Relay object
@@ -174,6 +185,11 @@ public:
174185 */
175186 void setMode (String newMode)
176187 {
188+ // Stop timer if switching away from timer mode
189+ if (mode == " timer" && newMode != " timer" )
190+ {
191+ stopTimer ();
192+ }
177193 mode = newMode;
178194 saveToPreferences ();
179195 }
@@ -191,6 +207,11 @@ public:
191207 {
192208 isOn = false ;
193209 digitalWrite (pin, LOW);
210+ // Stop any active timer when disabling
211+ if (timerActive)
212+ {
213+ stopTimer ();
214+ }
194215 }
195216 saveToPreferences ();
196217 }
@@ -255,7 +276,11 @@ public:
255276 {
256277 timerStart = millis ();
257278 }
258- saveToPreferences (); // Save timer state to persistent memory
279+ else
280+ {
281+ stopTimer ();
282+ }
283+ saveToPreferences ();
259284 }
260285
261286 /* *
@@ -275,6 +300,20 @@ public:
275300 * @return unsigned long containing the millis() value when timer started
276301 */
277302 unsigned long getTimerStart () { return timerStart; }
303+
304+ /* *
305+ * @brief Gets the remaining time for the timer
306+ * @return unsigned long containing the remaining time in seconds
307+ */
308+ unsigned long getRemainingTime ()
309+ {
310+ if (!timerActive)
311+ return 0 ;
312+ unsigned long elapsed = (millis () - timerStart) / 1000 ;
313+ if (elapsed >= timerDuration)
314+ return 0 ;
315+ return timerDuration - elapsed;
316+ }
278317};
279318
280319// Initialize preferences once
@@ -297,7 +336,7 @@ const long interval = 1000; // 1 seconds interval
297336 * @return bool Returns true if the time was successfully updated, false otherwise
298337 * @note Requires an active WiFi connection to function
299338 */
300- bool autoTimeUpdate ()
339+ bool rtcTimeUpdater ()
301340{
302341 if (WiFi.status () == WL_CONNECTED)
303342 {
@@ -563,6 +602,16 @@ void setup()
563602 response->print (" {\" onTime\" : " + String (relays[modeIndex-1 ]->getOnTime ()) +
564603 " , \" offTime\" : " + String (relays[modeIndex-1 ]->getOffTime ()) + " }" );
565604 request->send (response); });
605+
606+ // Add timer state endpoint inside server setup
607+ String timerStateEndpoint = " /api/led" + String (i) + " /timer/state" ;
608+ server.on (timerStateEndpoint.c_str (), HTTP_GET, [modeIndex](AsyncWebServerRequest *request)
609+ {
610+ AsyncResponseStream *response = request->beginResponseStream (" application/json" );
611+ const auto remaining = relays[modeIndex-1 ]->getRemainingTime ();
612+ response->print (" {\" active\" : " + String (relays[modeIndex-1 ]->isTimerActive () ? " true" : " false" ) +
613+ " , \" remaining\" : " + String (remaining) + " }" );
614+ request->send (response); });
566615 }
567616
568617 // Manual Mode Toggle endpoints for each relay
@@ -607,7 +656,7 @@ void loop1(void *pvParameters)
607656
608657 if (updateTime) // automatically updates time when true
609658 {
610- if (autoTimeUpdate ())
659+ if (rtcTimeUpdater ())
611660 {
612661 Serial.println (" Time updated successfully" );
613662 updateTime = false ;
0 commit comments