1 ////////////////////////////////////////////////////////////////////////////////////

    2 ///

    3 ///  \file tutorial_05.cpp

    4 ///  \brief This file is part of a set of tutorials for learning how to use

    5 ///        JAUS++.  This program demonstrates how to use the Events service

    6 ///        to request events from another component.

    7 ///

    8 ///  <br>Author(s): Daniel Barber

    9 ///  <br>Created: 3 July 2010

   10 ///  <br>Copyright (c) 2010

   11 ///  <br>Applied Cognition and Training in Immersive Virtual Environments

   12 ///  <br>(ACTIVE) Laboratory

   13 ///  <br>Institute for Simulation and Training (IST)

   14 ///  <br>University of Central Florida (UCF)

   15 ///  <br>All rights reserved.

   16 ///  <br>Email: dbarber@ist.ucf.edu

   17 ///  <br>Web:  http://active.ist.ucf.edu

   18 ///

   19 ///  Redistribution and use in source and binary forms, with or without

   20 ///  modification, are permitted provided that the following conditions are met:

   21 ///      * Redistributions of source code must retain the above copyright

   22 ///        notice, this list of conditions and the following disclaimer.

   23 ///      * Redistributions in binary form must reproduce the above copyright

   24 ///        notice, this list of conditions and the following disclaimer in the

   25 ///        documentation and/or other materials provided with the distribution.

   26 ///      * Neither the name of the ACTIVE LAB, IST, UCF, nor the

   27 ///        names of its contributors may be used to endorse or promote products

   28 ///        derived from this software without specific prior written permission.

   29 ///

   30 ///  THIS SOFTWARE IS PROVIDED BY THE ACTIVE LAB''AS IS'' AND ANY

   31 ///  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

   32 ///  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

   33 ///  DISCLAIMED. IN NO EVENT SHALL UCF BE LIABLE FOR ANY

   34 ///  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

   35 ///  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

   36 ///  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

   37 ///  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

   38 ///  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

   39 ///  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

   40 ///

   41 ////////////////////////////////////////////////////////////////////////////////////

   42 #include <jaus/core/component.h>

   43 #include <cxutils/keyboard.h>

   44 #include <iostream>

   45 

   46 // NOTE - Run another JAUS program like tutorial_01

   47 // so that this program can talk to it.

   48 

   49 // In this tutorial, a callback is used to show that

   50 // event messages have been received.

   51 

   52 // After looking at this tutorial program, try and modify

   53 // it to learn how to get other event subscriptions like

   54 // on change.

   55 //

   56 // Do the following:

   57 // Find a component with the Time Service, and request

   58 // just the Date Stamp information, at 1 Hz, then try

   59 // create an On Change Event for the Time Stamp (it should

   60 // update a lot).

   61 

   62 class EventTutorialCallback : public JAUS::Events::Callback

   63 {

   64 public:

   65     EventTutorialCallback()

   66     {

   67     }

   68     ~EventTutorialCallback()

   69     {

   70     }

   71     ////////////////////////////////////////////////////////////////////////////////////

   72     ///

   73     ///   \brief Method called when an event related message has been received.

   74     ///

   75     ///   \param[in] type Type of event (EveryChange, Periodic).

   76     ///   \param[in] eventID Event ID number.

   77     ///   \param[in] sequenceNumber The sequence number for the event (update number).

   78     ///   \param[in] message The message data associated with the event.

   79     ///

   80     ////////////////////////////////////////////////////////////////////////////////////

   81     virtual void ProcessEvent(const JAUS::Events::Type type,

   82                               const JAUS::Byte eventID,

   83                               const JAUS::Byte sequenceNumber,

   84                               const JAUS::Message* message)

   85     {

   86         if(message->GetMessageCode() == JAUS::REPORT_HEARTBEAT_PULSE)

   87         {

   88             const JAUS::ReportHeartbeatPulse* report =

   89                 dynamic_cast<const JAUS::ReportHeartbeatPulse*>(message);

   90 

   91             std::cout << "\tReceived Event Message [" << (int)sequenceNumber << "]!\n\t";

   92             report->Print();

   93         }

   94     }

   95 };

   96 

   97 int main(int argc, char* argv[])

   98 {

   99     JAUS::Component component;

  100 

  101     // Setup identification info.  For questions about this,

  102     // see the previous tutorial(s).

  103     JAUS::Discovery* discoveryService = NULL;

  104     discoveryService = component.DiscoveryService();

  105     discoveryService->SetSubsystemIdentification(JAUS::Subsystem::Vehicle,

  106                                                 "Robot");

  107     discoveryService->SetNodeIdentification("Primary Computer");

  108     discoveryService->SetComponentIdentification("Baseline");

  109 

  110     // The Events service is used to create and maintain

  111     // subscriptions to other components that support events.

  112     // It also acts as an interface that other services within

  113     // your component inherit from so that they can support

  114     // generation of events (see Liveness).  In this

  115     // tutorial example, we will use the Events service

  116     // to subscribe to Report Heartbeat Pulse messages from

  117     // another component.

  118     JAUS::Events* eventsService = NULL;

  119     eventsService = component.EventsService();

  120 

  121     // Register a callback to be notified when event messages

  122     // have been received.

  123     EventTutorialCallback callback;

  124     eventsService->RegisterCallback(&callback);

  125 

  126     JAUS::Address componentID(1000, 1, 5);

  127     // Initialize!

  128     std::cout << "Initializing component...";

  129     if(component.Initialize(componentID) == false)

  130     {

  131         std::cout << "Failed to initialize component [" << componentID.ToString() << "]\n";

  132         return 0;

  133     }

  134     std::cout << "Success!\n";

  135 

  136     // Now go into your main computer loop until the

  137     // component has been told to shutdown.

  138     JAUS::Time::Stamp displayStatusTimeMs = JAUS::Time::GetUtcTimeMs();

  139     while(true)

  140     {

  141         // See if we have any subscriptions for the type of

  142         // data we want (from any source), and if not, create one.

  143         if(eventsService->HaveSubscription(JAUS::REPORT_HEARTBEAT_PULSE, JAUS::Address()) == false)

  144         {

  145             // Find components with the service that supports

  146             // the type of data we want.

  147             JAUS::Address::List availableComponents;

  148             JAUS::Discovery* discoveryService = NULL;

  149             discoveryService = component.DiscoveryService();

  150             availableComponents =

  151                 discoveryService->GetSubsystem(component.GetComponentID())->GetComponentsWithService(JAUS::Liveness::Name);

  152 

  153             JAUS::Address::List::iterator c;

  154             for(c = availableComponents.begin();

  155                 c != availableComponents.end();

  156                 c++)

  157             {

  158                 // Don't subscribe to ourselves!

  159                 if((*c) == component.GetComponentID())

  160                 {

  161                     continue;

  162                 }

  163                 // Create a periodic event.  A periodic event is

  164                 // an event that happens at a fixed rate.  The

  165                 // alternative is an Every Change event, which

  166                 // occurs whenever the data is modified.

  167 

  168                 // First we must setup the query message for the

  169                 // type of report we want.  Since we want

  170                 // Report Heartbeat Pulse, we need a

  171                 // Query Heartbeat Pulse message.

  172                 JAUS::QueryHeartbeatPulse query;

  173                 std::cout << "Requesting Periodic Event From " << c->ToString();

  174                 // We are request a rate of 5 Hz, with a minimum acceptable rate

  175                 // of 1 Hz.  If the component we are requesting cannot support

  176                 // at least 1 Hz, the request will be canceled.

  177                 if(eventsService->RequestPeriodicEvent((*c), &query, 5, 1))

  178                 {

  179                     std::cout << "Success!\n";

  180                     break;

  181                     // Now that we have the subscription, you should

  182                     // see the callback being triggered when the

  183                     // data arrives at 5Hz!

  184                 }

  185                 else

  186                 {

  187                     std::cout << "Failure!\n";

  188                 }

  189             }

  190         }

  191 

  192         JAUS::Management* managementService = NULL;

  193         managementService = component.ManagementService();

  194         if(managementService->GetStatus() == JAUS::Management::Status::Shutdown)

  195         {

  196             // Exit program.

  197             break;

  198         }

  199 

  200         if(JAUS::Time::GetUtcTimeMs() - displayStatusTimeMs > 500)

  201         {

  202             // Print out status of the service.  You may see more

  203             // events being displayed than just the one we created in

  204             // this program.  That is because the Discovery Service

  205             // creates events to other components to be notified when

  206             // the system configuration changes.  This is part of

  207             // the features within JAUS++ to support redundancy.

  208             eventsService->PrintStatus(); std::cout << std::endl;

  209             displayStatusTimeMs = JAUS::Time::GetUtcTimeMs();

  210         }

  211 

  212         if(CxUtils::GetChar() == 27)

  213         {

  214             break;

  215         }

  216 

  217         CxUtils::SleepMs(1);

  218     }

  219 

  220     // Shutdown your component completely.  Any

  221     // services added or belonging to the component

  222     // will be deleted.

  223     component.Shutdown();

  224 

  225     return 0;

  226 }

  227 

  228 

  229 

  230 /* End of File */

  231