Starting Your Module¶
IDGIModule Reference¶
DGI modules are always based on the abstract interface IDGIModule.
IDGIModule is found in IDGIModule.hpp
- class
An interface for an object which can handle recieving incoming messages.
Public Functions
-
IDGIModule
() Constructor, initializes the reference to self.
- Description:
- Constructor for an IDGIModule. Gets the uuid from CGlobalConfiguration and makes a CPeerNode referencing it.
- Precondition:
- CGlobalConfiguration is loaded.
- Postcondition:
- m_me is created.
-
virtual
~IDGIModule
() Virtual destructor for inhertiance.
-
virtual void
HandleIncomingMessage
(boost::shared_ptr< const ModuleMessage > msg, CPeerNode peer) = 0 Handles received messages.
Protected Functions
-
CPeerNode
GetMe
() Gets a CPeerNode representing this process.
GetMe
- Description:
- Gets a CPeerNode that refers to this process.
- Return
- A CPeerNode referring to this process.
-
std::string
GetUUID
() const Gets the UUID of this process.
GetUUID
- Description:
- Gets this process’s UUID.
- Return
- This process’s UUID
-
Additionally, you will want to create a Run() method that will kick-off the actions your module peforms.
Module Creation¶
To create your module, first create a new directory for it in the Broker/src directory. You should select a short name for your module (typically 3 characters or less) use that as the name of your folder. For example, if you are creating a Volt-Var control module you might start your module like so:
$ cd Broker/src
$ mkdir vv
$ cd vv
$ touch VoltVar.cpp
$ touch VoltVar.hpp
This will create a folder for your module and start you out with two blank C++ files where you will create your module.
Module .hpp¶
The .hpp should contain your Module’s class declaration. Modules inherit from IDGIModule. In our example where we are creating VoltVar.hpp, this will get us started:
#ifndef VOLTVAR_HPP_
#define VOLTVAR_HPP_
#include "IDGIModule.hpp"
#include "CPeerNode.hpp"
#include "PeerSets.hpp"
#include "messages/ModuleMessage.pb.h"
namespace freedm {
namespace broker {
namespace vv {
/// Declaration of Garcia-Molina Invitation Leader Election algorithm.
class VVAgent
: public IDGIModule
{
public:
/// Constructor for using this object as a module.
VVAgent();
/// Module destructor
~VVAgent();
/// Called to start the system
int Run();
private:
/// Handles received messages
void HandleIncomingMessage(boost::shared_ptr<const ModuleMessage> msg, CPeerNode peer);
};
} // namespace vv
} // namespace broker
} // namespace freedm
We’ve created a constructor, destructor, Run() method, and a method for handling messages (HandleIncomingMessages()). Let’s implement these methods in VoltVar.cpp.
Module .cpp¶
Here are the implementations for the methods we’ve defined so far:
#include "VoltVar.hpp"
#include "CBroker.hpp"
#include "CLogger.hpp"
namespace freedm {
namespace broker {
namespace vv {
namespace {
/// This file's logger.
CLocalLogger Logger(__FILE__);
}
VVAgent::VVAgent()
{
}
VVAgent::~VVAgent()
{
}
int VVAgent::Run()
{
Logger.Warn<<"Volt Var Control Sure Is Neat!"<<std::endl;
}
void VVAgent::HandleIncomingMessage(boost::shared_ptr<const ModuleMessage> msg, CPeerNode peer)
{
Logger.Warn<<"Dropped message of unexpected type:\n" << msg->DebugString();
}
} // namespace vv
} // namespace broker
} // namespace freedm
What’s going on here? We’ve created an instance of CLocalLogger called Logger
. This allows us to log messages from this module. When creating your module you may find it handy to familiarize yourself with Using The DGI Logger.
Next, we need to register our module with the scheduler and message delivery system. In Broker/src/PosixMain.cpp locate the initialize modules section and add your new module:
// Initialize modules
boost::shared_ptr<IDGIModule> GM = boost::make_shared<gm::GMAgent>();
boost::shared_ptr<IDGIModule> SC = boost::make_shared<sc::SCAgent>();
boost::shared_ptr<IDGIModule> LB = boost::make_shared<lb::LBAgent>();
// My new module!!
boost::shared_ptr<IDGIModule> VV = boost::make_shared<lb::VVAgent>();
Just below that you’ll register your module with the dispatcher, which is responsible for delivering messages to your module:
// Instantiate and register the group management module
CBroker::Instance().RegisterModule("gm",
boost::posix_time::milliseconds(CTimings.Get("GM_PHASE_TIME")));
CDispatcher::Instance().RegisterReadHandler(GM, "gm");
// Instantiate and register the state collection module
CBroker::Instance().RegisterModule("sc",
boost::posix_time::milliseconds(CTimings.Get("SC_PHASE_TIME")));
CDispatcher::Instance().RegisterReadHandler(SC, "sc");
// StateCollection wants to receive Accept messages addressed to lb.
CDispatcher::Instance().RegisterReadHandler(SC, "lb");
// Instantiate and register the power management module
CBroker::Instance().RegisterModule("lb",
boost::posix_time::milliseconds(CTimings.Get("LB_PHASE_TIME")));
CDispatcher::Instance().RegisterReadHandler(LB, "lb");
// REGISTER YOUR NEW MODULE
CBroker::Instance().RegisterModule("vv", boost::posix_time::milliseconds(2000));
CDispatcher::Instance().RegisterReadHandler(VV, "vv");
What did we do here? I’ve registered our module with the Broker, which will allocate it 2000 milliseconds of execution time in the real time scheduler. Later, when we start working with the schedule in our module, we’ll cover adding entries to the timing configuration file, so that users can adjust the timing of your module for their system. Next, we will need to invoke a call to our Run() method to get our module going:
Logger.Debug << "Starting thread of Modules" << std::endl;
CBroker::Instance().Schedule(
"gm",
boost::bind(&gm::GMAgent::Run, boost::dynamic_pointer_cast<gm::GMAgent>(GM)),
false);
CBroker::Instance().Schedule(
"lb",
boost::bind(&lb::LBAgent::Run, boost::dynamic_pointer_cast<lb::LBAgent>(LB)),
false);
// New Module!
CBroker::Instance().Schedule(
"vv",
boost::bind(&lb::VVAgent::Run, boost::dynamic_pointer_cast<lb::VVAgent>(VV))
false);
When the broker starts, the Volt Var module’s Run() method will be called. However, before we run DGI with our new module, we need to add our new module to the CMake configuration. Edit Broker/src/CMakeLists.txt and add your new module:
...
CClockSynchronizer.cpp
CTimings.cpp
CPhysicalTopology.cpp
gm/GroupManagement.cpp
lb/LoadBalance.cpp
sc/StateCollection.cpp
vv/VoltVar.cpp
)
Then to build, you will invoke cmake
and then make
:
$ pwd
/home/scj7t4/FREEDM/Broker
$ cmake
$ make
If everything goes well, you can run PosixBroker. With careful observation you should be able to catch the message we log in the Run() method of our module:
2015-Feb-17 13:10:50.014181 : VoltVar.cpp : Warn(3):
Volt Var Control Sure Is Neat!
Next, let’s make our module do something go to Scheduling DGI Modules