3838#include < EmberIotUtil.h>
3939#include < WithSecureClient.h>
4040#include < EmberIotAuth.h>
41- #include < EmberIotShared.h>
4241#include < EmberIotStream.h>
4342#include < time.h>
4443
4544#define UPDATE_LAST_SEEN_INTERVAL 120000
46- #define EMBER_BUTTON_OFF 0
47- #define EMBER_BUTTON_ON 1
48- #define EMBER_BUTTON_PUSH 2
4945
5046/* *
5147 * @param dbUrl Realtime database URL, without protocol and slashes at the end. Example value: my-rtdb.firebaseio.com
@@ -172,6 +168,8 @@ class EmberIot : WithSecureClient
172168 return ;
173169 }
174170
171+ runPendingSchedules ();
172+
175173 uint8_t updateCount = 0 ;
176174 for (const bool i : hasUpdateByChannel)
177175 {
@@ -192,6 +190,14 @@ class EmberIot : WithSecureClient
192190#endif
193191 if (result)
194192 {
193+ for (size_t i = 0 ; i < EMBER_CHANNEL_COUNT; i++)
194+ {
195+ if (hasUpdateByChannel[i])
196+ {
197+ snprintf (EmberIotChannels::lastValues[i], EMBER_MAXIMUM_STRING_SIZE, " %s" , updateDataByChannel[i]);
198+ }
199+ }
200+
195201 for (bool & i : hasUpdateByChannel)
196202 {
197203 i = false ;
@@ -206,14 +212,29 @@ class EmberIot : WithSecureClient
206212 lastUpdatedChannels = millis ();
207213 }
208214
215+ EmberIotProp getChannelLastValue (const int channel)
216+ {
217+ return EmberIotProp (EmberIotChannels::lastValues[channel], false );
218+ }
219+
220+ /* *
221+ * Sets a callback to be executed when a scheduled action runs.
222+ * @param scheduleId schedule id.
223+ * @param callback function to be executed.
224+ */
225+ void setScheduleCallback (int scheduleId, EmberIotChannels::ScheduleJobCallback callback)
226+ {
227+ EmberIotChannels::setScheduleCallback (scheduleId, callback);
228+ }
229+
209230 /* *
210231 * Writes a string to a data channel.
211232 * @param channel Channel number.
212233 * @param value Value to be written.
213234 */
214235 void channelWrite (uint8_t channel, const char * value)
215236 {
216- if (!checkChannelChanged (updateDataByChannel[channel], value))
237+ if (hasUpdateByChannel[channel] && !checkChannelChanged (updateDataByChannel[channel], value))
217238 {
218239 return ;
219240 }
@@ -291,6 +312,73 @@ class EmberIot : WithSecureClient
291312 }
292313
293314private:
315+ void runPendingSchedules ()
316+ {
317+ time_t now = time (nullptr );
318+
319+ for (size_t i = 0 ; i < EMBER_MAX_SCHEDULES; i++)
320+ {
321+ EmberIotChannels::ScheduleJob *job = EmberIotChannels::jobs[i];
322+ if (job == nullptr || job->nextExecution < 0 || job->nextExecution > now || job->dataChannel < 0 || job->dataChannel >= EMBER_CHANNEL_COUNT)
323+ {
324+ continue ;
325+ }
326+
327+ char writtenData[EMBER_MAXIMUM_STRING_SIZE]{};
328+ switch (tolower (job->mode ))
329+ {
330+ case EmberIotChannels::JOB_MODE_DECREMENT:
331+ case EmberIotChannels::JOB_MODE_INCREMENT:
332+ {
333+ double out;
334+ FirePropUtil::str2int_errno ret = FirePropUtil::str2double (&out, job->value );
335+ if (ret != FirePropUtil::STR2INT_SUCCESS)
336+ {
337+ EMBER_DEBUGF (" Error parsing job value/str: %d/%s\n " , ret, job->value );
338+ break ;
339+ }
340+
341+ double dataChannelValue;
342+ FirePropUtil::str2int_errno retChannel = FirePropUtil::str2double (&dataChannelValue, EmberIotChannels::lastValues[job->dataChannel ]);
343+ if (retChannel == FirePropUtil::STR2INT_INCONVERTIBLE)
344+ {
345+ EMBER_DEBUGN (" Current data in channel is inconvertible to a number, setting to schedule value." );
346+ channelWrite (job->dataChannel , job->value );
347+ snprintf (writtenData, sizeof (writtenData), " %s" , job->value );
348+ break ;
349+ }
350+ else if (retChannel != FirePropUtil::STR2INT_SUCCESS)
351+ {
352+ EMBER_DEBUGF (" Error parsing data channel value/str: %d/%s\n " , ret, EmberIotChannels::lastValues[job->dataChannel ]);
353+ break ;
354+ }
355+
356+ double newValue = job->mode == EmberIotChannels::JOB_MODE_INCREMENT ? dataChannelValue + out : dataChannelValue - out;
357+ channelWrite (job->dataChannel , newValue);
358+ snprintf (writtenData, sizeof (writtenData), " %lf" , newValue);
359+ break ;
360+ }
361+ default :
362+ {
363+ channelWrite (job->dataChannel , job->value );
364+ snprintf (writtenData, sizeof (writtenData), " %s" , job->value );
365+ }
366+ }
367+
368+ EmberIotChannels::updateScheduleNextExecution (job->scheduleId );
369+
370+ if (EmberIotChannels::jobCallbacks[job->scheduleId ] != nullptr )
371+ {
372+ EmberIotChannels::jobCallbacks[job->scheduleId ](job);
373+ }
374+
375+ if (strlen (writtenData) > 0 )
376+ {
377+ EmberIotChannels::callChannelUpdate (job->dataChannel , writtenData, " sched" );
378+ }
379+ }
380+ }
381+
294382 bool checkChannelChanged (const char *lastVal, const char *newVal)
295383 {
296384 if (lastVal != nullptr && newVal == nullptr )
0 commit comments