Omnet++ 如何在传感器网络中添加更多节点

Omnet++ 如何在传感器网络中添加更多节点,omnet++,inet,Omnet++,Inet,在INET SensorNetworkShowcaseA中,有4个节点向服务器发送数据包。我创建了一个新的ned文件,在其中添加了第5个节点。其余的都一样 问题是,当我运行ini文件时,添加的节点(即节点5)生成数据包,但从不向服务器发送任何消息,因此,没有从节点5接收数据包。 从视觉上看,节点5从不更改要发送的状态 是否有人告诉我,为使添加的节点发送数据,还需要修改哪些内容 以下是ned文件和ini文件: 内德档案 import inet.networklayer.configurator.

在INET SensorNetworkShowcaseA中,有4个节点向服务器发送数据包。我创建了一个新的ned文件,在其中添加了第5个节点。其余的都一样

问题是,当我运行ini文件时,添加的节点(即节点5)生成数据包,但从不向服务器发送任何消息,因此,没有从节点5接收数据包。 从视觉上看,节点5从不更改要发送的状态

是否有人告诉我,为使添加的节点发送数据,还需要修改哪些内容

以下是ned文件和ini文件:

内德档案


import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
import inet.node.ethernet.Eth100M;
import inet.node.inet.StandardHost;
import inet.node.inet.SensorNode;
import inet.physicallayer.apskradio.packetlevel.ApskScalarRadioMedium;
import inet.visualizer.integrated.IntegratedVisualizer;


network MultihopSensorNetwork
{
    @display("bgb=81.6,51;bgi=showcases/warehouse,s");
    submodules:
        configurator: Ipv4NetworkConfigurator {
            @display("p=3.4662657,4.033473");
        }
        visualizer: IntegratedVisualizer {
            @display("p=3.4662657,9.264383");
        }
        radioMedium: ApskScalarRadioMedium {
            @display("p=3.4032426,14.0541315");
        }
        sensor5: SensorNode {
            @display("p=45.649998,40.699997");    //added
        }
        sensor4: SensorNode {
            @display("p=20.91,9.18;i=misc/sensor2");
        }
        sensor1: SensorNode {
            @display("p=14.96,21.08;i=misc/sensor2");
        }
        sensor2: SensorNode {
            @display("p=26.4,38.774998;i=misc/sensor2");
        }
        sensor3: SensorNode {
            @display("p=39.61,9.18;i=misc/sensor2");
        }
        gateway: SensorNode {
            @display("p=45.39,22.78;i=misc/sensorgateway");
        }
        server: StandardHost {
            @display("p=61.710003,24.82");
        }

    connections:
        gateway.ethg++ <--> Eth100M <--> server.ethg++;
}
xmac.cc

#include "inet/common/INETUtils.h"
#include "inet/common/ModuleAccess.h"
#include "inet/common/ProtocolTag_m.h"
#include "inet/linklayer/common/Ieee802Ctrl.h"
#include "inet/linklayer/common/InterfaceTag_m.h"
#include "inet/linklayer/common/MacAddressTag_m.h"
#include "inet/linklayer/xmac/XMac.h"
#include "inet/linklayer/xmac/XMacHeader_m.h"
#include "inet/networklayer/contract/IInterfaceTable.h"

namespace inet {

using namespace physicallayer;

Define_Module(XMac);

void XMac::initialize(int stage)
{
    MacProtocolBase::initialize(stage);
    if (stage == INITSTAGE_LOCAL) {
        animation     = par("animation");
        slotDuration  = par("slotDuration");
        bitrate       = par("bitrate");
        headerLength  = b(par("headerLength"));
        ctrlFrameLength  = b(par("ctrlFrameLength"));
        checkInterval = par("checkInterval");
        txPower       = par("txPower");
        useMacAcks    = par("useMACAcks");
        maxTxAttempts = par("maxTxAttempts");
        EV_DEBUG << "headerLength: " << headerLength << "ctrlFrameLength: " << ctrlFrameLength << ", bitrate: " << bitrate << endl;

        stats = par("stats");
        nbTxDataPackets = 0;
        nbTxPreambles = 0;
        nbRxDataPackets = 0;
        nbRxPreambles = 0;
        nbMissedAcks = 0;
        nbRecvdAcks=0;
        nbDroppedDataPackets=0;
        nbRxBrokenDataPackets = 0;
        nbTxAcks=0;

        txAttempts = 0;
        lastDataPktDestAddr = MacAddress::BROADCAST_ADDRESS;
        lastDataPktSrcAddr  = MacAddress::BROADCAST_ADDRESS;

        macState = INIT;
        txQueue = check_and_cast<queueing::IPacketQueue *>(getSubmodule("queue"));
        WATCH(macState);
    }
    else if (stage == INITSTAGE_LINK_LAYER) {
        cModule *radioModule = getModuleFromPar<cModule>(par("radioModule"), this);
        radioModule->subscribe(IRadio::radioModeChangedSignal, this);
        radioModule->subscribe(IRadio::transmissionStateChangedSignal, this);
        radio = check_and_cast<IRadio *>(radioModule);

        wakeup = new cMessage("wakeup", XMAC_WAKE_UP);

        data_timeout = new cMessage("data_timeout", XMAC_DATA_TIMEOUT);
        data_timeout->setSchedulingPriority(100);

        data_tx_over = new cMessage("data_tx_over", XMAC_DATA_TX_OVER);
        stop_preambles = new cMessage("stop_preambles", XMAC_STOP_PREAMBLES);
        send_preamble = new cMessage("send_preamble", XMAC_SEND_PREAMBLE);
        ack_tx_over = new cMessage("ack_tx_over", XMAC_ACK_TX_OVER);
        cca_timeout = new cMessage("cca_timeout", XMAC_CCA_TIMEOUT);
        cca_timeout->setSchedulingPriority(100);
        send_ack = new cMessage("send_ack", XMAC_SEND_ACK);
        start_xmac = new cMessage("start_xmac", XMAC_START_XMAC);
        ack_timeout = new cMessage("ack_timeout", XMAC_ACK_TIMEOUT);
        resend_data = new cMessage("resend_data", XMAC_RESEND_DATA);
        resend_data->setSchedulingPriority(100);
        switch_preamble_phase = new cMessage("switch_preamble_phase", SWITCH_PREAMBLE_PHASE);
        delay_for_ack_within_remote_rx = new cMessage("delay_for_ack_within_remote_rx", DELAY_FOR_ACK_WITHIN_REMOTE_RX);
        switching_done = new cMessage("switching_done", XMAC_SWITCHING_FINISHED);

        scheduleAt(simTime(), start_xmac);
    }
}

XMac::~XMac()
{
    cancelAndDelete(wakeup);
    cancelAndDelete(data_timeout);
    cancelAndDelete(data_tx_over);
    cancelAndDelete(stop_preambles);
    cancelAndDelete(send_preamble);
    cancelAndDelete(ack_tx_over);
    cancelAndDelete(cca_timeout);
    cancelAndDelete(send_ack);
    cancelAndDelete(start_xmac);
    cancelAndDelete(ack_timeout);
    cancelAndDelete(resend_data);
    cancelAndDelete(switch_preamble_phase);
    cancelAndDelete(delay_for_ack_within_remote_rx);
    cancelAndDelete(switching_done);
}

void XMac::finish()
{

    if (stats) {
        recordScalar("nbTxDataPackets", nbTxDataPackets);
        recordScalar("nbTxPreambles", nbTxPreambles);
        recordScalar("nbRxDataPackets", nbRxDataPackets);
        recordScalar("nbRxPreambles", nbRxPreambles);
        recordScalar("nbMissedAcks", nbMissedAcks);
        recordScalar("nbRecvdAcks", nbRecvdAcks);
        recordScalar("nbTxAcks", nbTxAcks);
        recordScalar("nbDroppedDataPackets", nbDroppedDataPackets);
        recordScalar("nbRxBrokenDataPackets", nbRxBrokenDataPackets);
    }
}

void XMac::configureInterfaceEntry()
{
    MacAddress address = parseMacAddressParameter(par("address"));

    // data rate
    interfaceEntry->setDatarate(bitrate);


    interfaceEntry->setMacAddress(address);
    interfaceEntry->setInterfaceToken(address.formInterfaceIdentifier());

    // capabilities
    interfaceEntry->setMtu(par("mtu"));
    interfaceEntry->setMulticast(false);
    interfaceEntry->setBroadcast(true);
}

void XMac::handleUpperPacket(Packet *packet)
{
    encapsulate(packet);
    EV_DETAIL << "CSMA received a message from upper layer, name is " << packet->getName() << ", CInfo removed, mac addr=" << packet->peekAtFront<XMacHeaderBase>()->getDestAddr() << endl;
    EV_DETAIL << "pkt encapsulated, length: " << packet->getBitLength() << "\n";
    txQueue->pushPacket(packet);
    EV_DEBUG << "Max queue length: " << txQueue->getMaxNumPackets() << ", packet put in queue"
              "\n  queue size: " << txQueue->getNumPackets() << " macState: "
              << macState << endl;
    // force wakeup now
    if (!txQueue->isEmpty() && wakeup->isScheduled() && (macState == SLEEP)) {
        cancelEvent(wakeup);
        scheduleAt(simTime() + dblrand()*0.01f, wakeup);
    }
}

void XMac::sendPreamble(MacAddress preamble_address)
{
    //~ diff with XMAC, @ in preamble!
    auto preamble = makeShared<XMacControlFrame>();
    preamble->setSrcAddr(interfaceEntry->getMacAddress());
    preamble->setDestAddr(preamble_address);
    preamble->setChunkLength(ctrlFrameLength);
    preamble->setType(XMAC_PREAMBLE);
    auto packet = new Packet("Preamble", preamble);
    packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    attachSignal(packet, simTime());
    sendDown(packet);
    nbTxPreambles++;
}

void XMac::sendMacAck()
{
    auto ack = makeShared<XMacControlFrame>();
    ack->setSrcAddr(interfaceEntry->getMacAddress());
    //~ diff with XMAC, ack_preamble_based
    ack->setDestAddr(lastPreamblePktSrcAddr);
    ack->setChunkLength(ctrlFrameLength);
    ack->setType(XMAC_ACK);
    auto packet = new Packet("XMacAck", ack);
    packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    attachSignal(packet, simTime());
    sendDown(packet);
    nbTxAcks++;
}

void XMac::handleSelfMessage(cMessage *msg)
{
    MacAddress address = interfaceEntry->getMacAddress();

    switch (macState)
    {
    case INIT:
        if (msg->getKind() == XMAC_START_XMAC) {
            EV_DEBUG << "State INIT, message XMAC_START, new state SLEEP" << endl;
            changeDisplayColor(BLACK);
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            macState = SLEEP;
            scheduleAt(simTime()+dblrand()*slotDuration, wakeup);
            return;
        }
        break;
    case SLEEP:
        if (msg->getKind() == XMAC_WAKE_UP) {
            EV_DEBUG << "node " << address << " : State SLEEP, message XMAC_WAKEUP, new state CCA, simTime " <<
                    simTime() << " to " << simTime() + 1.7f * checkInterval << endl;
            // this CCA is useful when in RX to detect preamble and has to make room for
            // 0.2f = Tx switch, 0.5f = Tx send_preamble, 1f = time_for_ack_back
            scheduleAt(simTime() + 1.7f * checkInterval, cca_timeout);
            radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
            changeDisplayColor(GREEN);
            macState = CCA;
            return;
        }
        // we receive an ACK back but it is too late
        else if (msg->getKind() == XMAC_ACK) {
            nbMissedAcks++;
            delete msg;
            return;
        }
        // received messages prior real-switching to SLEEP? I'm sorry, out
        else { return; }
        break;
    case CCA:
        if (msg->getKind() == XMAC_CCA_TIMEOUT)
        {
            // channel is clear and we wanna SEND
            if (!txQueue->isEmpty())
            {
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
                changeDisplayColor(YELLOW);
                macState = SEND_PREAMBLE;

                scheduleAt(simTime() + slotDuration, stop_preambles);

                scheduleAt(simTime() + 0.2f * checkInterval, switch_preamble_phase);
                return;
            }

            else
            {
                scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);
                return;
            }
        }
        if (msg->getKind() == XMAC_PREAMBLE) {
            auto incoming_preamble = check_and_cast<Packet *>(msg)->peekAtFront<XMacControlFrame>();

            // preamble is for me
            if (incoming_preamble->getDestAddr() == address || incoming_preamble->getDestAddr().isBroadcast() || incoming_preamble->getDestAddr().isMulticast()) {
                cancelEvent(cca_timeout);
                nbRxPreambles++;
                EV << "node " << address << " : State CCA, message XMAC_PREAMBLE received, new state SEND_ACK" << endl;
                macState = SEND_ACK;
                lastPreamblePktSrcAddr = incoming_preamble->getSrcAddr();
                changeDisplayColor(YELLOW);
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
            }

            else {
                EV << "node " << address << " : State CCA, message XMAC_PREAMBLE not for me." << endl;

                cancelEvent(cca_timeout);
                scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);
            }

            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_ACK) {
            EV_DEBUG << "State CCA, message XMAC_ACK, new state CCA" << endl;
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_DATA) {
            auto incoming_data = check_and_cast<Packet *>(msg)->peekAtFront<XMacDataFrameHeader>();

            // packet is for me
            if (incoming_data->getDestAddr() == address) {
                EV << "node " << address << " : State CCA, received XMAC_DATA, accepting it." << endl;
                cancelEvent(cca_timeout);
                cancelEvent(switch_preamble_phase);
                cancelEvent(stop_preambles);
                macState = WAIT_DATA;
                scheduleAt(simTime(), msg);
            }
            return;
        }
        break;

    case SEND_PREAMBLE:
        if (msg->getKind() == SWITCH_PREAMBLE_PHASE) {
            //~ make room for preamble + time_for_ack_back, check_interval is 10ms by default (from NetworkXMAC.ini)
            // 0.5f* = 5ms
            if (radio->getRadioMode() == IRadio::RADIO_MODE_RECEIVER) {
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
                changeDisplayColor(YELLOW);
                EV_DEBUG << "node " << address << " : preamble_phase tx, simTime = " << simTime() << endl;
                scheduleAt(simTime() + 0.5f * checkInterval, switch_preamble_phase);
            }
            // 1.0f* = 10ms
            else if (radio->getRadioMode() == IRadio::RADIO_MODE_TRANSMITTER) {
                radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
                changeDisplayColor(GREEN);
                EV_DEBUG << "node " << address << " : preamble_phase rx, simTime = " << simTime() << endl;
                scheduleAt(simTime() + 1.0f *checkInterval, switch_preamble_phase);
            }
            return;
        }
        // radio switch from above
        if (msg->getKind() == XMAC_SWITCHING_FINISHED) {
            if (radio->getRadioMode() == IRadio::RADIO_MODE_TRANSMITTER) {
                if (currentTxFrame == nullptr)
                    popTxQueue();
                auto pkt_preamble = currentTxFrame->peekAtFront<XMacHeaderBase>();
                sendPreamble(pkt_preamble->getDestAddr());
            }
            return;
        }
        if ((msg->getKind() == XMAC_ACK) || (msg->getKind() == XMAC_STOP_PREAMBLES)) {
            //~ ADDED THE SECOND CONDITION! :) if not, below
            if (msg->getKind() == XMAC_ACK) {
                delete msg;
                EV << "node " << address << " : State SEND_PREAMBLE, message XMAC_ACK, new state SEND_DATA" << endl;
            }
            else if (msg->getKind() == XMAC_STOP_PREAMBLES) {
                EV << "node " << address << " : State SEND_PREAMBLE, message XMAC_STOP_PREAMBLES" << endl;
            }
            macState = SEND_DATA;
            cancelEvent(stop_preambles);
            cancelEvent(switch_preamble_phase);
            changeDisplayColor(RED);
            radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
            txAttempts = 1;
            return;
        }

        if ((msg->getKind() == XMAC_PREAMBLE) || (msg->getKind() == XMAC_DATA)) {
            if (msg->getKind() == XMAC_DATA) {
                nbDroppedDataPackets++;
            }
            delete msg;
            return;
        }
        else {
            EV << "**node " << address << " : State SEND_PREAMBLE, received message " << msg->getKind() << endl;
            return;
        }
        break;

    case SEND_DATA:
        if (msg->getKind() == XMAC_STOP_PREAMBLES) {
            EV << "node " << address << " : State SEND_DATA, message XMAC_STOP_PREAMBLES" << endl;
            // send the data packet
            sendDataPacket();
            macState = WAIT_TX_DATA_OVER;
            return;
        }
        else if (msg->getKind() == XMAC_SWITCHING_FINISHED) {
            EV << "node " << address << " : State SEND_DATA, message RADIO_SWITCHING OVER, sending packet..." << endl;
            // send the data packet
            sendDataPacket();
            macState = WAIT_TX_DATA_OVER;
            return;
        }
        else {
            return;
        }
        break;

    case WAIT_TX_DATA_OVER:
        if (msg->getKind() == XMAC_DATA_TX_OVER) {
            EV_DEBUG << "node " << address << " : State WAIT_TX_DATA_OVER, message XMAC_DATA_TX_OVER, new state  SLEEP" << endl;
            // remove the packet just served from the queue
            deleteCurrentTxFrame();
            // if something in the queue, wakeup soon.
            if (!txQueue->isEmpty())
                scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
            else
                scheduleAt(simTime() + slotDuration, wakeup);
            macState = SLEEP;
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            changeDisplayColor(BLACK);
            return;
        }
        break;
    case WAIT_ACK:
        //not used
        break;
    case WAIT_DATA:
        if (msg->getKind() == XMAC_PREAMBLE) {
            //nothing happens
            nbRxPreambles++;
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_ACK) {
            //nothing happens
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_DATA) {
            auto packet = check_and_cast<Packet *>(msg);
            auto mac = packet->peekAtFront<XMacDataFrameHeader>();
            const MacAddress& dest = mac->getDestAddr();

            if ((dest == address) || dest.isBroadcast() || dest.isMulticast()) {
                decapsulate(packet);
                sendUp(packet);
                nbRxDataPackets++;
                cancelEvent(data_timeout);

                // if something in the queue, wakeup soon.
                if (!txQueue->isEmpty())
                    scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
                else
                    scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);

            }
            else {
                delete msg;
                msg = NULL;
                mac = NULL;
            }

            EV << "node " << address << " : State WAIT_DATA, message XMAC_DATA, new state  SLEEP" << endl;
            return;
        }
        // data does not arrives in time
        if (msg->getKind() == XMAC_DATA_TIMEOUT) {
            EV << "node " << address << " : State WAIT_DATA, message XMAC_DATA_TIMEOUT, new state SLEEP" << endl;
            // if something in the queue, wakeup soon.
            if (!txQueue->isEmpty())
                scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
            else
                scheduleAt(simTime() + slotDuration, wakeup);
            macState = SLEEP;
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            changeDisplayColor(BLACK);
            return;
        }
        break;
    case SEND_ACK:
        // send now the ack packet
        if (msg->getKind() == DELAY_FOR_ACK_WITHIN_REMOTE_RX) {
            EV_DEBUG << "node " << address << " : State SEND_ACK, message XMAC_SEND_ACK, new state WAIT_ACK_TX" << endl;
            sendMacAck();
            macState = WAIT_ACK_TX;
            return;
        }
        break;
    case WAIT_ACK_TX:
        // wait for the ACK to be sent back to the Transmitter
        if (msg->getKind() == XMAC_ACK_TX_OVER) {
            EV_DEBUG << "node " << address << " : State WAIT_ACK_TX, message XMAC_ACK_TX_OVER, new state WAIT_DATA" << endl;
            changeDisplayColor(GREEN);
            macState = WAIT_DATA;
            cancelEvent(cca_timeout);
            scheduleAt(simTime() + (slotDuration / 2), data_timeout);
            radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
            return;
        }
        break;
    }
    throw cRuntimeError("Undefined event of type %d in state %d (Radio state %d)!",
              msg->getKind(), macState, radio->getRadioMode());
}

void XMac::handleLowerPacket(Packet *msg)
{
    if (msg->hasBitError()) {
        EV << "Received " << msg << " contains bit errors or collision, dropping it\n";
        nbRxBrokenDataPackets++;
        delete msg;
        return;
    }
    const auto& hdr = msg->peekAtFront<XMacHeaderBase>();
    msg->setKind(hdr->getType());
    handleSelfMessage(msg);
}

void XMac::sendDataPacket()
{
    nbTxDataPackets++;
    if (currentTxFrame == nullptr)
        popTxQueue();
    auto packet = currentTxFrame->dup();
    const auto& hdr = packet->peekAtFront<XMacHeaderBase>();
    lastDataPktDestAddr = hdr->getDestAddr();
    ASSERT(hdr->getType() == XMAC_DATA);
    attachSignal(packet, simTime());
    sendDown(packet);
}

void XMac::receiveSignal(cComponent *source, simsignal_t signalID, intval_t value, cObject *details)
{
    Enter_Method_Silent();
    if (signalID == IRadio::transmissionStateChangedSignal) {
        IRadio::TransmissionState newRadioTransmissionState = (IRadio::TransmissionState)value;
        if (transmissionState == IRadio::TRANSMISSION_STATE_TRANSMITTING && newRadioTransmissionState == IRadio::TRANSMISSION_STATE_IDLE) {
            // Transmission of one packet is over
            if (macState == WAIT_TX_DATA_OVER) {
                scheduleAt(simTime(), data_tx_over);
            }
            if (macState == WAIT_ACK_TX) {
                scheduleAt(simTime(), ack_tx_over);
            }
        }
        transmissionState = newRadioTransmissionState;
    }
    else if (signalID ==IRadio::radioModeChangedSignal) {
        // Radio switching (to RX or TX) is over, ignore switching to SLEEP.
        if (macState == SEND_PREAMBLE) {
            scheduleAt(simTime(), switching_done);
        }
        else if (macState == SEND_ACK) {
            scheduleAt(simTime() + 0.5f * checkInterval, delay_for_ack_within_remote_rx);
        }
        else if (macState == SEND_DATA) {
            scheduleAt(simTime(), switching_done);
        }
    }
}

void XMac::attachSignal(Packet *packet, simtime_t_cref startTime)
{
    simtime_t duration = packet->getBitLength() / bitrate;
    packet->setDuration(duration);
}

void XMac::changeDisplayColor(XMAC_COLORS color)
{
    if (!animation)
        return;
    cDisplayString& dispStr = getContainingNode(this)->getDisplayString();
    switch (macState) {
        case INIT:
            dispStr.setTagArg("t", 0, "INIT");
            break;

        case SLEEP:
            dispStr.setTagArg("t", 0, "SLEEP");
            break;

        case CCA:
            dispStr.setTagArg("t", 0, "CCA");
            break;

        case SEND_ACK:
        case SEND_PREAMBLE:
        case SEND_DATA:
            dispStr.setTagArg("t", 0, "SEND");
            break;

        case WAIT_ACK:
        case WAIT_DATA:
        case WAIT_TX_DATA_OVER:
        case WAIT_ACK_TX:
            dispStr.setTagArg("t", 0, "WAIT");
            break;

        default:
            dispStr.setTagArg("t", 0, "");
            break;
    }
}


void XMac::decapsulate(Packet *packet)
{
    const auto& xmacHeader = packet->popAtFront<XMacDataFrameHeader>();
    packet->addTagIfAbsent<MacAddressInd>()->setSrcAddress(xmacHeader->getSrcAddr());
    packet->addTagIfAbsent<InterfaceInd>()->setInterfaceId(interfaceEntry->getInterfaceId());
    auto payloadProtocol = ProtocolGroup::ethertype.getProtocol(xmacHeader->getNetworkProtocol());
    packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(payloadProtocol);
    packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(payloadProtocol);
    EV_DETAIL << " message decapsulated " << endl;
}

void XMac::encapsulate(Packet *packet)
{
    auto pkt = makeShared<XMacDataFrameHeader>();
    pkt->setChunkLength(headerLength);

    auto dest = packet->getTag<MacAddressReq>()->getDestAddress();
    EV_DETAIL << "CInfo removed, mac addr=" << dest << endl;
    pkt->setNetworkProtocol(ProtocolGroup::ethertype.getProtocolNumber(packet->getTag<PacketProtocolTag>()->getProtocol()));
    pkt->setDestAddr(dest);

    //delete the control info
    delete packet->removeControlInfo();

    //set the src address to own mac address (nic module getId())
    pkt->setSrcAddr(interfaceEntry->getMacAddress());

    pkt->setType(XMAC_DATA);
    packet->setKind(XMAC_DATA);

    //encapsulate the network packet
    packet->insertAtFront(pkt);
    packet->getTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    EV_DETAIL << "pkt encapsulated\n";
}

} // namespace inet

多谢各位

更新

你能显示NED的代码> Syror Noad < /C>及其C++代码吗?Jerzy,我添加了SyrNoNo.End。你是指MAC算法C++代码吗?它与我现在在问题中添加的现有xmac.cc相同。你能推荐我吗?非常感谢。有什么建议吗?我看不出Node5为什么不发送数据包。您正在检查日志以确定节点是否发送数据包吗?嗨,Jerzy,我正在运行时模式和日志中进行可视化检查。在“发送的数据包”下的日志文件中,记录显示了节点5下的一个数字。看起来这个“packets sent”参数实际上显示了生成的数据包的数量,而不是发送的数据包,因为当我运行它时,节点5从未改变其状态,并且没有数据包从节点5传输到服务器。其他4个节点工作正常。但是节点5没有。在记录中,节点5发送的前导码数为0(问题中附有屏幕截图)。
#include "inet/common/INETUtils.h"
#include "inet/common/ModuleAccess.h"
#include "inet/common/ProtocolTag_m.h"
#include "inet/linklayer/common/Ieee802Ctrl.h"
#include "inet/linklayer/common/InterfaceTag_m.h"
#include "inet/linklayer/common/MacAddressTag_m.h"
#include "inet/linklayer/xmac/XMac.h"
#include "inet/linklayer/xmac/XMacHeader_m.h"
#include "inet/networklayer/contract/IInterfaceTable.h"

namespace inet {

using namespace physicallayer;

Define_Module(XMac);

void XMac::initialize(int stage)
{
    MacProtocolBase::initialize(stage);
    if (stage == INITSTAGE_LOCAL) {
        animation     = par("animation");
        slotDuration  = par("slotDuration");
        bitrate       = par("bitrate");
        headerLength  = b(par("headerLength"));
        ctrlFrameLength  = b(par("ctrlFrameLength"));
        checkInterval = par("checkInterval");
        txPower       = par("txPower");
        useMacAcks    = par("useMACAcks");
        maxTxAttempts = par("maxTxAttempts");
        EV_DEBUG << "headerLength: " << headerLength << "ctrlFrameLength: " << ctrlFrameLength << ", bitrate: " << bitrate << endl;

        stats = par("stats");
        nbTxDataPackets = 0;
        nbTxPreambles = 0;
        nbRxDataPackets = 0;
        nbRxPreambles = 0;
        nbMissedAcks = 0;
        nbRecvdAcks=0;
        nbDroppedDataPackets=0;
        nbRxBrokenDataPackets = 0;
        nbTxAcks=0;

        txAttempts = 0;
        lastDataPktDestAddr = MacAddress::BROADCAST_ADDRESS;
        lastDataPktSrcAddr  = MacAddress::BROADCAST_ADDRESS;

        macState = INIT;
        txQueue = check_and_cast<queueing::IPacketQueue *>(getSubmodule("queue"));
        WATCH(macState);
    }
    else if (stage == INITSTAGE_LINK_LAYER) {
        cModule *radioModule = getModuleFromPar<cModule>(par("radioModule"), this);
        radioModule->subscribe(IRadio::radioModeChangedSignal, this);
        radioModule->subscribe(IRadio::transmissionStateChangedSignal, this);
        radio = check_and_cast<IRadio *>(radioModule);

        wakeup = new cMessage("wakeup", XMAC_WAKE_UP);

        data_timeout = new cMessage("data_timeout", XMAC_DATA_TIMEOUT);
        data_timeout->setSchedulingPriority(100);

        data_tx_over = new cMessage("data_tx_over", XMAC_DATA_TX_OVER);
        stop_preambles = new cMessage("stop_preambles", XMAC_STOP_PREAMBLES);
        send_preamble = new cMessage("send_preamble", XMAC_SEND_PREAMBLE);
        ack_tx_over = new cMessage("ack_tx_over", XMAC_ACK_TX_OVER);
        cca_timeout = new cMessage("cca_timeout", XMAC_CCA_TIMEOUT);
        cca_timeout->setSchedulingPriority(100);
        send_ack = new cMessage("send_ack", XMAC_SEND_ACK);
        start_xmac = new cMessage("start_xmac", XMAC_START_XMAC);
        ack_timeout = new cMessage("ack_timeout", XMAC_ACK_TIMEOUT);
        resend_data = new cMessage("resend_data", XMAC_RESEND_DATA);
        resend_data->setSchedulingPriority(100);
        switch_preamble_phase = new cMessage("switch_preamble_phase", SWITCH_PREAMBLE_PHASE);
        delay_for_ack_within_remote_rx = new cMessage("delay_for_ack_within_remote_rx", DELAY_FOR_ACK_WITHIN_REMOTE_RX);
        switching_done = new cMessage("switching_done", XMAC_SWITCHING_FINISHED);

        scheduleAt(simTime(), start_xmac);
    }
}

XMac::~XMac()
{
    cancelAndDelete(wakeup);
    cancelAndDelete(data_timeout);
    cancelAndDelete(data_tx_over);
    cancelAndDelete(stop_preambles);
    cancelAndDelete(send_preamble);
    cancelAndDelete(ack_tx_over);
    cancelAndDelete(cca_timeout);
    cancelAndDelete(send_ack);
    cancelAndDelete(start_xmac);
    cancelAndDelete(ack_timeout);
    cancelAndDelete(resend_data);
    cancelAndDelete(switch_preamble_phase);
    cancelAndDelete(delay_for_ack_within_remote_rx);
    cancelAndDelete(switching_done);
}

void XMac::finish()
{

    if (stats) {
        recordScalar("nbTxDataPackets", nbTxDataPackets);
        recordScalar("nbTxPreambles", nbTxPreambles);
        recordScalar("nbRxDataPackets", nbRxDataPackets);
        recordScalar("nbRxPreambles", nbRxPreambles);
        recordScalar("nbMissedAcks", nbMissedAcks);
        recordScalar("nbRecvdAcks", nbRecvdAcks);
        recordScalar("nbTxAcks", nbTxAcks);
        recordScalar("nbDroppedDataPackets", nbDroppedDataPackets);
        recordScalar("nbRxBrokenDataPackets", nbRxBrokenDataPackets);
    }
}

void XMac::configureInterfaceEntry()
{
    MacAddress address = parseMacAddressParameter(par("address"));

    // data rate
    interfaceEntry->setDatarate(bitrate);


    interfaceEntry->setMacAddress(address);
    interfaceEntry->setInterfaceToken(address.formInterfaceIdentifier());

    // capabilities
    interfaceEntry->setMtu(par("mtu"));
    interfaceEntry->setMulticast(false);
    interfaceEntry->setBroadcast(true);
}

void XMac::handleUpperPacket(Packet *packet)
{
    encapsulate(packet);
    EV_DETAIL << "CSMA received a message from upper layer, name is " << packet->getName() << ", CInfo removed, mac addr=" << packet->peekAtFront<XMacHeaderBase>()->getDestAddr() << endl;
    EV_DETAIL << "pkt encapsulated, length: " << packet->getBitLength() << "\n";
    txQueue->pushPacket(packet);
    EV_DEBUG << "Max queue length: " << txQueue->getMaxNumPackets() << ", packet put in queue"
              "\n  queue size: " << txQueue->getNumPackets() << " macState: "
              << macState << endl;
    // force wakeup now
    if (!txQueue->isEmpty() && wakeup->isScheduled() && (macState == SLEEP)) {
        cancelEvent(wakeup);
        scheduleAt(simTime() + dblrand()*0.01f, wakeup);
    }
}

void XMac::sendPreamble(MacAddress preamble_address)
{
    //~ diff with XMAC, @ in preamble!
    auto preamble = makeShared<XMacControlFrame>();
    preamble->setSrcAddr(interfaceEntry->getMacAddress());
    preamble->setDestAddr(preamble_address);
    preamble->setChunkLength(ctrlFrameLength);
    preamble->setType(XMAC_PREAMBLE);
    auto packet = new Packet("Preamble", preamble);
    packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    attachSignal(packet, simTime());
    sendDown(packet);
    nbTxPreambles++;
}

void XMac::sendMacAck()
{
    auto ack = makeShared<XMacControlFrame>();
    ack->setSrcAddr(interfaceEntry->getMacAddress());
    //~ diff with XMAC, ack_preamble_based
    ack->setDestAddr(lastPreamblePktSrcAddr);
    ack->setChunkLength(ctrlFrameLength);
    ack->setType(XMAC_ACK);
    auto packet = new Packet("XMacAck", ack);
    packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    attachSignal(packet, simTime());
    sendDown(packet);
    nbTxAcks++;
}

void XMac::handleSelfMessage(cMessage *msg)
{
    MacAddress address = interfaceEntry->getMacAddress();

    switch (macState)
    {
    case INIT:
        if (msg->getKind() == XMAC_START_XMAC) {
            EV_DEBUG << "State INIT, message XMAC_START, new state SLEEP" << endl;
            changeDisplayColor(BLACK);
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            macState = SLEEP;
            scheduleAt(simTime()+dblrand()*slotDuration, wakeup);
            return;
        }
        break;
    case SLEEP:
        if (msg->getKind() == XMAC_WAKE_UP) {
            EV_DEBUG << "node " << address << " : State SLEEP, message XMAC_WAKEUP, new state CCA, simTime " <<
                    simTime() << " to " << simTime() + 1.7f * checkInterval << endl;
            // this CCA is useful when in RX to detect preamble and has to make room for
            // 0.2f = Tx switch, 0.5f = Tx send_preamble, 1f = time_for_ack_back
            scheduleAt(simTime() + 1.7f * checkInterval, cca_timeout);
            radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
            changeDisplayColor(GREEN);
            macState = CCA;
            return;
        }
        // we receive an ACK back but it is too late
        else if (msg->getKind() == XMAC_ACK) {
            nbMissedAcks++;
            delete msg;
            return;
        }
        // received messages prior real-switching to SLEEP? I'm sorry, out
        else { return; }
        break;
    case CCA:
        if (msg->getKind() == XMAC_CCA_TIMEOUT)
        {
            // channel is clear and we wanna SEND
            if (!txQueue->isEmpty())
            {
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
                changeDisplayColor(YELLOW);
                macState = SEND_PREAMBLE;

                scheduleAt(simTime() + slotDuration, stop_preambles);

                scheduleAt(simTime() + 0.2f * checkInterval, switch_preamble_phase);
                return;
            }

            else
            {
                scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);
                return;
            }
        }
        if (msg->getKind() == XMAC_PREAMBLE) {
            auto incoming_preamble = check_and_cast<Packet *>(msg)->peekAtFront<XMacControlFrame>();

            // preamble is for me
            if (incoming_preamble->getDestAddr() == address || incoming_preamble->getDestAddr().isBroadcast() || incoming_preamble->getDestAddr().isMulticast()) {
                cancelEvent(cca_timeout);
                nbRxPreambles++;
                EV << "node " << address << " : State CCA, message XMAC_PREAMBLE received, new state SEND_ACK" << endl;
                macState = SEND_ACK;
                lastPreamblePktSrcAddr = incoming_preamble->getSrcAddr();
                changeDisplayColor(YELLOW);
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
            }

            else {
                EV << "node " << address << " : State CCA, message XMAC_PREAMBLE not for me." << endl;

                cancelEvent(cca_timeout);
                scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);
            }

            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_ACK) {
            EV_DEBUG << "State CCA, message XMAC_ACK, new state CCA" << endl;
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_DATA) {
            auto incoming_data = check_and_cast<Packet *>(msg)->peekAtFront<XMacDataFrameHeader>();

            // packet is for me
            if (incoming_data->getDestAddr() == address) {
                EV << "node " << address << " : State CCA, received XMAC_DATA, accepting it." << endl;
                cancelEvent(cca_timeout);
                cancelEvent(switch_preamble_phase);
                cancelEvent(stop_preambles);
                macState = WAIT_DATA;
                scheduleAt(simTime(), msg);
            }
            return;
        }
        break;

    case SEND_PREAMBLE:
        if (msg->getKind() == SWITCH_PREAMBLE_PHASE) {
            //~ make room for preamble + time_for_ack_back, check_interval is 10ms by default (from NetworkXMAC.ini)
            // 0.5f* = 5ms
            if (radio->getRadioMode() == IRadio::RADIO_MODE_RECEIVER) {
                radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
                changeDisplayColor(YELLOW);
                EV_DEBUG << "node " << address << " : preamble_phase tx, simTime = " << simTime() << endl;
                scheduleAt(simTime() + 0.5f * checkInterval, switch_preamble_phase);
            }
            // 1.0f* = 10ms
            else if (radio->getRadioMode() == IRadio::RADIO_MODE_TRANSMITTER) {
                radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
                changeDisplayColor(GREEN);
                EV_DEBUG << "node " << address << " : preamble_phase rx, simTime = " << simTime() << endl;
                scheduleAt(simTime() + 1.0f *checkInterval, switch_preamble_phase);
            }
            return;
        }
        // radio switch from above
        if (msg->getKind() == XMAC_SWITCHING_FINISHED) {
            if (radio->getRadioMode() == IRadio::RADIO_MODE_TRANSMITTER) {
                if (currentTxFrame == nullptr)
                    popTxQueue();
                auto pkt_preamble = currentTxFrame->peekAtFront<XMacHeaderBase>();
                sendPreamble(pkt_preamble->getDestAddr());
            }
            return;
        }
        if ((msg->getKind() == XMAC_ACK) || (msg->getKind() == XMAC_STOP_PREAMBLES)) {
            //~ ADDED THE SECOND CONDITION! :) if not, below
            if (msg->getKind() == XMAC_ACK) {
                delete msg;
                EV << "node " << address << " : State SEND_PREAMBLE, message XMAC_ACK, new state SEND_DATA" << endl;
            }
            else if (msg->getKind() == XMAC_STOP_PREAMBLES) {
                EV << "node " << address << " : State SEND_PREAMBLE, message XMAC_STOP_PREAMBLES" << endl;
            }
            macState = SEND_DATA;
            cancelEvent(stop_preambles);
            cancelEvent(switch_preamble_phase);
            changeDisplayColor(RED);
            radio->setRadioMode(IRadio::RADIO_MODE_TRANSMITTER);
            txAttempts = 1;
            return;
        }

        if ((msg->getKind() == XMAC_PREAMBLE) || (msg->getKind() == XMAC_DATA)) {
            if (msg->getKind() == XMAC_DATA) {
                nbDroppedDataPackets++;
            }
            delete msg;
            return;
        }
        else {
            EV << "**node " << address << " : State SEND_PREAMBLE, received message " << msg->getKind() << endl;
            return;
        }
        break;

    case SEND_DATA:
        if (msg->getKind() == XMAC_STOP_PREAMBLES) {
            EV << "node " << address << " : State SEND_DATA, message XMAC_STOP_PREAMBLES" << endl;
            // send the data packet
            sendDataPacket();
            macState = WAIT_TX_DATA_OVER;
            return;
        }
        else if (msg->getKind() == XMAC_SWITCHING_FINISHED) {
            EV << "node " << address << " : State SEND_DATA, message RADIO_SWITCHING OVER, sending packet..." << endl;
            // send the data packet
            sendDataPacket();
            macState = WAIT_TX_DATA_OVER;
            return;
        }
        else {
            return;
        }
        break;

    case WAIT_TX_DATA_OVER:
        if (msg->getKind() == XMAC_DATA_TX_OVER) {
            EV_DEBUG << "node " << address << " : State WAIT_TX_DATA_OVER, message XMAC_DATA_TX_OVER, new state  SLEEP" << endl;
            // remove the packet just served from the queue
            deleteCurrentTxFrame();
            // if something in the queue, wakeup soon.
            if (!txQueue->isEmpty())
                scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
            else
                scheduleAt(simTime() + slotDuration, wakeup);
            macState = SLEEP;
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            changeDisplayColor(BLACK);
            return;
        }
        break;
    case WAIT_ACK:
        //not used
        break;
    case WAIT_DATA:
        if (msg->getKind() == XMAC_PREAMBLE) {
            //nothing happens
            nbRxPreambles++;
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_ACK) {
            //nothing happens
            delete msg;
            return;
        }
        if (msg->getKind() == XMAC_DATA) {
            auto packet = check_and_cast<Packet *>(msg);
            auto mac = packet->peekAtFront<XMacDataFrameHeader>();
            const MacAddress& dest = mac->getDestAddr();

            if ((dest == address) || dest.isBroadcast() || dest.isMulticast()) {
                decapsulate(packet);
                sendUp(packet);
                nbRxDataPackets++;
                cancelEvent(data_timeout);

                // if something in the queue, wakeup soon.
                if (!txQueue->isEmpty())
                    scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
                else
                    scheduleAt(simTime() + slotDuration, wakeup);
                macState = SLEEP;
                radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
                changeDisplayColor(BLACK);

            }
            else {
                delete msg;
                msg = NULL;
                mac = NULL;
            }

            EV << "node " << address << " : State WAIT_DATA, message XMAC_DATA, new state  SLEEP" << endl;
            return;
        }
        // data does not arrives in time
        if (msg->getKind() == XMAC_DATA_TIMEOUT) {
            EV << "node " << address << " : State WAIT_DATA, message XMAC_DATA_TIMEOUT, new state SLEEP" << endl;
            // if something in the queue, wakeup soon.
            if (!txQueue->isEmpty())
                scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
            else
                scheduleAt(simTime() + slotDuration, wakeup);
            macState = SLEEP;
            radio->setRadioMode(IRadio::RADIO_MODE_SLEEP);
            changeDisplayColor(BLACK);
            return;
        }
        break;
    case SEND_ACK:
        // send now the ack packet
        if (msg->getKind() == DELAY_FOR_ACK_WITHIN_REMOTE_RX) {
            EV_DEBUG << "node " << address << " : State SEND_ACK, message XMAC_SEND_ACK, new state WAIT_ACK_TX" << endl;
            sendMacAck();
            macState = WAIT_ACK_TX;
            return;
        }
        break;
    case WAIT_ACK_TX:
        // wait for the ACK to be sent back to the Transmitter
        if (msg->getKind() == XMAC_ACK_TX_OVER) {
            EV_DEBUG << "node " << address << " : State WAIT_ACK_TX, message XMAC_ACK_TX_OVER, new state WAIT_DATA" << endl;
            changeDisplayColor(GREEN);
            macState = WAIT_DATA;
            cancelEvent(cca_timeout);
            scheduleAt(simTime() + (slotDuration / 2), data_timeout);
            radio->setRadioMode(IRadio::RADIO_MODE_RECEIVER);
            return;
        }
        break;
    }
    throw cRuntimeError("Undefined event of type %d in state %d (Radio state %d)!",
              msg->getKind(), macState, radio->getRadioMode());
}

void XMac::handleLowerPacket(Packet *msg)
{
    if (msg->hasBitError()) {
        EV << "Received " << msg << " contains bit errors or collision, dropping it\n";
        nbRxBrokenDataPackets++;
        delete msg;
        return;
    }
    const auto& hdr = msg->peekAtFront<XMacHeaderBase>();
    msg->setKind(hdr->getType());
    handleSelfMessage(msg);
}

void XMac::sendDataPacket()
{
    nbTxDataPackets++;
    if (currentTxFrame == nullptr)
        popTxQueue();
    auto packet = currentTxFrame->dup();
    const auto& hdr = packet->peekAtFront<XMacHeaderBase>();
    lastDataPktDestAddr = hdr->getDestAddr();
    ASSERT(hdr->getType() == XMAC_DATA);
    attachSignal(packet, simTime());
    sendDown(packet);
}

void XMac::receiveSignal(cComponent *source, simsignal_t signalID, intval_t value, cObject *details)
{
    Enter_Method_Silent();
    if (signalID == IRadio::transmissionStateChangedSignal) {
        IRadio::TransmissionState newRadioTransmissionState = (IRadio::TransmissionState)value;
        if (transmissionState == IRadio::TRANSMISSION_STATE_TRANSMITTING && newRadioTransmissionState == IRadio::TRANSMISSION_STATE_IDLE) {
            // Transmission of one packet is over
            if (macState == WAIT_TX_DATA_OVER) {
                scheduleAt(simTime(), data_tx_over);
            }
            if (macState == WAIT_ACK_TX) {
                scheduleAt(simTime(), ack_tx_over);
            }
        }
        transmissionState = newRadioTransmissionState;
    }
    else if (signalID ==IRadio::radioModeChangedSignal) {
        // Radio switching (to RX or TX) is over, ignore switching to SLEEP.
        if (macState == SEND_PREAMBLE) {
            scheduleAt(simTime(), switching_done);
        }
        else if (macState == SEND_ACK) {
            scheduleAt(simTime() + 0.5f * checkInterval, delay_for_ack_within_remote_rx);
        }
        else if (macState == SEND_DATA) {
            scheduleAt(simTime(), switching_done);
        }
    }
}

void XMac::attachSignal(Packet *packet, simtime_t_cref startTime)
{
    simtime_t duration = packet->getBitLength() / bitrate;
    packet->setDuration(duration);
}

void XMac::changeDisplayColor(XMAC_COLORS color)
{
    if (!animation)
        return;
    cDisplayString& dispStr = getContainingNode(this)->getDisplayString();
    switch (macState) {
        case INIT:
            dispStr.setTagArg("t", 0, "INIT");
            break;

        case SLEEP:
            dispStr.setTagArg("t", 0, "SLEEP");
            break;

        case CCA:
            dispStr.setTagArg("t", 0, "CCA");
            break;

        case SEND_ACK:
        case SEND_PREAMBLE:
        case SEND_DATA:
            dispStr.setTagArg("t", 0, "SEND");
            break;

        case WAIT_ACK:
        case WAIT_DATA:
        case WAIT_TX_DATA_OVER:
        case WAIT_ACK_TX:
            dispStr.setTagArg("t", 0, "WAIT");
            break;

        default:
            dispStr.setTagArg("t", 0, "");
            break;
    }
}


void XMac::decapsulate(Packet *packet)
{
    const auto& xmacHeader = packet->popAtFront<XMacDataFrameHeader>();
    packet->addTagIfAbsent<MacAddressInd>()->setSrcAddress(xmacHeader->getSrcAddr());
    packet->addTagIfAbsent<InterfaceInd>()->setInterfaceId(interfaceEntry->getInterfaceId());
    auto payloadProtocol = ProtocolGroup::ethertype.getProtocol(xmacHeader->getNetworkProtocol());
    packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(payloadProtocol);
    packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(payloadProtocol);
    EV_DETAIL << " message decapsulated " << endl;
}

void XMac::encapsulate(Packet *packet)
{
    auto pkt = makeShared<XMacDataFrameHeader>();
    pkt->setChunkLength(headerLength);

    auto dest = packet->getTag<MacAddressReq>()->getDestAddress();
    EV_DETAIL << "CInfo removed, mac addr=" << dest << endl;
    pkt->setNetworkProtocol(ProtocolGroup::ethertype.getProtocolNumber(packet->getTag<PacketProtocolTag>()->getProtocol()));
    pkt->setDestAddr(dest);

    //delete the control info
    delete packet->removeControlInfo();

    //set the src address to own mac address (nic module getId())
    pkt->setSrcAddr(interfaceEntry->getMacAddress());

    pkt->setType(XMAC_DATA);
    packet->setKind(XMAC_DATA);

    //encapsulate the network packet
    packet->insertAtFront(pkt);
    packet->getTag<PacketProtocolTag>()->setProtocol(&Protocol::xmac);
    EV_DETAIL << "pkt encapsulated\n";
}

} // namespace inet

# wireless interface
**.wlan[*].typename = "WirelessInterface"
**.wlan[*].radio.typename = "ApskScalarRadio"
sim-time-limit = 100s
# misc
**.arp.typename = "GlobalArp" 
*.gateway.forwarding = true
**.maxTransmissionDuration = 100ms

# configurator
*.configurator.addStaticRoutes = false
*.configurator.config = xmldoc("config.xml")

# radio and radioMedium
**.radio.centerFrequency = 2.45GHz
**.radio.bandwidth = 2.8MHz

**.radio.transmitter.bitrate = 19200 bps
**.radio.transmitter.headerLength = 8b
**.radio.transmitter.preambleDuration = 0.0001s
**.radio.transmitter.power = 2.24mW

**.radio.receiver.energyDetection = -90dBm
**.radio.receiver.sensitivity = -100dBm  
**.radio.receiver.snirThreshold = -8dB

*.radioMedium.backgroundNoise.power = -110dBm

**.mac.headerLength = 8b

# app
*.sensor*.numApps = 1
*.sensor*.app[0].typename = "UdpBasicApp"
*.sensor*.app[0].destAddresses = "server"
*.sensor*.app[0].destPort = 1000
*.sensor*.app[0].sendInterval = 1s
*.sensor*.app[0].startTime = exponential(1s)
*.sensor*.app[0].messageLength = 10Byte

*.server.numApps = 1
*.server.app[0].typename = "UdpSink"
*.server.app[0].localPort = 1000

# visualizer
*.visualizer.*.routingTableVisualizer.displayRoutingTables = false
*.visualizer.*.routingTableVisualizer.displayRoutesIndividually = false
*.visualizer.*.routingTableVisualizer.lineShift = 0
*.visualizer.*.routingTableVisualizer.displayLabels = false

*.visualizer.*.infoVisualizer.modules = "*.server.app[0]"
*.visualizer.*.infoVisualizer.format = "%t"

*.visualizer.*.networkRouteVisualizer.displayRoutes = true

*.visualizer.*.physicalLinkVisualizer.displayLinks = true

[Config XMac]
network = MultihopSensorNetwork

**.wlan[*].mac.typename = "XMac"
**.wlan[*].mac.headerLength = 2B 
*.gateway.wlan[*].mac.slotDuration = 0.1s 
*.sensor*.wlan[*].mac.slotDuration = 0.25s