void DHASWifiNodesModule::checkHeartBeats() { time_t t; time(&t); t -= (3*NODE_HEARTBEAT); for (auto& it : mNodes) { DHASWifiNode* node = &it.second; if (node->lastHeartBeat <= t) { LOG("Node [" << node->driver->getName() <<"] @ " << node->driver->getInfo().ip << " heartbeat failure. Disconnecting"); close(node->socket); Dumais::JSON::JSON json; json.addValue("dwn","event"); json.addValue("closed","type"); json.addValue(node->driver->getInfo().ip,"ip"); json.addValue(node->driver->getName(),"name"); json.addValue(node->driver->getInfo().id,"id"); mpEventProcessor->processEvent(json); std::string ip = node->driver->getInfo().ip; node->driver->unRegisterCallBacks(mpRestEngine); delete node->driver; node->driver = 0; this->mNodesListLock.lock(); mNodes.erase(ip); this->mNodesListLock.unlock(); } } }
void KeypadLinc::toJSON(Dumais::JSON::JSON& obj) { std::stringstream ss; ss << "0x" << std::hex << std::setfill('0') << std::setw(6) << mID; obj.addValue(ss.str(),"id"); obj.addValue(this->getName(),"name"); obj.addValue(this->getDeviceType(),"type"); // obj.addValue(this->getState()?255:0,"level"); }
void DHASWifiNodesModule::receiveFromNode(DHASWifiNode* node) { //TODO: we could be receiving two messages in the same packet. we should accumulate in buffer until we find a terminating 0. // and all DWN devices should terminate a message with 0 char buf[2000]; int n = recv(node->socket,buf,2000,0); //LOG("receiving from node: " << n << " " << errno); if (n<=0) { if (n==-1 && errno == EAGAIN) return; LOG("Node failed [" << node->driver->getName() << "] @ " << node->driver->getInfo().ip << " (" << errno << "). Removing"); close(node->socket); Dumais::JSON::JSON json; json.addValue("dwn","event"); json.addValue("closed","type"); json.addValue(node->driver->getInfo().ip,"ip"); json.addValue(node->driver->getName(),"name"); json.addValue(node->driver->getInfo().id,"id"); mpEventProcessor->processEvent(json); std::string ip = node->driver->getInfo().ip; node->driver->unRegisterCallBacks(mpRestEngine); delete node->driver; node->driver = 0; this->mNodesListLock.lock(); mNodes.erase(ip); this->mNodesListLock.unlock(); return; } std::string payload (buf,n); //LOG("payload (" << n << "): " << payload); if (payload == "yo!\r\n") { time(&node->lastHeartBeat); } else { if (node->driver == 0) { LOG("ERROR: Can't process data from " << node->driver->getName() <<" ("<<node->driver->getInfo().id<<". Driver not associated"); } else { Dumais::JSON::JSON j; if (node->driver->processData(buf,n,j)) { j.addValue("dwn","event"); j.addValue(node->driver->getInfo().ip,"ip"); j.addValue(node->driver->getName(),"name"); j.addValue(node->driver->getInfo().id,"id"); mpEventProcessor->processEvent(j); } } } }
void DHASWifiNodesModule::discoverNode(std::string name, std::string ip, std::string id) { if (ip == "0.0.0.0") return; if (mNodes.find(ip) == mNodes.end()) { LOG("Found an advertisement from [" << name << "] at " << ip); if (mNodes.size() >= MAX_NODES_COUNT) { LOG("ERROR: The number of nodes registered in the system has reached maximum capacity"); return; } IDWN* driver = IDWN::createDriverInstance(name); if (driver == 0) { // TODO: should probably ignore all further broadcasts. LOG("ERROR: No suitable driver found for wifi node [" << name << "]"); return; } DHASWifiNode node; node.driver = driver; node.driver->getInfo().ip = ip; node.driver->getInfo().id = id; node.driver->getInfo().sendQueue = &mSendQueue; time(&node.lastHeartBeat); if (connectNode(&node)) { LOG("Node [" << name << "] @ " << ip << " connected."); this->mNodesListLock.lock(); mNodes[ip] = node; this->mNodesListLock.unlock(); node.driver->registerCallBacks(mpRestEngine); Dumais::JSON::JSON json; json.addValue("dwn","event"); json.addValue("new","type"); json.addValue(ip,"ip"); json.addValue(name,"name"); json.addValue(id,"id"); mpEventProcessor->processEvent(json); } else { LOG("Could not connect to node [" << name << "] @ " << ip); } } }
RESTEngine::ResponseCode RESTCallBack::call(Dumais::JSON::JSON& json, const std::string& paramString, const std::string& dataString, std::smatch& matches, std::shared_ptr<void> userData) { RESTParameters params(paramString, mParamList); // Let's check required params for (ParamMap::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it) { // todo later : handle/check in "path" parameters: http://server:port/param1/param2 if (it->second.mRequired && (it->second.mLocation == "query") ) { if (params.getParam(it->first).empty()) { std::cerr << "Missing mandatory parameter " << it->first << std::endl; // todo : replace empty parameter value by default parameter value json.addValue("Missing required parameter " + it->first, "error"); return RESTEngine::ResponseCode::BadRequest; } } } RESTEngine::ResponseCode responseCode = RESTEngine::ResponseCode::OK; RESTContext context ={ json, ¶ms, dataString, matches, responseCode, userData }; assert(mCallback); if (mCallback) mCallback(&context); return responseCode; }
void Thermostat::toJSON(Dumais::JSON::JSON& obj) { std::stringstream ss; ss << "0x" << std::hex << std::setfill('0') << std::setw(6) << mID; obj.addValue(ss.str(),"id"); obj.addValue(this->getName(),"name"); obj.addValue(this->getDeviceType(),"type"); obj.addValue((unsigned int)this->getTemperature(),"temperature"); obj.addValue((unsigned int)this->getHeatSetPoint(),"heatpoint"); obj.addValue((unsigned int)this->getCoolSetPoint(),"coolpoint"); obj.addValue((unsigned int)this->getHumidity(),"humidity"); obj.addValue((unsigned int)this->getOperatingMode(),"operatingmode"); obj.addValue((unsigned int)this->getOperatingState(),"operatingstate"); obj.addValue((unsigned int)mThermostatProgram.isActive(),"programactive"); }
void RESTCallBack::getDescription(Dumais::JSON::JSON& json) { json.addValue(mDescription,"description"); Dumais::JSON::JSON& params = json.addList("params"); for (ParamMap::const_iterator it = mParamList.begin(); it!=mParamList.end(); it++) { Dumais::JSON::JSON& j = params.addObject("param"); j.addValue(it->first,"name"); j.addValue(it->second.mDescription, "description"); } }
void KeypadLinc::processEvent(Dumais::JSON::JSON& json, unsigned char* buf) { // Get the status unsigned char flags = buf[8]; unsigned char status = (flags & 0b11100000)>>5; unsigned char cmd1 = buf[9]; unsigned char cmd2 = buf[10]; bool ackOfDirectMessage = (status==0b001); if (status==0b010) // Group cleanup direct message { json.addValue("insteon","event"); json.addValue(mID,"id"); json.addValue(this->getName(),"name"); json.addValue("unsolicited","trigger"); unsigned char level = 0; if (cmd1==0x11){ level = 255; json.addValue("keypad","type"); json.addValue(cmd2,"button"); json.addValue(level,"value"); /* we turn button off again so that it gets updated by script instead. This is a hack * otherwise the button is on, but if nothing reacts to it, it will stay on */ //turnOnOrOff(false,0,cmd2); } else if (cmd1==0x13) { level = 0; json.addValue("keypad","type"); json.addValue(cmd2,"button"); json.addValue(level,"value"); /* we turn button on again so that it gets updated by script instead. This is a hack * otherwise the button is on, but if nothing reacts to it, it will stay on */ //turnOnOrOff(true,0,cmd2); } } }