Skip to content

Commit bb90442

Browse files
authored
Merge pull request #3 from WebPlatformForEmbedded/timer
Absolute time scheduling functionality implemented
2 parents 1fe202b + b3356a5 commit bb90442

3 files changed

Lines changed: 154 additions & 29 deletions

File tree

Launcher.cpp

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
#include "Launcher.h"
2+
#include <inttypes.h>
23

34
namespace WPEFramework {
45

6+
ENUM_CONVERSION_BEGIN(Plugin::Launcher::mode)
7+
8+
{ Plugin::Launcher::mode::RELATIVE, _TXT("relative") },
9+
{ Plugin::Launcher::mode::ABSOLUTE, _TXT("absolute") },
10+
{ Plugin::Launcher::mode::ABSOLUTE_WITH_INTERVAL, _TXT("interval") },
11+
12+
ENUM_CONVERSION_END(Plugin::Launcher::mode)
13+
;
514
namespace Plugin {
615

716
SERVICE_REGISTRATION(Launcher, 1, 0);
@@ -70,6 +79,7 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
7079
{
7180
Time time;
7281
Time interval;
82+
mode timeMode = RELATIVE;
7383
string message;
7484
Config config;
7585

@@ -83,6 +93,8 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
8393

8494
if (config.ScheduleTime.IsSet() == true) {
8595

96+
timeMode = config.ScheduleTime.Mode.Value();
97+
8698
time = Time(config.ScheduleTime.Time.Value());
8799
if (time.IsValid() != true) {
88100
SYSLOG(Trace::Warning, (_T("Time format is wrong")));
@@ -99,12 +111,25 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
99111
if (_activity->IsOperational() == false) {
100112
// Well if we where able to parse the parameters (if needed) we are ready to start it..
101113
_observer.Register(&_notification);
102-
114+
Core::Time scheduledTime;
103115
if (time.IsValid() == true) {
104-
Core::Time scheduledTime(Core::Time::Now());
105-
uint64_t timeValueToTrigger = ((time.Hour() * 60 + time.Minute()) * 60 + time.Second()) * 1000;
106-
scheduledTime.Add(timeValueToTrigger);
116+
if (timeMode == RELATIVE) { //Schedule Job at relative timing
117+
scheduledTime = Core::Time::Now();
118+
119+
uint64_t timeValueToTrigger = ((((time.Hours() != (uint8_t)(~0)) ? time.Hours(): 0) * MinutesPerHour +
120+
((time.Minutes() != (uint8_t)(~0)) ? time.Minutes(): 0)) * SecondsPerMinute + time.Seconds()) * MilliSecondsPerSecond;
121+
scheduledTime.Add(timeValueToTrigger);
107122

123+
}
124+
else {
125+
//Schedule Job at absolute timing
126+
if (timeMode == ABSOLUTE_WITH_INTERVAL) {
127+
scheduledTime = FindAbsoluteTimeForSchedule(time, interval);
128+
}
129+
else {
130+
scheduledTime = FindAbsoluteTimeForSchedule(time, Time());
131+
}
132+
}
108133
PluginHost::WorkerPool::Instance().Schedule(scheduledTime, _activity);
109134
}
110135
else {
@@ -179,6 +204,44 @@ void Launcher::Update(const ProcessObserver::Info& info)
179204
}
180205
}
181206

207+
Core::Time Launcher::FindAbsoluteTimeForSchedule(const Time& absoluteTime, const Time& interval) {
208+
Core::Time startTime = Core::Time::Now();
209+
// Go to a first viable start time (compared to the current time, in seconds)
210+
Core::Time slotTime = Core::Time(startTime.Year(), startTime.Month(), startTime.Day(),
211+
(absoluteTime.HasHours() ? absoluteTime.Hours() : startTime.Hours()),
212+
(absoluteTime.HasMinutes() ? absoluteTime.Minutes() : startTime.Minutes()),
213+
absoluteTime.Seconds(), 0, false);
214+
215+
if (interval.IsValid() == false) {
216+
if (slotTime < startTime) {
217+
uint32_t jump (absoluteTime.HasHours() ? HoursPerDay * MinutesPerHour * SecondsPerMinute : (absoluteTime.HasMinutes() ? MinutesPerHour * SecondsPerMinute : SecondsPerMinute));
218+
slotTime.Add(jump * 100);
219+
}
220+
}
221+
else {
222+
uint32_t intervalJump = ( (interval.HasHours() ? interval.Hours() * MinutesPerHour * SecondsPerMinute : 0) +
223+
(interval.HasMinutes() ? interval.Minutes() * SecondsPerMinute : 0) +
224+
interval.Seconds() ) * 100;
225+
226+
ASSERT (intervalJump != 0);
227+
if (slotTime >= startTime) {
228+
Core::Time workTime (slotTime);
229+
230+
while (workTime.Sub(intervalJump) > startTime) {
231+
slotTime.Sub(intervalJump);
232+
}
233+
}
234+
else {
235+
// Now increment with the intervall till we reach a valid point
236+
while (slotTime < startTime) {
237+
slotTime.Add(intervalJump);
238+
}
239+
}
240+
}
241+
242+
return slotTime;
243+
}
244+
182245
} //namespace Plugin
183246

184247
} // namespace WPEFramework

Launcher.h

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ class Launcher : public PluginHost::IPlugin {
1212
Launcher(const Launcher&) = delete;
1313
Launcher& operator=(const Launcher&) = delete;
1414

15+
public:
16+
enum mode {
17+
RELATIVE,
18+
ABSOLUTE,
19+
ABSOLUTE_WITH_INTERVAL
20+
};
21+
1522
class ProcessObserver {
1623
private:
1724
ProcessObserver(const ProcessObserver&) = delete;
@@ -300,21 +307,26 @@ class Launcher : public PluginHost::IPlugin {
300307
public:
301308
Schedule()
302309
: Core::JSON::Container()
310+
, Mode(RELATIVE)
303311
, Time()
304312
, Interval() {
313+
Add(_T("mode"), &Mode);
305314
Add(_T("time"), &Time);
306315
Add(_T("interval"), &Interval);
307316
}
308317
Schedule(const Schedule& copy)
309318
: Core::JSON::Container()
319+
, Mode(copy.Mode)
310320
, Time(copy.Time)
311321
, Interval(copy.Interval) {
322+
Add(_T("mode"), &Mode);
312323
Add(_T("time"), &Time);
313324
Add(_T("interval"), &Interval);
314325
}
315326
~Schedule() {
316327
}
317328
public:
329+
Core::JSON::EnumType<mode> Mode;
318330
Core::JSON::String Time;
319331
Core::JSON::String Interval;
320332
};
@@ -343,6 +355,12 @@ class Launcher : public PluginHost::IPlugin {
343355
Schedule ScheduleTime;
344356
};
345357

358+
private:
359+
static constexpr uint32_t MilliSecondsPerSecond = 1000;
360+
static constexpr uint32_t SecondsPerMinute = 60;
361+
static constexpr uint32_t MinutesPerHour = 60;
362+
static constexpr uint32_t HoursPerDay = 24;
363+
346364
class Time {
347365
public:
348366
Time()
@@ -370,38 +388,43 @@ class Launcher : public PluginHost::IPlugin {
370388

371389
public:
372390
bool IsValid () const { return (HasSeconds() || HasMinutes() || HasHours()); }
373-
bool HasHours() const { return (_hour < 24); }
374-
bool HasMinutes() const { return (_minute < 60); }
375-
bool HasSeconds() const { return (_second < 60); }
376-
uint8_t Hour() const { return _hour; }
377-
uint8_t Minute() const { return _minute; }
378-
uint8_t Second() const { return _second; }
391+
bool HasHours() const { return (_hour < HoursPerDay); }
392+
bool HasMinutes() const { return (_minute < MinutesPerHour); }
393+
bool HasSeconds() const { return (_second < SecondsPerMinute); }
394+
uint8_t Hours() const { return _hour; }
395+
uint8_t Minutes() const { return _minute; }
396+
uint8_t Seconds() const { return _second; }
379397

380398
private:
381399
bool Parse(const string& time) {
382400
bool status = true;
383401
string t = time;
384402

385403
//Get hours
386-
uint8_t hour;
404+
uint8_t hour = (~0);
387405
string hValue = Split(t, ":");
388-
status = IsValidTime(hValue, hour, 24);
406+
if (hValue.empty() != true) {
407+
status = IsValidTime(hValue, hour, HoursPerDay);
408+
}
389409
if (status == true) {
390-
391-
//Get minutes
392-
uint8_t minute;
410+
//Get minutes
411+
uint8_t minute = (~0);
393412
string mValue = Split(t, ".");
394-
status = IsValidTime(mValue, minute, 60);
413+
if (mValue.empty() != true) {
414+
status = IsValidTime(mValue, minute, MinutesPerHour);
415+
}
395416
if (status == true) {
396417

397418
//Store seconds
398-
uint8_t second;
419+
uint8_t second = (~0);
399420
string sValue = t;
400-
status = IsValidTime(sValue, second, 60);
421+
if (sValue.empty() != true) {
422+
status = IsValidTime(sValue, second, SecondsPerMinute);
423+
}
401424
if (status == true) {
402425

403426
//Check all the time components are still valid
404-
if ((hour > 0 && second > 0) && (minute == 0)) {
427+
if ((hour != (~0) && second != (~0)) && (minute == (~0))) {
405428
status = false;
406429
TRACE(Trace::Information, (_T("Invalid time format")));
407430
}
@@ -416,7 +439,7 @@ class Launcher : public PluginHost::IPlugin {
416439
return status;
417440
}
418441

419-
private:
442+
private:
420443
inline bool IsDigit(const string& str) {
421444
return (str.find_first_not_of( "0123456789" ) == std::string::npos);
422445
}
@@ -450,7 +473,7 @@ class Launcher : public PluginHost::IPlugin {
450473
return word;
451474
}
452475

453-
private:
476+
private:
454477
uint8_t _hour;
455478
uint8_t _minute;
456479
uint8_t _second;
@@ -506,13 +529,16 @@ class Launcher : public PluginHost::IPlugin {
506529
_hasRun = true;
507530
// Check if the process is not active, no need to reschedule the same job again.
508531
if (_process.IsActive() == false) {
532+
533+
Core::Time currentTime(Core::Time::Now());
509534
_process.Launch(_options, &_pid);
510535
}
511536

512-
if (_interval.IsValid() == true && ((_interval.Hour() != 0) || (_interval.Minute() != 0) || (_interval.Second() != 0))) {
537+
if (_interval.IsValid() == true) {
513538
// Reschedule our next launch point...
514539
Core::Time scheduledTime(Core::Time::Now());
515-
uint64_t intervalTime = ((_interval.Hour() * 60 + _interval.Minute()) * 60 + _interval.Second()) * 1000;
540+
uint64_t intervalTime = ((((_interval.Hours() != (uint8_t)(~0)) ? _interval.Hours(): 0) * MinutesPerHour +
541+
((_interval.Minutes() != (uint8_t)(~0)) ? _interval.Minutes():0)) * SecondsPerMinute + _interval.Seconds()) * MilliSecondsPerSecond;
516542
scheduledTime.Add(intervalTime);
517543
PluginHost::WorkerPool::Instance().Schedule(scheduledTime,Core::ProxyType<Core::IDispatch>(*this));
518544
}
@@ -578,6 +604,7 @@ class Launcher : public PluginHost::IPlugin {
578604
private:
579605
void Update(const ProcessObserver::Info& info);
580606
bool Execute();
607+
Core::Time FindAbsoluteTimeForSchedule(const Time& absoluteTime, const Time& interval);
581608

582609
private:
583610
PluginHost::IShell* _service;

README.md

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Plugin to "Launch" linux applications and scripts
5858
}
5959
```
6060

61-
### How to schedule an application/script
61+
### How to schedule an application/script with relative time
6262

63-
1. Add schedule relative time information to the Launcher.json in the HH:MM.SS format (Hour:Minute.Second)
63+
1. Add 'relative' time information to the Launcher.json in the HH:MM.SS format (Hour:Minute.Second)
6464
```
6565
"configuration": {
6666
"command":"du",
@@ -69,15 +69,46 @@ Plugin to "Launch" linux applications and scripts
6969
{ "option": "-h"}
7070
],
7171
"schedule": {
72-
"absolute": false,
72+
"mode": "relative",
7373
"time": "06:04.10"
7474
}
7575
}
7676
```
7777

7878
Note:
79-
1. If field "absolute" is false or not set, it will treat the time as relative
79+
1. If field "mode" is empty or not set, it will treat the time as relative
8080
2. If relative time value is "00:00.00"/invalid format/not set, the launcher will ignore the given time and launch the application at the launcher activation time itself.
81+
3. If time format given is
82+
a. "XX", treat it as SS
83+
b. "XX.XX" treat it as MM.SS
84+
85+
### How to schedule an application/script with absolute time
86+
87+
1. Add 'absolute' time information to the Launcher.json in the HH:MM.SS format (Hour:Minute.Second)
88+
```
89+
"configuration": {
90+
"command":"du",
91+
"parameters": [
92+
{ "option": "-a", "value": "/etc" },
93+
{ "option": "-h"}
94+
],
95+
"schedule": {
96+
"mode": "absolute",
97+
"time": "06:04.10"
98+
}
99+
}
100+
```
101+
102+
Note:
103+
1. If absolute time value is invalid format/not set, the launcher will ignore the given time and launch the application at the launcher activation time itself.
104+
2. If time format given is
105+
a. "XX", treat it as SS, and schedule the application launch at next SSth time. i.e. if absolute time given is 25 and current time is 08:10:45, then the application will be
106+
launched at 08:11:25
107+
b. "XX.XX" treat it as MM.SS, and scedule the application launch at next MM:SSth time. i.e. if absolute time given is 30.20 and current time is 08:10:45, then the application will be
108+
launched at 09:30:20
109+
c. "00:00.00" treat it as midnight.
110+
3. If absolute time given is less than the current time, it will launch the application the same time at the subsequent day. i.e, if absolute time given is 13:00:00, it will launch
111+
the application at same time at the next day.
81112

82113
### How to schedule an application/script to run in an interval
83114

@@ -90,14 +121,18 @@ Note:
90121
{ "option": "-h"}
91122
],
92123
"schedule": {
93-
"absolute": false,
124+
"mode": "interval",
94125
"time": "06:04.10",
95126
"interval": "00:40.10"
96127
}
97128
}
98129
```
99130

100-
Note: If interval value is "00:00.00"/invalid format/not set, the launcher will treat it as invalid value and ignore the interval time settings.
131+
Note:
132+
1. If interval value is "00:00.00"/invalid format/not set, the launcher will treat it as invalid value and ignore the interval time settings.
133+
2. If mode is interval (absolute with interval) and interval is set, it will identify next matching time and schedule application launch to that time.
134+
i.e, if the absolute time given is 04:00:00, current time is 05:10:00 and interval is 00:30:00, then next scheduling time will be 05:30:00 (will be identified from the next intervals - 04:30:00, 05:00:00, 05:30:00)
135+
3. If mode is relative or absolute, the interval time will be taken only for the subsequent scheduling
101136

102137
# How to launch multiple scripts/applcations
103138

0 commit comments

Comments
 (0)