00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "jaus/core/discovery/discovery.h"
00041 #include "jaus/core/discovery/queryconfiguration.h"
00042 #include "jaus/core/discovery/queryidentification.h"
00043 #include "jaus/core/discovery/queryservices.h"
00044 #include "jaus/core/discovery/querysubsystemlist.h"
00045 #include "jaus/core/discovery/registerservices.h"
00046 #include "jaus/core/discovery/reportconfiguration.h"
00047 #include "jaus/core/discovery/reportidentification.h"
00048 #include "jaus/core/discovery/reportservices.h"
00049 #include "jaus/core/discovery/reportsubsystemlist.h"
00050 #include "jaus/core/management/querystatus.h"
00051 #include "jaus/core/control/queryauthority.h"
00052 #include "jaus/core/events/event.h"
00053 #include "jaus/core/transport/transport.h"
00054 #include "jaus/core/component.h"
00055
00056 #include <iostream>
00057 #include <tinyxml/tinyxml.h>
00058
00059 using namespace JAUS;
00060
00061 const std::string Discovery::Name = "urn:jaus:jss:core:Discovery";
00062
00068 Discovery::Discovery() : Events::Child(Service::ID(Discovery::Name), Service::ID(Events::Name))
00069 {
00070 mBroadcastDelayMs = 5000;
00071 mBroadcastTimeMs = 0;
00072 mDiscoverSubsystemsFlag = true;
00073 mComponentIdentification = "Component";
00074 mNodeIdentification = "Node";
00075 mSubsystemType = Subsystem::OtherSubsystem;
00076 }
00077
00078
00084 Discovery::~Discovery()
00085 {
00086 mCallbacksMutex.Lock();
00087 mCallbacks.clear();
00088 mCallbacksMutex.Unlock();
00089
00090 mSubsystemDataMutex.Lock();
00091 Subsystem::DeleteSubsystemMap(mSystem);
00092 mSubsystemDataMutex.Unlock();
00093 }
00094
00095
00106 bool Discovery::LoadSettings(const std::string& filename)
00107 {
00108 TiXmlDocument xml;
00109
00110 if(xml.LoadFile(filename.c_str()) == false)
00111 {
00112 return false;
00113 }
00114 TiXmlHandle doc(&xml);
00115 TiXmlNode* node;
00116 TiXmlElement* element;
00117 node = doc.FirstChild("JAUS").FirstChild("Discovery").FirstChild("Frequency").FirstChild().ToNode();
00118 if(node && node->Value())
00119 {
00120 SetDiscoveryFrequency(atof(node->Value()));
00121 }
00122 node = doc.FirstChild("JAUS").FirstChild("Discovery").FirstChild("DiscoverSubsystems").FirstChild().ToNode();
00123 if(node && node->Value())
00124 {
00125 DiscoverSubsystems(atoi(node->Value()) > 0 ? true : false);
00126 }
00127 node = doc.FirstChild("JAUS").FirstChild("Discovery").FirstChild("ComponentIdentification").FirstChild().ToNode();
00128 if(node && node->Value())
00129 {
00130 mComponentIdentification = node->Value();
00131 }
00132 node = doc.FirstChild("JAUS").FirstChild("Discovery").FirstChild("NodeIdentification").FirstChild().ToNode();
00133 if(node && node->Value())
00134 {
00135 mNodeIdentification = node->Value();
00136 }
00137 element = doc.FirstChild("JAUS").FirstChild("Discovery").FirstChild("SubsystemIdentification").ToElement();
00138 if(element && element->Attribute("type") && element->FirstChild() && element->FirstChild()->Value())
00139 {
00140 mSubsystemType = (Subsystem::Type)atoi(element->Attribute("type"));
00141 mSubsystemIdentification = element->FirstChild()->Value();
00142 }
00143 return true;
00144 }
00145
00146
00152 void Discovery::Initialize()
00153 {
00154 if(mSystem.size() == 0)
00155 {
00156 if(mDiscoverSubsystemsFlag)
00157 {
00158 mSubsystemList.insert(GetComponentID());
00159 }
00160 if(mSubsystemType == Subsystem::Vehicle)
00161 {
00162 mSystem[GetComponentID().mSubsystem] = new Vehicle();
00163 }
00164 else
00165 {
00166 mSystem[GetComponentID().mSubsystem] = new Subsystem();
00167 }
00168 mSystem[GetComponentID().mSubsystem]->mIdentification = mSubsystemIdentification;
00169 Service::ID::Set services = GetComponent()->GetServiceSet();
00170 mSystem[GetComponentID().mSubsystem]->AddComponent(GetComponentID(), services);
00171 mSystem[GetComponentID().mSubsystem]->GetComponent(GetComponentID())->mIdentification = mComponentIdentification;
00172 }
00173 }
00174
00175
00181 void Discovery::Shutdown()
00182 {
00183 mSubsystemDataMutex.Lock();
00184 Subsystem::DeleteSubsystemMap(mSystem);
00185 mSubsystemList.clear();
00186 mSubsystemDataMutex.Unlock();
00187 }
00188
00189
00200 void Discovery::Receive(const Message* message)
00201 {
00202 Subsystem::Map::iterator myInfo = mSystem.find(GetComponentID().mSubsystem);
00203 if(myInfo == mSystem.end())
00204 {
00205 Subsystem* ptr = NULL;
00206
00207
00208 if(mSubsystemType == Subsystem::Vehicle)
00209 {
00210 ptr = mSystem[GetComponentID().mSubsystem] = new Vehicle();
00211 ((Vehicle*)ptr)->mAuthority = GetComponent()->AccessControlService()->GetAuthorityCode();
00212 }
00213 else
00214 {
00215 ptr = mSystem[GetComponentID().mSubsystem] = new Subsystem();
00216 }
00217 ptr->mType = mSubsystemType;
00218 ptr->mIdentification = mSubsystemIdentification;
00219 ptr->mSubsystemID = GetComponentID().mSubsystem;
00220 ptr->GetComponent(GetComponentID())->mIdentification = mComponentIdentification;
00221 ptr->GetComponent(GetComponentID())->mServices = GetTransportService()->GetServices();
00222 ptr->GetComponent(GetComponentID())->mAuthorityLevel = GetComponent()->AccessControlService()->GetAuthorityCode();
00223 }
00224
00225 switch(message->GetMessageCode())
00226 {
00227 case QUERY_CONFIGURATION:
00228 {
00229 if(mDebugMessagesFlag)
00230 {
00231 Mutex::ScopedLock lock(&mDebugMessagesMutex);
00232 std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Received Message Type [QueryConfiguration] from " << message->GetSourceID().ToString() << std::endl;
00233 }
00234 const QueryConfiguration* query = dynamic_cast<const QueryConfiguration*>(message);
00235 if(query)
00236 {
00237 ReportConfiguration response(query->GetSourceID(), GetComponentID());
00238
00239 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00240 Subsystem::Map::const_iterator s = mSystem.find(GetComponentID().mSubsystem);
00241 if(s != mSystem.end())
00242 {
00243 Subsystem::Configuration::const_iterator node;
00244 Subsystem::Component::Set::const_iterator component;
00245
00246
00247 if(query->GetQueryType() == QueryConfiguration::NodeConfiguration)
00248 {
00249 node = s->second->mConfiguration.find(GetComponentID().mNode);
00250 if(node != s->second->mConfiguration.end())
00251 {
00252 for(component = node->second.begin();
00253 component != node->second.end();
00254 component++)
00255 {
00256 (*(response.GetNodes()))[node->first].push_back(ReportConfiguration::Record(component->mID.mComponent, 0));
00257 }
00258 }
00259 }
00260
00261 else
00262 {
00263 for(node = s->second->mConfiguration.begin();
00264 node != s->second->mConfiguration.end();
00265 node++)
00266 {
00267 for(component = node->second.begin();
00268 component != node->second.end();
00269 component++)
00270 {
00271 (*(response.GetNodes()))[node->first].push_back(ReportConfiguration::Record(component->mID.mComponent, 0));
00272 }
00273 }
00274 }
00275 }
00276
00277 Send(&response);
00278 if(mDebugMessagesFlag)
00279 {
00280 Mutex::ScopedLock lock(&mDebugMessagesMutex);
00281 std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Sent Message Type [ReportConfiguration] to " << message->GetSourceID().ToString() << std::endl;
00282 response.PrintMessageBody();
00283 }
00284 }
00285 }
00286 break;
00287 case QUERY_IDENTIFICATION:
00288 {
00289 if(mDebugMessagesFlag)
00290 {
00291 Mutex::ScopedLock lock(&mDebugMessagesMutex);
00292 std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Received Message Type [QueryIdentification] from " << message->GetSourceID().ToString() << std::endl;
00293 }
00294 const QueryIdentification* query = dynamic_cast<const QueryIdentification*>(message);
00295 bool haveData = false;
00296 ReportIdentification response(query->GetSourceID(), GetComponentID());
00297
00298 response.SetQueryType((ReportIdentification::QueryType)query->GetQueryType());
00299
00300 switch(query->GetQueryType())
00301 {
00302 case QueryIdentification::SubsystemIdentification:
00303
00304 if(mSubsystemIdentification.size() > 0)
00305 {
00306 haveData = true;
00307 response.SetIdentification(mSubsystemIdentification);
00308 response.SetType((ReportIdentification::IdentificationType)mSubsystemType);
00309 }
00310
00311 if(GetSubsystem(query->GetSourceID().mSubsystem)->mIdentification.size() == 0)
00312 {
00313 QueryIdentification myQuery(query->GetSourceID(), query->GetDestinationID());
00314 myQuery.SetQueryType(QueryIdentification::SubsystemIdentification);
00315 Send(&myQuery);
00316 }
00317 break;
00318 case QueryIdentification::NodeIdentification:
00319 if(mNodeIdentification.size() > 0)
00320 {
00321 haveData = true;
00322 response.SetIdentification(mNodeIdentification);
00323 response.SetType(ReportIdentification::Node);
00324 }
00325 break;
00326 case QueryIdentification::ComponentIdentification:
00327 if(mNodeIdentification.size() > 0)
00328 {
00329 haveData = true;
00330 response.SetIdentification(mComponentIdentification);
00331 response.SetType(ReportIdentification::Component);
00332 }
00333 break;
00334 default:
00335 break;
00336 }
00337
00338 {
00339 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00340 Subsystem::Map::iterator subsystem = mSystem.find(query->GetSourceID().mSubsystem);
00341 if(subsystem == mSystem.end() || subsystem->second->mConfiguration.size() == 0)
00342 {
00343 QueryConfiguration queryConfig(query->GetSourceID(), GetComponentID());
00344 queryConfig.SetQueryType(QueryConfiguration::SubsystemConfiguration);
00345 Send(&queryConfig);
00346 }
00347 }
00348
00349 if(haveData)
00350 {
00351 Send(&response);
00352 }
00353
00354
00355
00356
00357 if(query->GetDestinationID().mSubsystem == Address::GlobalBroadcast)
00358 {
00359 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00360 mSubsystemList.insert(query->GetSourceID());
00361 Subsystem::Map::iterator s = mSystem.find(GetComponentID().mSubsystem);
00362 if(s != mSystem.end())
00363 {
00364 s->second->mUpdateTime.SetCurrentTime();
00365 }
00366 if(query->GetSourceID().mSubsystem == GetComponentID().mSubsystem)
00367 {
00368 this->SignalEvent(REPORT_SUBSYSTEM_LIST);
00369 }
00370 }
00371 }
00372 break;
00373 case QUERY_SERVICES:
00374 {
00375 if(mDebugMessagesFlag)
00376 {
00377 Mutex::ScopedLock lock(&mDebugMessagesMutex);
00378 std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Received Message Type [QueryServices] from " << message->GetSourceID().ToString() << std::endl;
00379 }
00380 const QueryServices* query = dynamic_cast<const QueryServices*>(message);
00381 if(query)
00382 {
00383 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00384 Subsystem::Map::const_iterator s = mSystem.find(GetComponentID().mSubsystem);
00385 if(s != mSystem.end())
00386 {
00387 ReportServices report(query->GetSourceID(), GetComponentID());
00388 Subsystem::Configuration::const_iterator node;
00389 QueryServices::List::const_iterator queryNode;
00390
00391
00392 for(queryNode = query->GetNodeList()->begin();
00393 queryNode != query->GetNodeList()->end();
00394 queryNode++)
00395 {
00396 node = s->second->mConfiguration.find(queryNode->first);
00397 if(node != s->second->mConfiguration.end())
00398 {
00399
00400 std::vector<Byte>::const_iterator queryComponent;
00401 for(queryComponent = queryNode->second.begin();
00402 queryComponent != queryNode->second.end();
00403 queryComponent++)
00404 {
00405
00406 Subsystem::Component::Set::const_iterator component;
00407 for(component = node->second.begin();
00408 component != node->second.end();
00409 component++)
00410 {
00411 if(component->mID.mComponent == *queryComponent)
00412 {
00413 ReportServices::Record record(component->mID.mComponent);
00414 record.mServices = component->mServices;
00415 (*report.GetServices())[node->first].push_back(record);
00416 break;
00417 }
00418 }
00419 }
00420 }
00421 }
00422 Send(&report);
00423 }
00424 }
00425 }
00426 break;
00427 case QUERY_SUBSYSTEM_LIST:
00428 {
00429 ReportSubsystemList report(message->GetSourceID(), GetComponentID());
00430
00431 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00432
00433 *report.GetSubsystemList() = Address::ToList(mSubsystemList);
00434
00435 Send(&report);
00436 }
00437 break;
00438 case REGISTER_SERVICES:
00439 {
00440 const RegisterServices* registerServices = dynamic_cast<const RegisterServices*>(message);
00441 if(registerServices)
00442 {
00443 Subsystem::Map::iterator subsystem;
00444 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00445
00446 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00447
00448 if(subsystem == mSystem.end())
00449 {
00450 mSystem[message->GetSourceID().mSubsystem] = new Subsystem();
00451 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00452 subsystem->second->mSubsystemID = subsystem->first;
00453 }
00454
00455 subsystem->second->GetComponent(message->GetSourceID())->mServices = *registerServices->GetServices();
00456 subsystem->second->mUpdateTime.SetCurrentTime();
00457 }
00458 }
00459 break;
00460 case REPORT_CONFIGURATION:
00461 {
00462 const ReportConfiguration* report = dynamic_cast<const ReportConfiguration*>(message);
00463 if(report)
00464 {
00465 Subsystem::Map::iterator subsystem;
00466 QueryServices query(report->GetSourceID(), GetComponentID());
00467
00468 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00469
00470 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00471
00472 if(subsystem == mSystem.end())
00473 {
00474 mSystem[message->GetSourceID().mSubsystem] = new Subsystem();
00475 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00476 subsystem->second->mSubsystemID = subsystem->first;
00477 }
00478
00479 Address id(report->GetSourceID().mSubsystem, 0, 0);
00480
00481
00482 ReportConfiguration::Nodes::const_iterator node;
00483 for(node = report->GetNodes()->begin();
00484 node != report->GetNodes()->end();
00485 node++)
00486 {
00487 ReportConfiguration::Record::List::const_iterator record;
00488 id.mNode = node->first;
00489 for(record = node->second.begin();
00490 record != node->second.end();
00491 record++)
00492 {
00493 id.mComponent = record->mComponent;
00494 subsystem->second->GetComponent(id);
00495
00496 (*(query.GetNodeList()))[id.mNode].push_back(id.mComponent);
00497
00498
00499 QueryAuthority queryAuthority(id, GetComponentID());
00500 QueryStatus queryStatus(id, GetComponentID());
00501 Send(&queryAuthority);
00502
00503 }
00504 }
00505
00506 subsystem->second->mUpdateTime.SetCurrentTime();
00507
00508 if(query.GetNodeList()->size() == 0)
00509 {
00510 (*(query.GetNodeList()))[report->GetSourceID().mNode].push_back(report->GetSourceID().mComponent);
00511 }
00512 Send(&query);
00513
00514 if(report->GetSourceID().mSubsystem == GetComponentID().mSubsystem)
00515 {
00516 this->SignalEvent(REPORT_CONFIGURATION);
00517 }
00518 }
00519 }
00520 break;
00521 case REPORT_IDENTIFICATION:
00522 {
00523 const ReportIdentification* report = dynamic_cast<const ReportIdentification*>(message);
00524 if(report)
00525 {
00526 Subsystem::Map::iterator subsystem;
00527
00528
00529 RegisterServices registerServices(report->GetSourceID(), GetComponentID());
00530 *registerServices.GetServices() = GetTransportService()->GetServices();
00531 Send(®isterServices);
00532
00533 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00534
00535 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00536
00537 if(subsystem != mSystem.end())
00538 {
00539 if(report->GetQueryType() == ReportIdentification::SubsystemIdentification &&
00540 report->GetType() == ReportIdentification::Vehicle)
00541 {
00542
00543
00544
00545
00546 Vehicle* vehicle = dynamic_cast<Vehicle*>(subsystem->second);
00547 if(vehicle == NULL)
00548 {
00549 vehicle = new Vehicle();
00550 vehicle->mSubsystemID = subsystem->first;
00551 vehicle->CopySubsystemData(subsystem->second);
00552 delete subsystem->second;
00553 subsystem->second = vehicle;
00554 }
00555 }
00556 }
00557 else
00558 {
00559 if(report->GetType() == ReportIdentification::Vehicle)
00560 {
00561 mSystem[message->GetSourceID().mSubsystem] = new Vehicle();
00562 }
00563 else
00564 {
00565 mSystem[message->GetSourceID().mSubsystem] = new Subsystem();
00566 }
00567 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00568 subsystem->second->mSubsystemID = subsystem->first;
00569 }
00570
00571 switch(report->GetQueryType())
00572 {
00573 case ReportIdentification::SubsystemIdentification:
00574 {
00575 subsystem->second->mIdentification = report->GetIdentification();
00576 subsystem->second->mType = (Subsystem::Type)report->GetType();
00577
00578
00579 QueryConfiguration querySubsystemConfig(report->GetSourceID(), GetComponentID());
00580 querySubsystemConfig.SetQueryType(QueryConfiguration::SubsystemConfiguration);
00581 Send(&querySubsystemConfig);
00582
00583 if(subsystem->first == GetComponentID().mSubsystem)
00584 {
00585 mSubsystemIdentification = report->GetIdentification();
00586 mSubsystemType = (Subsystem::Type)report->GetType();
00587 }
00588 }
00589 break;
00590 case ReportIdentification::NodeIdentification:
00591 {
00592 if(subsystem->first == GetComponentID().mSubsystem)
00593 {
00594 mNodeIdentification = report->GetIdentification();
00595 }
00596
00597 QueryConfiguration queryConfig(report->GetSourceID(), GetComponentID());
00598 if(subsystem->second->mConfiguration.size() == 0)
00599 {
00600 queryConfig.SetQueryType(QueryConfiguration::SubsystemConfiguration);
00601 }
00602 else
00603 {
00604 queryConfig.SetQueryType(QueryConfiguration::NodeConfiguration);
00605 }
00606 Send(&queryConfig);
00607 }
00608
00609 break;
00610 case ReportIdentification::ComponentIdentification:
00611 {
00612 Subsystem::Component* component = subsystem->second->GetComponent(report->GetSourceID());
00613 component->mID = report->GetSourceID();
00614 component->mIdentification = report->GetIdentification();
00615
00616 if(subsystem->second->mConfiguration.size() == 0)
00617 {
00618 QueryConfiguration queryConfig(report->GetSourceID(), GetComponentID());
00619 queryConfig.SetQueryType(QueryConfiguration::SubsystemConfiguration);
00620 Send(&queryConfig);
00621 }
00622 }
00623 break;
00624 default:
00625 break;
00626 }
00627
00628 subsystem->second->mUpdateTime.SetCurrentTime();
00629 }
00630 }
00631 break;
00632 case REPORT_SERVICES:
00633 {
00634 const ReportServices* report = dynamic_cast<const ReportServices*>(message);
00635 if(report)
00636 {
00637 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00638
00639 Subsystem::Map::iterator subsystem;
00640 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00641
00642 if(subsystem == mSystem.end())
00643 {
00644 mSystem[message->GetSourceID().mSubsystem] = new Subsystem();
00645 subsystem = mSystem.find(message->GetSourceID().mSubsystem);
00646 subsystem->second->mSubsystemID = subsystem->first;
00647 }
00648
00649 ReportServices::Services::const_iterator service;
00650 for(service = report->GetServices()->begin();
00651 service != report->GetServices()->end();
00652 service++)
00653 {
00654 Address id(report->GetSourceID().mSubsystem,
00655 service->first, 0);
00656
00657 ReportServices::Record::List::const_iterator record;
00658 for(record = service->second.begin();
00659 record != service->second.end();
00660 record++)
00661 {
00662 id.mComponent = record->mComponent;
00663 subsystem->second->GetComponent(id)->mServices = record->mServices;
00664 }
00665 }
00666
00667 subsystem->second->mUpdateTime.SetCurrentTime();
00668
00669 }
00670 }
00671 break;
00672 case REPORT_SUBSYSTEM_LIST:
00673 default:
00674 break;
00675 };
00676
00677 }
00678
00679
00691 Message* Discovery::CreateMessage(const UShort messageCode) const
00692 {
00693 Message* message;
00694 switch(messageCode)
00695 {
00696 case QUERY_CONFIGURATION:
00697 message = new QueryConfiguration();
00698 break;
00699 case QUERY_IDENTIFICATION:
00700 message = new QueryIdentification();
00701 break;
00702 case QUERY_SERVICES:
00703 message = new QueryServices();
00704 break;
00705 case QUERY_SUBSYSTEM_LIST:
00706 message = new QuerySubsystemList();
00707 break;
00708 case REGISTER_SERVICES:
00709 message = new RegisterServices();
00710 break;
00711 case REPORT_CONFIGURATION:
00712 message = new ReportConfiguration();
00713 break;
00714 case REPORT_IDENTIFICATION:
00715 message = new ReportIdentification();
00716 break;
00717 case REPORT_SERVICES:
00718 message = new ReportServices();
00719 break;
00720 case REPORT_SUBSYSTEM_LIST:
00721 message = new ReportSubsystemList();
00722 break;
00723 default:
00724 message = NULL;
00725 break;
00726 };
00727 return message;
00728 }
00729
00730
00740 void Discovery::CheckServiceStatus(const unsigned int timeSinceLastCheckMs)
00741 {
00742 if(Time::GetUtcTimeMs() - mBroadcastTimeMs >= mBroadcastDelayMs)
00743 {
00744 QueryIdentification query(Address(GetComponentID().mSubsystem, 255, 255), GetComponentID());
00745
00746 query.SetQueryType(QueryIdentification::ComponentIdentification);
00747
00748 Send(&query, Service::LocalBroadcast);
00749
00750 if(mDiscoverSubsystemsFlag)
00751 {
00752 query.SetQueryType(QueryIdentification::SubsystemIdentification);
00753 query.SetDestinationID(Address(Address::GlobalBroadcast, 255, 255));
00754
00755 Send(&query, Service::GlobalBroadcast);
00756 }
00757
00758
00759 Address::List manualList = GetComponent()->TransportService()->GetManualConnections();
00760 Address::List::iterator manual;
00761 for(manual = manualList.begin(); manual != manualList.end(); manual++)
00762 {
00763 query.SetDestinationID(*manual);
00764 Send(&query);
00765 }
00766
00767 mBroadcastTimeMs = Time::GetUtcTimeMs();
00768 }
00769
00770
00771
00772 try
00773 {
00774 GetSubsystem(GetComponentID().mSubsystem)->GetComponent(GetComponentID())->mAuthorityLevel = GetComponent()->AccessControlService()->GetAuthorityCode();
00775 GetSubsystem(GetComponentID().mSubsystem)->GetComponent(GetComponentID())->mStatus = (int)GetComponent()->ManagementService()->GetStatus();
00776 if(GetVehicle(GetComponentID().mSubsystem)->mAuthority < GetComponent()->AccessControlService()->GetAuthorityCode())
00777 {
00778 GetVehicle(GetComponentID().mSubsystem)->mAuthority = GetComponent()->AccessControlService()->GetAuthorityCode();
00779 }
00780 }
00781 catch(Exception& e)
00782 {
00783 e.Print();
00784 }
00785
00786 Subsystem::Map system;
00787 Address::List lostComponents;
00788 mSubsystemDataMutex.Lock();
00789
00790
00791
00792 Subsystem::Map::iterator subsystem = mSystem.begin();
00793 while(subsystem != mSystem.end())
00794 {
00795 if(mBroadcastDelayMs*1.5 >= (unsigned int)(Time::GetUtcTimeMs() - subsystem->second->mUpdateTime.ToMs()))
00796 {
00797 subsystem++;
00798 continue;
00799 }
00800 Subsystem::Configuration::iterator node = subsystem->second->mConfiguration.begin();
00801 while(node != subsystem->second->mConfiguration.end())
00802 {
00803 Subsystem::Component::Set::iterator component = node->second.begin();
00804 while(component != node->second.end())
00805 {
00806 if(component->mID == GetComponentID() ||
00807 GetTransportService()->HaveConnection(component->mID))
00808 {
00809 component++;
00810 }
00811 else
00812 {
00813 lostComponents.push_back(component->mID);
00814 node->second.erase(component);
00815 component = node->second.begin();
00816 }
00817 }
00818 if(node->second.size() == 0)
00819 {
00820 subsystem->second->mConfiguration.erase(node);
00821 node = subsystem->second->mConfiguration.begin();
00822 }
00823 else
00824 {
00825 node++;
00826 }
00827 }
00828 if(subsystem->second->mConfiguration.size() == 0)
00829 {
00830 mSystem.erase(subsystem);
00831 subsystem = mSystem.begin();
00832 }
00833 else
00834 {
00835 subsystem++;
00836 }
00837 }
00838
00839
00840
00841
00842 Subsystem::CopySubsystemMap(mSystem, system);
00843
00844
00845 Address::List::iterator lostComponent;
00846 for(lostComponent = lostComponents.begin();
00847 lostComponent != lostComponents.end();
00848 lostComponent++)
00849 {
00850 if(mSubsystemList.find(*lostComponent) != mSubsystemList.end())
00851 {
00852 mSubsystemList.erase(mSubsystemList.find(*lostComponent));
00853 }
00854 }
00855
00856 mSubsystemDataMutex.Unlock();
00857
00858
00859
00860 Mutex::ScopedLock cbLock(&mCallbacksMutex);
00861 Callback::Set::iterator cb;
00862 for(cb = mCallbacks.begin();
00863 cb != mCallbacks.end();
00864 cb++)
00865 {
00866 (*cb)->ProcessSystemState(system);
00867 }
00868
00869
00870 Subsystem::DeleteSubsystemMap(system);
00871 }
00872
00873
00883 bool Discovery::GenerateEvent(const Events::Subscription& info) const
00884 {
00885 if(info.mpQueryMessage->GetMessageCode() == QUERY_CONFIGURATION)
00886 {
00887 ReportConfiguration report;
00888 ReportConfiguration::Record record;
00889 const QueryConfiguration* query = dynamic_cast<const QueryConfiguration*>(info.mpQueryMessage);
00890
00891 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00892 Subsystem::Map::const_iterator s = mSystem.find(GetComponentID().mSubsystem);
00893 if(s != mSystem.end())
00894 {
00895 Address::List list = s->second->GetAddressList();
00896 for(Address::List::iterator id = list.begin();
00897 id != list.end();
00898 id++)
00899 {
00900
00901 if(query->GetQueryType() == QueryConfiguration::SubsystemConfiguration)
00902 {
00903 if(id->mNode == GetComponentID().mNode)
00904 {
00905 record.mComponent = id->mComponent;
00906 record.mInstance = 0;
00907 (*report.GetNodes())[GetComponentID().mNode].push_back(record);
00908 }
00909 }
00910 else
00911 {
00912 record.mComponent = id->mComponent;
00913 record.mInstance = 0;
00914 (*report.GetNodes())[GetComponentID().mNode].push_back(record);
00915 }
00916 }
00917 }
00918 else
00919 {
00920 record.mComponent = GetComponentID().mComponent;
00921 (*report.GetNodes())[GetComponentID().mNode].push_back(record);
00922 }
00923 SendEvent(info, &report);
00924 return true;
00925 }
00926 else if(info.mpQueryMessage->GetMessageCode() == QUERY_SUBSYSTEM_LIST)
00927 {
00928 ReportSubsystemList report;
00929 Mutex::ScopedLock lock(&mSubsystemDataMutex);
00930 *report.GetSubsystemList() = Address::ToList(mSubsystemList);
00931 SendEvent(info, &report);
00932 return true;
00933 }
00934 return false;
00935 }
00936
00937
00953 bool Discovery::IsEventSupported(const Events::Type type,
00954 const double requestedPeriodicRate,
00955 const Message* queryMessage,
00956 double& confirmedPeriodicRate,
00957 std::string& errorMessage) const
00958 {
00959 bool result = false;
00960 switch(queryMessage->GetMessageCode())
00961 {
00962 case QUERY_CONFIGURATION:
00963 case QUERY_SUBSYSTEM_LIST:
00964 confirmedPeriodicRate = requestedPeriodicRate;
00965 result = true;
00966 break;
00967 default:
00968 result = false;
00969 break;
00970 };
00971 return result;
00972 }
00973
00974
00984 void Discovery::SetSubsystemIdentification(const Subsystem::Type type,
00985 const std::string& identification)
00986 {
00987 mSubsystemType = type;
00988 mSubsystemIdentification = identification;
00989 }
00990
00991
01002 bool Discovery::SetDiscoveryFrequency(const double frequencyHz)
01003 {
01004 if(frequencyHz > 0)
01005 {
01006 mBroadcastDelayMs = (unsigned int)(1000.0/frequencyHz);
01007 return true;
01008 }
01009 return false;
01010 }
01011
01012
01018 Discovery::List Discovery::GetSubsystemList() const
01019 {
01020 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01021
01022 Discovery::List list;
01023 Subsystem::Map::const_iterator subsystem;
01024
01025 for(subsystem = mSystem.begin();
01026 subsystem != mSystem.end();
01027 subsystem++)
01028 {
01029 if(mSubsystemsToDiscover.size() == 0 ||
01030 mSubsystemsToDiscover.find(subsystem->first) != mSubsystemsToDiscover.end())
01031 {
01032 list[subsystem->first] = subsystem->second->mIdentification;
01033 }
01034 }
01035
01036 return list;
01037 }
01038
01039
01045 Discovery::List Discovery::GetVehicleList() const
01046 {
01047 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01048
01049 Discovery::List list;
01050 Subsystem::Map::const_iterator subsystem;
01051
01052 for(subsystem = mSystem.begin();
01053 subsystem != mSystem.end();
01054 subsystem++)
01055 {
01056 if(subsystem->second->mType == Subsystem::Vehicle)
01057 {
01058 if(mSubsystemsToDiscover.size() == 0 ||
01059 mSubsystemsToDiscover.find(subsystem->first) != mSubsystemsToDiscover.end())
01060 {
01061 list[subsystem->first] = subsystem->second->mIdentification;
01062 }
01063 }
01064 }
01065
01066 return list;
01067 }
01068
01069
01075 Address::List Discovery::GetComponentsWithService(const std::string& serviceName) const
01076 {
01077 Address::List list;
01078 Subsystem::Map subsystems;
01079 this->GetSubsystems(subsystems);
01080 Subsystem::Map::iterator s;
01081 for(s = subsystems.begin();
01082 s != subsystems.end();
01083 s++)
01084 {
01085 Address::List components;
01086 components = s->second->GetComponentsWithService(serviceName);
01087 for(unsigned int i = 0; i < (unsigned int)components.size(); i++)
01088 {
01089 list.push_back(components[i]);
01090 }
01091 }
01092 Subsystem::DeleteSubsystemMap(subsystems);
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 return list;
01115 }
01116
01117
01129 Subsystem::Ptr Discovery::GetSubsystem(const UShort id)
01130 {
01131 bool unlock = false;
01132 if(mSubsystemDataMutex.IsLocked() == false)
01133 {
01134 mSubsystemDataMutex.Lock();
01135 unlock = true;
01136 }
01137
01138 Subsystem::Map::iterator subsystem = mSystem.find(id);
01139 if(subsystem != mSystem.end())
01140 {
01141 return Subsystem::Ptr(subsystem->second, &mSubsystemDataMutex, unlock);
01142 }
01143 if(unlock)
01144 {
01145 mSubsystemDataMutex.Unlock();
01146 }
01147
01148 return Subsystem::Ptr(NULL, NULL);
01149 }
01150
01151
01163 const Subsystem::Ptr Discovery::GetSubsystem(const UShort id) const
01164 {
01165 bool unlock = false;
01166 if(mSubsystemDataMutex.IsLocked() == false)
01167 {
01168 mSubsystemDataMutex.Lock();
01169 unlock = true;
01170 }
01171
01172 Subsystem::Map::const_iterator subsystem = mSystem.find(id);
01173 if(subsystem != mSystem.end())
01174 {
01175 return Subsystem::Ptr(subsystem->second, &mSubsystemDataMutex, unlock);
01176 }
01177 if(unlock)
01178 {
01179 mSubsystemDataMutex.Unlock();
01180 }
01181
01182 return Subsystem::Ptr(NULL, NULL);
01183 }
01184
01185
01199 Vehicle::Ptr Discovery::GetVehicle(const UShort id)
01200 {
01201 bool unlock = false;
01202 if(mSubsystemDataMutex.IsLocked() == false)
01203 {
01204 mSubsystemDataMutex.Lock();
01205 unlock = true;
01206 }
01207
01208 Subsystem::Map::iterator subsystem = mSystem.find(id);
01209 if(subsystem != mSystem.end())
01210 {
01211 Vehicle* vehicle = dynamic_cast<Vehicle *>(subsystem->second);
01212 if(vehicle)
01213 {
01214 return Vehicle::Ptr(vehicle, &mSubsystemDataMutex, unlock);
01215 }
01216 }
01217 if(unlock)
01218 {
01219 mSubsystemDataMutex.Unlock();
01220 }
01221
01222 return Vehicle::Ptr(NULL, NULL);
01223 }
01224
01225
01239 const Vehicle::Ptr Discovery::GetVehicle(const UShort id) const
01240 {
01241 bool unlock = false;
01242 if(mSubsystemDataMutex.IsLocked() == false)
01243 {
01244 mSubsystemDataMutex.Lock();
01245 unlock = true;
01246 }
01247
01248 Subsystem::Map::const_iterator subsystem = mSystem.find(id);
01249 if(subsystem != mSystem.end())
01250 {
01251 Vehicle* vehicle = (Vehicle *)dynamic_cast<const Vehicle *>(subsystem->second);
01252 if(vehicle)
01253 {
01254 return Vehicle::Ptr(vehicle, &mSubsystemDataMutex, unlock);
01255 }
01256 }
01257 if(unlock)
01258 {
01259 mSubsystemDataMutex.Unlock();
01260 }
01261
01262 return Vehicle::Ptr(NULL, NULL);
01263 }
01264
01265
01276 void Discovery::GetSubsystems(Subsystem::Map& subsystems) const
01277 {
01278 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01279
01280 Subsystem::DeleteSubsystemMap(subsystems);
01281
01282 Subsystem::CopySubsystemMap(mSystem, subsystems);
01283
01284
01285 Subsystem::Map::iterator si = subsystems.begin();
01286 while(si != subsystems.end() && mSubsystemsToDiscover.size() > 0)
01287 {
01288 if(mSubsystemsToDiscover.find(si->first) == mSubsystemsToDiscover.end())
01289 {
01290 delete si->second;
01291 subsystems.erase(si);
01292 si = subsystems.begin();
01293 }
01294 else
01295 {
01296 si++;
01297 }
01298 }
01299 }
01300
01301
01312 void Discovery::GetVehicles(Vehicle::Map& vehicles) const
01313 {
01314 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01315
01316 Vehicle::DeleteVehicleMap(vehicles);
01317 Subsystem::Map::const_iterator subsystem;
01318 for(subsystem = mSystem.begin();
01319 subsystem != mSystem.end();
01320 subsystem++)
01321 {
01322 if(subsystem->second->mType == Subsystem::Vehicle)
01323 {
01324 if(mSubsystemsToDiscover.size() == 0 ||
01325 mSubsystemsToDiscover.find(subsystem->first) != mSubsystemsToDiscover.end())
01326 {
01327 vehicles[subsystem->first] = (Vehicle *)subsystem->second->Clone();
01328 }
01329 }
01330 }
01331 }
01332
01333
01345 void Discovery::RegisterCallback(Callback* callback, const bool add)
01346 {
01347 Mutex::ScopedLock lock(&mCallbacksMutex);
01348 if(add)
01349 {
01350 mCallbacks.insert(callback);
01351 }
01352 else
01353 {
01354 Callback::Set::iterator cb;
01355 cb = mCallbacks.find(callback);
01356 if(cb != mCallbacks.end())
01357 {
01358 mCallbacks.erase(cb);
01359 }
01360 }
01361 }
01362
01363
01369 void Discovery::PrintSystemConfiguration() const
01370 {
01371 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01372
01373 Subsystem::Map::const_iterator subsystem;
01374 for(subsystem = mSystem.begin();
01375 subsystem != mSystem.end();
01376 subsystem++)
01377 {
01378 std::cout << "========================================================================\n";
01379 std::cout << "Subsystem [" << subsystem->first << "] - " << subsystem->second->mIdentification << std::endl;
01380 Subsystem::Configuration::const_iterator node;
01381 for(node = subsystem->second->mConfiguration.begin();
01382 node != subsystem->second->mConfiguration.end();
01383 node++)
01384 {
01385 Subsystem::Component::Set::const_iterator component;
01386 for(component = node->second.begin();
01387 component != node->second.end();
01388 component++)
01389 {
01390 std::cout << " " << component->mIdentification << " - " << component->mID.ToString() << std::endl;
01391 std::cout << " " << component->mIdentification << " - Authority Level - " << component->mAuthorityLevel << std::endl;
01392 std::cout << " " << component->mIdentification << " - Status - ";
01393 switch((Byte)component->mStatus)
01394 {
01395 case Management::Status::Ready:
01396 std::cout << "Ready\n";
01397 break;
01398 case Management::Status::Standby:
01399 std::cout << "Standby\n";
01400 break;
01401 case Management::Status::Shutdown:
01402 std::cout << "Shutdown\n";
01403 break;
01404 case Management::Status::Failure:
01405 std::cout << "Failure\n";
01406 break;
01407 case Management::Status::Emergency:
01408 std::cout << "Emergency\n";
01409 break;
01410 default:
01411 std::cout << "Intialized\n";
01412 break;
01413 }
01414 Service::ID::Set::const_iterator service;
01415 unsigned int count = 0;
01416 for(service = component->mServices.begin();
01417 service != component->mServices.end();
01418 service++)
01419 {
01420 std::cout << " " << ++count << " - " << service->mName << std::endl;
01421 }
01422 }
01423 }
01424 std::cout << std::endl;
01425 }
01426 }
01427
01428
01434 void Discovery::PrintStatus() const
01435 {
01436
01437 mSubsystemDataMutex.Lock();
01438 std::cout << "Subsystem Identification: " << mSubsystemIdentification << std::endl;
01439 std::cout << "There are " << mSystem.size() << " Subsystems on Network.\n";
01440 mSubsystemDataMutex.Unlock();
01441 }
01442
01443
01444
01451 void Discovery::TriggerDiscoveryCallbacks()
01452 {
01453 Subsystem::Map system;
01454 std::set<UShort> toDiscover;
01455 {
01456 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01457 Subsystem::CopySubsystemMap(mSystem, system);
01458 toDiscover = mSubsystemsToDiscover;
01459 }
01460
01461 Subsystem::Map::iterator si = system.begin();
01462 while(si != system.end() && toDiscover.size() > 0)
01463 {
01464 if(toDiscover.find(si->first) == toDiscover.end())
01465 {
01466 delete si->second;
01467 system.erase(si);
01468 si = system.begin();
01469 }
01470 else
01471 {
01472 si++;
01473 }
01474 }
01475
01476
01477 Mutex::ScopedLock cbLock(&mCallbacksMutex);
01478 Callback::Set::iterator cb;
01479 for(cb = mCallbacks.begin();
01480 cb != mCallbacks.end();
01481 cb++)
01482 {
01483 (*cb)->ProcessSystemState(system);
01484 }
01485
01486 Subsystem::DeleteSubsystemMap(system);
01487 }
01488
01489
01498 void Discovery::SetSubsystemsToDiscover(const std::set<UShort>& toDiscover)
01499 {
01500 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01501 mSubsystemsToDiscover = toDiscover;
01502 }
01503
01504
01511 std::set<UShort> Discovery::GetSubsystemsToDiscover() const
01512 {
01513 Mutex::ScopedLock lock(&mSubsystemDataMutex);
01514 return mSubsystemsToDiscover;
01515 }
01516
01517