Skip to content

Commit d96dd2a

Browse files
committed
Time parsing and Job scheduling part added
1 parent ac6b868 commit d96dd2a

2 files changed

Lines changed: 224 additions & 11 deletions

File tree

Launcher.cpp

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,35 +80,48 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
8080
config.FromString(_service->ConfigLine());
8181

8282
_closeTime = (config.CloseTime.Value());
83-
Core::Process::Options options(config.Command.Value().c_str());
83+
_options.Set(config.Command.Value().c_str());
8484
auto iter = config.Parameters.Elements();
8585

8686
while (iter.Next() == true) {
8787
const Config::Parameter& element(iter.Current());
8888

8989
if ((element.Option.IsSet() == true) && (element.Option.Value().empty() == false)) {
9090
if ((element.Value.IsSet() == true) && (element.Value.Value().empty() == false)) {
91-
options.Set(element.Option.Value(), element.Value.Value());
91+
_options.Set(element.Option.Value(), element.Value.Value());
9292
}
9393
else {
94-
options.Set(element.Option.Value());
94+
_options.Set(element.Option.Value());
9595
}
9696
}
9797
}
98+
printf("%s:%s:%d \n", __FILE__, __func__, __LINE__);
99+
if (config.ScheduleTime.IsSet() == true) {
100+
101+
string time(config.ScheduleTime.Time.Value());
102+
if (time.empty() == false) {
103+
if (_time.Parse(time) != true) {
104+
TRACE_L1("Time format is wrong");
105+
}
106+
}
107+
108+
string interval(config.ScheduleTime.Interval.Value());
109+
if (interval.empty() == false) {
110+
if (_interval.Parse(interval) != true) {
111+
TRACE_L1("Interval format is wrong");
112+
}
113+
}
114+
printf("%s:%s:%d %s %s\n", __FILE__, __func__, __LINE__, time.c_str(), interval.c_str());
115+
}
98116

99117
_observer.Register(&_notification);
100118

101119
// Well if we where able to parse the parameters (if needed) we are ready to start it..
102-
_process.Launch(options, &_pid);
103-
104-
if (_pid == 0) {
120+
bool status = LaunchJob(_time);
121+
if (status == false) {
105122
_observer.Unregister(&_notification);
106123
message = _T("Could not spawn the requested app/script [") + config.Command.Value() + ']';
107124
}
108-
else {
109-
_memory = Core::Service<MemoryObserverImpl>::Create<Exchange::IMemory>(_pid);
110-
}
111-
112125
return (message);
113126
}
114127

@@ -143,6 +156,36 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
143156
return (string());
144157
}
145158

159+
bool Launcher::ScheduleJob(Time time)
160+
{
161+
Core::Time scheduledTime(Core::Time::Now());
162+
uint64_t timeValueToTrigger = ((time.Hour() * 60 + time.Minute()) * 60 + time.Second()) * 1000;
163+
164+
scheduledTime.Add(timeValueToTrigger);
165+
PluginHost::WorkerPool::Instance().Schedule(scheduledTime, _activity);
166+
}
167+
168+
bool Launcher::LaunchJob(Time time)
169+
{
170+
bool status = true;
171+
if (time.Hour() == 0 && time.Minute() == 0 && time.Second() == 0) {
172+
_process.Launch(_options, &_pid);
173+
174+
if (_pid == 0) {
175+
_observer.Unregister(&_notification);
176+
status = false;
177+
}
178+
else {
179+
_memory = Core::Service<MemoryObserverImpl>::Create<Exchange::IMemory>(_pid);
180+
ScheduleJob(_interval);
181+
}
182+
}
183+
else {
184+
ScheduleJob(_time);
185+
}
186+
return status;
187+
}
188+
146189
void Launcher::Update(const ProcessObserver::Info& info)
147190
{
148191
// This can potentially be called on a socket thread, so the deactivation (wich in turn kills this object) must be done
@@ -163,7 +206,6 @@ void Launcher::Update(const ProcessObserver::Info& info)
163206
}
164207
}
165208

166-
167209
} //namespace Plugin
168210

169211
} // namespace WPEFramework

Launcher.h

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,45 @@ class Launcher : public PluginHost::IPlugin {
292292
Core::JSON::String Value;
293293
};
294294

295+
public:
296+
class Schedule : public Core::JSON::Container {
297+
private:
298+
Schedule& operator=(const Schedule&) = delete;
299+
300+
public:
301+
Schedule()
302+
: Core::JSON::Container()
303+
, Time()
304+
, Interval() {
305+
Add(_T("time"), &Time);
306+
Add(_T("interval"), &Interval);
307+
}
308+
Schedule(const Schedule& copy)
309+
: Core::JSON::Container()
310+
, Time(copy.Time)
311+
, Interval(copy.Interval) {
312+
Add(_T("time"), &Time);
313+
Add(_T("interval"), &Interval);
314+
}
315+
~Schedule() {
316+
}
317+
public:
318+
Core::JSON::String Time;
319+
Core::JSON::String Interval;
320+
};
321+
295322
public:
296323
Config()
297324
: Core::JSON::Container()
298325
, Command()
299326
, Parameters()
300327
, CloseTime(3)
328+
, ScheduleTime()
301329
{
302330
Add(_T("command"), &Command);
303331
Add(_T("parameters"), &Parameters);
304332
Add(_T("closetime"), &CloseTime);
333+
Add(_T("schedule"), &ScheduleTime);
305334
}
306335
~Config()
307336
{
@@ -311,6 +340,133 @@ class Launcher : public PluginHost::IPlugin {
311340
Core::JSON::String Command;
312341
Core::JSON::ArrayType<Parameter> Parameters;
313342
Core::JSON::DecUInt8 CloseTime;
343+
Schedule ScheduleTime;
344+
};
345+
346+
public:
347+
class Time {
348+
Time()
349+
: _hour(0)
350+
, _minute(0)
351+
, _second(0)
352+
{
353+
}
354+
355+
~Time ()
356+
{
357+
}
358+
359+
uint8_t Hour() { return _hour; }
360+
uint8_t Minute() { return _minute; }
361+
uint8_t Second() { return _second; }
362+
363+
bool Parse(string time) {
364+
bool status = true;
365+
printf("%s:%s:%d: time = %s\n", __FILE__, __func__, __LINE__, time.c_str());
366+
367+
//Get hours
368+
uint8_t hour;
369+
string hValue = Split(time, ":");
370+
status = IsValidTime(hValue, hour, 24);
371+
if (status == true) {
372+
373+
//Get minutes
374+
uint8_t minute;
375+
string mValue = Split(time, ".");
376+
status = IsValidTime(mValue, minute, 60);
377+
if (status == true) {
378+
379+
//Store seconds
380+
uint8_t second;
381+
string sValue = time;
382+
status = IsValidTime(sValue, second, 60);
383+
if (status == true) {
384+
385+
//Check all the time components are still valid
386+
if ((hour > 0 && second > 0) && (minute == 0)) {
387+
status = false;
388+
TRACE(Trace::Information, (_T("Invalid time format")));
389+
}
390+
else { //Update time components
391+
_hour = hour;
392+
_minute = minute;
393+
_second = second;
394+
}
395+
}
396+
printf("%s:%s:%d: HH = %s MM = %s SS = %s\n", __FILE__, __func__, __LINE__, hValue.c_str(), mValue.c_str(), sValue.c_str());
397+
}
398+
}
399+
return status;
400+
}
401+
402+
private:
403+
inline bool IsDigit(const string& str) {
404+
return (str.find_first_not_of( "0123456789" ) == std::string::npos);
405+
}
406+
407+
inline bool IsValidTime(const string& str, uint8_t& time, const uint8_t limit) {
408+
bool status = true;
409+
if (IsDigit(str)) {
410+
int t = atoi(str.c_str());
411+
if (t > limit || t < 0) {
412+
status = false;
413+
TRACE(Trace::Information, (_T("Invalid time %s"), str.c_str()));
414+
}
415+
else {
416+
time = t;
417+
}
418+
}
419+
else {
420+
status = false;
421+
TRACE(Trace::Information, (_T("Invalid time %s"), str.c_str()));
422+
}
423+
return status;
424+
}
425+
426+
inline string Split(string& str, const string delimiter) {
427+
string word;
428+
size_t position = str.find(delimiter, 0);
429+
if (position != string::npos) {
430+
word = str.substr(0, position);
431+
str = str.substr(word.size() + 1, str.size());
432+
}
433+
printf("%s:%s:%d: %s: %s\n", __FILE__, __func__, __LINE__, word.c_str(), str.c_str());
434+
return word;
435+
}
436+
437+
private:
438+
uint8_t _hour;
439+
uint8_t _minute;
440+
uint8_t _second;
441+
};
442+
443+
private:
444+
class PeriodicSync : public Core::IDispatchType<void> {
445+
private:
446+
PeriodicSync() = delete;
447+
PeriodicSync(const PeriodicSync&) = delete;
448+
PeriodicSync& operator=(const PeriodicSync&) = delete;
449+
450+
public:
451+
PeriodicSync(Launcher* launcher)
452+
: _launcher(launcher)
453+
{
454+
ASSERT(launcher != nullptr);
455+
}
456+
~PeriodicSync()
457+
{
458+
}
459+
460+
public:
461+
virtual void Dispatch() override
462+
{
463+
Time time;
464+
printf("%s:%s:%d: \n", __FILE__, __func__, __LINE__);
465+
_launcher->LaunchJob(time);
466+
}
467+
468+
private:
469+
Launcher* _launcher;
314470
};
315471

316472
public:
@@ -324,6 +480,11 @@ class Launcher : public PluginHost::IPlugin {
324480
, _closeTime(0)
325481
, _notification(this)
326482
, _memory(nullptr)
483+
, _time()
484+
, _interval()
485+
, _options("")
486+
, _client(this)
487+
, _activity(Core::ProxyType<PeriodicSync>::Create(_client))
327488
{
328489
}
329490
#ifdef __WIN32__
@@ -360,8 +521,11 @@ class Launcher : public PluginHost::IPlugin {
360521
// to this plugin. This Metadata can be used by the MetData plugin to publish this information to the ouside world.
361522
string Information() const override;
362523

524+
bool LaunchJob(Time time);
525+
363526
private:
364527
void Update(const ProcessObserver::Info& info);
528+
bool ScheduleJob(Time time);
365529

366530
private:
367531
PluginHost::IShell* _service;
@@ -371,7 +535,14 @@ class Launcher : public PluginHost::IPlugin {
371535
Core::Sink<Notification> _notification;
372536
Exchange::IMemory* _memory;
373537

538+
Time _time;
539+
Time _interval;
540+
374541
static ProcessObserver _observer;
542+
543+
Launcher* _client;
544+
Core::Process::Options _options;
545+
Core::ProxyType<Core::IDispatchType<void> > _activity;
375546
};
376547

377548
} //namespace Plugin

0 commit comments

Comments
 (0)