OSDN Git Service

9f6babbea7c718b2baa643d86676f30c535707c0
[dennco/dennco.git] / Source / DNEngine.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 //
17 //  Created by tkawata on 1/28/2012.
18 //
19
20
21 #include "TKLock.h"
22 #include "TKContainer.h"
23 #include "TKUICell.h"
24 #include "DNTimeKeeper.h"
25 #include "DNServerHTTP.h"
26 #include "DNServerSerialPort.h"
27 #include "TKContainer.h"
28 #include "DNContainerBuilder.h"
29 #include "DNEngine.h"
30 #include "DNAlert.h"
31 #include "DNXML.h"
32 #include "DNXMLElement.h"
33 #include "DNGlobal.h"
34 #include "DNUtils.h"
35 #include "TKLog.h"
36
37 #include <stdlib.h>
38 #include <sstream>
39 #include <iostream>
40
41 DNEngine::DNEngine(const char *contentPath) :
42     mContainer(NULL),mPortNumber(9080),mHTTPServer(NULL),mSerialServer(NULL),mValid(false), mDoTickThread(NULL)
43 {
44     mTimeKeeper = new DNTimeKeeper();
45     mContainer = TKContainer::createContainer();
46     mUIPath = "/ui/index.html";
47
48     dnGlobal()->updateRunningStatus(DNGlobal::STOPPED);
49
50     std::string basePath(contentPath);
51     std::string containerRoot = basePath;
52     containerRoot.append("/Container");
53     
54     bool succeeded = false;
55     succeeded = parseSettingFile(contentPath);
56     if (!succeeded || !dnGlobal()->isErrorStatusNormal())
57     {
58         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
59         {
60             dnGlobal()->setMessage1("property.xml parse error");
61             dnGlobal()->setMessage2("failed to parse setting file /property.xml");
62         }
63         else
64         {
65             dnGlobal()->setMessage1("property.xml parse error");
66         }
67         return;
68     }
69
70     std::string dataStorePath = containerRoot;
71     dataStorePath.append("/data.db");
72
73     succeeded = mContainer->setDataStore(dataStorePath.c_str());
74     if (!succeeded)
75     {
76         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
77         {
78             dnGlobal()->setMessage1("Initialization failed");
79             dnGlobal()->setMessage2("Failed to the setup data store");
80         }
81         else
82         {
83             dnGlobal()->setMessage1("Initialization failed");
84         }
85         return;
86     }
87
88     succeeded = parseContainerFile(containerRoot.c_str());
89     if (!succeeded)
90     {
91         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
92         {
93             dnGlobal()->setMessage1("Initialization failed");
94             dnGlobal()->setMessage2("Failed to parse container file");
95         }
96         else
97         {
98             dnGlobal()->setMessage1("Initialization failed");
99         }
100         return;
101     }
102
103     mValid = true;
104 }
105
106 DNEngine::~DNEngine()
107 {
108     mValid = false;
109     
110     if (mContainer)
111     {
112         delete mContainer;
113         mContainer = NULL;
114     }
115         
116     if (mHTTPServer)
117     {
118         delete mHTTPServer;
119         mHTTPServer = NULL;
120     }
121     
122     if (mTimeKeeper)
123     {
124         delete mTimeKeeper;
125         mTimeKeeper = NULL;
126     }
127 }
128
129
130 bool DNEngine::parseSettingFile(const char *contentRoot)
131 {
132     bool valid = false;
133
134     DNXML *xml = DNXML::createXMLFromFile(contentRoot, "property.xml");
135     if (xml)
136     {
137         valid = true;
138         DNXMLElement *element = xml->getRoot();
139         if (!element)
140         {
141             valid = false;
142             std::string message = "Failed to load property.xml file";
143             TKLog::printf("ERROR wile loading property.xml file.\n%s\n",message.c_str());
144             if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
145             {
146                 dnGlobal()->setMessage1("Initialization failed");
147                 dnGlobal()->setMessage2(message);
148             }
149             else
150             {
151                 dnGlobal()->setMessage1("Initialization failed");
152             }
153         }
154
155         if (valid && element->name != "dennco")
156         {
157             valid = false;
158             std::string message = "First element of property.xml should be <dennco>";
159             TKLog::printf("ERROR wile parsing property.xml file.\n%s\n",message.c_str());
160             if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
161             {
162                 dnGlobal()->setMessage1("Initialization failed");
163                 dnGlobal()->setMessage2(message);
164             }
165             else
166             {
167                 dnGlobal()->setMessage1("Initialization failed");
168             }
169         }
170
171         if (valid)
172         {
173             DNXMLElement *e = element->inner;
174             while(e)
175             {
176                 if (e->name == "TickIntervalSec")
177                 {
178                     std::istringstream is(e->text);
179                     float t = 0.0;
180                     is >> t;
181                     if (t>0)
182                     {
183                         setTickIntervalSec(t);
184                     }
185                     else
186                     {
187                         valid = false;
188                         std::string message = "Error in property.xml. TickIntervalSec is not configured properly.";
189                         TKLog::printf("ERROR wile parsing property.xml file.\n%s\n",message.c_str());
190                         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
191                         {
192                             dnGlobal()->setMessage1("Initialization failed");
193                             dnGlobal()->setMessage2(message);
194                         }
195                         else
196                         {
197                             dnGlobal()->setMessage1("Initialization failed");
198                         }
199                     }
200                 }
201                 else if (e->name == "UIPath")
202                 {
203                     mUIPath = e->text;
204                 }
205                 else if (e->name == "EnableHTTPServer")
206                 {
207
208                 }
209                 else if (e->name == "EnableSerialServer")
210                 {
211
212                 }
213                 e = e->next;
214             }
215         }
216
217         delete xml;
218     }
219     return valid;
220 }
221
222 bool DNEngine::parseContainerFile(const char *containerRoot)
223 {
224     DNContainerBuilder builder(mContainer);
225     return builder.buildContainerFromXHTML(containerRoot);
226 }
227
228
229 bool DNEngine::startHTTPServer(int portNumber)
230 {
231     if (mHTTPServer && mHTTPServer->isRunning())
232     {
233         mHTTPServer->stop();
234         delete mHTTPServer;
235         mHTTPServer = NULL;
236     }
237     mHTTPServer = new DNServerHTTP(this);
238     if (mHTTPServer)
239     {
240         mHTTPServer->setPortNumber(portNumber);
241         mHTTPServer->start();
242     }
243     return true;
244 }
245
246 void DNEngine::stopHTTPServer()
247 {
248     if (mHTTPServer && mHTTPServer->isRunning())
249     {
250         mHTTPServer->stop();
251         delete mHTTPServer;
252         mHTTPServer = NULL;
253     }    
254 }
255
256 bool DNEngine::startSerialServer()
257 {
258     if (mSerialServer && mSerialServer->isRunning())
259     {
260         mSerialServer->stop();
261         delete mSerialServer;
262         mSerialServer = NULL;
263     }
264     mSerialServer = new DNServerSerialPort(this);
265     if (mSerialServer)
266     {
267         if (mSerialServer->setup())
268         {
269             mSerialServer->start();
270             return true;
271         }
272         else
273         {
274             return false;
275         }
276     }
277     return false;
278 }
279
280 void DNEngine::stopSerialServer()
281 {
282     if (mSerialServer && mSerialServer->isRunning())
283     {
284         mSerialServer->stop();
285         delete mSerialServer;
286         mSerialServer = NULL;
287     }
288 }
289
290 void DNEngine::setTickIntervalSec(float interval)
291 {
292     if (mTimeKeeper)
293         mTimeKeeper->setIntevalSec(interval);
294 }
295
296 bool DNEngine::startEngine()
297 {
298     if (!mDoTickThread)
299         mDoTickThread = DNThread::createThread(DNEngine::doTickThread, this);
300
301     return mDoTickThread->start();
302 }
303
304 bool DNEngine::stopEngine()
305 {
306     bool r = false;
307     dnGlobal()->updateRunningStatus(DNGlobal::STOPPING);
308     if (mDoTickThread)
309     {
310         r = mDoTickThread->waitForExit(5000);
311         delete mDoTickThread;
312         mDoTickThread = NULL;
313     }
314     if (mContainer)
315     {
316         mContainer->doDestroy();
317         mContainer->releaseDataStore();
318     }
319
320     return r;
321 }
322
323 void DNEngine::doTickThread(void *self)
324 {
325     if (!dnGlobal()->updateRunningStatus(DNGlobal::RUNNIING))
326     {
327         return;
328     }
329
330     DNEngine *engine = (DNEngine*)self;
331     
332     while(dnGlobal()->getRunningStatus() == DNGlobal::RUNNIING && engine->isValid())
333     {
334         engine->mContainer->doTick(engine->mTimeKeeper->getTickTime());
335         engine->mTimeKeeper->sleepUntilNextInterval();
336     }
337
338     dnGlobal()->updateRunningStatus(DNGlobal::STOPPED);
339 }
340
341 float DNEngine::doClientGetRequest(const char* path)
342 {
343     std::string fqn = getFQNString("/",path);
344     TKUICell *cell = (TKUICell*)mContainer->getInterfaceCell(fqn);
345     float result = 0;
346     if (cell)
347     {
348         result = cell->getValue();
349     }
350     return result;
351 }
352
353 bool DNEngine::doClientSetRequest(const char* path, const char* value)
354 {
355     return doClientSetRequest(path, atof(value));
356 }
357
358 bool DNEngine::doClientSetRequest(const char* path, float value)
359 {
360     std::string fqn = getFQNString("/",path);
361     TKUICell *cell = (TKUICell*)mContainer->getInterfaceCell(fqn);
362     bool result = false;
363     if (cell)
364     {
365         cell->setValue(value);
366         result = true;
367     }
368     return result;
369 }
370
371 std::string DNEngine::getContentPath()
372 {
373     if (mContainer)
374         return mContainer->getContentPath();
375     else
376         return "";
377 }
378
379 std::string DNEngine::getUIPath()
380 {
381     return mUIPath;
382 }