55   const char * pzLayerName = 
"PHYAPITest::ShimLayer";
    57   static std::uint8_t PAYLOAD_BUFFER[0xffff] = {0xBE};
    69   dAntennaAzimuthDegrees_{},        
    70   dAntennaElevationDegrees_{},
    93                                                  "Packet size in bytes.");
    96   configRegistrar.registerNumeric<
float>(
"packetrate",
    99                                         "Defines the transmit rate in packets per second.");
   101   configRegistrar.registerNumeric<std::uint16_t>(
"destination",
   104                                                  "Defines the destination NEM Id.",
   107   configRegistrar.registerNumeric<std::uint64_t>(
"bandwidth",
   110                                                  "Defines the transmitter bandwidth in Hz.",
   113   configRegistrar.registerNumeric<std::uint16_t>(
"antennaprofileid",
   116                                                  "Defines the antenna profile id. The antenna profile id is"   117                                                  " used to identify the appropriate antenna pattern and"   118                                                  " blockage pattern to use when calculating the receive"   119                                                  " power for each packet.");
   121   configRegistrar.registerNumeric<
double>(
"antennaazimuth",
   124                                          "Defines the antenna azimuth pointing angle in degrees.",
   128   configRegistrar.registerNumeric<
double>(
"antennaelevation",
   131                                          "Defines the antenna elevation pointing angle in degrees.",
   136   configRegistrar.registerNonNumeric<std::string>(
"frequency",
   139                                                   "Defines a list of transmit frquency segments with each item"   140                                                   " containing the following 3 elements:  1) frequency (center"   141                                                   " frequency Hz), 2) duration (semgent duraton in usec), and 3)"   142                                                   " offset (transmit offset from TxTime in usec)."   143                                                   " <Frequency>:<Duration>:<Offset>",
   146                                                   "^\\d+(\\.\\d+)?[GMK]?:\\d+(\\.\\d+)?:\\d+(\\.\\d+)?$");
   148   configRegistrar.registerNumeric<
float>(
"txpower",
   151                                          "Defines the transmit power in dBm.");
   153   configRegistrar.registerNonNumeric<std::string>(
"transmitter",
   156                                                   "Defines a list of additional collaborative transmitters to be"   157                                                   " included.  Each item in the list will include NEM ID and"   158                                                   " transmit power in dBm. <NEM Id>:<Tx Power>.",
   161                                                   "^\\d+:\\d+(\\.\\d+)?$");
   176   for(
const auto & item : update)
   178       if(item.first == 
"packetsize")
   180           u16PacketSize_ = item.second[0].asUINT16();
   184                                   "SHIMI %03d %s::%s %s = %hu bytes", 
   191       else if(item.first == 
"packetrate")
   193           float fPacketRate = item.second[0].asFloat();
   197                                   "SHIMI %03d %s::%s %s = %3.2f pps", 
   204           if(fPacketRate > 0.0)
   210       else if(item.first == 
"destination")
   212           dst_ =  item.second[0].asUINT16();
   216                                   "SHIMI %03d %s::%s %s = %hu", 
   223       else if(item.first == 
"bandwidth")
   225           u64BandwidthHz_ = item.second[0].asUINT64();
   229                                   "SHIMI %03d %s::%s %s = %ju",
   236       else if(item.first == 
"antennaprofileid")
   238           antennaProfileId_ = item.second[0].asUINT16();
   242                                   "SHIMI %03d %s::%s %s = %hu", 
   249       else if(item.first == 
"antennaazimuth")
   251           dAntennaAzimuthDegrees_ = item.second[0].asDouble();
   255                                   "SHIMI %03d %s::%s %s = %lf deg", 
   260                                   dAntennaAzimuthDegrees_);
   262       else if(item.first == 
"antennaelevation")
   264           dAntennaElevationDegrees_ = item.second[0].asDouble();
   268                                   "SHIMI %03d %s::%s %s = %lf deg", 
   273                                   dAntennaElevationDegrees_);
   275       else if(item.first == 
"txpower")
   277           fTxPowerdBm_ = item.second[0].asFloat();
   281                                   "SHIMI %03d %s::%s %s = %f dBm", 
   288       else if(item.first == 
"transmitter")
   290           for(
const auto & any : item.second)
   292               std::string sValue = any.asString();
   298               if(tokens.size() == 2)
   305                                           "SHIMI %03d %s::%s %s NEM = %hu, txpwr = %f dBm", 
   314                   transmitters_.push_back({u16TxNEM, fTxPower});
   320                                           "SHIMI %03d %s::%s invalid format %s (%s), expected (NEM:txpwr)", 
   327                   throw makeException<ConfigurationException>(
"PHYAPITestShimLayer: Invalid format %s = %s",
   333       else if(item.first == 
"frequency")
   335           for(
const auto & any : item.second)
   337               std::string sValue = any.asString();
   343               if(tokens.size() == 3)
   351                                           "SHIMI %03d %s::%s %s freq %ju Hz, duration %lf, offset %lf",
   361                   frequencySegments_.push_back({u64TxFrequency,
   363                         std::chrono::duration_cast<Microseconds>(offset)});
   369                                           "SHIMI %03d %s::%s invalid format %s (%s), expected (freq:duration:offset)", 
   376                   throw makeException<ConfigurationException>(
"PHYAPITestShimLayer: Invalid format %s = %s",
   384           throw makeException<ConfigureException>(
"%s: Unexpected configuration item %s",
   413   if(txTimedEventId_ != 0)
   432   if(txInterval_ > DoubleSeconds::zero())
   437        scheduleTimedEvent(Clock::now() + std::chrono::duration_cast<Microseconds>(txInterval_),
   439                           std::chrono::duration_cast<Microseconds>(txInterval_));
   462                          "SHIMI %03d %s::%s, unexpected control message, drop", 
   474                          "SHIMI %03d %s::%s, unexpected control message, drop", 
   490                            "SHIMI %03d %s::%s src %hu dst %hu size %zu controls %zu",
   499    for(
const auto & pControlMessage : msgs)
   501        switch(pControlMessage->getId())
   505              const auto pFrequencyControlMessage =
   511                                               "SHIMI %03d %s::%s Frequency Control Message",
   522              const auto pReceivePropertiesControlMessage =
   528                                               "SHIMI %03d %s::%s Receive Properties Control Message",
   540                                    "SHIMI %03d %s::%s Unknown control message id %hu",
   544                                    pControlMessage->getId());
   556                          "SHIMI %03d %s::%s, unexpected packet, drop", 
   577                                                                     frequencySegments_)};
   579   if(antennaProfileId_)
   582                                                                     dAntennaAzimuthDegrees_,
   583                                                                     dAntennaElevationDegrees_));
 
A Packet class that allows upstream processing to strip layer headers as the packet travels up the st...
The Registrar interface provides access to all of the emulator registrars. 
static AntennaProfileControlMessage * create(AntennaProfileId id, double dAntennaAzimuthDegrees, double dAntennaElevationDegrees)
virtual ConfigurationRegistrar & configurationRegistrar()=0
std::vector< std::string > getTokens(const std::string &sInput, const char *pzDelimeter)
void postStart() override
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
Recieve Properties Control Message is sent from the emulator physical layer with every upstream packe...
static TransmitterControlMessage * create(const Transmitters &transmitters)
std::uint16_t toUINT16(std::uint16_t u16Min=std::numeric_limits< std::uint16_t >::min(), std::uint16_t u16Max=std::numeric_limits< std::uint16_t >::max()) const
std::list< const ControlMessage * > ControlMessages
void processUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs) override
float toFloat(float fMin=std::numeric_limits< float >::lowest(), float fMax=std::numeric_limits< float >::max()) const
void processUpstreamControl(const ControlMessages &msgs) override
NEMId getDestination() const
constexpr NEMId NEM_BROADCAST_MAC_ADDRESS
std::uint64_t toUINT64(std::uint64_t u64Min=std::numeric_limits< std::uint64_t >::min(), std::uint64_t u64Max=std::numeric_limits< std::uint64_t >::max()) const
Store source, destination, creation time and priority information for a packet. 
static FrequencyControlMessage * create(std::uint64_t u64BandwidthHz, const FrequencySegments &frequencySegments)
void processTimedEvent(TimerEventId eventId, const TimePoint &expireTime, const TimePoint &scheduleTime, const TimePoint &fireTime, const void *arg) override
Interface used to create a Shim layer plugin implementation. 
The Frequency Control Message is sent to the emulator physical layer to specify the frequency segment...
void initialize(Registrar ®istrar) override
const PacketInfo & getPacketInfo() const
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
std::chrono::microseconds Microseconds
void processDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs) override
std::chrono::duration< double > DoubleSeconds
DECLARE_SHIM_LAYER(EMANE::Models::PHYAPITest::ShimLayer)
void processDownstreamControl(const ControlMessages &msgs) override
The RadioServiceProvider interface provides access to radio (RF) model specific services. 
void configure(const ConfigurationUpdate &update) override
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
void registerNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", T minValue=std::numeric_limits< T >::lowest(), T maxValue=std::numeric_limits< T >::max(), std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
Clock::time_point TimePoint
virtual bool cancelTimedEvent(TimerEventId eventId)=0
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
#define LOGGER_STANDARD_LOGGING_FN_VARGS(logger, level, fn, fmt, args...)
shim layer used to test the universal phy send/recv api 
void sendDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs=empty)
Parameter conversion class with range checks. 
ShimLayer(NEMId id, PlatformServiceProvider *pPlatformService, RadioServiceProvider *pRadioService)