Subversion Repositories HomeAutomation

Rev

Rev 995 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 995 Rev 997
1
/***************************************************************************
1
/***************************************************************************
2
 *   Copyright (C) December 10, 2008 by Mattias Runge                             *
2
 *   Copyright (C) December 10, 2008 by Mattias Runge                             *
3
 *   mattias@runge.se                                                      *
3
 *   mattias@runge.se                                                      *
4
 *   virtualmachine.cpp                                            *
4
 *   virtualmachine.cpp                                            *
5
 *                                                                         *
5
 *                                                                         *
6
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   This program is free software; you can redistribute it and/or modify  *
7
 *   it under the terms of the GNU General Public License as published by  *
7
 *   it under the terms of the GNU General Public License as published by  *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 *   (at your option) any later version.                                   *
9
 *   (at your option) any later version.                                   *
10
 *                                                                         *
10
 *                                                                         *
11
 *   This program is distributed in the hope that it will be useful,       *
11
 *   This program is distributed in the hope that it will be useful,       *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU General Public License for more details.                          *
14
 *   GNU General Public License for more details.                          *
15
 *                                                                         *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU General Public License     *
16
 *   You should have received a copy of the GNU General Public License     *
17
 *   along with this program; if not, write to the                         *
17
 *   along with this program; if not, write to the                         *
18
 *   Free Software Foundation, Inc.,                                       *
18
 *   Free Software Foundation, Inc.,                                       *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20
 ***************************************************************************/
20
 ***************************************************************************/
21
 
21
 
22
#include "virtualmachine.h"
22
#include "virtualmachine.h"
23
 
23
 
24
VirtualMachine* VirtualMachine::myInstance = NULL;
24
VirtualMachine* VirtualMachine::myInstance = NULL;
25
 
25
 
26
VirtualMachine& VirtualMachine::getInstance()
26
VirtualMachine& VirtualMachine::getInstance()
27
{
27
{
28
    if (myInstance == NULL)
28
    if (myInstance == NULL)
29
    {
29
    {
30
        myInstance = new VirtualMachine();
30
        myInstance = new VirtualMachine();
31
    }
31
    }
32
 
32
 
33
    return *myInstance;
33
    return *myInstance;
34
}
34
}
35
 
35
 
36
void VirtualMachine::deleteInstance()
36
void VirtualMachine::deleteInstance()
37
{
37
{
38
    if (myInstance != NULL)
38
    if (myInstance != NULL)
39
    {
39
    {
40
        delete myInstance;
40
        delete myInstance;
41
        myInstance = NULL;
41
        myInstance = NULL;
42
    }
42
    }
43
}
43
}
44
 
44
 
45
VirtualMachine::VirtualMachine()
45
VirtualMachine::VirtualMachine()
46
{
46
{
47
    Thread<VirtualMachine>();
-
 
48
}
47
}
49
 
48
 
50
VirtualMachine::~VirtualMachine()
49
VirtualMachine::~VirtualMachine()
51
{
50
{
52
    stop();
51
    stop();
-
 
52
 
-
 
53
    ///FIXME: Verify that this works and does not cause segfaults
-
 
54
    for (map<int, SocketThread*>::iterator iter = mySocketThreads.begin(); iter != mySocketThreads.end(); iter++)
-
 
55
    {
-
 
56
        delete iter->second;
-
 
57
        mySocketThreads.erase(iter);
-
 
58
    }
53
}
59
}
54
 
60
 
55
void VirtualMachine::run()
61
void VirtualMachine::run()
56
{
62
{
57
    SyslogStream &slog = SyslogStream::getInstance();
-
 
58
 
-
 
59
    string basePath = Settings::get("BasePath") + "Services/";
-
 
60
    string scriptName = "Base.js";
-
 
61
    string scriptFileName = basePath + "System/" + scriptName;
-
 
62
 
-
 
63
    if (!file_exists(scriptFileName))
-
 
64
    {
-
 
65
        slog << "Failed to load :" + scriptFileName + "\n";
-
 
66
    }
-
 
67
 
-
 
68
    string scriptSource = file_get_contents(scriptFileName);
-
 
69
 
-
 
70
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
-
 
71
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
-
 
72
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
-
 
73
 
-
 
74
    // Create a template for the global object.
-
 
75
    myGlobal = ObjectTemplate::New();
63
    myGlobal = ObjectTemplate::New();
76
 
-
 
77
    //associates "print" on script to the Print function
-
 
78
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine_log));
64
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine_log));
79
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine_sendCanMessage));
65
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine_sendCanMessage));
80
    myGlobal->Set(String::New("sendCanNMTMessage"), FunctionTemplate::New(VirtualMachine_sendCanNMTMessage));
66
    myGlobal->Set(String::New("sendCanNMTMessage"), FunctionTemplate::New(VirtualMachine_sendCanNMTMessage));
81
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine_loadScript));
67
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine_loadScript));
82
    myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine_startIntervalThread));
68
    myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine_startIntervalThread));
83
    myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine_stopIntervalThread));
69
    myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine_stopIntervalThread));
84
    myGlobal->Set(String::New("startSocketThread"), FunctionTemplate::New(VirtualMachine_startSocketThread));
70
    myGlobal->Set(String::New("startSocketThread"), FunctionTemplate::New(VirtualMachine_startSocketThread));
85
    myGlobal->Set(String::New("stopSocketThread"), FunctionTemplate::New(VirtualMachine_stopSocketThread));
71
    myGlobal->Set(String::New("stopSocketThread"), FunctionTemplate::New(VirtualMachine_stopSocketThread));
86
    myGlobal->Set(String::New("sendToSocketThread"), FunctionTemplate::New(VirtualMachine_sendToSocketThread));
72
    myGlobal->Set(String::New("sendToSocketThread"), FunctionTemplate::New(VirtualMachine_sendToSocketThread));
87
    myGlobal->Set(String::New("uint2hex"), FunctionTemplate::New(VirtualMachine_uint2hex));
73
    myGlobal->Set(String::New("uint2hex"), FunctionTemplate::New(VirtualMachine_uint2hex));
88
 
-
 
89
    //create context for the script
-
 
90
    myContext = Context::New(NULL, myGlobal);
74
    myContext = Context::New(NULL, myGlobal);
91
 
75
 
92
 
76
 
93
    //access global context within this scope
-
 
94
    Context::Scope context_scope(myContext);
-
 
95
    //exception handler
-
 
96
    TryCatch tryCatch;
-
 
97
    //compile script to binary code - JIT
-
 
98
    Handle<Script> script = Script::Compile(source, name);
-
 
99
 
-
 
100
    //check if we got problems on compilation
-
 
101
    if (script.IsEmpty())
-
 
102
    {
-
 
103
        printException(&tryCatch);
-
 
104
        slog << "\n";
-
 
105
        return;
-
 
106
    }
-
 
107
    else
-
 
108
    {
-
 
109
        //no errors , let's continue
-
 
110
        Handle<Value> result = script->Run();
-
 
111
 
-
 
112
        //check if execution ended with errors
-
 
113
        if (result.IsEmpty())
-
 
114
        {
-
 
115
            printException(&tryCatch);
-
 
116
            slog << "\n";
-
 
117
            return;
-
 
118
        }
-
 
119
        else
-
 
120
        {
-
 
121
            loadScript("System/Startup.js");
77
    if (loadScript("System/Base.js"))
122
 
-
 
123
            if (file_exists(basePath + "Autostart.js"))
-
 
124
            {
78
    {
-
 
79
        loadScript("System/Startup.js");
-
 
80
 
125
                loadScript("Autostart.js");
81
        loadScript("Autostart.js");
126
            }
82
 
-
 
83
        Context::Scope contextScope(myContext);
127
           
84
 
128
            myFunctionHandleNMTMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleNMTMessage")));
85
        myFunctionHandleNMTMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleNMTMessage")));
129
            myFunctionOfflineCheck = Handle<Function>::Cast(myContext->Global()->Get(String::New("offlineCheck")));
86
        myFunctionOfflineCheck = Handle<Function>::Cast(myContext->Global()->Get(String::New("offlineCheck")));
130
            myFunctionHandleMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleMessage")));
87
        myFunctionHandleMessage = Handle<Function>::Cast(myContext->Global()->Get(String::New("handleMessage")));
131
            myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
88
        myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
132
        }
89
    }
-
 
90
    else
-
 
91
    {
-
 
92
        ///FIXME: We should probably exit the application here
-
 
93
        return;
133
    }
94
    }
134
 
95
 
135
    const int argc = 0;
96
    const int argc = 0;
136
    Handle<Value> argv[argc] = { };
97
    Handle<Value> argv[argc] = { };
137
 
-
 
138
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv); // argc and argv are your standard arguments to a function
98
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv);
139
 
99
 
140
    mySemaphore.lock();
100
    mySemaphore.lock();
141
 
101
 
142
    while (1)
-
 
143
    {
-
 
144
        string expression;
102
    string expression;
-
 
103
    CanMessage canMessage;
145
 
104
 
-
 
105
    while (true)
-
 
106
    {
146
        while (myExpressions.size() > 0)
107
        while (myExpressions.size() > 0)
147
        {
108
        {
148
            expression = myExpressions.pop();
109
            expression = myExpressions.pop();
-
 
110
            runExpression(expression);
-
 
111
        }
-
 
112
 
-
 
113
        while (myCanMessages.size() > 0)
-
 
114
        {
-
 
115
            canMessage = myCanMessages.pop();
149
 
116
 
-
 
117
            if (canMessage.getClassName() == "nmt")
-
 
118
            {
-
 
119
                expression = "handleNMTMessage(";
-
 
120
                expression += "'" + canMessage.getClassName() + "', ";
-
 
121
                expression += "'" + canMessage.getCommandName() + "', ";
-
 
122
                expression += canMessage.getJSONData();
-
 
123
                expression += ");";
-
 
124
                runExpression(expression);
-
 
125
            }
-
 
126
            else
-
 
127
            {
-
 
128
                expression = "handleMessage(";
-
 
129
                expression += "'" + canMessage.getClassName() + "', ";
-
 
130
                expression += "'" + canMessage.getDirectionFlag() + "', ";
-
 
131
                expression += "'" + canMessage.getModuleName() + "', ";
-
 
132
                expression += "" + itos(canMessage.getModuleId()) + ", ";
-
 
133
                expression += "'" + canMessage.getCommandName() + "', ";
-
 
134
                expression += canMessage.getJSONData();
-
 
135
                expression += ");";
150
            runExpression(expression);
136
                runExpression(expression);
151
        }
137
            }
152
 
-
 
153
        CanMessage canMessage;
-
 
154
 
-
 
155
        while (myCanMessages.size() > 0)
-
 
156
        {
-
 
157
            canMessage = myCanMessages.pop();
-
 
158
 
-
 
159
            if (canMessage.getClassName() == "nmt")
-
 
160
            {
-
 
161
                callHandleNMTMessage(canMessage);
-
 
162
            }
-
 
163
            else
-
 
164
            {
-
 
165
                callHandleMessage(canMessage);
-
 
166
            }
-
 
167
        }
138
        }
168
 
139
 
169
        mySemaphore.wait();
140
        mySemaphore.wait();
170
    }
141
    }
171
 
142
 
172
    mySemaphore.unlock();
143
    mySemaphore.unlock();
173
}
144
}
174
 
145
 
175
void VirtualMachine::queueCanMessage(CanMessage canMessage)
146
void VirtualMachine::queueCanMessage(CanMessage canMessage)
176
{
147
{
177
    myCanMessages.push(canMessage);
148
    myCanMessages.push(canMessage);
178
    mySemaphore.broadcast();
149
    mySemaphore.broadcast();
179
}
150
}
180
 
151
 
181
void VirtualMachine::queueExpression(string expression)
152
void VirtualMachine::queueExpression(string expression)
182
{
153
{
183
    myExpressions.push(expression);
154
    myExpressions.push(expression);
184
    mySemaphore.broadcast();
155
    mySemaphore.broadcast();
185
}
156
}
186
 
157
 
187
bool VirtualMachine::loadScript(string scriptName)
158
bool VirtualMachine::loadScript(string scriptName)
188
{
159
{
189
    SyslogStream &slog = SyslogStream::getInstance();
160
    SyslogStream &slog = SyslogStream::getInstance();
190
 
161
 
191
    string basePath = Settings::get("BasePath") + "Services/";
162
    string basePath = Settings::get("BasePath") + "Services/";
192
    string scriptFileName = basePath + scriptName;
163
    string scriptFileName = basePath + scriptName;
193
 
164
 
194
    if (!file_exists(scriptFileName))
165
    if (!file_exists(scriptFileName))
195
    {
166
    {
196
        slog << "Failed to load " + scriptFileName + "\n";
167
        slog << "Failed to load " + scriptFileName + ", file does not exist.\n";
197
        return false;
168
        return false;
198
    }
169
    }
199
 
170
 
200
    string scriptSource = file_get_contents(scriptFileName);
171
    string scriptSource = file_get_contents(scriptFileName);
201
 
172
 
202
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
173
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
203
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
-
 
204
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
174
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
205
 
175
 
206
    //access global context within this scope
-
 
207
    Context::Scope context_scope(myContext);
176
    Context::Scope contextScope(myContext);
208
    //exception handler
-
 
-
 
177
 
209
    TryCatch tryCatch;
178
    TryCatch tryCatch;
210
    //compile script to binary code - JIT
-
 
-
 
179
 
211
    Handle<Script> script = Script::Compile(source, name);
180
    Handle<Script> script = Script::Compile(source, name);
212
 
181
 
213
    //check if we got problems on compilation
-
 
214
    if (script.IsEmpty())
182
    if (script.IsEmpty())
215
    {
183
    {
216
        printException(&tryCatch);
184
        printException(&tryCatch);
217
        slog << "\n";
-
 
218
        return false;
185
        return false;
219
    }
186
    }
220
    else
187
    else
221
    {
188
    {
222
        //no errors , let's continue
-
 
223
        Handle<Value> result = script->Run();
189
        Handle<Value> result = script->Run();
224
 
190
 
225
        //check if execution ended with errors
-
 
226
        if (result.IsEmpty())
191
        if (result.IsEmpty())
227
        {
192
        {
228
            printException(&tryCatch);
193
            printException(&tryCatch);
229
            slog << "\n";
-
 
230
            return false;
194
            return false;
231
        }
195
        }
232
 
196
 
233
        slog << "Loaded " + scriptName + "\n";
197
        slog << "Loaded " + scriptName + "\n";
234
    }
198
    }
235
 
199
 
236
    return true;
200
    return true;
237
}
201
}
238
 
202
 
239
void VirtualMachine::callHandleNMTMessage(CanMessage canMessage)
203
void VirtualMachine::callHandleNMTMessage(CanMessage canMessage)
240
{
204
{
241
    const int argc = 3;
205
    const int argc = 3;
242
 
206
 
243
    string jsonData = canMessage.getJSONData();
207
    string jsonData = canMessage.getJSONData();
244
 
208
 
245
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
209
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
246
                                String::New(canMessage.getCommandName().c_str()),
210
                                String::New(canMessage.getCommandName().c_str()),
247
                                String::New(jsonData.c_str()) };
211
                                String::New(jsonData.c_str()) };
248
 
212
 
249
    Handle<Value> result = myFunctionHandleNMTMessage->Call(myFunctionHandleNMTMessage, argc, argv); // argc and argv are your standard arguments to a function
213
    Handle<Value> result = myFunctionHandleNMTMessage->Call(myFunctionHandleNMTMessage, argc, argv); // argc and argv are your standard arguments to a function
250
}
214
}
251
 
215
 
252
void VirtualMachine::callHandleMessage(CanMessage canMessage)
216
void VirtualMachine::callHandleMessage(CanMessage canMessage)
253
{
217
{
254
    const int argc = 6;
218
    const int argc = 6;
255
 
219
 
256
    string jsonData = canMessage.getJSONData();
220
    string jsonData = canMessage.getJSONData();
257
 
221
 
258
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
222
    Handle<Value> argv[argc] = {String::New(canMessage.getClassName().c_str()),
259
                                String::New(canMessage.getDirectionFlag().c_str()),
223
                                String::New(canMessage.getDirectionFlag().c_str()),
260
                                String::New(canMessage.getModuleName().c_str()),
224
                                String::New(canMessage.getModuleName().c_str()),
261
                                Integer::New(canMessage.getModuleId()),
225
                                Integer::New(canMessage.getModuleId()),
262
                                String::New(canMessage.getCommandName().c_str()),
226
                                String::New(canMessage.getCommandName().c_str()),
263
                                String::New(jsonData.c_str()) };
227
                                String::New(jsonData.c_str()) };
264
 
228
 
265
    Handle<Value> result = myFunctionHandleMessage->Call(myFunctionHandleMessage, argc, argv); // argc and argv are your standard arguments to a function
229
    Handle<Value> result = myFunctionHandleMessage->Call(myFunctionHandleMessage, argc, argv); // argc and argv are your standard arguments to a function
266
}
230
}
267
 
231
 
268
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
232
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
269
{
233
{
270
    IntervalThread intervalThread(timeout);
234
    IntervalThread intervalThread(timeout);
271
 
235
 
272
    myIntervalThreads[intervalThread.getId()] = intervalThread;
236
    myIntervalThreads[intervalThread.getId()] = intervalThread;
273
    myIntervalThreads[intervalThread.getId()].start();
237
    myIntervalThreads[intervalThread.getId()].start();
274
 
238
 
275
    return intervalThread.getId();
239
    return intervalThread.getId();
276
}
240
}
277
 
241
 
278
bool VirtualMachine::stopIntervalThread(unsigned int id)
242
bool VirtualMachine::stopIntervalThread(unsigned int id)
279
{
243
{
280
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
244
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
281
    {
245
    {
282
        myIntervalThreads.erase(id);
246
        myIntervalThreads.erase(id);
283
        return true;
247
        return true;
284
    }
248
    }
285
 
249
 
286
    return false;
250
    return false;
287
}
251
}
288
 
252
 
289
unsigned int VirtualMachine::startSocketThread(string address, int port, unsigned int reconnectTimeout)
253
unsigned int VirtualMachine::startSocketThread(string address, int port, unsigned int reconnectTimeout)
290
{
254
{
291
    SocketThread *socketThread = new SocketThread(address, port, reconnectTimeout);
255
    SocketThread *socketThread = new SocketThread(address, port, reconnectTimeout);
292
    mySocketThreads[socketThread->getId()] = socketThread;
256
    mySocketThreads[socketThread->getId()] = socketThread;
293
    mySocketThreads[socketThread->getId()]->start();
257
    mySocketThreads[socketThread->getId()]->start();
294
 
258
 
295
    return socketThread->getId();
259
    return socketThread->getId();
296
}
260
}
297
 
261
 
298
bool VirtualMachine::stopSocketThread(unsigned int id)
262
bool VirtualMachine::stopSocketThread(unsigned int id)
299
{
263
{
300
   
-
 
301
 
-
 
302
    if (mySocketThreads.find(id) != mySocketThreads.end())
264
    if (mySocketThreads.find(id) != mySocketThreads.end())
303
    {
265
    {
304
        //mySocketThreads[id]->stop();
-
 
305
        delete mySocketThreads[id];
266
        delete mySocketThreads[id];
306
 
267
 
307
        mySocketThreads.erase(id);
268
        mySocketThreads.erase(id);
308
        return true;
269
        return true;
309
    }
270
    }
310
 
271
 
311
    return false;
272
    return false;
312
}
273
}
313
 
274
 
314
void VirtualMachine::sendToSocketThread(unsigned int id, string data)
275
void VirtualMachine::sendToSocketThread(unsigned int id, string data)
315
{
276
{
316
    if (mySocketThreads.find(id) != mySocketThreads.end())
277
    if (mySocketThreads.find(id) != mySocketThreads.end())
317
    {
278
    {
318
        mySocketThreads[id]->send(data);
279
        mySocketThreads[id]->send(data);
319
    }
280
    }
320
}
281
}
321
 
282
 
322
bool VirtualMachine::runExpression(string expression)
283
bool VirtualMachine::runExpression(string expression)
323
{
284
{
324
    SyslogStream &slog = SyslogStream::getInstance();
-
 
325
 
-
 
326
    string scriptName = "runExpression";
285
    string scriptName = "runExpression";
327
 
286
 
328
    Handle<String> source =  String::New(expression.c_str(), expression.length());
287
    Handle<String> source =  String::New(expression.c_str(), expression.length());
329
    //each script name must be unique , for this demo I just run one embedded script, so the name can be fixed
-
 
330
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
288
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
331
 
289
 
332
    //access global context within this scope
-
 
333
    Context::Scope context_scope(myContext);
290
    Context::Scope contextScope(myContext);
334
    //exception handler
-
 
-
 
291
 
335
    TryCatch tryCatch;
292
    TryCatch tryCatch;
336
    //compile script to binary code - JIT
-
 
-
 
293
 
337
    Handle<Script> script = Script::Compile(source, name);
294
    Handle<Script> script = Script::Compile(source, name);
338
 
295
 
339
    //check if we got problems on compilation
-
 
340
    if (script.IsEmpty())
296
    if (script.IsEmpty())
341
    {
297
    {
342
        printException(&tryCatch);
298
        printException(&tryCatch);
343
        slog << "\n";
-
 
344
        return false;
299
        return false;
345
    }
300
    }
346
    else
301
    else
347
    {
302
    {
348
        //no errors , let's continue
-
 
349
        Handle<Value> result = script->Run();
303
        Handle<Value> result = script->Run();
350
 
304
 
351
        //check if execution ended with errors
-
 
352
        if (result.IsEmpty())
305
        if (result.IsEmpty())
353
        {
306
        {
354
            printException(&tryCatch);
307
            printException(&tryCatch);
355
            slog << "\n";
-
 
356
            return false;
308
            return false;
357
        }
309
        }
358
    }
310
    }
359
 
311
 
360
    return true;
312
    return true;
361
}
313
}
362
 
314
 
363
void VirtualMachine::printException(TryCatch* tryCatch)
315
void VirtualMachine::printException(TryCatch* tryCatch)
364
{
316
{
365
    SyslogStream &slog = SyslogStream::getInstance();
317
    SyslogStream &slog = SyslogStream::getInstance();
366
 
318
 
367
    HandleScope handle_scope;
319
    HandleScope handleScope;
368
    String::Utf8Value exception(tryCatch->Exception());
320
    String::Utf8Value exception(tryCatch->Exception());
369
    Handle<v8::Message> message = tryCatch->Message();
321
    Handle<v8::Message> message = tryCatch->Message();
370
 
322
 
371
    string strException = *exception;
323
    string strException = *exception;
372
 
324
 
373
    if (message.IsEmpty())
325
    if (message.IsEmpty())
374
    {
326
    {
375
        // V8 didn't provide any extra information about this error; just print the exception.
-
 
376
        slog << strException + "\n";
327
        slog << strException + "\n\n";
377
    }
328
    }
378
    else
329
    else
379
    {
330
    {
380
        // Print (filename):(line number): (message).
-
 
381
        String::Utf8Value filename(message->GetScriptResourceName());
331
        String::Utf8Value filename(message->GetScriptResourceName());
382
        int linenum = message->GetLineNumber();
-
 
383
 
-
 
384
        string strFilename = *filename;
332
        string strFilename = *filename;
385
       
333
       
386
        slog << strFilename + ":" + itos(linenum) + ": " + strException + "\n";
334
        slog << strFilename + ":" + itos(message->GetLineNumber()) + ": " + strException + "\n";
387
 
335
 
388
        // Print line of source code.
-
 
389
        String::Utf8Value sourceline(message->GetSourceLine());
336
        String::Utf8Value sourceline(message->GetSourceLine());
390
 
-
 
391
        string strSourceline = *sourceline;
337
        string strSourceline = *sourceline;
392
 
338
 
393
        slog << strSourceline + "\n";
339
        slog << strSourceline + "\n";
394
 
340
 
395
        string underline;
-
 
396
        // Print wavy underline (GetUnderline is deprecated).
-
 
397
        int start = message->GetStartColumn();
341
        string underline = rpad("", message->GetStartColumn(), ' ');
398
        for (int i = 0; i < start; i++)
-
 
399
        {
-
 
400
            underline += " ";
-
 
401
        }
-
 
402
 
-
 
403
        int end = message->GetEndColumn();
342
        underline = rpad(underline, message->GetEndColumn(), '^');
404
        for (int i = start; i < end; i++)
-
 
405
        {
-
 
406
            underline += "^";
-
 
407
        }
-
 
408
 
343
 
409
        slog << underline + "\n";
344
        slog << underline + "\n\n";
410
    }
345
    }
411
}
346
}
412
 
347
 
413
 
348
 
414
Handle<Value> VirtualMachine_log(const Arguments& args)
349
Handle<Value> VirtualMachine_log(const Arguments& args)
415
{
350
{
416
    SyslogStream &slog = SyslogStream::getInstance();
351
    SyslogStream &slog = SyslogStream::getInstance();
417
 
352
 
418
    String::AsciiValue str(args[0]);
353
    String::AsciiValue str(args[0]);
419
 
354
 
420
    slog << *str;
355
    slog << *str;
421
 
356
 
422
    return Undefined();
357
    return Undefined();
423
}
358
}
424
 
359
 
425
Handle<Value> VirtualMachine_sendCanMessage(const Arguments& args)
360
Handle<Value> VirtualMachine_sendCanMessage(const Arguments& args)
426
{
361
{
427
    //SyslogStream &slog = SyslogStream::getInstance();
-
 
428
    CanNetManager &canMan = CanNetManager::getInstance();
362
    CanNetManager &canMan = CanNetManager::getInstance();
429
 
363
 
430
    CanMessage canMessage;
364
    CanMessage canMessage;
431
 
365
 
432
    String::AsciiValue className(args[0]);
366
    String::AsciiValue className(args[0]);
433
    canMessage.setClassName(*className);
367
    canMessage.setClassName(*className);
434
    String::AsciiValue directionFlag(args[1]);
368
    String::AsciiValue directionFlag(args[1]);
435
    canMessage.setDirectionFlag(*directionFlag);
369
    canMessage.setDirectionFlag(*directionFlag);
436
    String::AsciiValue moduleName(args[2]);
370
    String::AsciiValue moduleName(args[2]);
437
    canMessage.setModuleName(*moduleName);
371
    canMessage.setModuleName(*moduleName);
438
    canMessage.setModuleId(args[3]->Uint32Value());
372
    canMessage.setModuleId(args[3]->Uint32Value());
439
    String::AsciiValue commandName(args[4]);
373
    String::AsciiValue commandName(args[4]);
440
    canMessage.setCommandName(*commandName);
374
    canMessage.setCommandName(*commandName);
441
 
375
 
442
    String::AsciiValue dataString(args[5]);
376
    String::AsciiValue dataString(args[5]);
443
 
377
 
444
    vector<string> parts = explode(",", trim(*dataString, ','));
378
    vector<string> parts = explode(",", trim(*dataString, ','));
445
    map<string, CanVariable> data;
379
    map<string, CanVariable> data;
446
 
380
 
447
    for (int n = 0; n < parts.size(); n++)
381
    for (int n = 0; n < parts.size(); n++)
448
    {
382
    {
449
        vector<string> keyAndValue = explode(":", parts[n]);
383
        vector<string> keyAndValue = explode(":", parts[n]);
450
 
384
 
451
        //string key = trim(keyAndValue[0], ' ');
-
 
452
        //string value = trim(keyAndValue[1], ' ');
-
 
453
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
385
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
454
    }
386
    }
455
 
387
 
456
    canMessage.setData(data);
388
    canMessage.setData(data);
457
   
389
   
458
    canMan.sendMessage(canMessage);
390
    canMan.sendMessage(canMessage);
459
 
391
 
460
    return Undefined();
392
    return Undefined();
461
}
393
}
462
 
394
 
463
Handle<Value> VirtualMachine_sendCanNMTMessage(const Arguments& args)
395
Handle<Value> VirtualMachine_sendCanNMTMessage(const Arguments& args)
464
{
396
{
465
    //SyslogStream &slog = SyslogStream::getInstance();
-
 
466
    CanNetManager &canMan = CanNetManager::getInstance();
397
    CanNetManager &canMan = CanNetManager::getInstance();
467
 
398
 
468
    CanMessage canMessage;
399
    CanMessage canMessage;
469
 
400
 
470
    String::AsciiValue className(args[0]);
401
    String::AsciiValue className(args[0]);
471
    canMessage.setClassName(*className);
402
    canMessage.setClassName(*className);
472
    String::AsciiValue commandName(args[1]);
403
    String::AsciiValue commandName(args[1]);
473
    canMessage.setCommandName(*commandName);
404
    canMessage.setCommandName(*commandName);
474
 
405
 
475
    String::AsciiValue dataString(args[2]);
406
    String::AsciiValue dataString(args[2]);
476
 
407
 
477
    vector<string> parts = explode(",", trim(*dataString, ','));
408
    vector<string> parts = explode(",", trim(*dataString, ','));
478
    map<string, CanVariable> data;
409
    map<string, CanVariable> data;
479
 
410
 
480
    for (int n = 0; n < parts.size(); n++)
411
    for (int n = 0; n < parts.size(); n++)
481
    {
412
    {
482
        vector<string> keyAndValue = explode(":", parts[n]);
413
        vector<string> keyAndValue = explode(":", parts[n]);
483
 
414
 
484
        //string key = trim(keyAndValue[0], ' ');
-
 
485
        //string value = trim(keyAndValue[1], ' ');
-
 
486
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
415
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
487
    }
416
    }
488
 
417
 
489
    canMessage.setData(data);
418
    canMessage.setData(data);
490
 
419
 
491
    canMan.sendMessage(canMessage);
420
    canMan.sendMessage(canMessage);
492
 
421
 
493
    return Undefined();
422
    return Undefined();
494
}
423
}
495
 
424
 
496
Handle<Value> VirtualMachine_loadScript(const Arguments& args)
425
Handle<Value> VirtualMachine_loadScript(const Arguments& args)
497
{
426
{
498
    VirtualMachine &vm = VirtualMachine::getInstance();
427
    VirtualMachine &vm = VirtualMachine::getInstance();
499
 
428
 
500
    String::AsciiValue str(args[0]);
429
    String::AsciiValue str(args[0]);
501
 
430
 
502
    return Boolean::New(vm.loadScript(*str));
431
    return Boolean::New(vm.loadScript(*str));
503
}
432
}
504
 
433
 
505
Handle<Value> VirtualMachine_startIntervalThread(const Arguments& args)
434
Handle<Value> VirtualMachine_startIntervalThread(const Arguments& args)
506
{
435
{
507
    VirtualMachine &vm = VirtualMachine::getInstance();
436
    VirtualMachine &vm = VirtualMachine::getInstance();
508
 
437
 
509
    unsigned int timeout = args[0]->Uint32Value();
438
    unsigned int timeout = args[0]->Uint32Value();
510
 
439
 
511
    return Integer::New(vm.startIntervalThread(timeout));
440
    return Integer::New(vm.startIntervalThread(timeout));
512
}
441
}
513
 
442
 
514
Handle<Value> VirtualMachine_stopIntervalThread(const Arguments& args)
443
Handle<Value> VirtualMachine_stopIntervalThread(const Arguments& args)
515
{
444
{
516
    VirtualMachine &vm = VirtualMachine::getInstance();
445
    VirtualMachine &vm = VirtualMachine::getInstance();
517
 
446
 
518
    unsigned int id = args[0]->Uint32Value();
447
    unsigned int id = args[0]->Uint32Value();
519
 
448
 
520
    return Boolean::New(vm.stopIntervalThread(id));
449
    return Boolean::New(vm.stopIntervalThread(id));
521
}
450
}
522
 
451
 
523
Handle<Value> VirtualMachine_startSocketThread(const Arguments& args)
452
Handle<Value> VirtualMachine_startSocketThread(const Arguments& args)
524
{
453
{
525
    VirtualMachine &vm = VirtualMachine::getInstance();
454
    VirtualMachine &vm = VirtualMachine::getInstance();
526
 
455
 
527
    String::AsciiValue address(args[0]);
456
    String::AsciiValue address(args[0]);
528
    int port = args[1]->Uint32Value();
457
    int port = args[1]->Uint32Value();
529
    unsigned int reconnectTimeout = args[2]->Uint32Value();
458
    unsigned int reconnectTimeout = args[2]->Uint32Value();
530
 
459
 
531
    return Integer::New(vm.startSocketThread(*address, port, reconnectTimeout));
460
    return Integer::New(vm.startSocketThread(*address, port, reconnectTimeout));
532
}
461
}
533
 
462
 
534
Handle<Value> VirtualMachine_stopSocketThread(const Arguments& args)
463
Handle<Value> VirtualMachine_stopSocketThread(const Arguments& args)
535
{
464
{
536
    VirtualMachine &vm = VirtualMachine::getInstance();
465
    VirtualMachine &vm = VirtualMachine::getInstance();
537
 
466
 
538
    unsigned int id = args[0]->Uint32Value();
467
    unsigned int id = args[0]->Uint32Value();
539
 
468
 
540
    return Boolean::New(vm.stopSocketThread(id));
469
    return Boolean::New(vm.stopSocketThread(id));
541
}
470
}
542
 
471
 
543
Handle<Value> VirtualMachine_sendToSocketThread(const Arguments& args)
472
Handle<Value> VirtualMachine_sendToSocketThread(const Arguments& args)
544
{
473
{
545
    VirtualMachine &vm = VirtualMachine::getInstance();
474
    VirtualMachine &vm = VirtualMachine::getInstance();
546
 
475
 
547
    unsigned int id = args[0]->Uint32Value();
476
    unsigned int id = args[0]->Uint32Value();
548
    String::AsciiValue data(args[1]);
477
    String::AsciiValue data(args[1]);
549
 
478
 
550
    vm.sendToSocketThread(id, *data);
479
    vm.sendToSocketThread(id, *data);
551
 
480
 
552
    return Undefined();
481
    return Undefined();
553
}
482
}
554
 
483
 
555
Handle<Value> VirtualMachine_uint2hex(const Arguments& args)
484
Handle<Value> VirtualMachine_uint2hex(const Arguments& args)
556
{
485
{
557
    VirtualMachine &vm = VirtualMachine::getInstance();
486
    VirtualMachine &vm = VirtualMachine::getInstance();
558
 
487
 
559
    unsigned int id = args[0]->Uint32Value();
488
    unsigned int id = args[0]->Uint32Value();
560
    unsigned int length = args[1]->Uint32Value();
489
    unsigned int length = args[1]->Uint32Value();
561
    string hexId = uint2hex(id, length);
490
    string hexId = uint2hex(id, length);
562
 
491
 
563
    return String::New(hexId.c_str());
492
    return String::New(hexId.c_str());
564
}
493
}
565
 
494
 
566
 
495