int TransactionQueue::AddTicket(Command &cmd) { string target = cmd.GetTargetsid(); int type = cmd.GetType(); int ticket = GetNextTicketID(); string targetsid = cmd.GetTargetsid(); vector<Transaction>::iterator it; /* if the command object is register command */ if(type == FX_REGISTER) { /* first find the register transaction */ for( it = _transq.begin(); it < _transq.end(); it++) { if((*it).GetType() == 0 ) { /* We have found the register transaction * Update the command object and do the transaction */ (*it).SetCommand(cmd); (*it).SetTicketid(ticket); DoTransaction((*it).GetID()); return ticket; } } /* not existing a register transaction * add a new transaction and do it */ Transaction tmp(cmd); tmp.SetTicketid(ticket); DoTransaction(Add(Transaction(cmd))); return ticket; } else { /* not a register command */ /* find if there exists a transaction * whose targetid and type is the same * as the command. */ for( it = _transq.begin(); it < _transq.end(); it++) { if( ((*it).GetTargetsid().compare(targetsid) == 0) && \ ((*it).GetType() == cmd.GetType()) ) { /* We have found the specific transaction * Update the command object and do the transaction */ (*it).SetCommand(cmd); (*it).SetTicketid(ticket); DoTransaction((*it).GetID()); return ticket; } } Transaction tmp(cmd); tmp.SetTicketid(ticket); DoTransaction(Add(Transaction(cmd))); return ticket; } }
bool LoopModule::ExecCommand(const Command& command, bool wantAnswer) { if(command.GetType() == ctGET) // получить состояние связанного модуля { return AddLink(command,wantAnswer) ? true : false; } // if else if(command.GetType() == ctSET) // установить состояние связанного модуля { return AddLink(command,wantAnswer) ? true : false; } // if return true; }
/** * @brief main * je tu obsiahnuta kompletna implementacia vzhladom na demonstracne ucely, na ktore mala tato cast zadania sluzit * @param argc * @param argv * @return */ int main(int argc, char* argv[]) { atexit (Exit_fix_terminal); ///< na konci sa opat na stavi cin na blokujuci changemode(-1); ///< ulozi sa aktualny stav terminalu try { if (argc != 3) { std::cerr << "Usage: <host> <port>\n"; return 1; } Network connection(argv[1], argv[2]); ///< vytvorenie pripojenia na server connection.Connect(); cout << "Join game: 0\nCreate game: 1\nYour Choice:" << endl; int b; cin >> b; if( !b ) { ServerInfoList list = connection.GetServerList(); for( auto x: list.list ) { cout << x << endl; } int gameid; cout << "Enter game id to join: "; cin >> gameid; connection.Join(gameid); ///< pripojenie sa k uz existujucej hre } else { ServerInfoList list = connection.GetMapList(); for( auto x: list.list ) ///< zobrazia sa nazvy vsetkych dostupnych map { cout << "#- " << x.map << " -#" <<endl; } std::string mapname ; std::string gamename ; int players_max; float delay; int timeout; cout << "Enter game name: "; cin >> gamename; cout << "Enter maximum number of players: "; cin >> players_max; cout << "Enter map name: "; cin >> mapname; cout << "Enter delay (0.5-5.0 s): "; cin >> delay; cout << "Enter amount of time to wait for start of the game in seconds: "; cin >> timeout; connection.CreateServer(gamename, players_max, mapname, delay, timeout); ///< vytvorenie novej hry } /** server posle staticku mapu */ connection.ReadPacket(); if (connection.GetHeaderType() != packetHeader::STATIC_MAP ) { throw std::runtime_error( "Invalid packet received form server." ); } cout << "packet received" << endl; Map map = connection.GetPacketContent<Map>(); ///< obsah danej mapy sa upravy tak aby sa vykreslilo iba pozadie - inicializacia pohladu Map::MapMatrix background = map.items; for (auto &row: background) { for (auto &column: row) { switch(column) { case Map::GRASS: case Map::WALL: break; default: column = Map::GRASS; break; } } } MapUpdate updatepacket = connection.GetMapUpdate(); ///< server zaslal prvy update Map::MapMatrix screenbuffer = background; for ( auto item: updatepacket.players ) ///< v terminalovej verzii je kazdy hrac rovnaky { screenbuffer[item.x][item.y] = static_cast<Map::StaticTypes>( Map::PLAYER_BASE ); } for (auto &row: screenbuffer) ///< vykreslenie prveho update { for (auto &column: row) { switch(column) { case Map::GRASS: cout<<"░"; break; case Map::WALL: cout << "█"; break; case Map::GATE: cout << 'G'; break; case Map::KEY: cout << 'K'; break; case Map::FINISH: cout << 'F'; break; case Map::PLAYER_BASE: cout << 'P'; default: break; } } cout << endl; } //cin.ignore(INT_MAX); changemode(1); ///< nastavenie cin na neblokujuci /* MAIN GAME LOOP */ while ( !cin.eof() ) { if ( kbhit() ) ///< reakcia na stisk klavesy { char c; cin.get(c); if ( c == 27 ) // ESC { cout << "ESCAPE"; connection.Leave(); break; } if( c == 'w' ) { Command c; c.SetType(Command::GO); connection.SendCommand(c); } if( c == 's' ) { Command c; c.SetType(Command::STOP); connection.SendCommand(c); } if( c == 'a' ) { Command c; c.SetType(Command::LEFT); connection.SendCommand(c); } if( c == 'd' ) { Command c; c.SetType(Command::RIGHT); connection.SendCommand(c); } if( c == 'e' ) { Command c; c.SetType(Command::TAKE); connection.SendCommand(c); } if( c == 'q' ) { Command c; c.SetType(Command::OPEN); connection.SendCommand(c); } } if ( connection.Ready() ) ///< reakcia na packet, ktory prave dorazil { connection.ReadPacket(); if( connection.GetHeaderType() == packetHeader::COMMAND ) { Command c = connection.GetPacketContent<Command>(); if( c.GetType() == Command::TEXT ) ///< ak mi sietou neprisiel novy obsah mapy tak prisla textova sprava, ktoru vypisem { cout << c.GetText() << endl; } else { cout << "Received packet different than text or gameupdate"; } } else if ( connection.GetHeaderType() == packetHeader::GAME_UPDATE ) ///< server zaslal game update { MapUpdate updatepacket = connection.GetPacketContent<MapUpdate>(); Map::MapMatrix screenbuffer = background; screenbuffer[updatepacket.treasure.x][updatepacket.treasure.y] = Map::FINISH; ///< vlozenie pokladu for ( auto item: updatepacket.gates ) ///< vlozenie bran { if ( item.optionFlag == true ) { screenbuffer[item.x][item.y] = Map::GATE; } else { screenbuffer[item.x][item.y] = Map::GATE_OPEN; } } for ( auto item: updatepacket.keys ) ///< vlozenie klucov { if ( item.optionFlag == true ) { screenbuffer[item.x][item.y] = Map::KEY; } } for ( auto item: updatepacket.guards ) ///< vlozenie strazcov { screenbuffer[item.x][item.y] = static_cast<Map::StaticTypes>( Map::GUARD_BASE); } for ( auto item: updatepacket.players ) ///< vlozenie hracov { if(item.optionFlag == true ) ///< vykresluju sa len hraci, ktori su zivi { screenbuffer[item.x][item.y] = static_cast<Map::StaticTypes>( Map::PLAYER_BASE + item.dir); } } for (auto &row: screenbuffer) ///< vykreslenie celej hry { for (auto &column: row) { switch(column) { case Map::GRASS: cout<<" "; break; case Map::WALL: cout << "█"; break; case Map::GATE: cout << "G"; break; case Map::GATE_OPEN: cout << "░"; break; case Map::GUARD_BASE: cout << "X"; break; case Map::KEY: cout << "K"; break; case Map::FINISH: cout << "F"; break; case static_cast<Map::StaticTypes>( Map::PLAYER_BASE + 0): cout << "↑"; break; case static_cast<Map::StaticTypes>( Map::PLAYER_BASE + 1): cout << "→"; break; case static_cast<Map::StaticTypes>( Map::PLAYER_BASE + 2): cout << "↓"; break; case static_cast<Map::StaticTypes>( Map::PLAYER_BASE + 3): cout << "←"; break; default: break; } } cout << endl; } cout << endl; } else { //cout << "Unknown packet header " << connection.GetHeaderType() << endl; } } std::this_thread::sleep_for (std::chrono::milliseconds(10)); ///< klient sa uspi na 10 misec. a znova kontroluje obsah socketu } changemode(0); ///< nastavi sa cin na povodny blokujuci }
bool CompositeCommandsModule::ExecCommand(const Command& command, bool wantAnswer) { if(wantAnswer) PublishSingleton = UNKNOWN_COMMAND; size_t argsCount = command.GetArgsCount(); if(command.GetType() == ctGET) { if(wantAnswer) PublishSingleton = NOT_SUPPORTED; } else if(command.GetType() == ctSET) { if(argsCount < 1) { PublishSingleton = PARAMS_MISSED; } else { // есть параметры String which = command.GetArg(0); if(which == CC_DELETE_COMMAND) // очистить все команды { Clear(); if(wantAnswer) PublishSingleton = REG_DEL; // говорим, что удалили всё PublishSingleton.Status = true; } // CC_DELETE_COMMAND else if(which == CC_SAVE_COMMAND) // сохранить команды в EEPROM { SaveCommands(); if(wantAnswer) PublishSingleton = REG_SUCC; // говорим, что сохранили PublishSingleton.Status = true; } // CC_SAVE_COMMAND else if(which == CC_PROCESS_COMMAND) // выполнить команду { if(argsCount > 1) { // хватает аргументов uint8_t cmd = abs(atoi(command.GetArg(1))); ProcessCommand(cmd); // выполняем составную команду if(wantAnswer) PublishSingleton = REG_SUCC; // говорим, что выполнили PublishSingleton.Status = true; } else { // не хватает аргументов if(wantAnswer) PublishSingleton = PARAMS_MISSED; } } // CC_PROCESS_COMMAND else if(which == CC_ADD_COMMAND) // добавить параметр в список составной команды { if(argsCount > 3) { uint8_t listIdx = abs(atoi(command.GetArg(1))); uint8_t action = abs(atoi(command.GetArg(2))); uint8_t param = abs(atoi(command.GetArg(3))); AddCommand(listIdx,action,param); // добавляем команду if(wantAnswer) PublishSingleton = REG_SUCC; // говорим, что добавили PublishSingleton.Status = true; } else { // не хватает аргументов if(wantAnswer) PublishSingleton = PARAMS_MISSED; } } // CC_ADD_COMMAND } // else } // ctSET // отвечаем на команду MainController->Publish(this,command); return PublishSingleton.Status; }
bool SoilMoistureModule::ExecCommand(const Command& command, bool wantAnswer) { if(wantAnswer) PublishSingleton = NOT_SUPPORTED; if(command.GetType() == ctSET) // установка свойств { } // ctSET else if(command.GetType() == ctGET) // запрос свойств { uint8_t argsCnt = command.GetArgsCount(); if(argsCnt < 1) { if(wantAnswer) PublishSingleton = PARAMS_MISSED; // не хватает параметров } // argsCnt < 1 else { String param = command.GetArg(0); if(param == ALL) // запросили показания со всех датчиков: CTGET=SOIL|ALL { PublishSingleton.Status = true; uint8_t _cnt = State.GetStateCount(StateSoilMoisture); if(wantAnswer) PublishSingleton = _cnt; for(uint8_t i=0;i<_cnt;i++) { OneState* stateHumidity = State.GetStateByOrder(StateSoilMoisture,i); if(stateHumidity) { HumidityPair hp = *stateHumidity; if(wantAnswer) { PublishSingleton << PARAM_DELIMITER << (hp.Current); } } // if } // for } // param == ALL else if(param == PROP_CNT) // запросили данные о кол-ве датчиков: CTGET=SOIL|CNT { PublishSingleton.Status = true; if(wantAnswer) { PublishSingleton = PROP_CNT; uint8_t _cnt = State.GetStateCount(StateSoilMoisture); PublishSingleton << PARAM_DELIMITER << _cnt; } } // PROP_CNT else if(param != GetID()) // если только не запросили без параметров { // запросили показания с датчика по индексу uint8_t idx = param.toInt(); uint8_t _cnt = State.GetStateCount(StateSoilMoisture); if(idx >= _cnt) { // плохой индекс if(wantAnswer) PublishSingleton = NOT_SUPPORTED; } // плохой индекс else { if(wantAnswer) PublishSingleton = param; OneState* stateHumidity = State.GetStateByOrder(StateSoilMoisture,idx); if(stateHumidity) { PublishSingleton.Status = true; HumidityPair hp = *stateHumidity; if(wantAnswer) { PublishSingleton << PARAM_DELIMITER << (hp.Current); } } // if } // else нормальный индекс } // if param != GetID() } // else } MainController->Publish(this,command); return true; }
bool ZeroStreamListener::ExecCommand(const Command& command, bool wantAnswer) { if(wantAnswer) PublishSingleton = UNKNOWN_COMMAND; bool canPublish = true; // флаг, что можем публиковать size_t argsCnt = command.GetArgsCount(); if(command.GetType() == ctGET) { PublishSingleton = NOT_SUPPORTED; if(!argsCnt) // нет аргументов { PublishSingleton = PARAMS_MISSED; } else { if(argsCnt < 1) { // мало параметров PublishSingleton = PARAMS_MISSED; } // if else { String t = command.GetArg(0); // получили команду t.toUpperCase(); if(t == PING_COMMAND) // пинг { PublishSingleton.Status = true; PublishSingleton = PONG; PublishSingleton.AddModuleIDToAnswer = false; } // if else if(t == UNI_RF_CHANNEL_COMMAND) { PublishSingleton.Status = true; PublishSingleton = UNI_RF_CHANNEL_COMMAND; PublishSingleton << PARAM_DELIMITER; PublishSingleton << UniDispatcher.GetRFChannel(); PublishSingleton.AddModuleIDToAnswer = false; } #if defined(USE_UNIVERSAL_SENSORS) && defined(UNI_USE_REGISTRATION_LINE) else if(t == UNI_SEARCH) // поиск универсального модуля на линии регистрации { PublishSingleton.AddModuleIDToAnswer = false; if(uniRegistrator.IsModulePresent()) { // датчик найден, отправляем его внутреннее состояние PublishSingleton.Status = true; UniRawScratchpad scratch; uniRegistrator.CopyScratchpad(&scratch); byte* raw = (byte*) &scratch; PublishSingleton = ""; // теперь пишем весь скратчпад вызывающему, пущай сам разбирается, как с ним быть for(byte i=0;i<sizeof(UniRawScratchpad);i++) { PublishSingleton << WorkStatus::ToHex(raw[i]); } // for } // if else { // датчика нету PublishSingleton = UNI_NOT_FOUND; } // else } #endif // UNI_USE_REGISTRATION_LINE else if(t == ID_COMMAND) { PublishSingleton.Status = true; PublishSingleton.AddModuleIDToAnswer = false; PublishSingleton = ID_COMMAND; PublishSingleton << PARAM_DELIMITER << MainController->GetSettings()->GetControllerID(); } else if(t == WIRED_COMMAND) // получить количество жёстко указанных в прошивке обычных датчиков { PublishSingleton.Status = true; PublishSingleton.AddModuleIDToAnswer = false; PublishSingleton = WIRED_COMMAND; PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetHardCodedSensorsCount(uniTemp); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetHardCodedSensorsCount(uniHumidity); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetHardCodedSensorsCount(uniLuminosity); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetHardCodedSensorsCount(uniSoilMoisture); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetHardCodedSensorsCount(uniPH); //TODO: Тут остальные типы датчиков указывать !!! } else if(t == UNI_COUNT_COMMAND) // получить количество зарегистрированных универсальных датчиков { PublishSingleton.Status = true; PublishSingleton.AddModuleIDToAnswer = false; PublishSingleton = UNI_COUNT_COMMAND; PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetUniSensorsCount(uniTemp); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetUniSensorsCount(uniHumidity); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetUniSensorsCount(uniLuminosity); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetUniSensorsCount(uniSoilMoisture); PublishSingleton << PARAM_DELIMITER << UniDispatcher.GetUniSensorsCount(uniPH); //TODO: Тут остальные типы датчиков указывать !!! } else if(t == SMS_NUMBER_COMMAND) // номер телефона для управления по СМС { PublishSingleton.Status = true; PublishSingleton.AddModuleIDToAnswer = false; PublishSingleton = SMS_NUMBER_COMMAND; PublishSingleton << PARAM_DELIMITER << MainController->GetSettings()->GetSmsPhoneNumber(); } else if(t == STATUS_COMMAND) // получить статус всего железного добра { if(wantAnswer) { // входящий поток установлен, значит, можем писать прямо в него canPublish = false; // скажем, что мы не хотим публиковать через контроллер - будем писать в поток сами Stream* pStream = command.GetIncomingStream(); pStream->print(OK_ANSWER); pStream->print(COMMAND_DELIMITER); WORK_STATUS.WriteStatus(pStream,true); // просим записать статус // тут можем писать остальные статусы, типа показаний датчиков и т.п.: size_t modulesCount = MainController->GetModulesCount(); // получаем кол-во зарегистрированных модулей // const char* noDataByte = "FF"; // байт - нет данных с датчика // пробегаем по всем модулям String moduleName; moduleName.reserve(20); for(size_t i=0;i<modulesCount;i++) { yield(); // немного даём поработать другим модулям AbstractModule* mod = MainController->GetModule(i); // if(mod == this) // себя пропускаем // continue; // проверяем, не пустой ли модуль. для этого смотрим, сколько у него датчиков вообще uint8_t tempCount = mod->State.GetStateCount(StateTemperature); uint8_t humCount = mod->State.GetStateCount(StateHumidity); uint8_t lightCount = mod->State.GetStateCount(StateLuminosity); uint8_t waterflowCountInstant = mod->State.GetStateCount(StateWaterFlowInstant); uint8_t waterflowCount = mod->State.GetStateCount(StateWaterFlowIncremental); uint8_t soilMoistureCount = mod->State.GetStateCount(StateSoilMoisture); uint8_t phCount = mod->State.GetStateCount(StatePH); //TODO: тут другие типы датчиков!!! if((tempCount + humCount + lightCount + waterflowCountInstant + waterflowCount + soilMoistureCount + phCount) < 1) // пустой модуль, без интересующих нас датчиков continue; uint8_t flags = 0; if(tempCount) flags |= StateTemperature; if(humCount) flags |= StateHumidity; if(lightCount) flags |= StateLuminosity; if(waterflowCountInstant) flags |= StateWaterFlowInstant; if(waterflowCount) flags |= StateWaterFlowIncremental; if(soilMoistureCount) flags |= StateSoilMoisture; if(phCount) flags |= StatePH; //TODO: Тут другие типы датчиков!!! // показание каждого модуля идут так: // 1 байт - флаги о том, какие датчики есть pStream->write(WorkStatus::ToHex(flags)); // 1 байт - длина ID модуля moduleName = mod->GetID(); uint8_t mnamelen = moduleName.length(); pStream->write(WorkStatus::ToHex(mnamelen)); // далее идёт имя модуля pStream->write(moduleName.c_str()); // затем идут данные из модуля, сначала - показания температуры, если они есть PrintSensorsValues(tempCount,StateTemperature,mod,pStream); // затем идёт кол-во датчиков влажности, если они есть PrintSensorsValues(humCount,StateHumidity,mod,pStream); // затем идут показания датчиков освещенности, если они есть PrintSensorsValues(lightCount,StateLuminosity,mod,pStream); // затем идут моментальные показания датчиков расхода воды, если они есть PrintSensorsValues(waterflowCountInstant,StateWaterFlowInstant,mod,pStream); // затем идут накопительные показания датчиков расхода воды, если они есть PrintSensorsValues(waterflowCount,StateWaterFlowIncremental,mod,pStream); // затем идут датчики влажности почвы, если они есть PrintSensorsValues(soilMoistureCount,StateSoilMoisture,mod,pStream); // затем идут датчики pH, если они есть PrintSensorsValues(phCount,StatePH,mod,pStream); //TODO: тут другие типы датчиков!!! } // for pStream->print(NEWLINE); // пишем перевод строки } // wantAnswer } // STATUS_COMMAND else if(t == REGISTERED_MODULES_COMMAND) // пролистать зарегистрированные модули { PublishSingleton.AddModuleIDToAnswer = false; PublishSingleton.Status = true; PublishSingleton = F(""); size_t cnt = MainController->GetModulesCount(); for(size_t i=0;i<cnt;i++) { AbstractModule* mod = MainController->GetModule(i); if(mod != this) { if(PublishSingleton.Text.length()) PublishSingleton << PARAM_DELIMITER; PublishSingleton << mod->GetID(); }// if } // for } else { // неизвестная команда } // else } // else } // elsse } // ctGET else if(command.GetType() == ctSET) { if(!argsCnt) // нет аргументов { PublishSingleton = PARAMS_MISSED; } else { if(argsCnt < 2) { // мало параметров PublishSingleton = PARAMS_MISSED; String t = command.GetArg(0); if(t == RESET_COMMAND) { resetFunc(); // ресетимся, писать в ответ ничего не надо } // RESET_COMMAND else if(t == F("AUTO")) // CTSET=0|AUTO - перевести в автоматический режим { // очищаем общий буфер ответов PublishSingleton = ""; // выполняем команды ModuleInterop.QueryCommand(ctSET, F("STATE|MODE|AUTO"),false,false); ModuleInterop.QueryCommand(ctSET, F("WATER|MODE|AUTO"),false,false); ModuleInterop.QueryCommand(ctSET, F("LIGHT|MODE|AUTO"),false,false); // говорим, что выполнили PublishSingleton = REG_SUCC; PublishSingleton.Status = true; } // AUTO } // if else { String t = command.GetArg(0); // получили команду #ifdef USE_REMOTE_MODULES if(t == ADD_COMMAND) // запросили регистрацию нового модуля { // ищем уже зарегистрированный String reqID = command.GetArg(1); AbstractModule* mod = c->GetModuleByID(reqID); if(mod) { // модуль уже зарегистрирован PublishSingleton = REG_ERR; PublishSingleton << PARAM_DELIMITER << reqID; } // if else { // регистрируем новый модуль RemoteModule* remMod = new RemoteModule(reqID); c->RegisterModule(remMod); PublishSingleton.Status = true; PublishSingleton = REG_SUCC; PublishSingleton << PARAM_DELIMITER << reqID; } // else } else #endif if(t == SMS_NUMBER_COMMAND) // номер телефона для управления по SMS { GlobalSettings* sett = MainController->GetSettings(); sett->SetSmsPhoneNumber(command.GetArg(1)); sett->Save(); PublishSingleton.Status = true; PublishSingleton = SMS_NUMBER_COMMAND; PublishSingleton << PARAM_DELIMITER << REG_SUCC; } else if(t == UNI_RF_CHANNEL_COMMAND) { byte ch = atoi(command.GetArg(1)); UniDispatcher.SetRFChannel(ch); #ifdef USE_NRF_GATE nrfGate.SetChannel(ch); #endif PublishSingleton.Status = true; PublishSingleton = UNI_RF_CHANNEL_COMMAND; PublishSingleton << PARAM_DELIMITER << REG_SUCC; } #if defined(USE_UNIVERSAL_SENSORS) && defined(UNI_USE_REGISTRATION_LINE) else if(t == UNI_REGISTER) // зарегистрировать универсальный модуль, висящий на линии { PublishSingleton.AddModuleIDToAnswer = false; if(uniRegistrator.IsModulePresent()) { // модуль есть на линии, регистрируем его в системе. // сначала вычитываем переданный скратчпад и назначаем его модулю. // считаем, что на вызывающей стороне разобрались, что с чем, с остальным // разберётся модуль регистрации. const char* scratchData = command.GetArg(1); // теперь конвертируем данные скратчпада из текстового представления в нормальное char buff[3] = {0}; uint8_t len = strlen(scratchData); UniRawScratchpad scratch; byte* raw = (byte* )&scratch; for(uint8_t i=0;i<len;i+=2) { buff[0] = scratchData[i]; buff[1] = scratchData[i+1]; *raw = WorkStatus::FromHex(buff); raw++; } // for if(uniRegistrator.SetScratchpadData(&scratch)) { uniRegistrator.Register(); PublishSingleton.Status = true; PublishSingleton = REG_SUCC; } // if else { // разные типы скратчпадов, возможно, подсоединили другой модуль PublishSingleton = UNI_DIFFERENT_SCRATCHPAD; } } // if else { // модуля нет на линии PublishSingleton = UNI_NOT_FOUND; } } // UNI_REGISTER #endif // UNI_USE_REGISTRATION_LINE else if(t == ID_COMMAND) { //String newID = command.GetArg(1); MainController->GetSettings()->SetControllerID((uint8_t)atoi(command.GetArg(1))); PublishSingleton.Status = true; PublishSingleton = ID_COMMAND; PublishSingleton << PARAM_DELIMITER << REG_SUCC; } #ifdef USE_DS3231_REALTIME_CLOCK else if(t == SETTIME_COMMAND) { // установка даты/времени String rawDatetime = command.GetArg(1); int8_t idx = rawDatetime.indexOf(F(" ")); String tm, dt; if(idx != -1) { dt = rawDatetime.substring(0,idx); tm = rawDatetime.substring(idx+1); String month,day,year; String hour,minute,sec; idx = dt.indexOf(F(".")); if(idx != -1) { day = dt.substring(0,idx); dt = dt.substring(idx+1); } idx = dt.indexOf(F(".")); if(idx != -1) { month = dt.substring(0,idx); year = dt.substring(idx+1); } idx = tm.indexOf(F(":")); if(idx != -1) { hour = tm.substring(0,idx); tm = tm.substring(idx+1); } idx = tm.indexOf(F(":")); if(idx != -1) { minute = tm.substring(0,idx); sec = tm.substring(idx+1); } // вычисляем день недели int yearint = year.toInt(); int monthint = month.toInt(); int dayint = day.toInt(); int dow; byte mArr[12] = {6,2,2,5,0,3,5,1,4,6,2,4}; dow = (yearint % 100); dow = dow*1.25; dow += dayint; dow += mArr[monthint-1]; if (((yearint % 4)==0) && (monthint<3)) dow -= 1; while (dow>7) dow -= 7; DS3231Clock cl = MainController->GetClock(); cl.setTime(sec.toInt(),minute.toInt(),hour.toInt(),dow,dayint,monthint,yearint); PublishSingleton.Status = true; PublishSingleton = REG_SUCC; } // if } #endif else { // неизвестная команда } // else } // else argsCount > 1 } // else } // if // отвечаем на команду if(canPublish) // можем публиковать MainController->Publish(this,command); else PublishSingleton = F(""); // просто очищаем общий буфер return PublishSingleton.Status; }
//------------------------------------------------------------------------------------------------------------------------------------------------------- bool PhModule::ExecCommand(const Command& command, bool wantAnswer) { if(wantAnswer) PublishSingleton = NOT_SUPPORTED; uint8_t argsCnt = command.GetArgsCount(); if(command.GetType() == ctSET) // установка свойств { if(argsCnt < 1) { if(wantAnswer) PublishSingleton = PARAMS_MISSED; } else { String param = command.GetArg(0); if(param == PH_SETTINGS_COMMAND) // установить настройки: CTSET=PH|T_SETT|calibration_factor|ph4Voltage|ph7Voltage|ph10Voltage|temp_sensor_index|samples_temp|ph_target|ph_histeresis|mix_time|reagent_time { if(argsCnt < 11) { if(wantAnswer) PublishSingleton = PARAMS_MISSED; } else { // аргументов хватает calibration = atoi(command.GetArg(1)); ph4Voltage = atoi(command.GetArg(2)); ph7Voltage = atoi(command.GetArg(3)); ph10Voltage = atoi(command.GetArg(4)); phTemperatureSensorIndex = atoi(command.GetArg(5)); int samplesTemp = atoi(command.GetArg(6)); phSamplesTemperature.Value = samplesTemp/100; phSamplesTemperature.Fract = samplesTemp%100; phTarget = atoi(command.GetArg(7)); phHisteresis = atoi(command.GetArg(8)); phMixPumpTime = atoi(command.GetArg(9)); phReagentPumpTime = atoi(command.GetArg(10)); SaveSettings(); PublishSingleton.Status = true; PublishSingleton = REG_SUCC; } } // PH_SETTINGS_COMMAND } // else argsCount >= 1 } // ctSET else if(command.GetType() == ctGET) // запрос свойств { if(argsCnt < 1) { if(wantAnswer) PublishSingleton = PARAMS_MISSED; // не хватает параметров } // argsCnt < 1 else { String param = command.GetArg(0); if(param == ALL) // запросили показания со всех датчиков: CTGET=PH|ALL { PublishSingleton.Status = true; uint8_t _cnt = State.GetStateCount(StatePH); if(wantAnswer) PublishSingleton = _cnt; for(uint8_t i=0;i<_cnt;i++) { OneState* stateHumidity = State.GetStateByOrder(StatePH,i); if(stateHumidity) { HumidityPair hp = *stateHumidity; if(wantAnswer) { PublishSingleton << PARAM_DELIMITER << (hp.Current); } } // if } // for } // param == ALL else if(param == PH_SETTINGS_COMMAND) // получить/установить настройки: CTGET=PH|T_SETT, CTSET=PH|T_SETT|calibration_factor|ph4Voltage|ph7Voltage|ph10Voltage|temp_sensor_index|samples_temp|ph_target|ph_histeresis|mix_time|reagent_time { PublishSingleton.Status = true; if(wantAnswer) { PublishSingleton = PH_SETTINGS_COMMAND; PublishSingleton << PARAM_DELIMITER << calibration; PublishSingleton << PARAM_DELIMITER << ph4Voltage; PublishSingleton << PARAM_DELIMITER << ph7Voltage; PublishSingleton << PARAM_DELIMITER << ph10Voltage; PublishSingleton << PARAM_DELIMITER << phTemperatureSensorIndex; PublishSingleton << PARAM_DELIMITER << phSamplesTemperature; PublishSingleton << PARAM_DELIMITER << phTarget; PublishSingleton << PARAM_DELIMITER << phHisteresis; PublishSingleton << PARAM_DELIMITER << phMixPumpTime; PublishSingleton << PARAM_DELIMITER << phReagentPumpTime; } } // PH_SETTINGS_COMMAND else if(param == PROP_CNT) // запросили данные о кол-ве датчиков: CTGET=PH|CNT { PublishSingleton.Status = true; if(wantAnswer) { PublishSingleton = PROP_CNT; uint8_t _cnt = State.GetStateCount(StatePH); PublishSingleton << PARAM_DELIMITER << _cnt; } } // PROP_CNT else if(param != GetID()) // если только не запросили без параметров { // запросили показания с датчика по индексу uint8_t idx = param.toInt(); uint8_t _cnt = State.GetStateCount(StatePH); if(idx >= _cnt) { // плохой индекс if(wantAnswer) PublishSingleton = NOT_SUPPORTED; } // плохой индекс else { if(wantAnswer) PublishSingleton = param; OneState* stateHumidity = State.GetStateByOrder(StatePH,idx); if(stateHumidity) { PublishSingleton.Status = true; HumidityPair hp = *stateHumidity; if(wantAnswer) { PublishSingleton << PARAM_DELIMITER << (hp.Current); } } // if } // else нормальный индекс } // if param != GetID() } // else } MainController->Publish(this,command); return true; }