Skip to content

Commit 3d099c8

Browse files
committed
Absolute time scheduling functionality implemented
1 parent 1fe202b commit 3d099c8

3 files changed

Lines changed: 145 additions & 24 deletions

File tree

Launcher.cpp

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
7070
{
7171
Time time;
7272
Time interval;
73+
bool absolute = false;
7374
string message;
7475
Config config;
7576

@@ -83,6 +84,8 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
8384

8485
if (config.ScheduleTime.IsSet() == true) {
8586

87+
absolute = config.ScheduleTime.Absolute.Value();
88+
8689
time = Time(config.ScheduleTime.Time.Value());
8790
if (time.IsValid() != true) {
8891
SYSLOG(Trace::Warning, (_T("Time format is wrong")));
@@ -99,13 +102,20 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
99102
if (_activity->IsOperational() == false) {
100103
// Well if we where able to parse the parameters (if needed) we are ready to start it..
101104
_observer.Register(&_notification);
102-
103105
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);
106+
if (absolute == true) {
107+
//Schedule Job at absolute timing
108+
Core::Time scheduledTime = FindAbsoluteTimeForSchedule(time, interval);
109+
PluginHost::WorkerPool::Instance().Schedule(scheduledTime, _activity);
110+
}
111+
else { //Schedule Job at relative timing
112+
Core::Time scheduledTime(Core::Time::Now();
113+
uint64_t timeValueToTrigger = ((((time.Hour() != (uint8_t)(~0)) ? time.Hour(): 0) * MinutesPerHour +
114+
((time.Minute() != (uint8_t)(~0)) ? time.Minute(): 0)) * SecondsPerMinute + time.Second()) * MilliSecondsPerSecond;
115+
scheduledTime.Add(timeValueToTrigger);
107116

108-
PluginHost::WorkerPool::Instance().Schedule(scheduledTime, _activity);
117+
PluginHost::WorkerPool::Instance().Schedule(scheduledTime, _activity);
118+
}
109119
}
110120
else {
111121
PluginHost::WorkerPool::Instance().Submit(_activity);
@@ -179,6 +189,65 @@ void Launcher::Update(const ProcessObserver::Info& info)
179189
}
180190
}
181191

192+
Core::Time Launcher::FindAbsoluteTimeForSchedule(const Time absoluteTime, const Time interval) {
193+
194+
Core::Time scheduledTime;
195+
Core::Time currentTime(Core::Time::Now());
196+
197+
uint64_t absoluteTimeInMilliSeconds = 0;
198+
uint64_t currentTimeInMilliSeconds = 0;
199+
200+
if (!absoluteTime.HasHours()) { //Hour is don't care condition, so schedule based on the MM.SS
201+
uint64_t nextScheduleTimeInMilliSeconds = 0;
202+
uint64_t timeLimitInMilliSeconds = 0;
203+
if (!absoluteTime.HasMinutes()) { //Minute is don't care condition, so schedule based on the SS
204+
absoluteTimeInMilliSeconds = (absoluteTime.Second() * MilliSecondsPerSecond);
205+
currentTimeInMilliSeconds = (currentTime.Seconds() * MilliSecondsPerSecond);
206+
timeLimitInMilliSeconds = (SecondsPerMinute * MilliSecondsPerSecond);
207+
}
208+
else {
209+
absoluteTimeInMilliSeconds = ((absoluteTime.Minute() * SecondsPerMinute) + absoluteTime.Second()) * MilliSecondsPerSecond;
210+
currentTimeInMilliSeconds = ((currentTime.Minutes() * SecondsPerMinute) + currentTime.Seconds()) * MilliSecondsPerSecond;
211+
timeLimitInMilliSeconds = MinutesPerHour * SecondsPerMinute * MilliSecondsPerSecond;
212+
}
213+
if (currentTimeInMilliSeconds < absoluteTimeInMilliSeconds) { //Time is not reached
214+
nextScheduleTimeInMilliSeconds = absoluteTimeInMilliSeconds - currentTimeInMilliSeconds;
215+
}
216+
else {
217+
nextScheduleTimeInMilliSeconds = (timeLimitInMilliSeconds - currentTimeInMilliSeconds) + absoluteTimeInMilliSeconds;
218+
}
219+
scheduledTime = currentTime.Add(nextScheduleTimeInMilliSeconds);
220+
}
221+
else {
222+
absoluteTimeInMilliSeconds = ((absoluteTime.Hour() * MinutesPerHour + absoluteTime.Minute()) * SecondsPerMinute + absoluteTime.Second()) * MilliSecondsPerSecond;
223+
currentTimeInMilliSeconds = ((currentTime.Hours() * MinutesPerHour + currentTime.Minutes()) * SecondsPerMinute + currentTime.Seconds()) * MilliSecondsPerSecond;
224+
if (currentTimeInMilliSeconds < absoluteTimeInMilliSeconds) { //Time is not reached
225+
scheduledTime = currentTime.Add(absoluteTimeInMilliSeconds - currentTimeInMilliSeconds);
226+
}
227+
else { //Time is already hit, find next suitable time
228+
uint64_t nextScheduleTimeInMilliSeconds = 0;
229+
if (interval.IsValid() == true) {
230+
uint64_t intervalTimeInMilliSeconds = ((((interval.Hour() != ~0) ? interval.Hour(): 0) * MinutesPerHour +
231+
((interval.Minute() != ~0) ? interval.Minute(): 0)) * SecondsPerMinute + interval.Second()) * MilliSecondsPerSecond;
232+
nextScheduleTimeInMilliSeconds = absoluteTimeInMilliSeconds + intervalTimeInMilliSeconds;
233+
do {
234+
if (currentTimeInMilliSeconds < nextScheduleTimeInMilliSeconds) {
235+
break;
236+
}
237+
nextScheduleTimeInMilliSeconds += intervalTimeInMilliSeconds;
238+
} while(1);
239+
scheduledTime = currentTime.Add(nextScheduleTimeInMilliSeconds - currentTimeInMilliSeconds);
240+
}
241+
else {
242+
uint64_t timeLimitInMilliSeconds = (((HoursPerDay * MinutesPerHour) * SecondsPerMinute) * MilliSecondsPerSecond);
243+
nextScheduleTimeInMilliSeconds = (timeLimitInMilliSeconds - currentTimeInMilliSeconds) + absoluteTimeInMilliSeconds;
244+
scheduledTime = currentTime.Add(nextScheduleTimeInMilliSeconds);
245+
}
246+
}
247+
}
248+
return scheduledTime;
249+
}
250+
182251
} //namespace Plugin
183252

184253
} // namespace WPEFramework

Launcher.h

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -300,21 +300,26 @@ class Launcher : public PluginHost::IPlugin {
300300
public:
301301
Schedule()
302302
: Core::JSON::Container()
303+
, Absolute(false)
303304
, Time()
304305
, Interval() {
306+
Add(_T("absolute"), &Absolute);
305307
Add(_T("time"), &Time);
306308
Add(_T("interval"), &Interval);
307309
}
308310
Schedule(const Schedule& copy)
309311
: Core::JSON::Container()
312+
, Absolute(copy.Absolute)
310313
, Time(copy.Time)
311314
, Interval(copy.Interval) {
315+
Add(_T("absolute"), &Absolute);
312316
Add(_T("time"), &Time);
313317
Add(_T("interval"), &Interval);
314318
}
315319
~Schedule() {
316320
}
317321
public:
322+
Core::JSON::Boolean Absolute;
318323
Core::JSON::String Time;
319324
Core::JSON::String Interval;
320325
};
@@ -343,6 +348,12 @@ class Launcher : public PluginHost::IPlugin {
343348
Schedule ScheduleTime;
344349
};
345350

351+
private:
352+
static constexpr uint32_t MilliSecondsPerSecond = 1000;
353+
static constexpr uint32_t SecondsPerMinute = 60;
354+
static constexpr uint32_t MinutesPerHour = 60;
355+
static constexpr uint32_t HoursPerDay = 24;
356+
346357
class Time {
347358
public:
348359
Time()
@@ -370,9 +381,9 @@ class Launcher : public PluginHost::IPlugin {
370381

371382
public:
372383
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); }
384+
bool HasHours() const { return (_hour < HoursPerDay); }
385+
bool HasMinutes() const { return (_minute < MinutesPerHour); }
386+
bool HasSeconds() const { return (_second < SecondsPerMinute); }
376387
uint8_t Hour() const { return _hour; }
377388
uint8_t Minute() const { return _minute; }
378389
uint8_t Second() const { return _second; }
@@ -383,25 +394,30 @@ class Launcher : public PluginHost::IPlugin {
383394
string t = time;
384395

385396
//Get hours
386-
uint8_t hour;
397+
uint8_t hour = (~0);
387398
string hValue = Split(t, ":");
388-
status = IsValidTime(hValue, hour, 24);
399+
if (hValue.empty() != true) {
400+
status = IsValidTime(hValue, hour, HoursPerDay);
401+
}
389402
if (status == true) {
390-
391-
//Get minutes
392-
uint8_t minute;
403+
//Get minutes
404+
uint8_t minute = (~0);
393405
string mValue = Split(t, ".");
394-
status = IsValidTime(mValue, minute, 60);
406+
if (mValue.empty() != true) {
407+
status = IsValidTime(mValue, minute, MinutesPerHour);
408+
}
395409
if (status == true) {
396410

397411
//Store seconds
398-
uint8_t second;
412+
uint8_t second = (~0);
399413
string sValue = t;
400-
status = IsValidTime(sValue, second, 60);
414+
if (sValue.empty() != true) {
415+
status = IsValidTime(sValue, second, SecondsPerMinute);
416+
}
401417
if (status == true) {
402418

403419
//Check all the time components are still valid
404-
if ((hour > 0 && second > 0) && (minute == 0)) {
420+
if ((hour != (~0) && second != (~0)) && (minute == (~0))) {
405421
status = false;
406422
TRACE(Trace::Information, (_T("Invalid time format")));
407423
}
@@ -416,7 +432,7 @@ class Launcher : public PluginHost::IPlugin {
416432
return status;
417433
}
418434

419-
private:
435+
private:
420436
inline bool IsDigit(const string& str) {
421437
return (str.find_first_not_of( "0123456789" ) == std::string::npos);
422438
}
@@ -450,7 +466,7 @@ class Launcher : public PluginHost::IPlugin {
450466
return word;
451467
}
452468

453-
private:
469+
private:
454470
uint8_t _hour;
455471
uint8_t _minute;
456472
uint8_t _second;
@@ -509,10 +525,11 @@ class Launcher : public PluginHost::IPlugin {
509525
_process.Launch(_options, &_pid);
510526
}
511527

512-
if (_interval.IsValid() == true && ((_interval.Hour() != 0) || (_interval.Minute() != 0) || (_interval.Second() != 0))) {
528+
if (_interval.IsValid() == true) {
513529
// Reschedule our next launch point...
514530
Core::Time scheduledTime(Core::Time::Now());
515-
uint64_t intervalTime = ((_interval.Hour() * 60 + _interval.Minute()) * 60 + _interval.Second()) * 1000;
531+
uint64_t intervalTime = ((((_interval.Hour() != (uint8_t)(~0)) ? _interval.Hour(): 0) * MinutesPerHour +
532+
((_interval.Minute() != (uint8_t)(~0)) ? _interval.Minute():0)) * SecondsPerMinute + _interval.Second()) * MilliSecondsPerSecond;
516533
scheduledTime.Add(intervalTime);
517534
PluginHost::WorkerPool::Instance().Schedule(scheduledTime,Core::ProxyType<Core::IDispatch>(*this));
518535
}
@@ -578,6 +595,7 @@ class Launcher : public PluginHost::IPlugin {
578595
private:
579596
void Update(const ProcessObserver::Info& info);
580597
bool Execute();
598+
Core::Time FindAbsoluteTimeForSchedule(const Time absoluteTime, const Time interval);
581599

582600
private:
583601
PluginHost::IShell* _service;

README.md

Lines changed: 37 additions & 3 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",
@@ -78,6 +78,37 @@ Plugin to "Launch" linux applications and scripts
7878
Note:
7979
1. If field "absolute" is false 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+
"absolute": true,
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

@@ -97,7 +128,10 @@ Note:
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 absolute time given is less than the current time 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)
101135

102136
# How to launch multiple scripts/applcations
103137

0 commit comments

Comments
 (0)