Send message only once instead of periodically - omnet++

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.

Related

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

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

why do RSU start sending BSM messages to nodes after it receives scheduled self-message even though I didn't implement any BSM sending

I'm trying to learn veins, this is the initialization in the RSU application class :
void rsuApp::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if(stage == 0){
event = new cMessage("event");
EV << "Scheduling first send to t=5.0s\n";
scheduleAt(200.0, event);
}
}
I scheduled a self-message at second 200
this is the handleSelfMsg() function code:
void rsuApp::handleSelfMsg(cMessage* msg) {
BaseWaveApplLayer::handleSelfMsg(msg);
findHost()->getDisplayString().updateWith("r=360,pink");
}
during simulation before the rsu receives the selfMsg (before second 200 ) nothing happened but when the RSU receives the self message at second 200 it starts to sends BSM to other nodes even though i didn't implement any BSM sending
I don't know if BSM and beacons are the same things but I set the sendBeacons parameter in omnetpp.ini to false but the RSU still send BSM messages after receiving the self message
*.rsu[*].appl.sendBeacons = false
so I want to know why the RSU start sending BSM to other nodes after receiving the self message
is there a relation between scheduled events and BSM?
In your method handleSelfMsg you call BaseWaveApplLayer::handleSelfMsg(msg). This method is populating and transmitting a Basic Safety Message (BSM) as a broadcast to all other nodes in the scenario.
sendBeacons just controls whether this is being done regularly in order to send periodic beacons. If enabled, the same method as above is called and a BSM is transmitted (see here).

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;

Is There way to find the queue is empty using rabbit-template

I have subscriber which collects the messages until reaches the specified limit and then pass collected messages to the processor to perform some operations. Code works fine, problem is subscriber waits Until it collects specified number messages. If we have lesser message program control will not pass to processor.
For example Lets say my chunk size is 100 and if I have 100 or multiple of 100 messages then program works fine But if I have messages < 100 or 150 some of messages are read by subscriber but they were never passed to processor. Is there way I can figure-out is that Queue is empty using rabbit template so that I can check that condition and break the loop
#RabbitListener(id="messageListener",queues = "#{rabbitMqConfig.getSubscriberQueueName()}",containerFactory="queueListenerContainer")
public void receiveMessage(Message message, Channel channel, #Header("id") String messageId,
#Header("amqp_deliveryTag") Long deliveryTag) {
LOGGER.info(" Message:"+ message.toString());
if(messageList.size() < appConfig.getSubscriberChunkSize() ) {
messageList.add(message);
deliveryTagList.add(deliveryTag);
if(messageList.size() == appConfig.getSubscriberChunkSize()) {
LOGGER.info("------------- Calling Message processor --------------");
Message [] messageArry = new Message[messageList.size()];
messageArry = messageList.toArray(messageArry);
LOGGER.info("message Array Length: "+messageArry.length);
messageProcessor.process(messageArry);
messageList = new ArrayList<Message>(Arrays.asList(messageArry));
LOGGER.info("message Array to List conversion Size: "+messageList.size());
LOGGER.info("-------------- Completed Message processor -----------");
eppQ2Publisher.sendMessages(messageList, channel, deliveryTagList);
messageList.clear();
deliveryTagList.clear();
}
} else {
// do nothing..
}
There are two ways to achieve this.
Add an #EventListener to listen for ListenerContainerIdleEvents which are published when no messages have been received for some time; set the container's idleEventInterval property. The source of the event is the listener container; it contains the #RabbitListener's id. See Detecting Idle Consumers.
Use RabbitAdmin.getQueueProperties().
You can use RabbitAdmin.getQueueInfo("queue name").getMessageCount() that will be 0 for empty queue.

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!

Resources