コード例 #1
0
json_spirit::Object ZWaveController::GetValue(uint64 value_id){

	EnterCriticalSection(&g_criticalSection);

	json_spirit::Object rtn;

	bool found = false;
	for (list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it)
	{
		NodeInfo* nodeInfo = *it;

		for (list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2)
		{
			ValueID v = *it2;
			uint64 vid = v.GetId();

			if (vid == value_id && ZWaveController::ExposeValue(v)){
				rtn.push_back(json_spirit::Pair("value", ZWaveController::GetValueInfo(v)));
				found = true;
				break;
			}
		}

		if (found){
			break;
		}

	}

	LeaveCriticalSection(&g_criticalSection);

	return rtn;

}
コード例 #2
0
bool ZWaveController::RefreshValue(uint64 value_id, string &error_msg){

	EnterCriticalSection(&g_criticalSection);

	bool success = false;
	bool found = false;
	error_msg = "";

	for (list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it)
	{
		NodeInfo* nodeInfo = *it;

		for (list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2)
		{
			ValueID v = *it2;
			uint64 vid = v.GetId();
			int node_id = v.GetNodeId();
			if (vid == value_id){
				found = true;
				success = Manager::Get()->RefreshValue(v);
				if (!success){
					error_msg = "Call to ZWave library RefreshValue failed (returned false)";
				}
				break;
			}
		}
	}
	LeaveCriticalSection(&g_criticalSection);

	if (!found){
		error_msg = "Value id " + to_string(value_id) + " could not be found";
	}

	return success;
}
コード例 #3
0
json_spirit::Object ZWaveController::GetValueChangesSince(uint64 since_milliseconds, uint64 only_node_id){

	if (since_milliseconds < ZWaveController::expire_seconds){
		return ZWaveController::GetAllValues(only_node_id);
	}

	json_spirit::Object rtn;

	uint64 current_milliseconds = Utils::GetTimeMilliseconds();
	string s_current_milliseconds = boost::lexical_cast<string>(current_milliseconds);
	rtn.push_back(json_spirit::Pair("time", s_current_milliseconds));

	std::vector<json_spirit::Value> values;

	EnterCriticalSection(&g_criticalSection);

	for (std::vector<ValueChange>::iterator i = ValueChange::value_changes.begin(); i != ValueChange::value_changes.end(); ++i){
		ValueChange vc = *i;
		if (i->time_added >= since_milliseconds && i->time_added <= current_milliseconds - 1){
			for (list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it)
			{
				NodeInfo* nodeInfo = *it;

				if (only_node_id != 0 && only_node_id != (uint64)nodeInfo->m_nodeId){
					continue;
				}


				for (list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2)
				{
					ValueID v = *it2;
					uint64 vid = v.GetId();

					if (vid == vc.value_id && ZWaveController::ExposeValue(v)){
						values.push_back(ZWaveController::GetValueInfo(v));
					}
				}
			}
		}
	}

	LeaveCriticalSection(&g_criticalSection);

	rtn.push_back(json_spirit::Pair("values", values));

	return rtn;

}
コード例 #4
0
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;
	}

}
コード例 #5
0
/*
 * 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);
}
コード例 #6
0
//-----------------------------------------------------------------------------
// <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;
	}
}
コード例 #7
0
ファイル: Main.cpp プロジェクト: rainisto/lights-control
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);
}
コード例 #8
0
bool ZWaveController::SetValue(uint64 value_id, string new_value, string &error_msg){

	EnterCriticalSection(&g_criticalSection);

	bool success = false;
	bool found = false;
	error_msg = "";

	for (list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it)
	{
		NodeInfo* nodeInfo = *it;

		for (list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2)
		{
			ValueID v = *it2;
			uint64 vid = v.GetId();
			int node_id = v.GetNodeId();
			if (vid == value_id){

				found = true;

				// make sure it's not a read only prop
				if (Manager::Get()->IsValueReadOnly(v)){
					error_msg = "This is a read only property";
				}

				else {

					bool bool_new_value;
					uint8 int8_new_value;
					int16 int16_new_value;
					int32 int32_new_value;

					switch (v.GetType()){

					case ValueID::ValueType::ValueType_Bool:
						if (
							new_value == ""
							|| new_value == "0"
							|| boost::iequals(new_value, "false")
							|| boost::iequals(new_value, "off")
							|| boost::iequals(new_value, "no")
							){
							bool_new_value = false;
						}
						else {
							bool_new_value = true;
						}
						success = Manager::Get()->SetValue(v, bool_new_value);
						if (!success){
							error_msg = "Call to ZWave library SetValue failed";
						}
						break;

					case ValueID::ValueType::ValueType_Byte:
						try {
							int8_new_value = (uint8)(boost::lexical_cast<int>(new_value));
							success = Manager::Get()->SetValue(v, int8_new_value);
							if (!success){
								error_msg = "Call to ZWave library SetValue failed";
							}
						}
						catch (boost::bad_lexical_cast const&) {
							error_msg = "Type required is byte (number from 0 to 255); could not convert new_value to byte";
						}
						break;

					case ValueID::ValueType::ValueType_Short:
						try {
							int16_new_value = boost::lexical_cast<int16>(new_value);
							success = Manager::Get()->SetValue(v, int16_new_value);
							if (!success){
								error_msg = "Call to ZWave library SetValue failed";
							}
						}
						catch (boost::bad_lexical_cast const&) {
							error_msg = "Type required is short (number from 0 to 65,535); could not convert new_value to short";
						}
						break;

					case ValueID::ValueType::ValueType_Decimal:
					case ValueID::ValueType::ValueType_Int:
						try {
							int32_new_value = boost::lexical_cast<int32>(new_value);
							success = Manager::Get()->SetValue(v, int32_new_value);
							if (!success){
								error_msg = "Call to ZWave library SetValue failed";
							}
						}
						catch (boost::bad_lexical_cast const&) {
							error_msg = "Type required is int32 (number from 0 to 4,294,967,295); could not convert new_value to int32";
						}
						break;

					case ValueID::ValueType::ValueType_Schedule:
						error_msg = "No support for setting 'schedule' value types yet";
						break;

					case ValueID::ValueType::ValueType_List:
					case ValueID::ValueType::ValueType_String:
					case ValueID::ValueType::ValueType_Button:
					case ValueID::ValueType::ValueType_Raw:
						success = Manager::Get()->SetValue(v, new_value);
						if (!success){
							error_msg = "Call to ZWave library SetValue failed";
						}
						break;

					default:
						error_msg = "Value is an unknown type, could not set";

					}

				}

				break;
			}
		}

	}

	LeaveCriticalSection(&g_criticalSection);

	if (!found){
		error_msg = "Value id " + to_string(value_id) + " could not be found";
	}

	return success;
}
コード例 #9
0
// Callback that is triggered when a value, group or node changes
void ZWaveController::OnNotification(Notification const* _notification, void* _context){

	// Must do this inside a critical section to avoid conflicts with the main thread
	EnterCriticalSection(&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());

				ValueID v = _notification->GetValueID();

				Logger::LogNotice("added value id " + to_string(v.GetId())  + " to node " + to_string(v.GetNodeId()) );

				if (!ZWaveController::init_failed && ZWaveController::initial_node_queries_complete){
					if (ZWaveController::ExposeValue(v)){
						uint64 vid = v.GetId();
						ValueChange::add_change(vid);
					}
				}

			}
			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 (!ZWaveController::init_failed && ZWaveController::initial_node_queries_complete){
						ValueID v = *it;
						uint64 vid = v.GetId();
						ValueChange::remove_change(vid);
					}

					if ((*it) == _notification->GetValueID())
					{
						nodeInfo->m_values.erase(it);
						break;
					}

				}
			}
			break;
		}

		case Notification::Type_ValueChanged:
		{
			// One of the node values has changed
			if (NodeInfo* nodeInfo = GetNodeInfo(_notification))
			{

				if (!ZWaveController::init_failed && ZWaveController::initial_node_queries_complete){

					// the value that changed
					ValueID v = _notification->GetValueID();

					string new_val;
					Manager::Get()->GetValueAsString(v, &new_val);
					Logger::LogNotice("node " + to_string(v.GetNodeId()) + ", value " + to_string(v.GetId()) + " (" + Manager::Get()->GetValueLabel(v) + "), has been changed to " + new_val);

					ValueChange::remove_expired_value_changes();

					// first remove this value from the change queue if it's already in there
					if (ZWaveController::ExposeValue(v)){
						string new_value;
						Manager::Get()->GetValueAsString(v, &new_value);

						uint64 vid = v.GetId();
						ValueChange::remove_change(vid);
						ValueChange::add_change(vid);
					}
				}

			}
			break;
		}

		case Notification::Type_Group:
		{
			// One of the node's association groups has changed
			if (NodeInfo* nodeInfo = GetNodeInfo(_notification))
			{
				nodeInfo = nodeInfo;		// placeholder for real action
			}
			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);

			Logger::LogNotice("node " + to_string(nodeInfo->m_nodeId) + " added");

			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);
					Logger::LogNotice("node " + to_string(nodeInfo->m_nodeId) + " removed");
					delete nodeInfo;
					break;
				}
			}
			break;
		}

		case Notification::Type_NodeEvent:
		{
			// We have received an event from the node, caused by a
			// basic_set or hail message.
			if (NodeInfo* nodeInfo = GetNodeInfo(_notification))
			{
				if (nodeInfo->m_nodeId == 5 || nodeInfo->m_nodeId == 6){
					Logger::LogNotice("node event received from node id " + to_string(nodeInfo->m_nodeId));
				}
				else {
					Logger::LogNotice("node event received from node id " + to_string(nodeInfo->m_nodeId));
				}
			}
			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:
		{
			ZWaveController::homeId = _notification->GetHomeId();
			Logger::LogNotice("controller driver is ready");
			break;
		}

		case Notification::Type_DriverFailed:
		{
			ZWaveController::init_failed = true;
			Logger::LogNotice("controller initialization failed. make sure another program is not already controlling the controller");
			break;
		}

		case Notification::Type_AwakeNodesQueried:
		case Notification::Type_AllNodesQueried:
		case Notification::Type_AllNodesQueriedSomeDead:
		{
			ZWaveController::initial_node_queries_complete = true;
			Logger::LogNotice("all zwave node queries complete");
			break;
		}

		case Notification::Type_NodeQueriesComplete:
		{
			Logger::LogNotice("node " + to_string(_notification->GetNodeId()) + " queries complete");
			break;
		}

		case Notification::Type_DriverReset:
		case Notification::Type_NodeNaming:
		case Notification::Type_NodeProtocolInfo:
		default:
		{
//			Logger::LogNotice("node " + to_string(_notification->GetNodeId()) + "");
		}

	} // end of switch

	LeaveCriticalSection(&g_criticalSection);
}
コード例 #10
0
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;

}
コード例 #11
0
ファイル: Main.cpp プロジェクト: Clancey/open-zwave
//-----------------------------------------------------------------------------
// <main>
// Create the driver and then wait
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
	pthread_mutexattr_t mutexattr;

	pthread_mutexattr_init ( &mutexattr );
	pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
	pthread_mutex_init( &g_criticalSection, &mutexattr );
	pthread_mutexattr_destroy( &mutexattr );

	pthread_mutex_lock( &initMutex );


	printf("Starting MinOZW with OpenZWave Version %s\n", Manager::getVersionAsString().c_str());

	// Create the OpenZWave Manager.
	// The first argument is the path to the config files (where the manufacturer_specific.xml file is located
	// The second argument is the path for saved Z-Wave network state and the log file.  If you leave it NULL 
	// the log file will appear in the program's working directory.
	Options::Create( "../../../config/", "", "" );
	Options::Get()->AddOptionInt( "SaveLogLevel", LogLevel_Detail );
	Options::Get()->AddOptionInt( "QueueLogLevel", LogLevel_Debug );
	Options::Get()->AddOptionInt( "DumpTrigger", LogLevel_Error );
	Options::Get()->AddOptionInt( "PollInterval", 500 );
	Options::Get()->AddOptionBool( "IntervalBetweenPolls", true );
	Options::Get()->AddOptionBool("ValidateValueChanges", true);
	Options::Get()->Lock();

	Manager::Create();

	// Add a callback handler to the manager.  The second argument is a context that
	// is passed to the OnNotification method.  If the OnNotification is a method of
	// a class, the context would usually be a pointer to that class object, to
	// avoid the need for the notification handler to be a static.
	Manager::Get()->AddWatcher( OnNotification, NULL );

	// Add a Z-Wave Driver
	// Modify this line to set the correct serial port for your PC interface.

#ifdef DARWIN
	string port = "/dev/cu.usbserial";
#elif WIN32
        string port = "\\\\.\\COM6";
#else
	string port = "/dev/ttyUSB0";
#endif
	if ( argc > 1 )
	{
		port = argv[1];
	}
	if( strcasecmp( port.c_str(), "usb" ) == 0 )
	{
		Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid );
	}
	else
	{
		Manager::Get()->AddDriver( port );
	}

	// Now we just wait for either the AwakeNodesQueried or AllNodesQueried notification,
	// then write out the config file.
	// In a normal app, we would be handling notifications and building a UI for the user.
	pthread_cond_wait( &initCond, &initMutex );

	// Since the configuration file contains command class information that is only 
	// known after the nodes on the network are queried, wait until all of the nodes 
	// on the network have been queried (at least the "listening" ones) before
	// writing the configuration file.  (Maybe write again after sleeping nodes have
	// been queried as well.)
	if( !g_initFailed )
	{

		// The section below demonstrates setting up polling for a variable.  In this simple
		// example, it has been hardwired to poll COMMAND_CLASS_BASIC on the each node that 
		// supports this setting.
		pthread_mutex_lock( &g_criticalSection );
		for( list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it )
		{
			NodeInfo* nodeInfo = *it;

			// skip the controller (most likely node 1)
			if( nodeInfo->m_nodeId == 1) continue;

			printf("NodeID: %d \n ", nodeInfo->m_nodeId);
			printf("\t NodeName: %s \n ", Manager::Get()->GetNodeName(nodeInfo->m_homeId,nodeInfo->m_nodeId).c_str());
			printf("\t ManufacturerName: %s \n ", Manager::Get()->GetNodeManufacturerName(nodeInfo->m_homeId,nodeInfo->m_nodeId).c_str());
			printf("\t NodeProductName: %s \n ", Manager::Get()->GetNodeProductName(nodeInfo->m_homeId,nodeInfo->m_nodeId).c_str());

			printf("Values announced by the nodes without polling: \n");
			for( list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2 )
			{
				ValueID v = *it2;
				printf("\t ValueLabel: %s \n", Manager::Get()->GetValueLabel(v).c_str());
				printf("\t\t ValueType: %d \n", v.GetType());
				printf("\t\t ValueHelp: %s \n", Manager::Get()->GetValueHelp(v).c_str());
				printf("\t\t ValueUnits: %s \n", Manager::Get()->GetValueUnits(v).c_str());
				printf("\t\t ValueMin: %d \n", Manager::Get()->GetValueMin(v));
				printf("\t\t ValueMax: %d \n", Manager::Get()->GetValueMax(v));

				if( v.GetCommandClassId() == COMMAND_CLASS_BASIC )
				{
//					Manager::Get()->EnablePoll( v, 2 );		// enables polling with "intensity" of 2, though this is irrelevant with only one value polled
					break;
				}
			}
		}
		pthread_mutex_unlock( &g_criticalSection );

		// If we want to access our NodeInfo list, that has been built from all the
		// notification callbacks we received from the library, we have to do so
		// from inside a Critical Section.  This is because the callbacks occur on other 
		// threads, and we cannot risk the list being changed while we are using it.  
		// We must hold the critical section for as short a time as possible, to avoid
		// stalling the OpenZWave drivers.
		// At this point, the program just waits for 3 minutes (to demonstrate polling),
		// then exits
		for( int i = 0; i < 60*3; i++ )
		{
			pthread_mutex_lock( &g_criticalSection );
			// but NodeInfo list and similar data should be inside critical section
			pthread_mutex_unlock( &g_criticalSection );
			sleep(1);
		}

		Driver::DriverData data;
		Manager::Get()->GetDriverStatistics( g_homeId, &data );
		printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.m_SOFCnt, data.m_ACKWaiting, data.m_readAborts, data.m_badChecksum);
		printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.m_readCnt, data.m_writeCnt, data.m_CANCnt, data.m_NAKCnt, data.m_ACKCnt, data.m_OOFCnt);
		printf("Dropped: %d Retries: %d\n", data.m_dropped, data.m_retries);
	}

	// program exit (clean up)
	if( strcasecmp( port.c_str(), "usb" ) == 0 )
	{
		Manager::Get()->RemoveDriver( "HID Controller" );
	}
	else
	{
		Manager::Get()->RemoveDriver( port );
	}
	Manager::Get()->RemoveWatcher( OnNotification, NULL );
	Manager::Destroy();
	Options::Destroy();
	pthread_mutex_destroy( &g_criticalSection );
	return 0;
}
コード例 #12
0
ファイル: Main.cpp プロジェクト: drewcovi/node-openzwave
//-----------------------------------------------------------------------------
// <main>
// Create the driver and then wait
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
	InitializeCriticalSection( &g_criticalSection );

	// Create the OpenZWave Manager.
	// The first argument is the path to the config files (where the manufacturer_specific.xml file is located
	// The second argument is the path for saved Z-Wave network state and the log file.  If you leave it NULL 
	// the log file will appear in the program's working directory.
	//Options::Create( "../../../../../../config/", "", "" );
	Options::Create("C:/source/ideas/openzwave-1.0.791/config/", "", "");
	Options::Get()->AddOptionInt( "SaveLogLevel", LogLevel_Detail );
	Options::Get()->AddOptionInt( "QueueLogLevel", LogLevel_Debug );
	Options::Get()->AddOptionInt( "DumpTrigger", LogLevel_Error );
	Options::Get()->AddOptionInt( "PollInterval", 500 );
	Options::Get()->AddOptionBool( "IntervalBetweenPolls", true );
	Options::Get()->AddOptionBool("ValidateValueChanges", true);
	Options::Get()->Lock();

	Manager::Create();

	// Add a callback handler to the manager.  The second argument is a context that
	// is passed to the OnNotification method.  If the OnNotification is a method of
	// a class, the context would usually be a pointer to that class object, to
	// avoid the need for the notification handler to be a static.
	Manager::Get()->AddWatcher( OnNotification, NULL );

	// Add a Z-Wave Driver
	// Modify this line to set the correct serial port for your PC interface.

	string port = "\\\\.\\COM4";

	Manager::Get()->AddDriver( ( argc > 1 ) ? argv[1] : port );
	//Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid );

	// Now we just wait for either the AwakeNodesQueried or AllNodesQueried notification,
	// then write out the config file.
	// In a normal app, we would be handling notifications and building a UI for the user.

	// Since the configuration file contains command class information that is only 
	// known after the nodes on the network are queried, wait until all of the nodes 
	// on the network have been queried (at least the "listening" ones) before
	// writing the configuration file.  (Maybe write again after sleeping nodes have
	// been queried as well.)
	while( !g_nodesQueried )
	{
		Sleep( 1000 );
	}

	if( !g_initFailed )
	{

		Manager::Get()->WriteConfig( g_homeId );

		// The section below demonstrates setting up polling for a variable.  In this simple
		// example, it has been hardwired to poll COMMAND_CLASS_BASIC on the each node that 
		// supports this setting.
		EnterCriticalSection( &g_criticalSection );
		for( list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it )
		{
			NodeInfo* nodeInfo = *it;

			// skip the controller (most likely node 1)
			if( nodeInfo->m_nodeId == 1) continue;

			for( list<ValueID>::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2 )
			{
				ValueID v = *it2;
				if( v.GetCommandClassId() == 0x20 )
				{
					Manager::Get()->EnablePoll( v, 2 );		// enables polling with "intensity" of 2, though this is irrelevant with only one value polled
					break;
				}
			}
		}
		LeaveCriticalSection( &g_criticalSection );

		// If we want to access our NodeInfo list, that has been built from all the
		// notification callbacks we received from the library, we have to do so
		// from inside a Critical Section.  This is because the callbacks occur on other 
		// threads, and we cannot risk the list being changed while we are using it.  
		// We must hold the critical section for as short a time as possible, to avoid
		// stalling the OpenZWave drivers.
		// At this point, the program just waits for 3 minutes (to demonstrate polling),
		// then exits
		for( int i = 0; i < 60*3*10; i++ )
		{
			Sleep(90);				// do most of your work outside critical section

			EnterCriticalSection( &g_criticalSection );
			Sleep(10);				// but NodeInfo list and similar data should be inside critical section
			LeaveCriticalSection( &g_criticalSection );
		}

		Driver::DriverData data;
		Manager::Get()->GetDriverStatistics( g_homeId, &data );
		printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.m_SOFCnt, data.m_ACKWaiting, data.m_readAborts, data.m_badChecksum);
		printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.m_readCnt, data.m_writeCnt, data.m_CANCnt, data.m_NAKCnt, data.m_ACKCnt, data.m_OOFCnt);
		printf("Dropped: %d Retries: %d\n", data.m_dropped, data.m_retries);
	}

	// program exit (clean up)
	Manager::Destroy();
	Options::Destroy();
	DeleteCriticalSection( &g_criticalSection );
	return 0;
}
コード例 #13
0
ファイル: agozwave.cpp プロジェクト: JoakimLindbom/agocontrol
//-----------------------------------------------------------------------------
// <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 );
}