bool DHASWifiNodesModule:: processDataFromMulticastSocket() { char buf[2000]; struct sockaddr_in src; socklen_t addrlen; addrlen = sizeof(struct sockaddr_in); int n = recvfrom(mSocket, buf, 2000, 0, (struct sockaddr*)&src, &addrlen); if(n<0) { if (errno == EAGAIN) return true; // Why would this happen? close(mSocket); LOG("Multicast listener read returned " << n << "(" << errno << "). Socket closed."); return false; } else if (n>0) { std::string str(buf,n); Dumais::JSON::JSON json; json.parse(str); char* ip = inet_ntoa(src.sin_addr); this->discoverNode(json["name"].str(),ip,json["id"].str()); } return true; }
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 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"); } }
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 Subscription::toJSON(Dumais::JSON::JSON& json) { Dumais::JSON::JSON& j = json.addObject("subscription"); j.addValue(getID(),"id"); j.addValue(mDevice,"device"); j.addValue(mDeviceStatus,"devicestate"); }
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 Insteon::listModules(Dumais::JSON::JSON& json) { for (std::map<InsteonID,InsteonDevice*>::iterator it=mModules.begin();it!=mModules.end();it++) { Dumais::JSON::JSON& obj = json.addObject("module"); it->second->toJSON(obj); // printf("TEST %s\r\n",obj.stringify(false).c_str()); } }
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 Thermostat::getProgramPoints(Dumais::JSON::JSON& json) { json.addList("points"); for (unsigned char i=0;i<(24*7);i++) { ProgramPoint point = mThermostatProgram.getPoint(i); if (point.mode > 0) { Dumais::JSON::JSON& obj = json["points"].addObject("ProgramPoint"); obj.addValue(point.temp,"temperature"); obj.addValue(point.mode,"mode"); obj.addValue(i,"hour"); } } }
void RESTEngine::documentInterface(Dumais::JSON::JSON& json) { json.addList("api"); for (CallbackMap::iterator it = mCallbacks.begin(); it != mCallbacks.end(); it++) { std::string method = it->first; std::transform(method.begin(),method.end(),method.begin(),::toupper); for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) { Dumais::JSON::JSON& j = json["api"].addObject(); it2->mpCallback->getDescription(j); j.addValue(it2->uri,"path"); j.addValue(method,"method"); } } return; }
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); } } }
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); } } }
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); } } } }