call back (reinstantiation) of a module through another module at run time with change of parameter

589 views Asked by At

I am using this module hierarchy :

Node: {udpApp[0]<->udp<->networkLayer->wlan[0]} and wlan[0]: {CNPCBeacon<->mac<->radio}

With some ini parameter for udpApp as: I have given some initial parameter in the ini file for udpApp as :

**.host*.numUdpApps = 2
**.host*.udpApp[0].typename = "UDPBasicApp" 
**.host*.udpApp[0].destAddresses = "gw1"
**.host*.udpApp[0].startTime = 1.32s
**.host*.udpApp[0].stopTime = 1.48s

But at run time I want to change the startTime and stopTime for udpAPP[0] through CNPCBeacon module.

Hence I changed CNPCBeacon.cc as:-

cModule* parentmod = getParentModule();
cModule* grantParentmod = parentmod->getParentModule();
cModule* udpmod = grantParentmod->getSubmodule("udpApp",0);
double varHoldingStartTime = udpmod->par("startTime").doubleValue();
double varGoldingStopTime = udpmod->par("stopTime").doubleValue();
varHoldingStartTime = SIMTIME_DBL(4.2);
varGoldingStopTime = SIMTIME_DBL(4.5);
udpmod->par("startTime").setDoubleValue(varHoldingStartTime);
udpmod->par("stopTime").setDoubleValue(varGoldingStopTime);
EV<<"New start and stop time is "<<udpmod->par("startTime").str()<<"\t"<<udpmod->par("stopTime").str()<<endl;`

Which successfully change the parameters. However it doesn't initiate the udpApp[0] module again. So I try to use dynamic casting of this module as:

UDPBasicApp* udpBasicMod = dynamic_cast<UDPBasicApp*>(udpmod);
sendTimer = new cMessage("sendTimer");
scheduleAt(iniSchduleTime, sendTimer);

and it resulted in following error:-

error in module (CNPCBeacon) BSoneNode.gw1.wlan[0].CNPCBeacon (id=23) at event #1496, t=4: scheduleAt() of module (UDPBasicApp)BSoneNode.gw1.udpApp[0] called in the context of module (CNPCBeacon)BSoneNode.gw1.wlan[0].CNPCBeacon: method called from the latter module lacks Enter_Method() or Enter_Method_Silent()?.

Is there also any other way to instantiate a module through other sub module.

Thanks for this help.

2

There are 2 answers

4
user4786271 On

I am a bit lost in the hierarchy and relation between your modules and sub-modules, however I think if your want to create (or re-create) a module dynamically you could use the built-in approach suggested by OMNeT++: https://omnetpp.org/doc/omnetpp/manual/usman.html#sec186

Maybe you could use the one-liner directly once you have (re-)defined the parameter values:

cModuleType *moduleType = cModuleType::get("foo.nodes.WirelessNode");
cModule *mod = moduleType->createScheduleInit("node", this);

On the other hand you error message complains about: Enter_Method() and/or Enter_Method_Silent()

These macros should be used in case that you try to call a function of a module (example X::get()) from within another module:

Y::doSmthWithXsGet()
{
    x->get();
}

For this to work Enter_Method() (or Enter_Method_Silent()) has to be written in the beginning of X::get()

X::get()
{
    Enter_Method();
    /* rest of the code */
}

You can read Direct Method Calls section of the OMNeT++ userman to see what that means.


The weird thing is that you are getting this error for the scheduleAt() method, which is a method which belongs to the fundamental OMNeT++ class cSimpleModule. That means, in order to use this method in your class you will have to inherit from cSimpleModule in your class definition.

Maybe simply doing something like:

class MyCurrentClass: public cSimpleModule
{
    /* further class definition */
};

... could solve your prob.

0
Peter On

The solution for reinitializing a module (target module) through another module (requesting module) is creating handleParamterChange() function in target module. handleParameterChange() is used to reread the changed parameter at tun time. However it won't start scheduleAt() event to reinitialize the event for the target module. So I just added the scheduleAt() event in this function as :

void UDPBasicApp:: handleParameterChange(const char* parname) 
{
    if(parname) 
    {
          if((strcmp(parname, "startTime")==0) && 
             (startTime !=  par("startTime").doubleValue()) 
                    startTime = par("startTime").doubleValue();
           if(strcmp(parname,"stopTime")==0)&& 
             (stopTime !=  par("stopTime").doubleValue())
           { 
                stopTime = par("stopTime").doubleValue(); 
                selfMsg->setKind(START); 
                scheduleAt((simtime_t)(startTime), selfMsg);
           }
}

Note here that selfMsg is defined in the initialize function of UdpBasciApp.cc in INET framework.