bool ZWaveController::ExposeValue(ValueID v){ return true; switch (v.GetGenre()){ case ValueID::ValueGenre::ValueGenre_Basic: case ValueID::ValueGenre::ValueGenre_User: case ValueID::ValueGenre::ValueGenre_Config: return true; case ValueID::ValueGenre::ValueGenre_System: case ValueID::ValueGenre::ValueGenre_Count: default: return false; } }
/* * MyNode::removeValue * Per notification, remove value from node. */ void MyNode::removeValue (ValueID id) { vector<MyValue*>::iterator it; bool found = false; for (it = values.begin(); it != values.end(); it++) { if ((*it)->id == id) { delete *it; values.erase(it); found = true; break; } } if (!found) fprintf(stderr, "removeValue not found Home 0x%08x Node %d Genre %s Class %s Instance %d Index %d Type %s\n", id.GetHomeId(), id.GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); setTime(time(NULL)); setChanged(true); }
//----------------------------------------------------------------------------- // <OnNotification> // Callback that is triggered when a value, group or node changes //----------------------------------------------------------------------------- void OnNotification (Notification const* _notification, void* _context) { ValueID id = _notification->GetValueID(); switch (_notification->GetType()) { case Notification::Type_ValueAdded: Log::Write(LogLevel_Info, "Notification: Value Added Home 0x%08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->addValue(id); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Type_ValueRemoved: Log::Write(LogLevel_Info, "Notification: Value Removed Home 0x%08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->removeValue(id); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Type_ValueChanged: Log::Write(LogLevel_Info, "Notification: Value Changed Home 0x%08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->saveValue(id); pthread_mutex_unlock(&nlock); break; case Notification::Type_ValueRefreshed: Log::Write(LogLevel_Info, "Notification: Value Refreshed Home 0x%08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Type_Group: { Log::Write(LogLevel_Info, "Notification: Group Home 0x%08x Node %d Group %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetGroupIdx()); uint8 *v = NULL; int8 n = Manager::Get()->GetAssociations(homeId, _notification->GetNodeId(), _notification->GetGroupIdx(), &v); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->addGroup(_notification->GetNodeId(), _notification->GetGroupIdx(), n, v); pthread_mutex_unlock(&nlock); if (v != NULL) delete [] v; } break; case Notification::Type_NodeNew: Log::Write(LogLevel_Info, "Notification: Node New Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&glock); needsave = true; pthread_mutex_unlock(&glock); break; case Notification::Type_NodeAdded: Log::Write(LogLevel_Info, "Notification: Node Added Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); new MyNode(_notification->GetNodeId()); pthread_mutex_unlock(&nlock); pthread_mutex_lock(&glock); needsave = true; pthread_mutex_unlock(&glock); break; case Notification::Type_NodeRemoved: Log::Write(LogLevel_Info, "Notification: Node Removed Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); MyNode::remove(_notification->GetNodeId()); pthread_mutex_unlock(&nlock); pthread_mutex_lock(&glock); needsave = true; pthread_mutex_unlock(&glock); break; case Notification::Type_NodeProtocolInfo: Log::Write(LogLevel_Info, "Notification: Node Protocol Info Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->saveValue(id); pthread_mutex_unlock(&nlock); pthread_mutex_lock(&glock); needsave = true; pthread_mutex_unlock(&glock); break; case Notification::Type_NodeNaming: Log::Write(LogLevel_Info, "Notification: Node Naming Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->saveValue(id); pthread_mutex_unlock(&nlock); break; case Notification::Type_NodeEvent: Log::Write(LogLevel_Info, "Notification: Node Event Home %08x Node %d Status %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetEvent(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->saveValue(id); pthread_mutex_unlock(&nlock); break; case Notification::Type_PollingDisabled: Log::Write(LogLevel_Info, "Notification: Polling Disabled Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); //pthread_mutex_lock(&nlock); //nodes[_notification->GetNodeId()]->setPolled(false); //pthread_mutex_unlock(&nlock); break; case Notification::Type_PollingEnabled: Log::Write(LogLevel_Info, "Notification: Polling Enabled Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType())); //pthread_mutex_lock(&nlock); //nodes[_notification->GetNodeId()]->setPolled(true); //pthread_mutex_unlock(&nlock); break; case Notification::Type_SceneEvent: Log::Write(LogLevel_Info, "Notification: Scene Event Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s Scene Id %d", _notification->GetHomeId(), _notification->GetNodeId(), valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(), id.GetIndex(), valueTypeStr(id.GetType()), _notification->GetSceneId()); break; case Notification::Type_CreateButton: Log::Write(LogLevel_Info, "Notification: Create button Home %08x Node %d Button %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetButtonId()); break; case Notification::Type_DeleteButton: Log::Write(LogLevel_Info, "Notification: Delete button Home %08x Node %d Button %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetButtonId()); break; case Notification::Type_ButtonOn: Log::Write(LogLevel_Info, "Notification: Button On Home %08x Node %d Button %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetButtonId()); break; case Notification::Type_ButtonOff: Log::Write(LogLevel_Info, "Notification: Button Off Home %08x Node %d Button %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetButtonId()); break; case Notification::Type_DriverReady: Log::Write(LogLevel_Info, "Notification: Driver Ready, homeId %08x, nodeId %d", _notification->GetHomeId(), _notification->GetNodeId()); pthread_mutex_lock(&glock); homeId = _notification->GetHomeId(); nodeId = _notification->GetNodeId(); if (Manager::Get()->IsStaticUpdateController(homeId)) { cmode = "SUC"; SUCnodeId = Manager::Get()->GetSUCNodeId(homeId); } else if (Manager::Get()->IsPrimaryController(homeId)) cmode = "Primary"; else cmode = "Slave"; pthread_mutex_unlock(&glock); break; case Notification::Type_DriverFailed: Log::Write(LogLevel_Info, "Notification: Driver Failed, homeId %08x", _notification->GetHomeId()); pthread_mutex_lock(&glock); done = false; needsave = false; homeId = 0; cmode = ""; pthread_mutex_unlock(&glock); pthread_mutex_lock(&nlock); for (int i = 1; i < MAX_NODES; i++) MyNode::remove(i); pthread_mutex_unlock(&nlock); break; case Notification::Type_DriverReset: Log::Write(LogLevel_Info, "Notification: Driver Reset, homeId %08x", _notification->GetHomeId()); pthread_mutex_lock(&glock); done = false; needsave = true; homeId = _notification->GetHomeId(); if (Manager::Get()->IsStaticUpdateController(homeId)) { cmode = "SUC"; SUCnodeId = Manager::Get()->GetSUCNodeId(homeId); } else if (Manager::Get()->IsPrimaryController(homeId)) cmode = "Primary"; else cmode = "Slave"; pthread_mutex_unlock(&glock); pthread_mutex_lock(&nlock); for (int i = 1; i < MAX_NODES; i++) MyNode::remove(i); pthread_mutex_unlock(&nlock); break; case Notification::Type_EssentialNodeQueriesComplete: Log::Write(LogLevel_Info, "Notification: Essential Node %d Queries Complete", _notification->GetNodeId()); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Type_NodeQueriesComplete: Log::Write(LogLevel_Info, "Notification: Node %d Queries Complete", _notification->GetNodeId()); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->sortValues(); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); pthread_mutex_lock(&glock); needsave = true; pthread_mutex_unlock(&glock); break; case Notification::Type_AwakeNodesQueried: Log::Write(LogLevel_Info, "Notification: Awake Nodes Queried"); break; case Notification::Type_AllNodesQueriedSomeDead: Log::Write(LogLevel_Info, "Notification: Awake Nodes Queried Some Dead"); break; case Notification::Type_AllNodesQueried: Log::Write(LogLevel_Info, "Notification: All Nodes Queried"); break; case Notification::Type_Notification: switch (_notification->GetNotification()) { case Notification::Code_MsgComplete: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Message Complete", _notification->GetHomeId(), _notification->GetNodeId()); break; case Notification::Code_Timeout: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Timeout", _notification->GetHomeId(), _notification->GetNodeId()); break; case Notification::Code_NoOperation: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d No Operation Message Complete", _notification->GetHomeId(), _notification->GetNodeId()); pthread_mutex_lock(&glock); noop = true; pthread_mutex_unlock(&glock); break; case Notification::Code_Awake: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Awake", _notification->GetHomeId(), _notification->GetNodeId()); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Code_Sleep: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Sleep", _notification->GetHomeId(), _notification->GetNodeId()); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; case Notification::Code_Dead: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Dead", _notification->GetHomeId(), _notification->GetNodeId()); pthread_mutex_lock(&nlock); nodes[_notification->GetNodeId()]->setTime(time(NULL)); nodes[_notification->GetNodeId()]->setChanged(true); pthread_mutex_unlock(&nlock); break; default: Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Unknown %d", _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetNotification()); break; } break; case Notification::Type_ControllerCommand: Log::Write(LogLevel_Info, "Notification: ControllerCommand home %08x Event %d Error %d", _notification->GetHomeId(), _notification->GetEvent(), _notification->GetNotification()); pthread_mutex_lock(&nlock); web_controller_update((OpenZWave::Driver::ControllerState)_notification->GetEvent(), (OpenZWave::Driver::ControllerError)_notification->GetNotification(), (void *)_context); pthread_mutex_unlock(&nlock); break; default: Log::Write(LogLevel_Info, "Notification: type %d home %08x node %d genre %d class %d instance %d index %d type %d", _notification->GetType(), _notification->GetHomeId(), _notification->GetNodeId(), id.GetGenre(), id.GetCommandClassId(), id.GetInstance(), id.GetIndex(), id.GetType()); break; } }
void OnNotification(Notification const* _notification, void* _context) { // Must do this inside a critical section to avoid conflicts with the main thread pthread_mutex_lock(&g_criticalSection); switch (_notification->GetType()) { case Notification::Type_ValueAdded: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { // Add the new value to our list nodeInfo->m_values.push_back(_notification->GetValueID()); } break; } case Notification::Type_ValueRemoved: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { // Remove the value from out list for (list<ValueID>::iterator it = nodeInfo->m_values.begin(); it != nodeInfo->m_values.end(); ++it) { if ((*it) == _notification->GetValueID()) { nodeInfo->m_values.erase(it); break; } } } break; } case Notification::Type_ValueChanged: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { // One of the node values has changed // TBD... ValueID id = _notification->GetValueID(); string str; printf("Notification Value Changed: Value Changed Home 0x%08x Node %d Genre %d Class %d Instance %d Index %d Type %d\n", _notification->GetHomeId(), _notification->GetNodeId(), id.GetGenre(), id.GetCommandClassId(), id.GetInstance(), id.GetIndex(), id.GetType()); if (Manager::Get()->GetValueAsString(id, &str)) { int level = 0; printf("Values: %s\n", str.c_str()); level = atoi(str.c_str()); nodeInfo->m_level = level; //printf("Node %d Level %d\n",id, level); //printf("Node %s value %d\n", uuidstr , level); } } break; } case Notification::Type_Group: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { // One of the node's association groups has changed // TBD... nodeInfo = nodeInfo; } break; } case Notification::Type_NodeAdded: { // Add the new node to our list NodeInfo* nodeInfo = new NodeInfo(); nodeInfo->m_homeId = _notification->GetHomeId(); nodeInfo->m_nodeId = _notification->GetNodeId(); nodeInfo->m_polled = false; g_nodes.push_back(nodeInfo); break; } case Notification::Type_NodeRemoved: { // Remove the node from our list uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); for (list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it) { NodeInfo* nodeInfo = *it; if ((nodeInfo->m_homeId == homeId) && (nodeInfo->m_nodeId == nodeId)) { g_nodes.erase(it); break; } } break; } case Notification::Type_NodeEvent: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { // We have received an event from the node, caused by a // basic_set or hail message. // TBD... nodeInfo = nodeInfo; nodeInfo->m_level = _notification->GetByte(); printf("\n\n\nReceived Node Event with value %s\n\n\n", nodeInfo->m_level); } break; } case Notification::Type_PollingDisabled: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { nodeInfo->m_polled = false; } break; } case Notification::Type_PollingEnabled: { if (NodeInfo * nodeInfo = GetNodeInfo(_notification)) { nodeInfo->m_polled = true; } break; } case Notification::Type_DriverReady: { g_homeId = _notification->GetHomeId(); break; } case Notification::Type_DriverFailed: { g_initFailed = true; pthread_cond_broadcast(&initCond); break; } case Notification::Type_AwakeNodesQueried: case Notification::Type_AllNodesQueried: { pthread_cond_broadcast(&initCond); break; } default: { } } pthread_mutex_unlock(&g_criticalSection); }
json_spirit::Object ZWaveController::GetValueInfo(ValueID v){ int home_id = (int)v.GetHomeId(); int node_id = (int)v.GetNodeId(); string product_name = Manager::Get()->GetNodeProductName(home_id, node_id); string product_id = Manager::Get()->GetNodeProductId(home_id, node_id); string product_type = Manager::Get()->GetNodeProductType(home_id, node_id); string node_type = Manager::Get()->GetNodeType(home_id, node_id); json_spirit::Object prop_info; prop_info.push_back(json_spirit::Pair("node_id", node_id)); prop_info.push_back(json_spirit::Pair("node_type", node_type)); prop_info.push_back(json_spirit::Pair("product_name", product_name)); prop_info.push_back(json_spirit::Pair("product_id", product_id)); prop_info.push_back(json_spirit::Pair("product_type", product_type)); uint64 vid = v.GetId(); string s_vid = boost::lexical_cast<string>(vid); prop_info.push_back(json_spirit::Pair("value_id", s_vid)); prop_info.push_back(json_spirit::Pair("label", Manager::Get()->GetValueLabel(v))); prop_info.push_back(json_spirit::Pair("help_text", Manager::Get()->GetValueHelp(v))); bool bool_prop_value; uint8 int8_prop_value; int32 int32_prop_value; string s_int32_prop_value; int16 int16_prop_value; string str_prop_value; switch (v.GetType()){ case ValueID::ValueType::ValueType_Bool: prop_info.push_back(json_spirit::Pair("type", "bool")); prop_info.push_back(json_spirit::Pair("type_help", "0/1, true/false, on/off")); Manager::Get()->GetValueAsBool(v, &bool_prop_value); prop_info.push_back(json_spirit::Pair("value", bool_prop_value)); break; case ValueID::ValueType::ValueType_Byte: prop_info.push_back(json_spirit::Pair("type", "byte")); prop_info.push_back(json_spirit::Pair("type_help", "number from 0 to 255")); Manager::Get()->GetValueAsByte(v, &int8_prop_value); prop_info.push_back(json_spirit::Pair("value", int8_prop_value)); break; case ValueID::ValueType::ValueType_Short: prop_info.push_back(json_spirit::Pair("type", "short")); prop_info.push_back(json_spirit::Pair("type_help", "number from 0 to 65,535")); Manager::Get()->GetValueAsShort(v, &int16_prop_value); prop_info.push_back(json_spirit::Pair("value", int16_prop_value)); break; case ValueID::ValueType::ValueType_Decimal: case ValueID::ValueType::ValueType_Int: prop_info.push_back(json_spirit::Pair("type", "int32")); prop_info.push_back(json_spirit::Pair("type_help", "number from 0 to 4,294,967,295")); Manager::Get()->GetValueAsInt(v, &int32_prop_value); // do all this checking below because of a bug in openzwave: https://code.google.com/p/open-zwave/issues/detail?id=382 s_int32_prop_value = boost::lexical_cast<string>(int32_prop_value); Manager::Get()->GetValueAsString(v, &str_prop_value); if (boost::iequals(s_int32_prop_value, str_prop_value)){ // bug did not happen prop_info.push_back(json_spirit::Pair("value", int32_prop_value)); } else { // bug DID happen prop_info.push_back(json_spirit::Pair("value", str_prop_value)); } break; case ValueID::ValueType::ValueType_List: { prop_info.push_back(json_spirit::Pair("type", "list")); prop_info.push_back(json_spirit::Pair("type_help", "list")); Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("value", str_prop_value)); std::vector<string> list_options; Manager::Get()->GetValueListItems(v, &list_options); std::vector<json_spirit::Value> values; for (std::vector<string>::iterator i = list_options.begin(); i != list_options.end(); ++i){ string opt = *i; values.push_back(opt); } prop_info.push_back(json_spirit::Pair("list_options", values)); break; } case ValueID::ValueType::ValueType_Schedule: prop_info.push_back(json_spirit::Pair("type", "schedule")); prop_info.push_back(json_spirit::Pair("type_help", "schedule")); Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("value", str_prop_value)); break; case ValueID::ValueType::ValueType_String: prop_info.push_back(json_spirit::Pair("type", "string")); prop_info.push_back(json_spirit::Pair("type_help", "string")); Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("value", str_prop_value)); break; case ValueID::ValueType::ValueType_Button: prop_info.push_back(json_spirit::Pair("type", "button")); prop_info.push_back(json_spirit::Pair("type_help", "button (string)")); Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("value", str_prop_value)); break; case ValueID::ValueType::ValueType_Raw: prop_info.push_back(json_spirit::Pair("type", "raw")); prop_info.push_back(json_spirit::Pair("type_help", "raw (string)")); Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("value", str_prop_value)); break; default: prop_info.push_back(json_spirit::Pair("type", "unknown")); prop_info.push_back(json_spirit::Pair("type_help", "unknown")); prop_info.push_back(json_spirit::Pair("value", "")); break; } Manager::Get()->GetValueAsString(v, &str_prop_value); prop_info.push_back(json_spirit::Pair("string value", str_prop_value)); prop_info.push_back(json_spirit::Pair("max", Manager::Get()->GetValueMax(v))); prop_info.push_back(json_spirit::Pair("min", Manager::Get()->GetValueMin(v))); prop_info.push_back(json_spirit::Pair("units", Manager::Get()->GetValueUnits(v))); prop_info.push_back(json_spirit::Pair("is_polled", Manager::Get()->IsValuePolled(v))); prop_info.push_back(json_spirit::Pair("read_only", Manager::Get()->IsValueReadOnly(v))); prop_info.push_back(json_spirit::Pair("write_only", Manager::Get()->IsValueWriteOnly(v))); prop_info.push_back(json_spirit::Pair("has_been_set", Manager::Get()->IsValueSet(v))); switch (v.GetGenre()){ case ValueID::ValueGenre::ValueGenre_Basic: prop_info.push_back(json_spirit::Pair("genre", "basic")); break; case ValueID::ValueGenre::ValueGenre_User: prop_info.push_back(json_spirit::Pair("genre", "user")); break; case ValueID::ValueGenre::ValueGenre_Config: prop_info.push_back(json_spirit::Pair("genre", "config")); break; case ValueID::ValueGenre::ValueGenre_System: prop_info.push_back(json_spirit::Pair("genre", "system")); break; case ValueID::ValueGenre::ValueGenre_Count: prop_info.push_back(json_spirit::Pair("genre", "count")); break; default: prop_info.push_back(json_spirit::Pair("genre", "unknown")); break; } return prop_info; }
//----------------------------------------------------------------------------- // <OnNotification> // Callback that is triggered when a value, group or node changes //----------------------------------------------------------------------------- void OnNotification ( Notification const* _notification, void* _context ) { qpid::types::Variant::Map eventmap; // Must do this inside a critical section to avoid conflicts with the main thread pthread_mutex_lock( &g_criticalSection ); switch( _notification->GetType() ) { case Notification::Type_ValueAdded: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Add the new value to our list nodeInfo->m_values.push_back( _notification->GetValueID() ); uint8 basic = Manager::Get()->GetNodeBasic(_notification->GetHomeId(),_notification->GetNodeId()); uint8 generic = Manager::Get()->GetNodeGeneric(_notification->GetHomeId(),_notification->GetNodeId()); uint8 specific = Manager::Get()->GetNodeSpecific(_notification->GetHomeId(),_notification->GetNodeId()); ValueID id = _notification->GetValueID(); string label = Manager::Get()->GetValueLabel(id); stringstream tempstream; tempstream << (int) _notification->GetNodeId(); tempstream << "/"; tempstream << (int) id.GetInstance(); string nodeinstance = tempstream.str(); tempstream << "-"; tempstream << label; string tempstring = tempstream.str(); ZWaveNode *device; if (basic == BASIC_TYPE_CONTROLLER) { if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); device->setDevicetype("remote"); } else { device = new ZWaveNode(nodeinstance, "remote"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } } else switch(id.GetCommandClassId()) { case COMMAND_CLASS_SWITCH_MULTILEVEL: if (label == "Level") { if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); device->setDevicetype("dimmer"); } else { device = new ZWaveNode(nodeinstance, "dimmer"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } // Manager::Get()->EnablePoll(id); } break; case COMMAND_CLASS_SWITCH_BINARY: if (label == "Switch") { if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); } else { device = new ZWaveNode(nodeinstance, "switch"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } // Manager::Get()->EnablePoll(id); } break; case COMMAND_CLASS_SENSOR_BINARY: if (label == "Sensor") { if ((device = devices.findId(tempstring)) != NULL) { device->addValue(label, id); } else { device = new ZWaveNode(tempstring, "binarysensor"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } // Manager::Get()->EnablePoll(id); } break; case COMMAND_CLASS_SENSOR_MULTILEVEL: if (label == "Luminance") { device = new ZWaveNode(tempstring, "brightnesssensor"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } else if (label == "Temperature") { if (generic == GENERIC_TYPE_THERMOSTAT) { if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); } else { device = new ZWaveNode(nodeinstance, "thermostat"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } } else { device = new ZWaveNode(tempstring, "temperaturesensor"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } } else { printf("WARNING: unhandled label for SENSOR_MULTILEVEL: %s - adding generic multilevelsensor\n",label.c_str()); if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); } else { device = new ZWaveNode(nodeinstance, "multilevelsensor"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } } // Manager::Get()->EnablePoll(id); break; case COMMAND_CLASS_METER: if (label == "Power") { device = new ZWaveNode(tempstring, "powermeter"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } else if (label == "Energy") { device = new ZWaveNode(tempstring, "energymeter"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } else { printf("WARNING: unhandled label for CLASS_METER: %s - adding generic multilevelsensor\n",label.c_str()); if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); } else { device = new ZWaveNode(nodeinstance, "multilevelsensor"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } } // Manager::Get()->EnablePoll(id); break; case COMMAND_CLASS_BASIC_WINDOW_COVERING: // if (label == "Open") { if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); device->setDevicetype("drapes"); } else { device = new ZWaveNode(nodeinstance, "drapes"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } // Manager::Get()->EnablePoll(id); // } break; case COMMAND_CLASS_THERMOSTAT_SETPOINT: if (polling) Manager::Get()->EnablePoll(id); case COMMAND_CLASS_THERMOSTAT_MODE: case COMMAND_CLASS_THERMOSTAT_FAN_MODE: case COMMAND_CLASS_THERMOSTAT_FAN_STATE: case COMMAND_CLASS_THERMOSTAT_OPERATING_STATE: cout << "adding thermostat label: " << label << endl; if ((device = devices.findId(nodeinstance)) != NULL) { device->addValue(label, id); device->setDevicetype("thermostat"); } else { device = new ZWaveNode(nodeinstance, "thermostat"); device->addValue(label, id); devices.add(device); agoConnection->addDevice(device->getId().c_str(), device->getDevicetype().c_str()); } break; default: printf("Notification: Unassigned Value Added Home 0x%08x Node %d Genre %d Class %x Instance %d Index %d Type %d - Label: %s\n", _notification->GetHomeId(), _notification->GetNodeId(), id.GetGenre(), id.GetCommandClassId(), id.GetInstance(), id.GetIndex(), id.GetType(),label.c_str()); // printf("Notification: Unassigned Value Added Home 0x%08x Node %d Genre %d Class %x Instance %d Index %d Type %d - ID: %" PRIu64 "\n", _notification->GetHomeId(), _notification->GetNodeId(), id.GetGenre(), id.GetCommandClassId(), id.GetInstance(), id.GetIndex(), id.GetType(),id.GetId()); } } break; } case Notification::Type_ValueRemoved: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Remove the value from out list for( list<ValueID>::iterator it = nodeInfo->m_values.begin(); it != nodeInfo->m_values.end(); ++it ) { if( (*it) == _notification->GetValueID() ) { nodeInfo->m_values.erase( it ); break; } } } break; } case Notification::Type_ValueChanged: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // One of the node values has changed // TBD... // nodeInfo = nodeInfo; ValueID id = _notification->GetValueID(); string str; printf("Notification: Value Changed Home 0x%08x Node %d Genre %d Class %d Instance %d Index %d Type %d\n", _notification->GetHomeId(), _notification->GetNodeId(), id.GetGenre(), id.GetCommandClassId(), id.GetInstance(), id.GetIndex(), id.GetType()); if (Manager::Get()->GetValueAsString(id, &str)) { qpid::types::Variant cachedValue; cachedValue.parse(str); valueCache[id] = cachedValue; string label = Manager::Get()->GetValueLabel(id); string units = Manager::Get()->GetValueUnits(id); // TODO: send proper types and don't convert everything to string string level = str; string eventtype = ""; if (str == "True") level="255"; if (str == "False") level="0"; printf("Value: %s Label: %s Unit: %s\n",str.c_str(),label.c_str(),units.c_str()); if ((label == "Basic") || (label == "Switch") || (label == "Level")) { eventtype="event.device.statechanged"; } if (label == "Luminance") { eventtype="event.environment.brightnesschanged"; } if (label == "Temperature") { eventtype="event.environment.temperaturechanged"; if (units=="F" && unitsystem==0) { units="C"; str = float2str((atof(str.c_str())-32)*5/9); level = str; } else if (units =="C" && unitsystem==1) { units="F"; str = float2str(atof(str.c_str())*9/5 + 32); level = str; } } if (label == "Relative Humidity") { eventtype="event.environment.humiditychanged"; } if (label == "Battery Level") { eventtype="event.device.batterylevelchanged"; } if (label == "Alarm Level") { eventtype="event.security.alarmlevelchanged"; } if (label == "Alarm Type") { eventtype="event.security.alarmtypechanged"; } if (label == "Sensor") { eventtype="event.security.sensortriggered"; } if (label == "Energy") { eventtype="event.environment.energychanged"; } if (label == "Power") { eventtype="event.environment.powerchanged"; } if (label == "Mode") { eventtype="event.environment.modechanged"; } if (label == "Fan Mode") { eventtype="event.environment.fanmodechanged"; } if (label == "Fan State") { eventtype="event.environment.fanstatechanged"; } if (label == "Operating State") { eventtype="event.environment.operatingstatechanged"; } if (label == "Cooling 1") { eventtype="event.environment.coolsetpointchanged"; } if (label == "Heating 1") { eventtype="event.environment.heatsetpointchanged"; } if (label == "Fan State") { eventtype="event.environment.fanstatechanged"; } if (eventtype != "") { ZWaveNode *device = devices.findValue(id); if (device != NULL) { if (debug) printf("Sending %s event from child %s\n",eventtype.c_str(), device->getId().c_str()); agoConnection->emitEvent(device->getId().c_str(), eventtype.c_str(), level.c_str(), units.c_str()); } } } } break; } case Notification::Type_Group: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // One of the node's association groups has changed // TBD... nodeInfo = nodeInfo; eventmap["description"]="Node association added"; eventmap["state"]="associationchanged"; eventmap["nodeid"] = _notification->GetNodeId(); eventmap["homeid"] = _notification->GetHomeId(); agoConnection->emitEvent("zwavecontroller", "event.zwave.associationchanged", eventmap); } break; } case Notification::Type_NodeAdded: { // Add the new node to our list NodeInfo* nodeInfo = new NodeInfo(); nodeInfo->m_homeId = _notification->GetHomeId(); nodeInfo->m_nodeId = _notification->GetNodeId(); nodeInfo->m_polled = false; g_nodes.push_back( nodeInfo ); // todo: announce node eventmap["description"]="Node added"; eventmap["state"]="nodeadded"; eventmap["nodeid"] = _notification->GetNodeId(); eventmap["homeid"] = _notification->GetHomeId(); agoConnection->emitEvent("zwavecontroller", "event.zwave.networkchanged", eventmap); break; } case Notification::Type_NodeRemoved: { // Remove the node from our list uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); eventmap["description"]="Node removed"; eventmap["state"]="noderemoved"; eventmap["nodeid"] = _notification->GetNodeId(); eventmap["homeid"] = _notification->GetHomeId(); agoConnection->emitEvent("zwavecontroller", "event.zwave.networkchanged", eventmap); for( list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; if( ( nodeInfo->m_homeId == homeId ) && ( nodeInfo->m_nodeId == nodeId ) ) { g_nodes.erase( it ); break; } } break; } case Notification::Type_NodeEvent: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // We have received an event from the node, caused by a // basic_set or hail message. ValueID id = _notification->GetValueID(); string label = Manager::Get()->GetValueLabel(id); stringstream level; level << (int) _notification->GetByte(); string eventtype = "event.device.statechanged"; ZWaveNode *device = devices.findValue(id); if (device != NULL) { if (debug) printf("Sending %s event from child %s\n",eventtype.c_str(), device->getId().c_str()); agoConnection->emitEvent(device->getId().c_str(), eventtype.c_str(), level.str().c_str(), ""); } else { cout << "no agocontrol device found for node event - Label: " << label << " Level: " << level << endl; } } break; } case Notification::Type_SceneEvent: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { int scene = _notification->GetSceneId(); ValueID id = _notification->GetValueID(); string label = Manager::Get()->GetValueLabel(id); stringstream tempstream; tempstream << (int) _notification->GetNodeId(); tempstream << "/1"; string nodeinstance = tempstream.str(); string eventtype = "event.device.statechanged"; ZWaveNode *device; if ((device = devices.findId(nodeinstance)) != NULL) { if (debug) printf("Sending %s for scene %d event from child %s\n", eventtype.c_str(), scene, device->getId().c_str()); agoConnection->emitEvent(device->getId().c_str(), eventtype.c_str(), scene, ""); } else { cout << "WARNING: no agocontrol device found for scene event" << endl; cout << "Node: " << nodeinstance << " Scene: " << scene << endl; } } break; } case Notification::Type_PollingDisabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = false; } break; } case Notification::Type_PollingEnabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = true; } break; } case Notification::Type_DriverReady: { g_homeId = _notification->GetHomeId(); break; } case Notification::Type_DriverFailed: { g_initFailed = true; pthread_cond_broadcast(&initCond); break; } case Notification::Type_AwakeNodesQueried: case Notification::Type_AllNodesQueried: case Notification::Type_AllNodesQueriedSomeDead: { pthread_cond_broadcast(&initCond); break; } case Notification::Type_DriverReset: case Notification::Type_Notification: case Notification::Type_NodeNaming: case Notification::Type_NodeProtocolInfo: case Notification::Type_NodeQueriesComplete: case Notification::Type_EssentialNodeQueriesComplete: { break; } default: { cout << "WARNING: Unhandled OpenZWave Event: " << _notification->GetType() << endl; } } pthread_mutex_unlock( &g_criticalSection ); }