#include <SEESGroup.h>
Классы | |
| struct | ReservInfo |
Открытые типы | |
| typedef std::list< ReservInfo > | RList |
Открытые члены | |
| SEESGroup (int num, const std::string &name="") | |
| int | getNumber () |
| std::string | getName () |
| long | getP () |
| long | getU () |
| long | getF () |
| bool | isUdev () |
| bool | isFdev () |
| long | getReservPower () |
| void | step () |
| void | update () |
| void | updatePowerInfo () |
| void | requiredReserv (bool set) |
| bool | isNoReserv () |
| bool | isReadyForLoading () |
| void | addGroup (SEESGroup *gr) |
| bool | add (SEES *ses) |
| bool | del (SEES *ses) |
| void | clear () |
| bool | isProtection () |
| int | acceptQG (int num) throw (UniSetTypes::NameNotFound) |
| void | releaseQG (int num) throw (UniSetTypes::NameNotFound) |
| bool | canRun (int num) throw (UniSetTypes::NameNotFound) |
| SEES * | get (int num) |
| SESList | getSESList () |
| void | setReservStatePause (int s) |
| void | setCommandTimeout (int s) |
| void | setReservTime (int s) |
| void | setMaxWorkingDG (int s) |
| int | getWorkingDG () |
| void | setFdev (int f_min_, int f_max_, int f_msec) |
| void | setUdev (int u_min_, int u_max_, int U_msec) |
Открытые статические члены | |
| static void | init_dlog (DebugStream &dlog) |
Статические открытые данные | |
| static DebugStream | dlog |
Защищенные члены | |
| void | reserv (bool set) |
| void | checkReserv () |
| bool | resetReserv () |
| void | makeReservList () |
| void | checkAloneWorking () |
| void | updateCounters () |
Защищенные статические члены | |
| static void | update (RList &rlist, ReservInfo &ri) |
Защищенные данные | |
| UniSetTypes::uniset_mutex | lstMutex |
| int | gnum |
| std::string | myname |
| int | qf_locked |
| SESList | lst |
| SEES * | leader |
| RList | rlst |
| int | maxWorkingDG |
| int | countWorkingDG |
| UniSetTypes::uniset_mutex | maxrunMutex |
| int | reservStatePause |
| int | reservCommandTimeout |
| int | checkReservTime |
| PassiveTimer | ptCheckReserv |
| int | f_min |
| int | f_max |
| int | U_min |
| int | U_max |
| SandClock | sc_Fdev |
| SandClock | sc_Udev |
| bool | U_dev |
| bool | f_dev |
Друзья | |
| std::ostream & | operator<< (std::ostream &os, SEESGroup &g) |
| std::ostream & | operator<< (std::ostream &os, SEESGroup *g) |
| std::ostream & | print_chain (std::ostream &os, SEESGroup *g) |
| int SEESGroup::acceptQG | ( | int | num | ) | throw (UniSetTypes::NameNotFound) |
захват приоритета включения генераторного автомата
00576 { 00577 { // lock 00578 UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00579 00580 if( qf_locked != 0 ) 00581 { 00582 if( qf_locked == num ) 00583 { 00584 if( SEESGroup::dlog.debugging(Debug::INFO) ) 00585 SEESGroup::dlog[Debug::INFO] << myname << "(acceptQG): QG" << num << " ALREADY ACCEPTED..." << endl; 00586 return qf_locked; 00587 } 00588 00589 if( SEESGroup::dlog.debugging(Debug::INFO) ) 00590 SEESGroup::dlog[Debug::INFO] << myname << "(acceptQG): NOT ACCEPT QG" << num << " qf locked..." << endl; 00591 return qf_locked; 00592 } 00593 00594 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00595 { 00596 SEES* s(*it); 00597 if( s->isHaveQGLock() ) 00598 { 00599 if( (*it)->getNumber() == num ) 00600 { 00601 if( SEESGroup::dlog.debugging(Debug::INFO) ) 00602 SEESGroup::dlog[Debug::INFO] << myname << "(acceptQG): REPEAT ACCEPT QG" << num << endl; 00603 qf_locked = num; 00604 return qf_locked; 00605 } 00606 00607 if( SEESGroup::dlog.debugging(Debug::INFO) ) 00608 SEESGroup::dlog[Debug::INFO] << myname << "(acceptQG): NOT ACCEPT QG" << num 00609 << " but blocked ses" << (*it)->getNumber() << endl; 00610 s->setQGLock(true); 00611 qf_locked = (*it)->getNumber(); 00612 return qf_locked; 00613 } 00614 } 00615 } 00616 00617 ostringstream err; 00618 err << myname << "(acceptQG): Not found ses" + num; 00619 throw NameNotFound(err.str()); 00620 }
| void SEESGroup::checkAloneWorking | ( | ) | [protected] |
обновление информации о том "один ли ДГ на шинах"
Перекрестные ссылки lst.
00692 { 00693 { // lock 00694 UniSetTypes::uniset_mutex_lock lock(lstMutex, 4000); 00695 int count = getWorkingDG(); 00696 if( count > 0 ) 00697 { 00698 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00699 { 00700 if( (*it)->isOnMode() ) 00701 { 00702 if( count == 1 ) 00703 (*it)->setAloneWorking(true); 00704 else 00705 (*it)->setAloneWorking(false); 00706 } 00707 else 00708 (*it)->setAloneWorking(false); 00709 } 00710 } 00711 else 00712 { 00713 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00714 (*it)->setAloneWorking(true); 00715 } 00716 }// unlock 00717 }
| void SEESGroup::checkReserv | ( | ) | [protected] |
проверка необходимости запуска/остановки резерва
Перекрестные ссылки leader, myname, reserv(), resetReserv() и rlst.
00191 { 00192 UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00193 bool needCheck = false; 00194 00195 if( !leader ) 00196 { 00197 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00198 SEESGroup::dlog[Debug::LEVEL4] << myname << "(checkReserv): ignore.. no leader.." << endl; 00199 return; 00200 } 00201 00202 if( leader->isReservOnNeeded() ) 00203 { 00204 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00205 SEESGroup::dlog[Debug::LEVEL4] << myname << "(checkReserv): needON for " 00206 << leader->getName() << endl; 00207 00208 reserv(true); 00209 needCheck = true; 00210 } 00211 else if( leader->isReservOffNeeded() ) 00212 { 00213 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00214 SEESGroup::dlog[Debug::LEVEL4] << myname << "(checkReserv): needOFF for " 00215 << leader->getName() << endl; 00216 00217 reserv(false); 00218 needCheck = true; 00219 } 00220 else 00221 { 00222 // Сбрасываем все таймеры и тригеры 00223 // т.к. резерв никому не требуется 00224 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00225 { 00226 it->ptPause.setTiming(0); 00227 it->trChangeState.hi(true); 00228 it->waitRunning = false; 00229 it->waitStopping = false; 00230 } 00231 00232 resetReserv(); 00233 } 00234 00235 if( !needCheck ) 00236 ptCheckReserv.setTiming(UniSetTimer::WaitUpTime); 00237 }
| long SEESGroup::getF | ( | ) |
частота
Перекрестные ссылки lst.
Используется в UnionGroups::updateF() и updatePowerInfo().
00750 { 00751 // при параллельном включении: 00752 // частоты одинаковые 00753 { // lock 00754 UniSetTypes::uniset_mutex_lock lock(lstMutex, 3000); 00755 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00756 { 00757 if( (*it)->getF() > 0 ) 00758 return (*it)->getF(); 00759 } 00760 } // unlock 00761 00762 return 0; 00763 }
| long SEESGroup::getP | ( | ) |
суммарная мощность
Перекрестные ссылки lst.
Используется в UnionGroups::updateP().
00720 { 00721 // при параллельном включении: 00722 // мощности складываются.. 00723 long P=0; 00724 { // lock 00725 UniSetTypes::uniset_mutex_lock lock(lstMutex, 3000); 00726 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00727 P += (*it)->getP(); 00728 } // unlock 00729 00730 return P; 00731 }
| long SEESGroup::getReservPower | ( | ) |
резерв мощности
Перекрестные ссылки lst.
Используется в UnionGroups::updateReservPower().
00766 { 00767 long Pres=0; 00768 00769 { // lock 00770 UniSetTypes::uniset_mutex_lock lock(lstMutex, 3000); 00771 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00772 Pres += (*it)->getReservPower(); 00773 } // unlock 00774 00775 return Pres; 00776 }
| long SEESGroup::getU | ( | ) |
напряжение
Перекрестные ссылки lst.
Используется в updatePowerInfo() и UnionGroups::updateU().
00734 { 00735 // при параллельном включении: 00736 // напряжения одинаковые 00737 { // lock 00738 UniSetTypes::uniset_mutex_lock lock(lstMutex, 3000); 00739 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00740 { 00741 if( (*it)->getU() > 0 ) 00742 return (*it)->getU(); 00743 } 00744 } // unlock 00745 00746 return 0; 00747 }
| bool SEESGroup::isFdev | ( | ) |
отклонение частоты от нормы
Перекрестные ссылки f_dev.
Используется в UnionGroups::updateFdev().
00793 { 00794 return f_dev; 00795 }
| bool SEESGroup::isProtection | ( | ) |
| bool SEESGroup::isReadyForLoading | ( | ) |
готова ли группа к приёму нагрузки
Перекрестные ссылки lst.
Используется в UnionGroups::updateReadyForLoading().
00166 { 00167 // если есть хоть один работющий ДГ и он не перегружен (не требует резерва), то СЭС готова. 00168 UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00169 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00170 { 00171 if( (*it)->isOnMode() && !(*it)->isReservOnNeeded() ) 00172 return true; 00173 } 00174 00175 return false; 00176 }
| bool SEESGroup::isUdev | ( | ) |
отклонение напряжения от нормы
Перекрестные ссылки U_dev.
Используется в UnionGroups::updateUdev().
00788 { 00789 return U_dev; 00790 }
| void SEESGroup::makeReservList | ( | ) | [protected] |
обновление списка резервных ДГ
Перекрестные ссылки SEES::isAutoControl(), SEES::isOnMode(), leader, lst, myname и rlst.
00421 { 00422 UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00423 00424 // проходим по списку СЭС в группе 00425 // определяем главный ДГ (он должен быть один) 00426 // и какие есть резервные ДГ 00427 SEES* main = 0; 00428 RList rlist; 00429 00430 // Т.к. самым приоритетным считается ДГ с наименьшим заданным приоритетом, 00431 // то строим список резервных так: делаем map, сортируем по возрастанию приоритета 00432 // и строим уже список резервных 00433 // в map - добавляем только те ДГ, которые находятся в режиме "авто" 00434 typedef std::map<int,SEES*> PriorityMap; 00435 PriorityMap prmap; 00436 00437 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00438 { 00439 SEES* ses(*it); 00440 00441 if( ses->isAutoControl() && ses->getPriority()>0 ) 00442 prmap[ses->getPriority()] = ses; 00443 else 00444 ses->setLeader(false); // просто на всякий сбрасываем флаг 00445 00446 // если ГДГ не в режиме автомат, сбрасываем команды управления резервом 00447 if( !ses->isAutoControl() ) 00448 ses->resetReservCommand(); 00449 } 00450 00451 // формируем список резервных на основе "карты приоритетов" 00452 if( !prmap.empty() ) 00453 { 00454 PriorityMap::iterator it=prmap.begin(); 00455 // первый в списке, это самый приоритетный 00456 main = it->second; 00457 it++; 00458 // остальные добавляем в список в соответсвии с приоритетом 00459 while( it!=prmap.end() ) 00460 { 00461 rlist.push_back(it->second); 00462 it++; 00463 } 00464 } 00465 00466 // ------------------- 00467 // Есть особый случай: 00468 // Допустим, что НЕ приоритетный дизель, до перевода в "автомат" 00469 // был в ручную запущен. А переключателем "приоритета пуска" 00470 // выставлен приоритетным другой дизель. То после перевода обоих ДГ 00471 // в режим "автомат" будет противоречивое состояние: 00472 // Тот дизель который должен быть основным (и по идее начать автоматически запускаться) 00473 // не запущен, а тот который должен быть резервным (и должен быть остановлен), 00474 // оказывается запущенным (уже на шинах). 00475 // Для решения этого вопроса, здесь реализована следующая логика: 00476 // Если найденный "потенциальный" лидер, не запущен, то мы смотрим, 00477 // нет ли среди списка резервных уже запущенного. Если есть, то находим, 00478 // среди запущенных (резервных), ДГ с наименьшим приоритетом и делаем его лидером. 00479 // А нашего "потенциального" лидера (если был до этого найден), 00480 // переводим в список резервных. 00481 if( !main || (main && !main->isOnMode()) ) 00482 { 00483 RList::iterator rit = rlist.end(); 00484 for( RList::iterator it=rlist.begin(); it!=rlist.end(); ++it ) 00485 { 00486 if( !it->ses->isOnMode() ) 00487 continue; 00488 00489 long prior = it->ses->getPriority(); 00490 if( rit == rlist.end() || ( prior>0 && prior < rit->ses->getPriority() )) 00491 rit = it; 00492 } 00493 00494 // если нашли среди резервных "запущенный" 00495 if( rit != rlist.end() ) 00496 { 00497 if( main ) 00498 { 00499 // сперва добавляем "бывшего" лидера в список резервных 00500 ReservInfo ri(main); 00501 rlist.push_back(ri); 00502 } 00503 00504 // запоминаем нового лидера 00505 main = rit->ses; 00506 // удаляем его из списка резервных 00507 rlist.erase(rit); 00508 } 00509 } 00510 00511 // ------------------- 00512 if( !main ) 00513 { 00514 // Если не нашли (явного) приоритетного лидера (например у всех одинаковый приоритет) 00515 // а список резервных не пустой 00516 // то берём из резервных с наименьшим номером 00517 // и делаем его лидером (удалив из списка резервных) 00518 RList::iterator rit = rlist.end(); 00519 if( !rlist.empty() ) 00520 { 00521 for( RList::iterator it=rlist.begin(); it!=rlist.end(); ++it ) 00522 { 00523 long num = it->ses->getNumber(); 00524 if( rit == rlist.end() || num < rit->ses->getNumber() ) 00525 rit = it; 00526 } 00527 00528 if( rit != rlist.end() ) 00529 { 00530 main = rit->ses; 00531 rlist.erase(rit); 00532 } 00533 } 00534 } 00535 00536 // ------------------ 00537 if( main ) 00538 { 00539 // чтобы сохранить работу внутренних таймеров структуры ReservInfo 00540 // надо в новом списке обновить информацию взяв из старого 00541 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00542 update( rlist, (*it) ); 00543 00544 leader = main; 00545 rlst = rlist; 00546 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00547 { 00548 SEESGroup::dlog[Debug::LEVEL4] << myname << "(makeReservList): For leader='ses" << main->getNumber() 00549 << "' reserv(" << rlist.size() << "): ["; 00550 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00551 SEESGroup::dlog(Debug::LEVEL4) << " ses" << it->ses->getNumber(); // << ")" << it->ses->getName(); 00552 SEESGroup::dlog(Debug::LEVEL4) << " ]" << endl; 00553 } 00554 00555 // выставляем у всех признак, что они в резерве (не лидеры) 00556 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00557 { 00558 try 00559 { 00560 it->ses->setLeader(false); 00561 } 00562 catch(...){} 00563 } 00564 // и выставляем режим у "ведущего" 00565 leader->setLeader(true); 00566 } 00567 else 00568 { 00569 SEESGroup::dlog[Debug::LEVEL4] << myname << "(makeReservList): LEADER not found..." << endl; 00570 leader = 0; 00571 rlst.clear(); 00572 } 00573 }
| void SEESGroup::releaseQG | ( | int | num | ) | throw (UniSetTypes::NameNotFound) |
освобождение приоритета включения генераторного автомата Проверка можно ли запускать указанный СЭС например ограничение по максимльному разрешенному количеству одновременно работющих ДГ на шинах
00623 { 00624 { // lock 00625 UniSetTypes::uniset_mutex_lock lock(lstMutex, 4000); 00626 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00627 { 00628 SEES* s(*it); 00629 if( s->getNumber() == num ) 00630 { 00631 if( s->isHaveQGLock() ) 00632 SEESGroup::dlog[Debug::INFO] << myname << "(releaseQG): RELEASE QG" << num << endl; 00633 00634 s->setQGLock(false); 00635 qf_locked = 0; 00636 return; 00637 } 00638 } 00639 } 00640 00641 ostringstream err; 00642 err << myname << "(acceptQG): Not found ses" + num; 00643 throw NameNotFound(err.str()); 00644 }
| void SEESGroup::requiredReserv | ( | bool | set | ) |
| void SEESGroup::reserv | ( | bool | set | ) | [protected] |
функция запуска или остановки резерва
Перекрестные ссылки SEES::isProtection(), myname, rlst, SEESGroup::ReservInfo::waitRunning и SEESGroup::ReservInfo::waitStopping.
Используется в checkReserv().
00240 { 00241 // UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00242 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00243 { 00244 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00245 << " set=" << set 00246 << " rlist=" << rlst.size() << endl; 00247 } 00248 00249 if( rlst.empty() ) 00250 { 00251 SEESGroup::dlog[Debug::LEVEL4] << myname 00252 << "(reserv): rlst=0 RESERV NOT FOUND" << endl; 00253 00254 ptCheckReserv.setTiming(UniSetTimer::WaitUpTime); 00255 return; 00256 } 00257 00258 // Проходим по списку резервных 00259 // и ищем кто готов запускатся.. 00260 // Т.к. список выстроен в соответсвии с приоритетом 00261 // то можно остановиться на первом подходящем 00262 00263 // Если нам нужно запускать ищем в прямом порядке, 00264 // если останавливать, то в обратном. 00265 typedef list<ReservInfo*> TMPList; 00266 TMPList tmplist; 00267 if( set ) 00268 { 00269 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00270 tmplist.push_back( &(*it) ); 00271 } 00272 else 00273 { 00274 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00275 tmplist.push_front( &(*it) ); 00276 } 00277 00278 ReservInfo* rses = 0; 00279 for( TMPList::iterator it=tmplist.begin(); it!=tmplist.end(); ++it ) 00280 { 00281 ReservInfo* ri(*it); 00282 // Ловим момент, если резервный только что, запустился/остановился 00283 // и засекаем таймер на "паузу" 00284 // необходимую для прихода системы в устойчивое состояние 00285 // после пуска/остановки резерва 00286 // (например распределение нагрузки и т.п.) 00287 // а то может начать запускатся следующий резервный 00288 // если распределитель ещё не успел "поработать" 00289 // и основной(leader) остался загружен 00290 // несмотря на то, что уже запустился резервный 00291 if( set && ri->trChangeState.hi(ri->ses->getOMode()==mON) ) 00292 { 00293 ri->ptPause.setTiming(reservStatePause); 00294 ri->waitRunning = false; 00295 ri->waitStopping = false; 00296 } 00297 else if( !set && ri->trChangeState.hi(ri->ses->getOMode()==mOFF) ) 00298 { 00299 ri->ptPause.setTiming(reservStatePause); 00300 ri->waitRunning = false; 00301 ri->waitStopping = false; 00302 } 00303 00304 // ничего не делаем, пока резервный ses исполняет команду 00305 // либо он её выполнит, либо timeout, либо у него сработает защита 00306 if( (set && ri->waitRunning) || (!set && ri->waitStopping) ) 00307 { 00308 if( !ri->ptPause.checkTime() && !ri->ses->isProtection() ) 00309 { 00310 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00311 { 00312 int wmsec = ri->ptPause.getInterval() - ri->ptPause.getCurrent(); 00313 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00314 << " IGNORE. Wait processing command for ses" 00315 << ri->ses->getNumber() 00316 << " (sec=" << wmsec/1000 << " msec=" << wmsec%1000 << ")" 00317 << endl; 00318 } 00319 ptCheckReserv.setTiming(checkReservTime); 00320 return; 00321 } 00322 00323 ri->waitRunning = false; 00324 ri->waitStopping = false; 00325 ri->ptPause.setTiming(0); 00326 } 00327 00328 // Если пауза ещё не прошла, ждём... 00329 // либо признак нужности/ненужности резерва 00330 // снимется у leader, либо мы начнём 00331 // запускатся/останавливать следующий в списке 00332 if( !ri->ptPause.checkTime() && !ri->waitRunning && !ri->waitStopping ) 00333 { 00334 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00335 { 00336 int wmsec = ri->ptPause.getInterval() - ri->ptPause.getCurrent(); 00337 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00338 << " IGNORE. Wait state pause for ses" 00339 << ri->ses->getNumber() 00340 << " (sec=" << wmsec/1000 << " msec=" << wmsec%1000 << ")" 00341 << endl; 00342 } 00343 ptCheckReserv.setTiming(checkReservTime); 00344 return; 00345 } 00346 00347 // Эти условия должны проверятся ОБЯЗАТЕЛЬНО после ptStatePause 00348 // т.к. canReservRunning или canReservStopping вернут false 00349 // как только, резерв запустится/остановится. 00350 // а нам ведь надо ещё и паузу выждать, 00351 // прежде чем пытатся запускать/останавливать 00352 // следующий резервный в списке.. 00353 if( set && !ri->ses->canReservRunning() ) // требуется запуск, а не может 00354 continue; 00355 00356 if( !set && !ri->ses->canReservStopping() ) // требуется остановка, а не может 00357 continue; 00358 00359 rses = ri; 00360 break; 00361 } 00362 00363 if( !rses ) 00364 { 00365 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00366 << " FREE RESERV NOT FOUND" << endl; 00367 ptCheckReserv.setTiming(UniSetTimer::WaitUpTime); 00368 return; 00369 } 00370 00371 if( set ) 00372 { 00373 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00374 { 00375 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00376 << " SELECT RUN ses" << rses->ses->getNumber() << endl; 00377 } 00378 rses->ses->onReservCommand(); 00379 rses->waitRunning = true; 00380 rses->waitStopping = false; 00381 } 00382 else 00383 { 00384 if( SEESGroup::dlog.debugging(Debug::LEVEL4) ) 00385 { 00386 SEESGroup::dlog[Debug::LEVEL4] << myname << "(reserv):" 00387 << " SELECT STOP ses" << rses->ses->getNumber() << endl; 00388 } 00389 rses->ses->offReservCommand(); 00390 rses->waitRunning = false; 00391 rses->waitStopping = true; 00392 } 00393 00394 ptCheckReserv.setTiming(checkReservTime); 00395 rses->trChangeState.hi(false); 00396 rses->ptPause.setTiming(reservCommandTimeout); 00397 }
| bool SEESGroup::resetReserv | ( | ) | [protected] |
сброс команд управления резерва
Перекрестные ссылки lst, myname и rlst.
Используется в checkReserv().
00400 { 00401 // SEESGroup::dlog[Debug::LEVEL4] << myname << "(resetReserv): ..." << endl; 00402 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00403 { 00404 // если есть хоть один СЭС требущий резерв, 00405 // то сбрасывать команды нельзя... 00406 if( (*it)->isReservOnNeeded() || (*it)->isReservOffNeeded() ) 00407 return false; 00408 } 00409 00410 // сбрасываем команды 00411 for( RList::iterator it=rlst.begin(); it!=rlst.end(); ++it ) 00412 { 00413 SEESGroup::dlog[Debug::LEVEL4] << myname << "(resetReserv): сбрасываем команды резерва для ses" << it->ses->getNumber() << endl; 00414 it->ses->resetReservCommand(); 00415 } 00416 00417 return true; 00418 }
| void SEESGroup::update | ( | RList & | rlist, | |
| ReservInfo & | ri | |||
| ) | [static, protected] |
функция копирующая в список rlst, информацию из ri, если там есть такой ДГ
00153 { 00154 //UniSetTypes::uniset_mutex_lock lock(lstMutex, 5000); 00155 for( RList::iterator it=rlist.begin(); it!=rlist.end(); ++it ) 00156 { 00157 if( it->ses->getNumber() == ri.ses->getNumber() ) 00158 { 00159 (*it) = ri; 00160 return; 00161 } 00162 } 00163 }
| void SEESGroup::updateCounters | ( | ) | [protected] |
Обновление различных счётчиков
Перекрестные ссылки countWorkingDG и lst.
00673 { 00674 int count = 0; 00675 { // lock 00676 UniSetTypes::uniset_mutex_lock lock(lstMutex, 4000); 00677 for( SESList::iterator it=lst.begin(); it!=lst.end(); ++it ) 00678 { 00679 if( (*it)->isOnMode() ) 00680 count++; 00681 } 00682 } 00683 00684 // Обновляем информацию о текущем количестве работающих ДГ 00685 { 00686 uniset_mutex_lock l(maxrunMutex,200); 00687 countWorkingDG = count; 00688 } 00689 }
| void SEESGroup::updatePowerInfo | ( | ) |
Обновление расчётных параметров сети
Перекрестные ссылки getF(), getU(), sc_Fdev и sc_Udev.
00798 { 00799 bool u_res = false; 00800 // Фомирование сигнала по отклонению напряжения 00801 if( U_min > 0 ) 00802 { 00803 long u = getU(); 00804 if( u > 0 ) 00805 { 00806 if( u < U_min || u > U_max ) 00807 u_res = true; 00808 } 00809 } 00810 00811 // устанавливаем (или отключаем) таймер 00812 sc_Udev.rotate(u_res); 00813 00814 bool f_res = false; 00815 // Фомирование сигнала по отклонению напряжения 00816 if( f_min > 0 ) 00817 { 00818 long f = getF(); 00819 if( f > 0 ) 00820 { 00821 if( f < f_min || f > f_max ) 00822 f_res = true; 00823 } 00824 } 00825 00826 // устанавливаем (или отключаем) таймер 00827 sc_Fdev.rotate(f_res); 00828 }
int SEESGroup::countWorkingDG [protected] |
текущее количество работающих ДГ
Используется в updateCounters().
bool SEESGroup::f_dev [protected] |
флаг отклонение частоты от нормы
Используется в isFdev().
int SEESGroup::gnum [protected] |
номер данной группы
SEES* SEESGroup::leader [protected] |
указатель на "ведущий" ДГ в группе
Используется в checkReserv() и makeReservList().
SESList SEESGroup::lst [protected] |
номер СЭС заблокировавшей включение автомата список СЭС в группе
Используется в checkAloneWorking(), getF(), getP(), getReservPower(), getU(), isProtection(), isReadyForLoading(), makeReservList(), requiredReserv(), resetReserv() и updateCounters().
int SEESGroup::maxWorkingDG [protected] |
максимальное разрешённое количество одновременно работающих ДГ
std::string SEESGroup::myname [protected] |
исключительно для логов
Используется в checkReserv(), makeReservList(), reserv() и resetReserv().
RList SEESGroup::rlst [protected] |
список доступных резервных ДГ
Используется в checkReserv(), makeReservList(), reserv() и resetReserv().
SandClock SEESGroup::sc_Fdev [protected] |
специальная задержка на срабатывание по сигналу "отклонение частоты"
Используется в updatePowerInfo().
SandClock SEESGroup::sc_Udev [protected] |
специальная задержка на срабатывание по сигналу "отклонение напряжения"
Используется в updatePowerInfo().
bool SEESGroup::U_dev [protected] |
флаг отклонение напряжения от нормы
Используется в isUdev().
1.5.9