How to make one node communicate with multiple nodes? - omnet++

I am trying to make my nodes communicate among themselves without changing any data in the message.
Like node one and two echos tictocMsg with themselves node two and three echos the different message in this case rndMsg.
How ever this did not work with me.
simple Txc1
{
gates:
input in1;
input in2;
output out1;
output out2;
}
//
// Two instances (tic and toc) of Txc1 connected both ways.
// Tic and toc will pass messages to one another.
//
network Tictoc1
{
#display("bgb=628,433");
submodules:
tic: Txc1 {
#display("p=264,321");
}
toc: Txc1;
rnd: Txc1 {
#display("p=474,100");
}
connections allowunconnected:
toc.out1 --> tic.in1;
tic.out1 --> toc.in1;
toc.out2 --> rnd.in1;
rnd.out1 --> toc.in2;
}
I want to make toc node to send tictocMsg to tic node only and rndMsg to rnd node only
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* Derive the Txc1 class from cSimpleModule. In the Tictoc1 network,
* both the `tic' and `toc' modules are Txc1 objects, created by OMNeT++
* at the beginning of the simulation.
*/
class Txc1 : public cSimpleModule
{
protected:
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
// The module class needs to be registered with OMNeT++
Define_Module(Txc1);
void Txc1::initialize()
{
// Initialize is called at the beginning of the simulation.
// To bootstrap the tic-toc-tic-toc process, one of the modules needs
// to send the first message. Let this be `tic'.
// Am I Tic or Toc?
if (strcmp("tic", getName()) == 0) {
// create and send first message on gate "out". "tictocMsg" is an
// arbitrary string which will be the name of the message object.
cMessage *msg = new cMessage("tictocMsg");
send(msg, "out1");
}
if (strcmp("rnd",getName())==0){
cMessage *msg = new cMessage("rndMsg");
send(msg, "out1");
}
}
void Txc1::handleMessage(cMessage *msg)
{
// The handleMessage() method is called whenever a message arrives
// at the module. Here, we just send it to the other module, through
// gate `out'. Because both `tic' and `toc' does the same, the message
send(msg,"out1");
// send out the message
}
I have tried to change it to
send(msg,"in1","out1") ;
send(msg,"in2","out2") ;
tried
send(msg,out1)}
else{
send(msg,out2)}
}
by far both did not work for me is there any way to make it happen?

The node in the middle (i.e. toc) has to somehow recognize received messages. For example it may check the name of the message. Let's assume that:
toc after receiving message with the name tictocMsg sends it to tic,
toc after receiving message with the name rndMsg sends it to rnd,
tic and rnd after receiving message send it to toc.
The following piece of code performs the above rules:
void Txc1::handleMessage(cMessage *msg) {
if (isName("toc")) {
if (msg->isName("tictocMsg")) {
send(msg,"out1");
} else if (msg->isName("rndMsg")) {
send(msg,"out2");
}
} else {
// other nodes just sends this message back
send(msg,"out1");
}
}

Related

Timer-based sending of message

I want to implement a timer-based message scheme in VEINs/OMNeT++. Here is a scenario: one node sends message to many nodes (let's say 5 nodes). Each node after receiving message sets its timer to broadcast message to other nodes in a network basing on its distance from sender node, such that the furthest node, set shortest timer. And when a node receives message from other nodes before its timer expired, it cancels the timer. But if the timer expires and it has not received any message from other nodes it broadcast the message.
I tried followed explanation in this link
How to implement timers in Omnet++?
I have declared a timer message in the initialize() function
MyApp::Initialize(int stage)
{
RstValueEvt = new cMessage("reset value evt");
}
Then onWSM function for receiving message checks if a message is received again, I check the timer event, if it is scheduled I cancel the timer using:
MyApp::onWSM(BaseFrame1609* frame)
infoMsg* wsm = check _and_cast<infoMsg>(frame)
if(wsm.getrecipient==myId)
{
if(RstValueEvt->isScheduled())
{ cancelEvent(RstValueEvt); }
else{scheduleAt(simTime()+timer, RstValueEvt);
//creating copy of the message that I need to rebroadcast
cMessage* copyMessage = (cMessage *)infoMsg.dup;
}
}
My issue, is how to make this node broadcast the copy of message(infoMsg) to all nodes in the network when timer expires, that is how to handle this message in handleselfmsg fcn and onWSM fcn?
I suggest the following way to achieve your goal:
declare in your class a message for storing received broadcast message, e.g.
cMessage * toBroadcastMsg;
in constructor set
toBroadcastMsg = nullptr;
create an instance of selfmessage (timer):
MyApp::initialize() {
// ...
RstValueEvt = new cMessage("reset value evt");
// ... }
check whether your selfmessage (timer) expires:
MyApp::handleSelfMsg(cMessage* msg) {
// ...
if (RstValueEvt == msg && toBroadcastMsg != nullptr) {
// (2) send a message from toBroadcastMsg
// ...
toBroadcastMsg = nullptr;
}
schedule the timer after receiving a broadcast message as well as store a duplicate of received broadcast message:
MyApp::onWSM(BaseFrame1609_4* wsm) {
if(wsm.getrecipient == myId) {
if(RstValueEvt->isScheduled()) {
cancelEvent(RstValueEvt);
} else {
scheduleAt(simTime() + timer, RstValueEvt);
// (1) remember copy of the message for future use
toBroadcastMsg = wsm->dup;
}
}

How to check a received message type on OMNeT++?

I have declared three different message types in OMNeT++:
Layer
Ack
Reject
What I want to achieve is that every node in my network can send any type of message mentioned above. So that every message type has its own variables. But since the handleMessage(cMessage*) function accepts cMessage* type, I need to know the type of message to be able to cast it accordingly.
How would I go about it?
Here is my Layer message type:
message Layer {
int layer;
simtime_t timeFrame;
}
Each your message type is represented by a class that inherits from cMessage. Therefore, dynamic_cast may be used to recognize the type of message, for example this way:
void YourClass::handleMessage(cMessage * msg) {
Layer * layer = dynamic_cast<Layer*> (msg);
if (layer != nullptr) {
// received Layer
} else {
Ack* ack = dynamic_cast<Ack*> (msg);
if (ack != nullptr) {
// received Ack
} else {
Reject* rej= dynamic_cast<Reject*> (msg);
if (rej != nullptr) {
// received Reject
}
}
}

Message reception error in aggregator module in omnet++

Hey guys I have this code (Aggregator.cc) that is supposed to receive the messages sent from Temperature.cc and Heartrate.cc and concatenate them together however it is not doing so please help. In aggregator.cc it keeps telling me that tmsg and hmasg are not defined in the scope. Isn't aggregator supposed to have received the messages.
Temperature.cc
#include "Temperature.h"
Define_Module(Temperature);
void Temperature::initialize()
{
// TODO - Generated method body
cMessage *tmsg = new cMessage("hi");
send(tmsg,"temperatured");
}
void Temperature::handleMessage(cMessage *msg)
{
// TODO - Generated method body
}
Heartrate.cc
#include "Heartrate.h"
Define_Module(Heartrate);
void Heartrate::initialize()
{
// TODO - Generated method body
cMessage *hmsg = new cMessage("hello");
send(hmsg,"heartrateexit");
}
void Heartrate::handleMessage(cMessage *msg)
{
// TODO - Generated method body
}
Aggregator.cc
#include "Aggregator.h"
#include "Temperature.h"
#include "Heartrate.h"
Define_Module(Aggregator);
void Aggregator::initialize()
{
// TODO - Generated method body
}
void Aggregator::handleMessage(cMessage *msg)
{
// TODO - Generated method body
cPacket *data = new cPacket("data");
data ->addPar(tmsg); // added parameter of type cMessage
data ->addPar(hmsg); // added parameter of type cMessage
data->setByteLength(20);
cPacket *udp = new cPacket("data1"); // subclassed from cPacket
udp->setByteLength(30);
udp->encapsulate(data);
EV << udp->getByteLength();
EV << udp;
cPacket *payload = udp->decapsulate();
EV << payload;
}
network.ned
network Network
{
submodules:
aggregator: Aggregator {
#display("p=128,147");
}
heartrate: Heartrate {
#display("p=40,112");
}
temperature: Temperature {
#display("p=40,173");
}
connections:
temperature.tempexit --> aggregator.data;
heartrate.heartrateexit --> aggregator.data1;
}
You're trying to access local variables from another method. tmsg and hmsg are defined in the local scope of Temperature::initialize and Heartrate::initialize, respectively.
You'll need to add something to the payload of these messages, so that when you receive one at Aggregator::handleMessage(cMessage *msg), you know whether the msg argument is from Temperature or from Heartrate.
Also, in Temperature::initialize, the name of your gate doesn't match the one in your .ned file.

Instant Veins 4.7-i1 Localization Time of Arrival

I am a masters student working on localization, using ranging (time of arrival between vehicle and RSU) and relative location (Using emulated Inertial Navigation System).
I have done an implementation of my kalman filter based localization logic on Matlab, now I would like to implement this on veins. I want only the RSU to send out a message comprising of its location and ID
1) I know that i can use
double Coord = mobility->getCurrentPosition().x;
double Coord = mobility->getCurrentPosition().y;
to the location of RSU(and my vehicle as well), I do not understand how I should assign these coordinates to the message. I cannot use sstream since I understand that the message are supposed to be of type const char *
Thanks for any input
Edit 1: So this is what my new code on RSU looks like:
#include "RsuScOne.h"
#include <sstream>
Define_Module(RsuScOne);
void RsuScOne::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if (stage == 0) {
//Initializing members and pointers of your application goes here
//WaveShortMessage* wsm = new WaveShortMessage();
EV << "Initializing " << std::endl;
}
else if (stage == 1) {
//Initializing members that require initialized other modules goes here
}
}
void RsuScOne::finish() {
BaseWaveApplLayer::finish();
//statistics recording goes here
cancelEvent(sendWSAEvt);
}
void RsuScOne::onWSM(WaveShortMessage* wsm) {
//Your application has received a data message from another car or RSU
//code for handling the message goes here, see TraciDemo11p.cc for examples
populateWSM(wsm);
std::stringstream ss;
ss<<mobility->getCurrentPosition().x<<mobility->getCurrentPosition().y;
wsm->setWsmData(ss.str().c_str());
scheduleAt(simTime()+par("beaconInterval").doubleValue(), sendWSAEvt);
EV<<wsm;
}
void RsuScOne::handleSelfMsg(cMessage* msg) {
BaseWaveApplLayer::handleSelfMsg(msg);
}
But I realize that all that being done now is my RSU constantly sending a generic BSM, Why is this so?

ZeroMQ XSUB/XPUB proxy() API is not returning

I have written a demo Windows service using POCO library.
As per POCO API the function waitForTerminationRequest() waits for a service termination request.
Now, in this POCO based windows service, I want to start a ZeroMQ library based Message Queue proxy to implement an XSUB/XPUB message queue.
More can be learnt here http://zguide.zeromq.org/page:all.
For this I wrote another class ZeroMQProxy, which starts the proxy in the service's main function.
class ZeroMQProxy
{
private:
zmq::context_t context;
zmq::socket_t xsub;
zmq::socket_t xpub;
public:
ZeroMQProxy()
: context(1),
xsub(context, ZMQ_XSUB), // Publisher End Proxy Sockets
xpub(context, ZMQ_XPUB) // Subscriber End Proxy Sockets
{
}
~ZeroMQProxy()
{
}
void proxyopen()
{
xsub.bind("tcp://*:5559");
xpub.bind("tcp://*:5560");
zmq::proxy(xsub, xpub, nullptr);
}
void proxyclose()
{
}
};
class demopocoservice : public ServerApplication
{
private:
bool _helpRequested;
public:
demopocoservice() : _helpRequested(false)
{
}
~demopocoservice()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration();
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "poco display help")
.required(false)
.repeatable(false)
.callback(OptionCallback<demopocoservice>(
this, &demopocoservice::handleHelp)));
}
void handleHelp(const std::string& name,
const std::string& value)
{
_helpRequested = true;
displayHelp();
stopOptionsProcessing();
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("poco: Zero message Queue.");
helpFormatter.format(std::cout);
}
int main(const ArgVec& args)
{
if (!_helpRequested)
{
ZeroMQProxy zmqproxyObj;
zmqproxyObj.proxyopen();
waitForTerminationRequest();
zmqproxyObj.proxyclose();
}
return Application::EXIT_OK;
}
};
int main(int argc, char** argv)
{
cout << "Hello Poco ZMQ\n";
demopocoservice pobj;
pobj.run(argc, argv);
return 0;
}
My aim was when I start the service then the zmq::proxy() should have started the proxy and when I stop the service then proxy should be closed along with the sockets.
Problem is zmq::proxy() does not return back.
So I am not able to stop the service.
Even if I do net stop <service name> the waitForTerminationRequest() does not receive termination request because of zmq::proxy().
What should I do to stop/close the proxy when I stop the service?
ZeroMQ API confirms this:
Description
The zmq_proxy() function starts the built-in ØMQ proxy in the current application thread.
...
Before calling zmq_proxy() you must set any socket options, and connect or bind both frontend and backend sockets. The two conventional proxy models are:
zmq_proxy() runs in the current thread and returns only if/when the current context is closed.
Given this fact, best instantiate an independent thread for leaving the proxy operate there and let the caller return so as to continue your other code-execution flows remain independent from the independent zmq_proxy() execution.
Another fair move would be to ( always ) set LINGER == 0, before any further steps and/or measures are with a newly instantiated sockets taken.

Resources