1 //-----------------------------------------------------------------------------
2 //
3 //	Scene.cpp
4 //
5 //	A collection of ValueIDs to be used together.
6 //
7 //	Copyright (c) 2011 Greg Satz <satz@iranger.com>
8 //
9 //	SOFTWARE NOTICE AND LICENSE
10 //
11 //	This file is part of OpenZWave.
12 //
13 //	OpenZWave is free software: you can redistribute it and/or modify
14 //	it under the terms of the GNU Lesser General Public License as published
15 //	by the Free Software Foundation, either version 3 of the License,
16 //	or (at your option) any later version.
17 //
18 //	OpenZWave is distributed in the hope that it will be useful,
19 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
20 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 //	GNU Lesser General Public License for more details.
22 //
23 //	You should have received a copy of the GNU Lesser General Public License
24 //	along with OpenZWave.  If not, see <http://www.gnu.org/licenses/>.
25 //
26 //-----------------------------------------------------------------------------
27 
28 #include <cstring>
29 #include "Manager.h"
30 #include "platform/Log.h"
31 #include "value_classes/Value.h"
32 #include "value_classes/ValueID.h"
33 #include "Scene.h"
34 #include "Options.h"
35 
36 #include "tinyxml.h"
37 
38 namespace OpenZWave
39 {
40 	namespace Internal
41 	{
42 
43 		uint32 const c_sceneVersion = 1;
44 
45 //-----------------------------------------------------------------------------
46 // Statics
47 //-----------------------------------------------------------------------------
48 		uint8 Scene::s_sceneCnt = 0;
49 		Scene* Scene::s_scenes[256] =
50 		{ 0 };
51 
52 //-----------------------------------------------------------------------------
53 // <Scene::Scene>
54 // Constructor
55 //-----------------------------------------------------------------------------
Scene(uint8 const _sceneId)56 		Scene::Scene(uint8 const _sceneId) :
57 				m_sceneId(_sceneId), m_label("")
58 		{
59 			s_scenes[_sceneId] = this;
60 			s_sceneCnt++;
61 		}
62 
63 //-----------------------------------------------------------------------------
64 // <Scene::~Scene>
65 // Destructor
66 //-----------------------------------------------------------------------------
~Scene()67 		Scene::~Scene()
68 		{
69 			while (!m_values.empty())
70 			{
71 				SceneStorage* ss = m_values.back();
72 				m_values.pop_back();
73 				delete ss;
74 			}
75 
76 			s_sceneCnt--;
77 			s_scenes[m_sceneId] = NULL;
78 		}
79 
80 //-----------------------------------------------------------------------------
81 // <Scene::WriteXML>
82 // Write ourselves to an XML document
83 //-----------------------------------------------------------------------------
WriteXML(string const & _name)84 		void Scene::WriteXML(string const& _name)
85 		{
86 			char str[16];
87 
88 			// Create a new XML document to contain the driver configuration
89 			TiXmlDocument doc;
90 			TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", "");
91 			TiXmlElement* scenesElement = new TiXmlElement("Scenes");
92 			doc.LinkEndChild(decl);
93 			doc.LinkEndChild(scenesElement);
94 
95 			scenesElement->SetAttribute("xmlns", "http://code.google.com/p/open-zwave/");
96 
97 			snprintf(str, sizeof(str), "%d", c_sceneVersion);
98 			scenesElement->SetAttribute("version", str);
99 
100 			for (int i = 1; i < 256; i++)
101 			{
102 				if (s_scenes[i] == NULL)
103 				{
104 					continue;
105 				}
106 
107 				TiXmlElement* sceneElement = new TiXmlElement("Scene");
108 
109 				snprintf(str, sizeof(str), "%d", i);
110 				sceneElement->SetAttribute("id", str);
111 				sceneElement->SetAttribute("label", s_scenes[i]->m_label.c_str());
112 
113 				for (vector<SceneStorage*>::iterator vt = s_scenes[i]->m_values.begin(); vt != s_scenes[i]->m_values.end(); ++vt)
114 				{
115 					TiXmlElement* valueElement = new TiXmlElement("Value");
116 
117 					snprintf(str, sizeof(str), "0x%.8x", (*vt)->m_id.GetHomeId());
118 					valueElement->SetAttribute("homeId", str);
119 
120 					snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetNodeId());
121 					valueElement->SetAttribute("nodeId", str);
122 
123 					valueElement->SetAttribute("genre", Internal::VC::Value::GetGenreNameFromEnum((*vt)->m_id.GetGenre()));
124 
125 					snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetCommandClassId());
126 					valueElement->SetAttribute("commandClassId", str);
127 
128 					snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetInstance());
129 					valueElement->SetAttribute("instance", str);
130 
131 					snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetIndex());
132 					valueElement->SetAttribute("index", str);
133 
134 					valueElement->SetAttribute("type", Internal::VC::Value::GetTypeNameFromEnum((*vt)->m_id.GetType()));
135 
136 					TiXmlText* textElement = new TiXmlText((*vt)->m_value.c_str());
137 					valueElement->LinkEndChild(textElement);
138 
139 					sceneElement->LinkEndChild(valueElement);
140 				}
141 
142 				scenesElement->LinkEndChild(sceneElement);
143 			}
144 
145 			string userPath;
146 			Options::Get()->GetOptionAsString("UserPath", &userPath);
147 
148 			string filename = userPath + _name;
149 
150 			doc.SaveFile(filename.c_str());
151 		}
152 
153 //-----------------------------------------------------------------------------
154 // <Scene::ReadScene>
155 // Read scene configuration from an XML document
156 //-----------------------------------------------------------------------------
ReadScenes()157 		bool Scene::ReadScenes()
158 		{
159 			int32 intVal;
160 			char const* str;
161 
162 			// Load the XML document that contains the driver configuration
163 			string userPath;
164 			Options::Get()->GetOptionAsString("UserPath", &userPath);
165 
166 			string filename = userPath + "zwscene.xml";
167 
168 			TiXmlDocument doc;
169 			if (!doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8))
170 			{
171 				return false;
172 			}
173 
174 			TiXmlElement const* scenesElement = doc.RootElement();
175 
176 			// Version
177 			if (TIXML_SUCCESS == scenesElement->QueryIntAttribute("version", &intVal))
178 			{
179 				if ((uint32) intVal != c_sceneVersion)
180 				{
181 					Log::Write(LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str());
182 					return false;
183 				}
184 			}
185 			else
186 			{
187 				Log::Write(LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str());
188 				return false;
189 			}
190 
191 			TiXmlElement const* sceneElement = scenesElement->FirstChildElement();
192 			while (sceneElement)
193 			{
194 				Scene* scene = NULL;
195 
196 				if (TIXML_SUCCESS == sceneElement->QueryIntAttribute("id", &intVal))
197 				{
198 					scene = new Scene((uint8) intVal);
199 				}
200 
201 				if (scene == NULL)
202 				{
203 					continue;
204 				}
205 
206 				str = sceneElement->Attribute("label");
207 				if (str)
208 				{
209 					scene->m_label = str;
210 				}
211 
212 				// Read the ValueId for this scene
213 				TiXmlElement const* valueElement = sceneElement->FirstChildElement();
214 				while (valueElement)
215 				{
216 					char const* elementName = valueElement->Value();
217 					if (elementName && !strcmp(elementName, "Value"))
218 					{
219 						uint32 homeId = 0;
220 						str = valueElement->Attribute("homeId");
221 						if (str)
222 						{
223 							char *p;
224 							homeId = (uint32) strtol(str, &p, 0);
225 						}
226 						uint8 nodeId = 0;
227 						if (TIXML_SUCCESS == valueElement->QueryIntAttribute("nodeId", &intVal))
228 						{
229 							nodeId = intVal;
230 						}
231 						ValueID::ValueGenre genre = Internal::VC::Value::GetGenreEnumFromName(valueElement->Attribute("genre"));
232 						uint8 commandClassId = 0;
233 						if (TIXML_SUCCESS == valueElement->QueryIntAttribute("commandClassId", &intVal))
234 						{
235 							commandClassId = intVal;
236 						}
237 						uint8 instance = 0;
238 						if (TIXML_SUCCESS == valueElement->QueryIntAttribute("instance", &intVal))
239 						{
240 							instance = intVal;
241 						}
242 						uint8 index = 0;
243 						if (TIXML_SUCCESS == valueElement->QueryIntAttribute("index", &intVal))
244 						{
245 							index = intVal;
246 						}
247 						ValueID::ValueType type = Internal::VC::Value::GetTypeEnumFromName(valueElement->Attribute("type"));
248 						char const* data = valueElement->GetText();
249 
250 						scene->m_values.push_back(new SceneStorage(ValueID(homeId, nodeId, genre, commandClassId, instance, index, type), data));
251 					}
252 
253 					valueElement = valueElement->NextSiblingElement();
254 				}
255 				sceneElement = sceneElement->NextSiblingElement();
256 			}
257 			return true;
258 		}
259 
260 //-----------------------------------------------------------------------------
261 // <Scene::Get>
262 // Return the Scene object given the Scene Id
263 //-----------------------------------------------------------------------------
Get(uint8 const _sceneId)264 		Scene* Scene::Get(uint8 const _sceneId)
265 		{
266 			if (s_scenes[_sceneId] != NULL)
267 			{
268 				return s_scenes[_sceneId];
269 			}
270 			return NULL;
271 		}
272 
273 //-----------------------------------------------------------------------------
274 // <Scene::GetAllScenes>
275 // Return an array of uint8 of used Scene IDs and the count
276 //-----------------------------------------------------------------------------
GetAllScenes(uint8 ** _sceneIds)277 		uint8 Scene::GetAllScenes(uint8** _sceneIds)
278 		{
279 			if (s_sceneCnt > 0)
280 			{
281 				*_sceneIds = new uint8[s_sceneCnt];
282 				int j = 0;
283 				for (int i = 1; i < 256; i++)
284 				{
285 					if (s_scenes[i] != NULL)
286 					{
287 						(*_sceneIds)[j++] = s_scenes[i]->m_sceneId;
288 					}
289 				}
290 			}
291 			return s_sceneCnt;
292 		}
293 
294 //-----------------------------------------------------------------------------
295 // <Scene::AddValue>
296 // Add a ValueID and a string to the scene.
297 //-----------------------------------------------------------------------------
AddValue(ValueID const & _valueId,string const & _value)298 		bool Scene::AddValue(ValueID const& _valueId, string const& _value)
299 		{
300 			m_values.push_back(new SceneStorage(_valueId, _value));
301 			return true;
302 		}
303 
304 //-----------------------------------------------------------------------------
305 // <Scene::RemoveValue>
306 // Remove the first ValueID found
307 //-----------------------------------------------------------------------------
RemoveValue(ValueID const & _valueId)308 		bool Scene::RemoveValue(ValueID const& _valueId)
309 		{
310 			for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
311 			{
312 				if ((*it)->m_id == _valueId)
313 				{
314 					delete *it;
315 					m_values.erase(it);
316 					return true;
317 				}
318 			}
319 			return false;
320 		}
321 
322 //-----------------------------------------------------------------------------
323 // <Scene::RemoveValues>
324 // Remove all ValueIDs from given Home ID
325 //-----------------------------------------------------------------------------
RemoveValues(uint32 const _homeId)326 		void Scene::RemoveValues(uint32 const _homeId)
327 		{
328 			again: for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
329 			{
330 				if ((*it)->m_id.GetHomeId() == _homeId)
331 				{
332 					delete *it;
333 					m_values.erase(it);
334 					goto again;
335 				}
336 			}
337 			// If the scene is now empty, delete it.
338 			if (m_values.empty())
339 			{
340 				delete this;
341 			}
342 		}
343 
344 //-----------------------------------------------------------------------------
345 // <Scene::RemoveValues>
346 // Remove all ValueIDs from given Home ID and node ID
347 //-----------------------------------------------------------------------------
RemoveValues(uint32 const _homeId,uint8 const _nodeId)348 		void Scene::RemoveValues(uint32 const _homeId, uint8 const _nodeId)
349 		{
350 			for (int i = 1; i < 256; i++)
351 			{
352 				Scene *scene = Scene::Get(i);
353 				if (scene != NULL)
354 				{
355 					again: for (vector<SceneStorage*>::iterator it = scene->m_values.begin(); it != scene->m_values.end(); ++it)
356 					{
357 						if ((*it)->m_id.GetHomeId() == _homeId && (*it)->m_id.GetNodeId() == _nodeId)
358 						{
359 							delete *it;
360 							scene->m_values.erase(it);
361 							goto again;
362 						}
363 					}
364 					// If the scene is now empty, delete it.
365 					if (scene->m_values.empty())
366 					{
367 						delete scene;
368 					}
369 				}
370 			}
371 		}
372 
373 //-----------------------------------------------------------------------------
374 // <Scene::GetValues>
375 // Return all ValueIDs for the given scene.
376 //-----------------------------------------------------------------------------
GetValues(vector<ValueID> * o_value)377 		int Scene::GetValues(vector<ValueID>* o_value)
378 		{
379 			int size = (int) m_values.size();
380 			if (size > 0)
381 			{
382 				for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
383 				{
384 					o_value->push_back((*it)->m_id);
385 				}
386 			}
387 			return size;
388 		}
389 
390 //-----------------------------------------------------------------------------
391 // <Scene::GetValue>
392 // Return a ValueID's value as string
393 //-----------------------------------------------------------------------------
GetValue(ValueID const & _valueId,string * o_value)394 		bool Scene::GetValue(ValueID const& _valueId, string* o_value)
395 		{
396 			for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
397 			{
398 				if ((*it)->m_id == _valueId)
399 				{
400 					*o_value = (*it)->m_value;
401 					return true;
402 				}
403 			}
404 			return false;
405 		}
406 
407 //-----------------------------------------------------------------------------
408 // <Scene::SetValue>
409 // Set a ValueID's value as string
410 //-----------------------------------------------------------------------------
SetValue(ValueID const & _valueId,string const & _value)411 		bool Scene::SetValue(ValueID const& _valueId, string const& _value)
412 		{
413 			for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
414 			{
415 				if ((*it)->m_id == _valueId)
416 				{
417 					(*it)->m_value = _value;
418 					return true;
419 				}
420 			}
421 			return false;
422 		}
423 
424 //-----------------------------------------------------------------------------
425 // <Scene::Activate>
426 // Execute scene activation by running each ValueId/value
427 //-----------------------------------------------------------------------------
Activate()428 		bool Scene::Activate()
429 		{
430 			bool res = true;
431 			for (vector<SceneStorage*>::iterator it = m_values.begin(); it != m_values.end(); ++it)
432 			{
433 				if (!Manager::Get()->SetValue((*it)->m_id, (*it)->m_value))
434 				{
435 					res = false;
436 				}
437 			}
438 			return res;
439 		}
440 	} // namespace Internal
441 } // namespace OpenZWave
442