37 #include <libxml/parser.h> 45 const int PRECISION_FACTOR = 100;
47 xmlChar* toXmlChar(
const char * arg)
49 return reinterpret_cast<xmlChar*
>(
const_cast<char *
>(arg));
56 pPlatformService_{pPlatformService},
67 EMANE::Models::RFPipe::PCRManager::Open(
const std::string & uri, xmlParserCtxtPtr * ppContext, xmlDoc ** ppDocument, xmlNode ** ppRoot)
69 if((*ppContext = xmlNewParserCtxt()) == NULL)
71 std::stringstream excString;
72 excString <<
"EMANE::Models::RFPipe::PCRManager::Open: Failed to allocate parser context" << std::ends;
76 else if((*ppDocument = xmlCtxtReadFile(*ppContext, uri.c_str(), NULL, XML_PARSE_DTDVALID)) == NULL)
78 std::stringstream excString;
79 excString <<
"EMANE::Models::RFPipe::PCRManager::Open: Failed to parse document " << uri << std::ends;
83 else if((*ppContext)->valid ==
false)
85 std::stringstream excString;
86 excString <<
"EMANE::Models::RFPipe::PCRManager::Open: Document in " << uri <<
" is not valid" << std::ends;
90 else if((*ppRoot = xmlDocGetRootElement(*ppDocument)) == NULL)
92 std::stringstream excString;
93 excString <<
"EMANE::Models::RFPipe::PCRManager::Open: Could not get root element" << std::ends;
101 EMANE::Models::RFPipe::PCRManager::Close(xmlParserCtxtPtr * ppContext, xmlDoc ** ppDocument)
105 xmlFreeParserCtxt(*ppContext);
111 xmlFreeDoc(*ppDocument);
125 xmlParserCtxtPtr pContext{};
129 std::stringstream excString;
130 excString <<
"EMANE::Models::RFPipe::PCRManager::load: must supply curve file name" << std::ends;
136 Open(uri, &pContext, &doc, &root);
139 xmlNodePtr cur{root};
142 pcrEntryVector_.clear();
150 if((!xmlStrcmp(cur->name, toXmlChar(
"pcr"))))
152 getTable(cur->xmlChildrenNode);
159 Close(&pContext, &doc);
162 if(pcrEntryVector_.size() < 1)
164 std::stringstream excString;
165 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: need at least 1 point to define a pcr curve " << std::ends;
177 EMANE::Models::RFPipe::PCRManager::getTable(xmlNodePtr cur)
181 if((!xmlStrcmp(cur->name, toXmlChar(
"table"))))
185 getRows(cur->xmlChildrenNode);
195 EMANE::Models::RFPipe::PCRManager::getRows(xmlNodePtr cur)
199 if((!xmlStrcmp(cur->name, toXmlChar(
"row"))))
207 for(
const auto & entry : pcrEntryVector_)
209 if(fSINR == entry.fSINR_)
211 std::stringstream excString;
212 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: duplicate sinr value " << fSINR << std::ends;
215 else if(fSINR < entry.fSINR_)
217 std::stringstream excString;
218 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: out of order sinr value, must be in increasing value " << fSINR << std::ends;
223 pcrEntryVector_.push_back(EMANE::Models::RFPipe::PCRManager::PCREntry(fSINR, fPOR));
232 EMANE::Models::RFPipe::PCRManager::interpolate()
235 for(
size_t i = 0; i < (pcrEntryVector_.size() - 1); ++i)
238 const int x1{
static_cast<int>(pcrEntryVector_[i].fSINR_ * PRECISION_FACTOR)};
241 const float y1{pcrEntryVector_[i].fPOR_};
244 const int x2{
static_cast<int>(pcrEntryVector_[i + 1].fSINR_ * PRECISION_FACTOR)};
247 const float y2{pcrEntryVector_[i + 1].fPOR_};
250 const float slope{(y2 - y1) / (x2 - x1)};
253 for(
int dx = x1; dx < x2; ++dx)
256 porVector_.push_back((dx - x1) * slope + y1);
260 porVector_.push_back(pcrEntryVector_[pcrEntryVector_.size()-1].fPOR_);
268 if(fSINR < pcrEntryVector_.front().fSINR_)
274 else if(fSINR > pcrEntryVector_.back().fSINR_)
286 if(fSINR == pcrEntryVector_.front().fSINR_ && fSINR == pcrEntryVector_.back().fSINR_)
288 fPOR = pcrEntryVector_.front().fPOR_;
293 const int sinrScaled{
static_cast<int>(fSINR * PRECISION_FACTOR)};
296 const int sinrOffset{
static_cast<int>(pcrEntryVector_.front().fSINR_ * PRECISION_FACTOR)};
299 int idx{sinrScaled - sinrOffset};
302 if(idx >= static_cast<int>(porVector_.size()))
304 idx = porVector_.size() - 1;
308 fPOR = porVector_[idx];
312 if(tablePacketSize_ > 0)
314 fPOR = pow(fPOR,(
float) packetLen /(
float) tablePacketSize_);
319 "MACI %03hu PCRManager::%s: sinr %3.2f, len %zu, por %3.2f",
333 EMANE::Models::RFPipe::PCRManager::getAttribute(xmlNodePtr cur,
const xmlChar *
id)
335 std::string str{
"0"};
339 xmlChar *attr{xmlGetProp(cur,
id)};
343 str =
reinterpret_cast<const char *
>(attr);
354 EMANE::Models::RFPipe::PCRManager::getContent(xmlNodePtr cur)
356 std::string str{
"0"};
358 xmlChar *attr{xmlNodeGetContent(cur)};
362 str =
reinterpret_cast<const char *
>(attr);
PCRManager(EMANE::NEMId id, EMANE::PlatformServiceProvider *pPlatformService)
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
float toFloat(float fMin=std::numeric_limits< float >::lowest(), float fMax=std::numeric_limits< float >::max()) const
std::uint32_t toUINT32(std::uint32_t u32Min=std::numeric_limits< std::uint32_t >::min(), std::uint32_t u32Max=std::numeric_limits< std::uint32_t >::max()) const
float getPCR(float fSinr, size_t size)
Component start exception is used to indicate an exception during transition to the start state...
Parameter conversion class with range checks.
void load(const std::string &uri)