I'm using Veins 5.0. Here is the code I've written:
NodeMsg.msg
cplusplus{{
#import "veins/base/utils/Coord.h"
#import "veins/modules/utility/Consts80211p.h"
#include "veins/modules/messages/BaseFrame1609_4_m.h"
#include "veins/base/utils/SimpleAddress.h"
}};
namespace veins;
class noncobject Coord;
class BaseFrame1609_4;
class noncobject LAddress::L2Type;
packet mR_SA extends BaseFrame1609_4
{
int isWlan; // IEEE 80211p and LTE classification variables
int mrsuId;
int type;
int status;
int remainingCapacity;
int neighborVehiclesCount;
int checksum;
double direction;
double velocity;
double posX; // longitude
double posY; // latitude
simtime_t timestamp = 0;
LAddress::L2Type macId; // MAC address
}
Node.h
#include "veins/modules/mac/ieee80211p/DemoBaseApplLayerToMac1609_4Interface.h"
...
class VEINS_API Node : public DemoBaseApplLayer
{
...
public:
LAddress::L2Type nodeMacId = 0;
}
Node.cc
...
else if(stage == 1)
{
mac = FindModule<DemoBaseApplLayerToMac1609_4Interface*>::findSubModule(getParentModule());
ASSERT(mac);
nodeMacId = mac -> getMACAddress();
}
...
void Node::handleSelfMsg(cMessage* msg)
{
...
mR_SA* mr_sa = new mR_SA();
...
mr_sa -> setMacId(nodeMacId);
BaseFrame1609_4* wsm = new BaseFrame1609_4();
wsm -> encapsulate(mr_sa);
populateWSM(wsm);
sendDelayedDown(wsm, uniform(0.01, 0.50));
}
AnotherNode.cc
...
mR_SA* mr_sa = new mR_SA();
LAddress::L2Type nodeMacId = mr_sa -> getMacId();
EV_TRACE << "MAC address: " << nodeMacId << std::endl;
...
The log is displayed as the MAC address value obtained from Node is 326. However, the MAC address value received from the message by another node is 0. Why does this happen?
There are no errors at all when running the current code in simulation form after building. I suspected that a different type was the cause, so I did a cast to a long type, but the result was the same.
AnotherNode.cc is creating a fresh mR_SA using new, but is expecting to find the sending node's mac address in there. This will not work. Rather, you would need to cast the received cMessage to this type and use member accessors to get the mac address.
Related
I'm trying to overload << to print the protected members of a class as a string, but when I try to use it in another class doing std::cout << player2; I get "0x7f60b0100" as output.
"player2" is an Actor*, so I'm not sure what's happening.
class Actor {
private:
string type;
protected:
int health;
int damage;
vector<MoveType> moves;
public:
Actor(string type, int health): type{ type }, health{ health }{damage=0;}
virtual void Hit(int damage){health = health-damage;}
virtual void Heal(int amount){health=+amount;}
const vector<MoveType>& GetMoves() const {return moves;}
bool IsDead() { return health <= 0; }
friend ostream& operator<<(ostream& out, const Actor& actor){
return (out << "DAMAGE DONE: " << actor.damage << "HEALTH: "<< actor.health);
}
};
As you've said it's a pointer to an Actor instance, so that's what you get printed, the value of this pointer.
You need to derefernce the pointer:
std::cout << *player2;
I'm making a randomly generated network where the node will send an update massage after asking if the other node already know the update. Currently the update status is still predefined. I'm getting this error message when running the simulation:
send()/sendDelayed(): Gate index 1048576 out of range when accessing vector gate 'out[]' with size 1 -- in module (Sg1) Simplegossip1.node[2] (id=4), at t=0s event #1
Here's my code:
simplegossip1.ned
simple Sg1
{
parameters:
#display("i=block/routing");
bool updated;
gates:
input in[]; // declare in[] and out[] to be vector gates
output out[];
}
network Simplegossip1
{
parameters:
int count;
double connectedness; // 0.0<x<1.0
#display("bgb=640,444");
submodules:
node[count]: Sg1 {
gates:
in[]; // removed the size of gate
out[];
}
connections allowunconnected:
for i=0..count-2, for j=i+1..count-1, if uniform(0,1)<connectedness {
node[i].out++ --> node[j].in++;
node[i].in++ <-- node[j].out++;
}
}
Here's the cc file.
sg1.cc
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* First attempt for gossip protocol
*/
class Sg1 : public cSimpleModule
{
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Sg1);
void Sg1::initialize()
{
if (getIndex() == 0) {
cMessage *askupdated = new cMessage("Ask Update");
int m = gateSize("out");
int l = intuniform(0, m-1);
send(askupdated, "out",l);
}
}
void Sg1::handleMessage(cMessage *msg)
{
//gate randomizer
int n = gateSize("out");
int k = intuniform(0, n-1);
int sid = msg->getArrivalGateId();
bool updatestatus = par("updated");
EV << "Received message `" << msg->getName() << "', sending it out again\n";
if (strncmp (msg->getName(),"Ask Update",2) == 0) {
if (updatestatus == true){
delete msg;
cMessage *updated = new cMessage("Updated");
send(updated, "out", sid);
}
else {
delete msg;
cMessage *unupdated = new cMessage("Unupdated");
send(unupdated, "out", sid);
}
}
else if (strncmp (msg->getName(),"Unupdated",2) == 0) {
delete msg;
cMessage *update = new cMessage("Here is the update");
send(update, "out", sid);
}
else {
delete msg;
cMessage *askupdated = new cMessage("Ask Update");
send(askupdated, "out", sid);
}
}
And an omnet.ini file that only calling the Simplegossip1 network.
How do I solve this? Thanks in advance.
In the line:
int sid = msg->getArrivalGateId();
you read the gate ID. Then you use this value as a gate index:
send(updated, "out", sid);
However, a gate ID is not the same as gate index. Therefore there is an error during send().
In the simulation every object (e.g. module, gate, message) has a unique number (i.e. ID). It is clearly mentioned in
OMNeT++ Simulation Library.
You should check the current size of the gate and be sure that you do not try to send via index out of scope.
I'm making a randomly generated network where the node will send an update massage after asking if the other node already know the update. Currently the update status is still predefined. I'm getting this error message when running the simulation:
"(omnetpp::cModule)Simplegossip1: Unknown parameter 'updated' -- in module (Sg1) Simplegossip1.node[0] (id=2), at t=0s, event #1"
Here's my code:
simplegossip1.ned (I'm using code from here How to create a randomly connected graph in OMNeT++?)
simple Sg1
{
parameters:
#display("i=block/routing");
bool updated;
gates:
input in[]; // declare in[] and out[] to be vector gates
output out[];
}
network Simplegossip1
{
parameters:
int count;
double connectedness; // 0.0<x<1.0
submodules:
node[count]: Sg1 {
gates:
in[]; // removed the size of gate
out[];
}
connections allowunconnected:
for i=0..count-2, for j=i+1..count-1, if uniform(0,1)<connectedness {
node[i].out++ --> node[j].in++;
node[i].in++ <-- node[j].out++;
}
}
sg1.cc
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* First attempt for gossip protocol
*/
class Sg1 : public cSimpleModule
{
public:
cMessage *askupdated = new cMessage("Ask Update");
cMessage *updated = new cMessage("Updated");
cMessage *unupdated = new cMessage("Unupdated");
cMessage *update = new cMessage("Here is the update");
protected:
virtual void forwardMessage(cMessage *msg, int dest);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Sg1);
void Sg1::initialize()
{
if (getIndex() == 0) {
// Boot the process scheduling the initial message as a self-message.
char msgname[20];
sprintf(msgname, "tic-%d", getIndex());
cMessage *msg = new cMessage(msgname);
scheduleAt(0.0, msg);
}
}
void Sg1::handleMessage(cMessage *msg)
{
int n = gateSize("out");
int k = intuniform(0, n-1);
int sid = msg->getArrivalGateId();
bool updatestatus = getParentModule()->par("updated");
if (msg == askupdated) {
if (updatestatus == true){
forwardMessage(updated,sid);
}
else {
forwardMessage(unupdated,sid);
}
}
else if (msg == unupdated) {
forwardMessage(update,sid);
}
else {
forwardMessage(askupdated,k);
}
}
void Sg1::forwardMessage(cMessage *msg, int dest)
{
// In this example, we just pick a random gate to send it on.
// We draw a random number between 0 and the size of gate `out[]'.
EV << "Forwarding message " << msg << " on port out[" << dest << "]\n";
send(msg, "out", dest);
}
And an omnet.ini file that only calling the Simplegossip1 network.
How do I solve this? Thanks in advance.
You have to change the line
bool updatestatus = getParentModule()->par("updated");
into
bool updatestatus = par("updated");
because updated is the parameter of Sg1 not of the parent of Sg1.
I would like to make a new message type called wsm_info.
In this message type, I want to include a vehicle structure, as it follows:
struct vehicle{
int vehicle_id;
Coord vehicle_pos;
float speed;
};
In the veins example there is a function called: prepareWSM that's declared in BaseWaveApplLayer.h. This function is a virtual WaveShortMessage* type.
If the wsm_info was inherented from WaveShortMessage I wouldn't need to write and declare a new prepareWSM for wsm_info, right?
So how can I make this wsm_info message inherented of WaveShortMessage?
I tried to write like this in the wsm_info.h:
class wsm_info : public WaveShortMessage
Instead of, that was written previously:
class wsm_info : public ::omnetpp::cPacket
But the error that I get is the following one:
cannot initialize a variable of type wsm_info * with an rvalue of type WaveShortMessage
The full code of my msg_info is below:
cplusplus {{
#include "veins/base/utils/Coord.h"
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class noncobject Coord;
class WaveShortMessage;
struct vehicle {
int vehicle_id;
Coord vehicle_pos;
float speed;
};
message wsm_info extends WaveShortMessage {
//Version of the Wave Short Message
int wsmVersion = 0;
//Determine which security mechanism was used
int securityType = 0;
//Channel Number on which this packet was sent
int channelNumber;
//Data rate with which this packet was sent
int dataRate = 1;
//Power Level with which this packet was sent
int priority = 3;
//Unique number to identify the service
int psid = 0;
//Provider Service Context
string psc = "Service with some Data";
//Length of Wave Short Message
int wsmLength;
vehicle data;
int senderAddress = 0;
int recipientAddress = -1;
int serial = 0;
Coord senderPos;
simtime_t timestamp = 0;
}
Can anyone take a look on my code and point me where is wrong and why? Thanks!
The msg_info.msg should have the following content:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class noncobject Coord;
struct vehicle {
int vehicle_id;
Coord vehicle_pos;
float speed;
};
class WaveShortMessage;
packet wsm_info extends WaveShortMessage {
vehicle data;
}
You cannot use prepareWSM() because it creates a WaveShortMessage object which cannot be cast to wsm_info. Instead you may write a new method, for example:
In /veins/src/veins/modules/application/ieee80211p/BaseWaveApplLayer.h add:
#include "veins/modules/messages/wsm_info_m.h"
and in the class add the declaration:
wsm_info* prepare_wsm_info(std::string name, int dataLengthBits, t_channel channel, int priority, int rcvId, int serial=0);
In /veins/src/veins/modules/application/ieee80211p/BaseWaveApplLayer.cc add:
wsm_info* BaseWaveApplLayer::prepare_wsm_info(std::string name, int lengthBits, t_channel channel, int priority, int rcvId, int serial) {
wsm_info* wsm = new wsm_info(name.c_str());
// ... content similar to prepareWSM()
}
In order to set vehicle structure you can just write:
wsm_info* info = prepare_wsm_info(/* parameters */);
vehicle veh;
veh.speed = 60;
veh.vehicle_id = 3;
// ...
info->setData(veh);
Alternatively you can add parameters for vehicle in the definition of prepare_wsm_info().
If i get you right, you want to extend your wsm_info.msg, is that correct?
According to THIS question, you can modify your wsm_info.msg in the following way:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message wsm_info extends WaveShortMessage {
int vehicle_id;
Coord vehicle_pos;
float speed;
}
where must be declare wsm_info.msg ?in which folder?
I create my RPC Protocol with PB like:
enum EMessages {
E_MSG_METHOD_CONNECT = 0x8001,
E_MSG_EVENT_CONNECT = 0xA001,
...
}
struct MsgHeader {
required int32 sessionRef = 1;
required int32 transactionId = 2;
required int32 status = 3;
}
struct MSG_METHOD_CONNECT {
optional Messages opCode = 1 [default = E_MSG_METHOD_CONNECT];
required MsgHeader header = 2;
.. other fields ..
}
Now, I defined an interface and a template class to add a level of indirection:
class IMessage {
virtual INT getOpCode() = 0;
virtual STRING getName() = 0;
virtual size_t getSize() = 0;
virtual INT SerializeToString(STRING& out) = 0;
virtual INT ParseFromString(STRING& in) = 0;
....
}
template<class MESSAGE>
class IMessageImpl : public IMessage {
protected:
MESSAGE m_Message; ///< The Message Implementation
public:
virtual MESSAGE& getMessage() = 0;
};
And I will use it as:
IMessageImpl<MSG_METHOD_CONNECT> MsgConnect;
Now, when I receive the data from an endpoint I need, of course, to deserialize it according with the message opCode.
Reading this article I'm thinking to use a type map like boost::mpl::map but, since I never use it, I'm searching for some suggestions.
<< ------------------------ [EDIT] ------------------------ >>
Regarding the code above, I try to code it in the following way:
template<class MESSAGE>
class PBMessage : public IMessageImpl<MESSAGE>
{
public:
PBMessage() {};
/* ... other methods ... */
};
// Map of types. The key is the Message opCode
typedef typename mpl::map< mpl::pair<mpl::int_[100], PBMessage<MSG_METHOD_CONNECT> >,
mpl::pair<mpl::int_[101], PBMessage<MSG_EVENT_CONNECT> >,
> TMessageMap;
// The Message type
template < typename MessageMap, int opCode >
typedef typename mpl::at<MessageMap, mpl::int_<opCode> >::type::value TMessage;
And, to create a message from a received buffer I try to code (take it as pseudo-code):
class PBMessageFactory : public IMessageFactory {
public:
IMessage* createMessage(CHAR* buff, UINT size) {
int opCode = buff[0];
TMessage<TMessageMap, opCode> msg;
msg.ParseFromString( STRING(buff) );
}
};
But with no success...Is there someone could give me some suggestions how to retrieve types from a mpl::map?
Thanks,
Daniele.