50 #include "rnr/rnrconfig.h" 52 #include "rnr/appkit/Xml.h" 66 const string &strSearchPath,
67 const string &strXmlFileName,
70 vector<string> vecPath;
76 split(strSearchPath,
':', vecPath);
78 bFoundInstance =
false;
83 for(i=0; i<vecPath.size(); ++i)
85 fqname = vecPath[i] +
'/' + strXmlFileName;
86 if( access(fqname.c_str(), F_OK) == 0 )
88 LOGDIAG3(
"Loading Laelaps description XML file: %s.", fqname.c_str());
90 bFoundInstance =
true;
92 if( (rc = Xml::loadFile(fqname)) < 0 )
94 LOGERROR(
"Parse of Laelaps description from XML file %s failed.",
100 rc = setDescFromDOM(desc);
105 LOGDIAG2(
"Loaded Laelaps description from XML file %s.",
116 if( !bFoundInstance )
118 LOGERROR(
"XML file %s not found.", strXmlFileName.c_str());
125 int LaeXmlCfg::loadFile(
const string &strXmlFileName)
129 rc = Xml::loadFile(strXmlFileName);
131 return rc < 0? -LAE_ECODE_XML: LAE_OK;
134 int LaeXmlCfg::loadFile(
LaeDesc &desc,
const string &strXmlFileName)
138 if( (rc = Xml::loadFile(strXmlFileName)) == OK )
140 rc = setDescFromDOM(desc);
143 return rc < 0? -LAE_ECODE_XML: LAE_OK;
146 int LaeXmlCfg::saveFile(
const string &strXmlFileName)
150 rc = Xml::saveFile(strXmlFileName);
152 return rc < 0? -LAE_ECODE_XML: LAE_OK;
155 int LaeXmlCfg::saveFile(
const LaeDesc &desc,
const string &strXmlFileName)
159 if( (rc = setDOMFromDesc(desc)) == LAE_OK )
161 rc = Xml::saveFile(strXmlFileName);
164 return rc < 0? -LAE_ECODE_XML: LAE_OK;
167 int LaeXmlCfg::createTemplateFile(
const string &strXmlFileName)
171 if( strXmlFileName.empty() )
173 setErrorMsg(
"No file name.");
174 LOGERROR(
"%s", m_bufErrMsg);
175 return -LAE_ECODE_XML;
178 m_strXmlFileName = strXmlFileName;
181 if( (fp = fopen(m_strXmlFileName.c_str(),
"w+")) == NULL )
183 setErrorMsg(
"%s: %s(errno=%d).",
184 m_strXmlFileName.c_str(), strerror(errno), errno);
185 LOGERROR(
"%s", m_bufErrMsg);
186 return -LAE_ECODE_XML;
195 fprintf(fp,
" <!-- RoadNarrows Laelaps Top-Level Description -->\n");
196 fprintf(fp,
"%s", m_strXmlHead.c_str());
201 fprintf(fp,
" <!-- Laelaps robotic mobile base -->\n");
202 fprintf(fp,
" <%s>\n", m_strMajElemBase.c_str());
204 fprintf(fp,
" <!-- DESCRIPTION ELEMENTS HERE -->\n");
206 fprintf(fp,
" </%s>\n\n", m_strMajElemBase.c_str());
211 fprintf(fp,
" <!-- Laelaps package options -->\n");
212 fprintf(fp,
" <%s>\n", m_strMajElemOptions.c_str());
214 fprintf(fp,
" <!-- OPTION ELEMENTS HERE -->\n");
216 fprintf(fp,
" </%s>\n\n", m_strMajElemOptions.c_str());
221 fprintf(fp,
"%s", m_strXmlTail.c_str());
225 LOGDIAG3(
"Created file %s.", m_strXmlFileName.c_str());
240 if( m_pElemRoot == NULL )
242 setErrorMsg(
"Missing DOM and/or <%s> root element missing.",
243 m_strRootElemName.c_str());
244 LOGERROR(
"%s", m_bufErrMsg);
245 return -LAE_ECODE_XML;
249 for(pElem = m_pElemRoot->FirstChildElement();
251 pElem = pElem->NextSiblingElement())
253 if( (sValue = pElem->Value()) == NULL )
259 if( !strcasecmp(sValue, m_strMajElemBase.c_str()) )
261 setBaseDesc(pElem, desc);
265 else if( !strcasecmp(sValue, m_strMajElemOptions.c_str()) )
267 setOptionsDesc(pElem, desc);
272 warnUnknownElem(sValue);
279 int LaeXmlCfg::setBaseDesc(TiXmlElement *pElemMaj,
LaeDesc &desc)
282 string strAttrProdId(
"product_id");
283 string strElemProdName(
"product_name");
284 string strElemProdBrief(
"product_brief");
285 string strElemProdFamily(
"product_family");
286 string strElemProdModel(
"product_model");
287 string strElemProdHwVer(
"hw_version");
295 if( (rc = strToInt(elemAttr(pElemMaj, strAttrProdId), iVal)) < 0 )
297 setErrorMsg(
"%s: No %s attribute of <%s> found or value not an integer.",
298 m_strXmlFileName.c_str(),
299 strAttrProdId.c_str(),
300 m_strMajElemBase.c_str());
301 LOGERROR(
"%s", m_bufErrMsg);
302 return -LAE_ECODE_XML;
308 for(pElem = pElemMaj->FirstChildElement(), rc = LAE_OK;
309 (pElem != NULL) && (rc == LAE_OK);
310 pElem = pElem->NextSiblingElement())
312 if( (sValue = pElem->Value()) == NULL )
318 else if( !strcasecmp(sValue, strElemProdName.c_str()) )
324 else if( !strcasecmp(sValue, strElemProdBrief.c_str()) )
330 else if( !strcasecmp(sValue, strElemProdFamily.c_str()) )
336 else if( !strcasecmp(sValue, strElemProdModel.c_str()) )
342 else if( !strcasecmp(sValue, strElemProdHwVer.c_str()) )
350 warnUnknownElem(sValue);
354 LOGDIAG3(
"%s: Laelaps robotic base description set.",
355 m_strXmlFileName.c_str());
360 int LaeXmlCfg::setOptionsDesc(TiXmlElement *pElemMaj,
LaeDesc &desc)
363 string strElemOptToF(
"tof_option");
364 string strElemOptFCam(
"fcam_option");
371 for(pElem = pElemMaj->FirstChildElement();
373 pElem = pElem->NextSiblingElement())
375 if( (sValue = pElem->Value()) == NULL )
381 else if( !strcasecmp(sValue, strElemOptToF.c_str()) )
383 strText = elemText(pElem);
384 if( !strcasecmp(strText.c_str(), LaeDescOptions::PkgOptStd) )
386 desc.m_options.
m_strPkgToF = LaeDescOptions::PkgOptStd;
388 else if( !strcasecmp(strText.c_str(), LaeDescOptions::PkgOptDeluxe) )
390 desc.m_options.
m_strPkgToF = LaeDescOptions::PkgOptDeluxe;
394 LOGWARN(
"%s: unknown %s package option - assuming %s.",
395 strText.c_str(), strElemOptToF.c_str(), LaeDescOptions::PkgOptStd);
396 desc.m_options.
m_strPkgToF = LaeDescOptions::PkgOptStd;
401 else if( !strcasecmp(sValue, strElemOptFCam.c_str()) )
403 strText = elemText(pElem);
404 if( !strcasecmp(strText.c_str(), LaeDescOptions::PkgOptStd) )
406 desc.m_options.
m_strPkgFCam = LaeDescOptions::PkgOptStd;
410 LOGWARN(
"%s: unknown %s package option - assuming %s.",
411 strText.c_str(), strElemOptFCam.c_str(), LaeDescOptions::PkgOptStd);
412 desc.m_options.
m_strPkgFCam = LaeDescOptions::PkgOptStd;
418 warnUnknownElem(sValue);
422 LOGDIAG3(
"%s: Laelaps package options set.", m_strXmlFileName.c_str());
427 int LaeXmlCfg::setDOMFromDesc(
const LaeDesc &desc)
430 return -LAE_ECODE_GEN;
Laelaps robotic mobile platform full description class.
uint_t strToVersion(const std::string &str)
Convert version dotted string to integer equivalent.
std::string m_strProdBrief
product brief
void clear()
Clear description to the "unitialized" values.
std::string m_strPkgToF
range time-of-flight package
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Split string at the delimiter character.
std::string m_strProdModel
product model
The <b><i>Laelaps</i></b> namespace encapsulates all <b><i>Laelaps</i></b> related constructs...
Laelaps robotic base mobile platform description class interface.
std::string m_strProdHwVer
product hardware version string
Laelaps common utilities.
std::string m_strProdFamily
product family
uint_t m_uProdHwVer
product hardware version number
int m_eProdId
base product id
std::string m_strPkgFCam
front camera package
Laelaps motors, encoder, and controllers hardware abstraction interfaces.
<b><i>Laelaps</i></b> XML configuration class interface.
Top-level package include file.
std::string m_strProdName
product name