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