Subversion Repositories HomeAutomation

Rev

Rev 970 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 970 Rev 971
Line 57... Line 57...
57
 
57
 
58
void VirtualMachine::run()
58
void VirtualMachine::run()
59
{
59
{
60
    SyslogStream &slog = SyslogStream::getInstance();
60
    SyslogStream &slog = SyslogStream::getInstance();
61
 
61
 
62
    string basePath = Settings::get("BasePath") + "/Services/System/";
62
    string basePath = Settings::get("BasePath") + "Services/";
63
    string scriptName = "Base.js";
63
    string scriptName = "Base.js";
64
    string scriptFileName = basePath + scriptName;
64
    string scriptFileName = basePath + "System/" + scriptName;
65
 
65
 
66
    if (!file_exists(scriptFileName))
66
    if (!file_exists(scriptFileName))
67
    {
67
    {
68
        slog << "Failed to load :" << scriptFileName << "\n";
68
        slog << "Failed to load :" << scriptFileName << "\n";
69
    }
69
    }
70
 
70
 
71
    string scriptSource = file_get_contents(scriptFileName);
71
    string scriptSource = file_get_contents(scriptFileName);
72
 
72
 
73
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
73
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
74
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
74
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
75
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
75
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
76
 
76
 
77
    // Create a template for the global object.
77
    // Create a template for the global object.
Line 79... Line 79...
79
 
79
 
80
    //associates "print" on script to the Print function
80
    //associates "print" on script to the Print function
81
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine_log));
81
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine_log));
82
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine_sendCanMessage));
82
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine_sendCanMessage));
83
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine_loadScript));
83
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine_loadScript));
84
    myGlobal->Set(String::New("setTimeout"), FunctionTemplate::New(VirtualMachine_setTimeout));
-
 
85
    myGlobal->Set(String::New("setInterval"), FunctionTemplate::New(VirtualMachine_setInterval));
84
    myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine_startIntervalThread));
86
    myGlobal->Set(String::New("clearTimeout"), FunctionTemplate::New(VirtualMachine_clearInterval));
-
 
87
    myGlobal->Set(String::New("clearInterval"), FunctionTemplate::New(VirtualMachine_clearInterval));
85
    myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine_stopIntervalThread));
88
 
86
 
89
    //create context for the script
87
    //create context for the script
90
    myContext = Context::New(NULL, myGlobal);
88
    myContext = Context::New(NULL, myGlobal);
91
 
89
 
92
 
90
 
93
    //access global context within this scope
91
    //access global context within this scope
94
    Context::Scope context_scope(myContext);
92
    Context::Scope context_scope(myContext);
95
    //exception handler
93
    //exception handler
96
    TryCatch try_catch;
94
    TryCatch try_catch;
97
    //compile script to binary code - JIT
95
    //compile script to binary code - JIT
98
    Handle<Script> script = Script::Compile(source, name);
96
    Handle<Script> script = Script::Compile(source, name);
99
 
97
 
100
    //check if we got problems on compilation
98
    //check if we got problems on compilation
101
    if (script.IsEmpty())
99
    if (script.IsEmpty())
102
    {
100
    {
103
 
101
 
104
        // Print errors that happened during compilation.
102
        // Print errors that happened during compilation.
105
        String::AsciiValue error(try_catch.Exception());
103
        String::AsciiValue error(try_catch.Exception());
106
        slog << "Failed to compile script: " << *error << "\n";
104
        slog << "Failed to compile script: " << *error << "\n";
107
    }
105
    }
108
    else
106
    else
109
    {
107
    {
110
        //no errors , let's continue
108
        //no errors , let's continue
111
        Handle<Value> result = script->Run();
109
        Handle<Value> result = script->Run();
112
 
110
 
113
        //check if execution ended with errors
111
        //check if execution ended with errors
Line 117... Line 115...
117
            String::AsciiValue error(try_catch.Exception());
115
            String::AsciiValue error(try_catch.Exception());
118
            slog << "Constructor: Failed to run script: " << *error << "\n";
116
            slog << "Constructor: Failed to run script: " << *error << "\n";
119
        }
117
        }
120
        else
118
        else
121
        {
119
        {
122
            loadScript("System/Service.js");
-
 
123
            loadScript("System/ServiceManager.js");
-
 
124
            loadScript("System/CanMessage.js");
-
 
125
            loadScript("System/CanManager.js");
-
 
126
            loadScript("System/CanService.js");
-
 
127
            loadScript("System/Startup.js");
120
            loadScript("System/Startup.js");
128
 
121
 
129
            if (file_exists(basePath + "Autostart.js"))
122
            if (file_exists(basePath + "Autostart.js"))
130
            {
123
            {
131
                loadScript("Autostart.js");
124
                loadScript("Autostart.js");
132
            }
125
            }
133
           
126
           
134
            myFunctionHandleHeartbeat = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleHeartbeat")));
127
            myFunctionHandleHeartbeat = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleHeartbeat")));
135
            myFunctionOfflineCheck = Handle<Function>::Cast(myContext->Global()->Get(String::New("offlineCheck")));
128
            myFunctionOfflineCheck = Handle<Function>::Cast(myContext->Global()->Get(String::New("offlineCheck")));
136
            myFunctionHandleMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleMessage")));
129
            myFunctionHandleMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleMessage")));
137
            myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
130
            myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
138
        }
131
        }
139
    }
132
    }
140
 
133
 
141
    const int argc = 0;
134
    const int argc = 0;
142
    Handle<Value> argv[argc] = { };
135
    Handle<Value> argv[argc] = { };
143
 
136
 
144
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv); // argc and argv are your standard arguments to a function
137
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv); // argc and argv are your standard arguments to a function
145
 
138
 
146
    mySemaphore.lock();
139
    mySemaphore.lock();
147
 
140
 
148
    while (1)
141
    while (1)
149
    {
142
    {
150
        string expression;
143
        string expression;
151
 
144
 
152
        while (myExpressions.size() > 0)
145
        while (myExpressions.size() > 0)
153
        {
146
        {
154
            expression = myExpressions.pop();
147
            expression = myExpressions.pop();
155
 
148
 
156
            runExpression(expression);
149
            runExpression(expression);
157
        }
150
        }
158
 
151
 
159
        CanMessage canMessage;
152
        CanMessage canMessage;
160
 
153
 
161
        while (myCanMessages.size() > 0)
154
        while (myCanMessages.size() > 0)
162
        {
155
        {
163
            canMessage = myCanMessages.pop();
156
            canMessage = myCanMessages.pop();
164
 
157
 
165
            if (canMessage.isHeartbeat())
158
            if (canMessage.isHeartbeat())
166
            {
159
            {
167
                callHandleHeartbeat(stoi(canMessage.getData()["HardwareId"].getValue()));
160
                callHandleHeartbeat(stoi(canMessage.getData()["HardwareId"].getValue()));
168
            }
161
            }
169
            else
162
            else
170
            {
163
            {
171
                callHandleMessage(canMessage);
164
                callHandleMessage(canMessage);
172
            }
165
            }
173
        }
166
        }
174
 
167
 
175
        mySemaphore.wait();
168
        mySemaphore.wait();
176
    }
169
    }
177
 
170
 
178
    mySemaphore.unlock();
171
    mySemaphore.unlock();
179
}
172
}
180
 
173
 
181
void VirtualMachine::queueCanMessage(CanMessage canMessage)
174
void VirtualMachine::queueCanMessage(CanMessage canMessage)
182
{
175
{
183
    myCanMessages.push(canMessage);
176
    myCanMessages.push(canMessage);
184
    mySemaphore.broadcast();
177
    mySemaphore.broadcast();
185
}
178
}
186
 
179
 
187
void VirtualMachine::queueExpression(string expression)
180
void VirtualMachine::queueExpression(string expression)
188
{
181
{
189
    myExpressions.push(expression);
182
    myExpressions.push(expression);
190
    mySemaphore.broadcast();
183
    mySemaphore.broadcast();
191
}
184
}
192
 
185
 
193
bool VirtualMachine::loadScript(string scriptName)
186
bool VirtualMachine::loadScript(string scriptName)
194
{
187
{
195
    SyslogStream &slog = SyslogStream::getInstance();
188
    SyslogStream &slog = SyslogStream::getInstance();
196
 
189
 
197
    string basePath = Settings::get("BasePath") + "/Services/";
190
    string basePath = Settings::get("BasePath") + "/Services/";
198
    string scriptFileName = basePath + scriptName;
191
    string scriptFileName = basePath + scriptName;
199
 
192
 
200
    if (!file_exists(scriptFileName))
193
    if (!file_exists(scriptFileName))
201
    {
194
    {
202
        slog << "Failed to load :" << scriptFileName << "\n";
195
        slog << "Failed to load :" << scriptFileName << "\n";
203
        return false;
196
        return false;
204
    }
197
    }
205
 
198
 
206
    string scriptSource = file_get_contents(scriptFileName);
199
    string scriptSource = file_get_contents(scriptFileName);
207
 
200
 
208
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
201
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
209
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
202
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
210
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
203
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
211
 
204
 
212
    //access global context within this scope
205
    //access global context within this scope
213
    Context::Scope context_scope(myContext);
206
    Context::Scope context_scope(myContext);
214
    //exception handler
207
    //exception handler
215
    TryCatch try_catch;
208
    TryCatch try_catch;
216
    //compile script to binary code - JIT
209
    //compile script to binary code - JIT
217
    Handle<Script> script = Script::Compile(source, name);
210
    Handle<Script> script = Script::Compile(source, name);
218
 
211
 
219
    //check if we got problems on compilation
212
    //check if we got problems on compilation
220
    if (script.IsEmpty())
213
    if (script.IsEmpty())
221
    {
214
    {
222
        // Print errors that happened during compilation.
215
        // Print errors that happened during compilation.
223
        String::AsciiValue error(try_catch.Exception());
216
        String::AsciiValue error(try_catch.Exception());
224
        slog << "Failed to compile script: " << *error << "\n";
217
        slog << "Failed to compile script: " << *error << "\n";
225
        return false;
218
        return false;
226
    }
219
    }
227
    else
220
    else
228
    {
221
    {
229
        //no errors , let's continue
222
        //no errors , let's continue
230
        Handle<Value> result = script->Run();
223
        Handle<Value> result = script->Run();
231
 
224
 
232
        //check if execution ended with errors
225
        //check if execution ended with errors
233
        if (result.IsEmpty())
226
        if (result.IsEmpty())
234
        {
227
        {
235
            // Print errors that happened during execution.
228
            // Print errors that happened during execution.
236
            String::AsciiValue error(try_catch.Exception());
229
            String::AsciiValue error(try_catch.Exception());
237
            slog << "loadScript: Failed to run script: " << *error << "\n";
230
            slog << "loadScript: Failed to run script: " << *error << "\n";
238
            return false;
231
            return false;
239
        }
232
        }
240
    }
233
    }
241
 
234
 
242
    return true;
235
    return true;
243
}
236
}
244
 
237
 
245
void VirtualMachine::callHandleHeartbeat(int hardwareId)
238
void VirtualMachine::callHandleHeartbeat(int hardwareId)
246
{
239
{
247
    const int argc = 1;
240
    const int argc = 1;
248
    Handle<Value> argv[argc] = { Integer::New(hardwareId) };
241
    Handle<Value> argv[argc] = { Integer::New(hardwareId) };
249
 
242
 
250
    Handle<Value> result = myFunctionHandleHeartbeat->Call(myFunctionHandleHeartbeat, argc, argv); // argc and argv are your standard arguments to a function
243
    Handle<Value> result = myFunctionHandleHeartbeat->Call(myFunctionHandleHeartbeat, argc, argv); // argc and argv are your standard arguments to a function
251
}
244
}
Line 256... Line 249...
256
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
249
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
257
                                String::New(canMessage.getDirectionFlag().c_str()),
250
                                String::New(canMessage.getDirectionFlag().c_str()),
258
                                String::New(canMessage.getModuleName().c_str()),
251
                                String::New(canMessage.getModuleName().c_str()),
259
                                Integer::New(canMessage.getModuleId()),
252
                                Integer::New(canMessage.getModuleId()),
260
                                String::New(canMessage.getCommandName().c_str()),
253
                                String::New(canMessage.getCommandName().c_str()),
261
                                String::New(canMessage.getJSONData().c_str()) };
254
                                String::New(canMessage.getJSONData().c_str()) };
262
 
255
 
263
    Handle<Value> result = myFunctionHandleMessage->Call(myFunctionHandleMessage, argc, argv); // argc and argv are your standard arguments to a function
256
    Handle<Value> result = myFunctionHandleMessage->Call(myFunctionHandleMessage, argc, argv); // argc and argv are your standard arguments to a function
264
}
257
}
265
 
258
 
266
int VirtualMachine::setInterval(string expression, int interval, bool single)
259
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
267
{
260
{
268
    IntervalThread intervalThread(expression, interval, single);
261
    IntervalThread intervalThread(timeout);
269
    intervalThread.start();
-
 
270
 
262
 
271
    int timeoutId = myTimers.size();
-
 
272
    myTimers[timeoutId] = intervalThread;
263
    myIntervalThreads[intervalThread.getId()] = intervalThread;
273
    myTimers[timeoutId].start();
264
    myIntervalThreads[intervalThread.getId()].start();
274
 
265
 
275
    return timeoutId;
266
    return intervalThread.getId();
276
}
267
}
277
 
268
 
278
bool VirtualMachine::clearInterval(int timeoutId)
269
bool VirtualMachine::stopIntervalThread(unsigned int id)
279
{
270
{
280
    if (myTimers.find(timeoutId) != myTimers.end())
271
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
281
    {
272
    {
282
        myTimers.erase(timeoutId);
273
        myIntervalThreads.erase(id);
283
        return true;
274
        return true;
284
    }
275
    }
285
 
276
 
286
    return false;
277
    return false;
287
}
278
}
Line 355... Line 346...
355
    String::AsciiValue moduleName(args[2]);
346
    String::AsciiValue moduleName(args[2]);
356
    canMessage.setModuleName(*moduleName);
347
    canMessage.setModuleName(*moduleName);
357
    canMessage.setModuleId(args[3]->Uint32Value());
348
    canMessage.setModuleId(args[3]->Uint32Value());
358
    String::AsciiValue commandName(args[4]);
349
    String::AsciiValue commandName(args[4]);
359
    canMessage.setCommandName(*commandName);
350
    canMessage.setCommandName(*commandName);
360
 
351
 
361
    String::AsciiValue dataString(args[5]);
352
    String::AsciiValue dataString(args[5]);
362
 
353
 
363
    vector<string> parts = explode(",", trim(*dataString, ','));
354
    vector<string> parts = explode(",", trim(*dataString, ','));
364
    map<string, CanVariable> data;
355
    map<string, CanVariable> data;
365
 
356
 
366
    for (int n = 0; n < parts.size(); n++)
357
    for (int n = 0; n < parts.size(); n++)
367
    {
358
    {
368
        vector<string> keyAndValue = explode(":", parts[n]);
359
        vector<string> keyAndValue = explode(":", parts[n]);
369
 
360
 
370
        //string key = trim(keyAndValue[0], ' ');
361
        //string key = trim(keyAndValue[0], ' ');
371
        //string value = trim(keyAndValue[1], ' ');
362
        //string value = trim(keyAndValue[1], ' ');
372
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
363
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
373
    }
364
    }
374
 
365
 
375
    canMessage.setData(data);
366
    canMessage.setData(data);
376
   
367
   
377
    canMan.sendMessage(canMessage);
368
    canMan.sendMessage(canMessage);
378
 
369
 
379
    return Undefined();
370
    return Undefined();
380
}
371
}
381
 
372
 
382
Handle<Value> VirtualMachine_loadScript(const Arguments& args)
373
Handle<Value> VirtualMachine_loadScript(const Arguments& args)
383
{
374
{
384
    VirtualMachine &vm = VirtualMachine::getInstance();
375
    VirtualMachine &vm = VirtualMachine::getInstance();
385
 
376
 
386
    String::AsciiValue str(args[0]);
377
    String::AsciiValue str(args[0]);
387
 
378
 
388
    return Boolean::New(vm.loadScript(*str));
379
    return Boolean::New(vm.loadScript(*str));
389
}
380
}
390
 
381
 
391
Handle<Value> VirtualMachine_setInterval(const Arguments& args)
382
Handle<Value> VirtualMachine_startIntervalThread(const Arguments& args)
392
{
-
 
393
    VirtualMachine &vm = VirtualMachine::getInstance();
-
 
394
 
-
 
395
    String::AsciiValue expression(args[0]);
-
 
396
    unsigned int interval = args[1]->Uint32Value();
-
 
397
 
-
 
398
    return Integer::New(vm.setInterval(*expression, interval, false));
-
 
399
}
-
 
400
 
-
 
401
Handle<Value> VirtualMachine_setTimeout(const Arguments& args)
-
 
402
{
383
{
403
    VirtualMachine &vm = VirtualMachine::getInstance();
384
    VirtualMachine &vm = VirtualMachine::getInstance();
404
 
385
 
405
    String::AsciiValue expression(args[0]);
-
 
406
    unsigned int interval = args[1]->Uint32Value();
386
    unsigned int timeout = args[0]->Uint32Value();
407
 
387
 
408
    return Integer::New(vm.setInterval(*expression, interval, true));
388
    return Integer::New(vm.startIntervalThread(timeout));
409
}
389
}
410
 
390
 
411
Handle<Value> VirtualMachine_clearInterval(const Arguments& args)
391
Handle<Value> VirtualMachine_stopIntervalThread(const Arguments& args)
412
{
392
{
413
    VirtualMachine &vm = VirtualMachine::getInstance();
393
    VirtualMachine &vm = VirtualMachine::getInstance();
414
 
394
 
-
 
395
    unsigned int id = args[1]->Uint32Value();
-
 
396
 
415
    return Boolean::New(vm.clearInterval(args[0]->Uint32Value()));
397
    return Integer::New(vm.stopIntervalThread(id));
416
}
398
}