обратный вызов (восстановление) модуля через другой модуль во время выполнения с изменением параметра

Я использую эту иерархию модулей:

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

С некоторым параметром ini для udpApp как: я дал некоторый начальный параметр в файле ini для udpApp как:

**.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

Но во время выполнения я хочу изменить startTime и stopTime для udpAPP[0] через модуль CNPCBeacon.

Поэтому я изменил CNPCBeacon.cc как: -

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;`

Которые успешно меняют параметры. Однако он не инициирует модуль udpApp[0] снова. Поэтому я пытаюсь использовать динамическое литье этого модуля как:

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

и это привело к следующей ошибке: -

ошибка в модуле (CNPCBeacon) BSoneNode.gw1.wlan[0].CNPCBeacon (id=23) в событии #1496, t=4: scheduleAt() модуля (UDPBasicApp)BSoneNode.gw1.udpApp[0] вызывается в контексте модуля (CNPCBeacon)BSoneNode.gw1.wlan[0].CNPCBeacon: в методе, вызванном из последнего модуля, отсутствует Enter_Method() или Enter_Method_Silent()?.

Есть ли другой способ создать экземпляр модуля через другой подмодуль.

Спасибо за эту помощь.


person Peter    schedule 09.06.2015    source источник


Ответы (2)


Я немного потерялся в иерархии и связи между вашими модулями и подмодулями, однако я думаю, что если вы хотите создать (или воссоздать) модуль динамически, вы можете использовать встроенный подход, предложенный OMNeT++: https://omnetpp.org/doc/omnetpp/manual/usman.html#sec186

Возможно, вы могли бы использовать однострочник напрямую после того, как (пере) определили значения параметров:

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

С другой стороны, ваше сообщение об ошибке жалуется на: Enter_Method() и/или Enter_Method_Silent()

Эти макросы следует использовать в случае, если вы пытаетесь вызвать функцию модуля (пример X::get()) из другого модуля:

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

Чтобы это работало, Enter_Method() (или Enter_Method_Silent()) должно быть записано в начале X::get()

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

Чтобы узнать, что означает.


Странно то, что вы получаете эту ошибку для метода scheduleAt(), который является методом, принадлежащим фундаментальному классу OMNeT++ cSimpleModule. Это означает, что для использования этого метода в вашем классе вам придется наследоваться от cSimpleModule в вашем определении класса.

Может быть, просто сделать что-то вроде:

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

... может решить вашу проблему.

person user4786271    schedule 09.06.2015
comment
Привет @ user4786271, Нет, я не хочу создавать модуль динамически. Я хочу восстановить модуль во время выполнения. UdpAPP[0] уже определен в начале моделирования. Однако во время выполнения новое время запуска и время остановки создаются для этого генератора трафика через udpAPP. Теперь время запуска и остановки изменяется во время выполнения, но экземпляр модуля не создается. Я также пробовал функцию callInstantiate(), но во время моделирования говорит, что модуль уже создан. Что, по моему мнению, зависит от первого использования udpApp[0]. Как я могу вызвать всю функцию в несколько раз. - person Peter; 09.06.2015
comment
хм, жаль, что у меня нет прямого решения вашей проблемы. возможно нужно сначала убить (а может и удалить) модуль, т.е. (сделать mod->callFinish(), mod->deleteModule() ), а потом попробовать callInstantiate(). попробуйте это (если ваш дизайн позволяет это, и вся концепция вашего дизайна не ломается) :\ . - person user4786271; 09.06.2015
comment
Наконец найдите обходной путь. Я создал эту функцию в UdpBasicApp.cc :- void UDPBasicApp:: handleParameterChange(const char* parname) {if(parname) {if(strcmp(parname, "startTime")==0) {if(startTime != par("startTime").doubleValue()) startTime = par("startTime").doubleValue();} if(strcmp(parname,"stopTime")==0) { if(stopTime != par("stopTime").doubleValue()){ stopTime = par("stopTime").doubleValue(); selfMsg->setKind(START); scheduleAt((simtime_t)(startTime), selfMsg);}} - person Peter; 10.06.2015
comment
@Питер, здорово! Воспользуйтесь опцией Ответить на свой вопрос, чтобы указать свой обходной путь, или, по крайней мере, добавьте обходной путь к своему вопросу, отредактировав его. Это поможет будущим пользователям с похожей проблемой, так как поиск решения в комментариях встречается редко. - person user4786271; 10.06.2015

Решение для повторной инициализации модуля (целевого модуля) через другой модуль (запрашивающий модуль) заключается в создании функции handleParamterChange() в целевом модуле. handleParameterChange() используется для повторного чтения измененного параметра во время настройки. Однако он не запустит событие scheduleAt() для повторной инициализации события для целевого модуля. Поэтому я просто добавил событие scheduleAt() в эту функцию как:

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);
           }
}

Обратите внимание, что selfMsg определен в функции инициализации UdpBasciApp.cc в среде INET.

person Peter    schedule 13.06.2015