Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce splitter interface #8

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/veins-vlc/ISplitter.ned
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Copyright (C) 2006-2017 Agon Memedi <[email protected]>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//

package org.car2x.veinsvlc;

moduleinterface ISplitter {
gates:
output applicationOut; // output gate towards the application
input applicationIn; // input gate from the application

output nicOut; // output gate towards the 802.11p NIC
input nicIn; // input gate from the 802.11p NIC

output nicVlcHeadOut; // output gate towards the HeadLight
input nicVlcHeadIn; // input gate from the HeadLight

output nicVlcTailOut; // output gate towards the TailLight
input nicVlcTailIn; // input gate from the TailLight
}
141 changes: 51 additions & 90 deletions src/veins-vlc/Splitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,10 @@
#include "veins-vlc/utility/Utils.h"

using namespace veins;
using std::unique_ptr;

Define_Module(veins::Splitter);

Splitter::Splitter()
: annotationManager(NULL)

{
}

Splitter::~Splitter()
{
}

void Splitter::initialize()
{
// From upper layers --> lower layers
Expand Down Expand Up @@ -63,8 +54,7 @@ void Splitter::initialize()
tailVlcDelaySignal = registerSignal("tailVlcDelay");

// Other simulation modules
cModule* tmpMobility = getParentModule()->getSubmodule("veinsmobility");
mobility = dynamic_cast<TraCIMobility*>(tmpMobility);
mobility = FindModule<TraCIMobility*>::findSubModule(getParentModule());
ASSERT(mobility);

vlcPhys = getSubmodulesOfType<PhyLayerVlc>(getParentModule(), true);
Expand Down Expand Up @@ -99,37 +89,35 @@ void Splitter::handleMessage(cMessage* msg)

void Splitter::handleUpperMessage(cMessage* msg)
{
// Cast the message to a subclass
VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg);
unique_ptr<BaseFrame1609_4> wsm(check_and_cast<BaseFrame1609_4*>(msg));
const auto accessTechnology = getAccessTechnology(wsm.get());

// Handle WSMs if the VLC has to be "retrofitted" to non-VLC app
if (!vlcMsg) {
BaseFrame1609_4* wsm = dynamic_cast<BaseFrame1609_4*>(msg);

// If not a VlcMessage check whether it is a WSM to send directly
if (wsm) {
send(wsm, toDsrcNic);
return;
}
else
error("Not a VlcMessage, not BaseFrame1609_4");
}

// if (vlcMsg)...
int networkType = vlcMsg->getAccessTechnology();
if (networkType == DSRC) {
if (accessTechnology.test(Splitter::Interface::dsrc)) {
EV_INFO << "DSRC message received from upper layer!" << std::endl;
send(vlcMsg, toDsrcNic);
send(wsm->dup(), toDsrcNic);
}
else if (networkType == VLC) {
EV_INFO << "VLC message received from upper layer!" << std::endl;
if (accessTechnology.test(Splitter::Interface::vlc_head)) {
EV_INFO << "VLC head message received from upper layer!" << std::endl;

if (draw) {
// Won't draw at simTime() < 0.1 as TraCI is not connected and annotation fails
auto drawCones = [this]() {
// Headlight, right
drawRayLine(vlcPhys[0]->getAntennaPosition(), 100, headHalfAngle);
// left
drawRayLine(vlcPhys[0]->getAntennaPosition(), 100, -headHalfAngle);
};
// The cones will be drawn immediately as a message is received from the layer above
timerManager.create(veins::TimerSpecification(drawCones).oneshotAt(simTime()));
}
headlightPacketsSent += 1;
vlcPacketsSent += 1;
send(wsm->dup(), toVlcHead);
}
if (accessTechnology.test(Splitter::Interface::vlc_tail)) {
EV_INFO << "VLC tail message received from upper layer!" << std::endl;
if (draw) {
auto drawCones = [this]() {
// Taillight, left
drawRayLine(vlcPhys[1]->getAntennaPosition(), 30, tailHalfAngle, true);
// right
Expand All @@ -139,75 +127,48 @@ void Splitter::handleUpperMessage(cMessage* msg)
timerManager.create(veins::TimerSpecification(drawCones).oneshotAt(simTime()));
}

int lightModule = vlcMsg->getTransmissionModule();

switch (lightModule) {
case HEADLIGHT:
headlightPacketsSent++;
send(vlcMsg, toVlcHead);
break;
case TAILLIGHT:
taillightPacketsSent++;
send(vlcMsg, toVlcTail);
break;
case DONT_CARE:
error("behavior not specified for DONT_CARE");
break;
case BOTH_LIGHTS: {
vlcPacketsSent++;
VlcMessage* toHead = vlcMsg->dup();
toHead->setTransmissionModule(HEADLIGHT);
send(toHead, toVlcHead);

VlcMessage* toTail = vlcMsg->dup();
toTail->setTransmissionModule(TAILLIGHT);
send(toTail, toVlcTail);
delete vlcMsg;
vlcMsg = NULL;
break;
}
default:
error("\tThe light module has not been specified in the message!");
break;
}
}
else {
error("\tThe access technology has not been specified in the message!");
taillightPacketsSent += 1;
vlcPacketsSent += 1;
send(wsm->dup(), toVlcTail);
}
}

void Splitter::handleLowerMessage(cMessage* msg)
{
int lowerGate = msg->getArrivalGateId();

// !(lowerGate == fromDsrcNic) --> (lowerGate == fromVlcHead || fromVlcTail)
// If the message is from any of the VLC modules and we need to collect statistics
if (!(lowerGate == fromDsrcNic) && collectStatistics) {
vlcPacketsReceived++;
VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg);

emit(totalVlcDelaySignal, simTime() - vlcMsg->getCreationTime());

int srclightModule = vlcMsg->getTransmissionModule();
if (srclightModule == HEADLIGHT) {
headlightPacketsReceived++;
emit(headVlcDelaySignal, simTime() - vlcMsg->getCreationTime());
if (msg->getArrivalGateId() == fromDsrcNic) {
headlightPacketsReceived++;
if (VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg)) {
vlcMsg->setAccessTechnology(Splitter::Interfaces(Splitter::Interface::dsrc).to_ulong());
}
else if (srclightModule == TAILLIGHT) {
taillightPacketsReceived++;
emit(tailVlcDelaySignal, simTime() - vlcMsg->getCreationTime());
} else if (msg->getArrivalGateId() == fromVlcHead) {
headlightPacketsReceived += 1;
vlcPacketsReceived += 1;
emit(headVlcDelaySignal, simTime() - msg->getCreationTime());
emit(totalVlcDelaySignal, simTime() - msg->getCreationTime());
if (VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg)) {
vlcMsg->setAccessTechnology(Splitter::Interfaces(Splitter::Interface::vlc_head).to_ulong());
}
} else if (msg->getArrivalGateId() == fromVlcTail) {
taillightPacketsReceived += 1;
vlcPacketsReceived += 1;
emit(tailVlcDelaySignal, simTime() - msg->getCreationTime());
emit(totalVlcDelaySignal, simTime() - msg->getCreationTime());
if (VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg)) {
vlcMsg->setAccessTechnology(Splitter::Interfaces(Splitter::Interface::vlc_tail).to_ulong());
}
else
error("neither `head` nor `tail`");

}

send(msg, toApplication);
}

Splitter::Interfaces Splitter::getAccessTechnology(cPacket *msg) {
if (VlcMessage* vlcMsg = dynamic_cast<VlcMessage*>(msg)) {
if (lowerGate == fromVlcHead) vlcMsg->setTransmissionModule(HEADLIGHT);
if (lowerGate == fromVlcTail) vlcMsg->setTransmissionModule(TAILLIGHT);
return Interfaces(vlcMsg->getAccessTechnology());
}
else {
return Interface::dsrc; // fallback for non-vlc-messages
}

send(msg, toApplication);
}

void Splitter::drawRayLine(const AntennaPosition& ap, int length, double halfAngle, bool reverse)
Expand Down
22 changes: 18 additions & 4 deletions src/veins-vlc/Splitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <omnetpp.h>

#include "veins/modules/mobility/traci/TraCIMobility.h"
#include "veins/base/utils/EnumBitset.h"
#include "veins/modules/utility/TimerManager.h"
#include "veins/modules/world/annotations/AnnotationManager.h"

Expand All @@ -36,8 +37,15 @@ namespace veins {

class Splitter : public cSimpleModule {
public:
Splitter();
~Splitter();
enum class Interface : uint32_t {
dsrc,
vlc_head,
vlc_tail
};
using Interfaces = veins::EnumBitset<Interface>;

Splitter() {}
virtual ~Splitter() {}

protected:
// Gates
Expand All @@ -56,8 +64,8 @@ class Splitter : public cSimpleModule {
bool draw;
double headHalfAngle;
double tailHalfAngle;
TraCIMobility* mobility;
AnnotationManager* annotationManager;
TraCIMobility* mobility = nullptr;
AnnotationManager* annotationManager = nullptr;
veins::TimerManager timerManager{this};
std::vector<PhyLayerVlc*> vlcPhys;

Expand All @@ -79,8 +87,14 @@ class Splitter : public cSimpleModule {
virtual void finish();
void handleUpperMessage(cMessage* msg);
void handleLowerMessage(cMessage* msg);
virtual Interfaces getAccessTechnology(cPacket *msg);

void drawRayLine(const AntennaPosition& ap, int length, double halfAngle, bool reverse = false);
};

template <>
struct EnumTraits<Splitter::Interface> {
static const Splitter::Interface max = Splitter::Interface::vlc_tail;
};

} // namespace veins
22 changes: 11 additions & 11 deletions src/veins-vlc/Splitter.ned
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
// For the messages coming from the lower layer NICs, it just sends the
// message to the application; it is the taks of the application to
// figure out if the message is a WSM or a VLC Message, in case of need
package org.car2x.veinsvlc;

simple Splitter{
simple Splitter like ISplitter {
parameters:
@class(veins::Splitter);
bool debug = default(false);
Expand All @@ -38,7 +38,7 @@ simple Splitter{
double drawHeadHalfAngle = default(0) @unit(deg);
double drawTailHalfAngle = default(0) @unit(deg);

@signal[totalVlcDelay](type="simtime_t");
@signal[totalVlcDelay](type="simtime_t");
@statistic[totalVlcDelay](record=mean);

@signal[headVlcDelay](type="simtime_t");
Expand All @@ -48,15 +48,15 @@ simple Splitter{
@statistic[tailVlcDelay](record=mean);

gates:
output applicationOut; // output gate towards the application
input applicationIn; // input gate from the application
output applicationOut; // output gate towards the application
input applicationIn; // input gate from the application

output nicOut; // output gate towards the 802.11p NIC
input nicIn; // input gate from the 802.11p NIC
output nicOut; // output gate towards the 802.11p NIC
input nicIn; // input gate from the 802.11p NIC

output nicVlcHeadOut; // output gate towards the HeadLight
input nicVlcHeadIn; // input gate from the HeadLight
output nicVlcHeadOut; // output gate towards the HeadLight
input nicVlcHeadIn; // input gate from the HeadLight

output nicVlcTailOut; // output gate towards the TailLight
input nicVlcTailIn; // input gate from the TailLight
output nicVlcTailOut; // output gate towards the TailLight
input nicVlcTailIn; // input gate from the TailLight
}
32 changes: 14 additions & 18 deletions src/veins-vlc/application/simpleVlcApp/SimpleVlcApp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <omnetpp.h>
#include <veins-vlc/application/simpleVlcApp/SimpleVlcApp.h>
#include "veins-vlc/Splitter.h"

using namespace veins;

Expand Down Expand Up @@ -61,13 +62,13 @@ void SimpleVlcApp::initialize(int stage)
if (stage == 3) {
auto dsrc = [this]() {
VlcMessage* vlcMsg = new VlcMessage();
vlcMsg->setAccessTechnology(DSRC);
vlcMsg->setAccessTechnology(Splitter::Interfaces(Splitter::Interface::dsrc).to_ulong());
send(vlcMsg, toLower);
};
int vlcModule = BOTH_LIGHTS;
const Splitter::Interfaces vlcModule{Splitter::Interface::vlc_head, Splitter::Interface::vlc_head};
auto vlc = [this, vlcModule]() {
EV_INFO << "Sending VLC message of type: " << vlcModule << std::endl;
VlcMessage* vlcMsg = generateVlcMessage(VLC, vlcModule);
EV_INFO << "Sending VLC message of type: " << vlcModule.to_ulong() << std::endl;
VlcMessage* vlcMsg = generateVlcMessage(vlcModule.to_ulong());
send(vlcMsg, toLower);
};
timerManager.create(veins::TimerSpecification(vlc).oneshotAt(SimTime(20, SIMTIME_S)));
Expand All @@ -85,26 +86,22 @@ void SimpleVlcApp::handleMessage(cMessage* msg)
}
else {
VlcMessage* vlcMsg = check_and_cast<VlcMessage*>(msg);
int accessTech = vlcMsg->getAccessTechnology();
switch (accessTech) {
case DSRC: {
Splitter::Interfaces accessTechnology(vlcMsg->getAccessTechnology());
if (accessTechnology.test(Splitter::Interface::dsrc)) {
EV_INFO << "DSRC message received!" << std::endl;
delete vlcMsg;
break;
}
case VLC: {
else if (accessTechnology.test(Splitter::Interface::vlc_head)) {
EV_INFO << "VLC message received from: " << vlcMsg->getSourceNode() << std::endl;
delete vlcMsg;
break;
}
default:
error("message neither from DSRC nor VLC");
break;
}
else if (accessTechnology.test(Splitter::Interface::vlc_tail)) {
EV_INFO << "VLC message received from: " << vlcMsg->getSourceNode() << std::endl;
}

delete vlcMsg;
}
}

VlcMessage* SimpleVlcApp::generateVlcMessage(int accessTechnology, int sendingModule)
VlcMessage* SimpleVlcApp::generateVlcMessage(int accessTechnology)
{
VlcMessage* vlcMsg = new VlcMessage();

Expand All @@ -117,7 +114,6 @@ VlcMessage* SimpleVlcApp::generateVlcMessage(int accessTechnology, int sendingMo
vlcMsg->setSourceNode(this->sumoId.c_str());
vlcMsg->setDestinationNode("BROADCAST");
vlcMsg->setAccessTechnology(accessTechnology);
vlcMsg->setTransmissionModule(sendingModule);

// Set application layer packet length
vlcMsg->setByteLength(byteLength);
Expand Down
Loading