I get an error when trying to send to multiple modules using sendDirect - omnet++

I have to send the same message to multiple modules. I used the following code:
cMessage *msg=new cMessage("Broadcast");
msg->setKind(SENDTOALL);
cTopology topo;
topo.extractByModulePath(cStringTokenizer("**.router*.app[0]").asVector());
cTopology::Node *thisNode = topo.getNodeFor(this);
for (int i = 0; i < topo.getNumNodes(); i++) {
if (topo.getNode(i) == thisNode) continue; // skip ourselves
cModule *targetModule =topo.getNode(i)->getModule();
EV_INFO << "Get Full Name ------------------- "<<i<< topo.getNode(i)->getModule()->getFullPath()<<endl;
sendDirect(msg,targetModule,"in");
after sending the message to the first module and trying to send to the next module, I get the following error that the message already scheduled and the simulation stops at this point.
Can I get any advice? I will be really thankful.
Thank you in advance.

The message cannot be sent more than once. To send the same message to many modules, every time copy of this message must be created. dup() is the convenient method to make a copy, for example:
cMessage *copyMsg = msg->dup();
sendDirect(copyMsg ,targetModule,"in");
Reference: Simulation Manual - Broadcasting messages

Related

XMS.NET - Error while sending response back to reply queue/out queue

Regarding: “Sending response back to the out/reply queue.”
There is a requirement to send the response back to a different queue (reply queue).
While sending the response, we have to use the correlation and message id from the request message and pass it to the reply queue as header. I suspect the format of correlation/message id is wrong.
While reading the message, the correlation id and message id format are as below:
MessageId = “ID:616365323063633033343361313165646139306638346264”
CorrelationId = “ID:36626161303030305f322020202020202020202020202020”
While sending the back to out/reply queue, we are passing these ids as below:
ITextMessage txtReplyMessage = sessionOut.CreateTextMessage();
txtReplyMessage.JMSMessageID = “616365323063633033343361313165646139306638346264”;
txtReplyMessage.JMSCorrelationID = “36626161303030305f322020202020202020202020202020”;
txtReplyMessage.Text = sentMessage.Contents;
txtReplyMessage.JMSDeliveryMode = DeliveryMode.NonPersistent;
txtReplyMessage.JMSPriority = sentMessage.Priority;
messagePoducerOut.Send(txtReplyMessage);
Please note:
With the XMS.NET library, we need to pass the correlation and message id in string format as per shown above
With MQ API’s (which we were using earlier) passing the correlation and message ids we use to send in bytes format like below:
MQMessage queueMessage = new MQMessage();
string[] parms = document.name.Split('-');
queueMessage.MessageId = StringToByte(parms[1]);
queueMessage.CorrelationId = StringToByte(parms[2]);
queueMessage.CharacterSet = 1208;
queueMessage.Encoding = MQC.MQENC_NATIVE;
queueMessage.Persistence = 0; // Do not persist the replay message.
queueMessage.Format = "MQSTR ";
queueMessage.WriteString(document.contents);
queueOut.Put(queueMessage);
queueManagerOut.Commit();
Please help to troubleshoot the problem.
Troubleshooting is a bit difficult because you haven’t clearly specified the trouble (is there an exception, or is the message just not be correlated successfully?).
In your code you have missed to add the “ID:” prefix. However, to address the requirements, you should not need to bother too much about what is in this field, because you simply need to copy one value to the other:
txtReplyMessage.JMSCorrelationID = txtRequestMessage.JMSMessageID
A bit unclear what the issue is. Are you able to run the provided examples in the MQ tools/examples? This approach uses tmp queues(AMQ.*) as JMSReplyTo
Start the "server" application first.
Request/Response Client: "SimpleRequestor"
Request/Response Server: "SimpleRequestorServer"
You can find the exmaples at the default install location(win):
"C:\Program Files\IBM\MQ\tools\dotnet\samples\cs\xms\simple\wmq"
The "SimpleMessageSelector" will show how to use the selector pattern.
Note the format on the selector: "JMSCorrelationID = '00010203040506070809'"
IBM MQ SELECTOR

Is there a way to sniff/listen an unicast packet/message on Omnet?

I am doing development for WSN in Omnet. I want to sniff a unicast message but I don't have an idea how can i do it in Omnet. I made some research but i couldn't found any method for that
When I send data to another node, I am sending it as an unicast with this method :
cModule *nodeIndex = flatTopolojiModulu->getSubmodule("n", i);//n is array
sendDirect(new cMessage("msg"), nodeIndex, "in");
I am using sendDirect method because I am working on wireless network. According to this description : https://stackoverflow.com/a/36082721/5736731
sendDirect method is usually the case in wireless networks.
But when send message with sendDirect, a message is being handled by receiver node. For example, according to code example above:
if i=2, message that is sent only can handle by node which has index "2" from
void AnyClassName::handleMessage(cMessage *msg) function
An example of broadcasting messages can be found in OMNeT++ Manual.
You should create only one instance of message that all nodes have to receive, and then send a new copy of this message to each node in loop. The dup() method has to be used to create the copy of a message.
cMessage * msg = new cMessage("msg");
// totalN is the total number of nodes
for (int i = 0; i < totalN; ++i) {
cModule *nodeIndex = flatTopolojiModulu->getSubmodule("n", i);
sendDirect(msg->dup(), nodeIndex, "in");
}
// original message is no longer needed
delete msg;

Send message only once instead of periodically

I have developed a scenario where at first the vehicles send a self messsage and upon reception of the self message vehicles send a message to RSU.
The self message code is written in the initialize() method. But during simulation the vehicles send the message to RSU every second.
I want the message to be sent only once. What should I do?
I have attached the handleSelfmessage method of my TraCIDemo11p.cc class.
if(msg->isSelfMessage()==true)
{
cModule *tmpMobility = getParentModule()->getSubmodule("veinsmobility");
mobility = dynamic_cast<Veins::TraCIMobility*>(tmpMobility);
ASSERT(mobility);
t_channel channel = dataOnSch ? type_SCH : type_CCH;
WaveShortMessage* wsm = prepareWSM("data", dataLengthBits, channel, dataPriority, -1,2);
wsm->setSenderAddress(myAddress);
wsm->setRecipientAddress(1001);
sendMessage(wsm->getWsmData());
}
Your approach seems right, but obviously you have some problem in your implementation.
Alternatively you can create a new message and send it to yourself
myOneTimeMsg = new cMessage("OneTimeMsg");
scheduleAt(simTime()+1.0, myOneTimeMsg); // this will send the message at t=currentTime+1.0 seconds
Then you can handle that message as follows:
if(msg->isSelfMessage()==true){
if (msg == myOneTimeMsg) {
// do what you need next...
Amending the answer of #user4786271:
The handleSelfMsg method of TraCIDemo11p.cc obviously is executed for every self-message which this module receives - possibly also non WSMs. So if you just added the given code there, it will send a WSM for every of those self-messages. Thus, only checking for self-message type is not enough. You need to create a new message type and check for that type as shown by #user4786271.

Display issue in the log module of Omnet++ simulator

I use veins-4a2. First, I have executed a scnario with only vehicles. Now I have added RSU in my example. I need that every RSU receives data, displays a message in the module log of Omnet++. Like I did for nodes when they receives data, I have add the bold line in onData() function of the TraCIDemp11p like this:
void TraCIDemoRSU11p::onData(WaveShortMessage* wsm) {
findHost()->getDisplayString().updateWith("r=16,green");
annotations->scheduleErase(1, annotations->drawLine(wsm->getSenderPos(), mobi->getCurrentPosition(), "blue"));
**EV << " I am an RSU and I have received a data ! \n";**
//if (!sentMessage) sendMessage(wsm->getWsmData());
}
My problem is that "I am an RSU and I have received a data ! " isn't displayed in the log module.
When an RSU receives a data, this is what is displayed in the log module of omnet++:
** Event #4802 t=9.004337832007 RSUExampleScenario.node[4].nic.phy80211p (PhyLayer80211p, id=161), on `data' (Mac80211Pkt, id=669)
node[4]::PhyLayer80211p: AirFrame encapsulated, length: 1326
Make sure that is going in the onData function.
You can use ASSERT or exit function for that.
Print the message with DBG, EV or cout
DBG << "Test_DBG: I am an RSU and I have received a data!\n";
EV << "Test_EV: I am an RSU and I have received a data!\n";
std::cout << "Test_cout: I am an RSU and I have received a data!\n"
After set on print message, use one code to terminate the simulation
// terminate the simulation with error code 3
exit(3);
or use ASSERT
ASSERT2(0,"Test: I'm RSU");
If the simulation terminate with error, you will have sure that the onData is executed, if not, the onData is not called in any part of your code.
-Sorry, I don't have reputation to add just one comment- Good luck!
I don't know if you are aware of how onData works.
In the default veins, the onData is only called where one package with name data arrived in one car/node or RSU (through the handleLowerMsg).
In your case in a RSU, so are needed:
The cars/nodes need the appl.sendData with true
Calls for send packages with name data
Range of communication with the cars/nodes and the RSU. The default is 1 km of diameter.
A good test is create a small grid with the randomTrips.py and set the RSU in center, where all nodes can achieve it.
-Big for one comment, so I make a new answer - Good luck!

Read both header and body in one call using java

I have a mail reader class which sets the FetchProfile and later does a msg.getContent.
I want to do both reading of header and content in one call, basically download the full mail in one call. Because I have observed msg.getcontent makes a call to the server to get the body/content , if we can download the full mail in one call, a call to the server can be saved.
Is this possible?
The code is similar to this
inbox.open(Folder.READ_ONLY);
/* Get the messages which is unread in the Inbox */
Message messages[] = inbox.search(new FlagTerm(
new Flags(Flag.SEEN), false));
/* Use a suitable FetchProfile */
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.CONTENT_INFO);
inbox.fetch(messages, fp);
for (int i = 0; i < messages.length; i++) {
System.out.println("MESSAGE #" + (i + 1) + ":");
Message message = messages[i];
**String content = message.getContent();**
System.out.println("Content : " + content);
}
Appreciate any help.
Thanks and Regards
Raaghu.K
If you want the entire message in one call, and don't need to use any of the features of the IMAP protocol, you have two choices:
Use POP3 instead of IMAP.
Use the Message.writeTo method to write the message content to a file or byte array and process it from there, e.g., using the MimeMessage constructor that takes an InputStream. (This makes a local copy of the entire message.)

Resources