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);
124 xmlParserCtxtPtr pContext{};
128 std::stringstream excString;
129 excString <<
"EMANE::Models::RFPipe::PCRManager::load: must supply curve file name" << std::ends;
135 Open(uri, &pContext, &doc, &root);
138 xmlNodePtr cur{root};
141 pcrEntryVector_.clear();
149 if((!xmlStrcmp(cur->name, toXmlChar(
"pcr"))))
151 getTable(cur->xmlChildrenNode);
158 Close(&pContext, &doc);
161 if(pcrEntryVector_.size() < 1)
163 std::stringstream excString;
164 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: need at least 1 point to define a pcr curve " << std::ends;
176 EMANE::Models::RFPipe::PCRManager::getTable(xmlNodePtr cur)
180 if((!xmlStrcmp(cur->name, toXmlChar(
"table"))))
184 getRows(cur->xmlChildrenNode);
194 EMANE::Models::RFPipe::PCRManager::getRows(xmlNodePtr cur)
198 if((!xmlStrcmp(cur->name, toXmlChar(
"row"))))
206 for(
const auto & entry : pcrEntryVector_)
208 if(fSINR == entry.fSINR_)
210 std::stringstream excString;
211 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: duplicate sinr value " << fSINR << std::ends;
214 else if(fSINR < entry.fSINR_)
216 std::stringstream excString;
217 excString <<
"EMANE::Models::RFPipe::PCRManager::getRows: out of order sinr value, must be in increasing value " << fSINR << std::ends;
222 pcrEntryVector_.push_back(EMANE::Models::RFPipe::PCRManager::PCREntry(fSINR, fPOR));
231 EMANE::Models::RFPipe::PCRManager::interpolate()
234 for(
size_t i = 0; i < (pcrEntryVector_.size() - 1); ++i)
237 const int x1{
static_cast<int>(pcrEntryVector_[i].fSINR_ * PRECISION_FACTOR)};
240 const float y1{pcrEntryVector_[i].fPOR_};
243 const int x2{
static_cast<int>(pcrEntryVector_[i + 1].fSINR_ * PRECISION_FACTOR)};
246 const float y2{pcrEntryVector_[i + 1].fPOR_};
249 const float slope{(y2 - y1) / (x2 - x1)};
252 for(
int dx = x1; dx < x2; ++dx)
255 porVector_.push_back((dx - x1) * slope + y1);
259 porVector_.push_back(pcrEntryVector_[pcrEntryVector_.size()-1].fPOR_);
267 if(fSINR < pcrEntryVector_.front().fSINR_)
273 else if(fSINR > pcrEntryVector_.back().fSINR_)
285 if(fSINR == pcrEntryVector_.front().fSINR_ && fSINR == pcrEntryVector_.back().fSINR_)
287 fPOR = pcrEntryVector_.front().fPOR_;
292 const int sinrScaled{
static_cast<int>(fSINR * PRECISION_FACTOR)};
295 const int sinrOffset{
static_cast<int>(pcrEntryVector_.front().fSINR_ * PRECISION_FACTOR)};
298 int idx{sinrScaled - sinrOffset};
301 if(idx >= static_cast<int>(porVector_.size()))
303 idx = porVector_.size() - 1;
307 fPOR = porVector_[idx];
311 if(tablePacketSize_ > 0)
313 fPOR = pow(fPOR,(
float) packetLen /(
float) tablePacketSize_);
318 "MACI %03hu PCRManager::%s: sinr %3.2f, len %zu, por %3.2f",
332 EMANE::Models::RFPipe::PCRManager::getAttribute(xmlNodePtr cur,
const xmlChar *
id)
334 std::string str{
"0"};
338 xmlChar *attr{xmlGetProp(cur,
id)};
342 str =
reinterpret_cast<const char *
>(attr);
353 EMANE::Models::RFPipe::PCRManager::getContent(xmlNodePtr cur)
355 std::string str{
"0"};
357 xmlChar *attr{xmlNodeGetContent(cur)};
361 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)