powerguru-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Powerguru-commit] [SCM] powerguru branch, master, updated. 8637d9f769c9


From: Rob Savoye
Subject: [Powerguru-commit] [SCM] powerguru branch, master, updated. 8637d9f769c97b6e4e2d98eae131ab3423366388
Date: Sun, 18 Nov 2018 12:34:23 -0500 (EST)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "powerguru".

The branch, master has been updated
       via  8637d9f769c97b6e4e2d98eae131ab3423366388 (commit)
       via  77a3f80c568abe730f3cfdb20eb5dac0ed4bc65c (commit)
       via  9f7f37c2ca5a53212d7273fd06b58bd37d40af21 (commit)
       via  e5f008f4a10deee6a8758feffa01c1da3898a5ce (commit)
       via  eb87faa92cdc05f8558e60f457936ae0192e22b6 (commit)
       via  b18da55860579c8c66858b35b60df5949730a84b (commit)
       via  67ebdb7b39470c8510f56b3ad4fc8fd242e74f92 (commit)
       via  a7984d93f7c815fc830916063bf9e5119c287161 (commit)
       via  0162045baa5bb1ab27a9b8672305571f2e50cf8d (commit)
       via  1ab1416e07c6d8e2a15f43c7857216ae8f560133 (commit)
       via  97b72db1b3446761ecc5b21dc9b1c64e16d80eb5 (commit)
       via  492f9262f418331da9fec65fa5a79754ada731f0 (commit)
       via  55b3555870e7802a971b3594f0c2e5f13d75a72f (commit)
       via  72322653e11e3d03149b31ed3cac1b5f9160271d (commit)
       via  e93fdfe977d1e7dccf9de028eb2ad4a396cfc9ec (commit)
       via  a76210f7a92a795229380388bce80230efde690d (commit)
       via  fe72271bce330472c93b16f96403fe2c8d692af1 (commit)
       via  92ddf5a7c2c080e73f80546d8147d6838da039f5 (commit)
       via  64e9fb4b92da6f48656e0d42413662af96e86b30 (commit)
       via  8eb97acdebe677c4d9cb214a98a2213f10eb15d6 (commit)
       via  33fa0a0f48b344b596d8df7fcaa7e2c1e8bbe0ab (commit)
       via  3dac25dd99e2d61185231fa4e964ddd7bc40deb9 (commit)
       via  02ced6806507b8ad2220af46b23032bad688ff0f (commit)
       via  4228f1b7835f8edad0a517fe6c0077416b28f82d (commit)
       via  93e475a3bd17b2d2e18bc1b22ed2cc5c02f856ae (commit)
       via  5996a6563cf9dce9d38c4cbf5f271915382c55be (commit)
       via  92b1d7bcaa75b5920d529390e08c9b1795c32fd6 (commit)
       via  9c8e9a454cf5d93964cf06535ffec2613a0fc031 (commit)
       via  c1ebcf262351aace966d48e6d53d75aa73874760 (commit)
      from  85c3e9bed99f7dafda22e3438da2da6bf9140cba (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=8637d9f769c97b6e4e2d98eae131ab3423366388


commit 8637d9f769c97b6e4e2d98eae131ab3423366388
Author: Rob Savoye <address@hidden>
Date:   Sun Nov 18 10:22:21 2018 -0700

    Improve setting sysroot

diff --git a/configure.ac b/configure.ac
index ab96daf..df8022e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,15 +105,9 @@ with_top_level=""
 if test x"${cross_compiling}" = xyes; then
   AC_MSG_CHECKING([For a usable sysroot])
   dnl Check if /usr isn't part of the specified path
-  if test -d ${sysroot}/usr; then
-    sysroot=${withval}/usr
-  else 
-    dnl Check if the specified path supplies /usr
-    if test -d ${sysroot}/usr/include; then
-      sysroot=${sysroot}
-    else
+  if test ! -d ${sysroot}/usr && ! -d ${sysroot}/usr/include; then
       AC_MSG_ERROR([Specified sysroot \"${sysroot}\" doesn't exist!])
-    fi
+  else
     CXXFLAGS="--sysroot=${sysroot}"
     CFLAGS="--sysroot=${sysroot}"
     LDFLAGS="--sysroot=${sysroot}"
@@ -152,6 +146,8 @@ else
     export libslist="${libslist} /lib/${DEB_HOST_MULTIARCH} 
/usr/lib/${DEB_HOST_MULTIARCH}"
   fi
   export pathlist=$PATH
+  RASPI_FLAGS="-march=armv6z -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard"
+  AC_SUBST(RASPI_FLAGS)
 fi
 AM_CONDITIONAL(CROSS_COMPILING, [ test x$cross_compiling = xyes ])
 
@@ -163,7 +159,14 @@ save_CFLAGS="${CFLAGS}"
 CFLAGS="${save_CFLAGS} -Wall -Werror"
 
 # dnl libxml2's headers are sometimes in a libxml2 directory, but not always
-CPPFLAGS="-I${sysroot}/usr/include/libxml2"
+if test -d ${sysroot}/usr/local/include/libxml2; then
+   CPPFLAGS="-I${sysroot}/usr/local/include/libxml2"
+else
+   if test -d "${sysroot}/usr/include/libxml2"; then
+     CPPFLAGS="-I${sysroot}/usr/include/libxml2"
+   fi
+fi
+
 AC_MSG_CHECKING([For libxml2 development files])
 AC_TRY_COMPILE([#include <libxml/xmlstring.h>], [
   xmlChar foo = 'x';
@@ -176,7 +179,7 @@ AC_MSG_RESULT([${has_libxml}])
 if test x"${has_libxml}" = x"true"; then
   AC_DEFINE([HAVE_LIBXML], [1], [Has libxml2 development files])
   LIBXML_LIBS="-lxml2"
-  LIBXML_CPPFLAGS="-I${sysroot}/usr/include/libxml2"
+  LIBXML_CPPFLAGS="${CPPFLAGS}"
   AC_SUBST(LIBXML_CPPFLAGS)
   AC_SUBST(LIBXML_LIBS)
 fi
@@ -294,7 +297,7 @@ sim/Makefile
 devices/Makefile
 snmp/Makefile
 client/Makefile
-po/Makefile
+po/Makefile.in
 doc/Makefile
 doc/C/Makefile
 testsuite/Makefile

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=77a3f80c568abe730f3cfdb20eb5dac0ed4bc65c


commit 77a3f80c568abe730f3cfdb20eb5dac0ed4bc65c
Author: Rob Savoye <address@hidden>
Date:   Sun Nov 18 10:21:36 2018 -0700

    CLeanup xmlChar vs unsigned int mess. Drop BAD_CAST macros

diff --git a/lib/msgs.cc b/lib/msgs.cc
index 099f37e..c24f4ff 100644
--- a/lib/msgs.cc
+++ b/lib/msgs.cc
@@ -27,25 +27,27 @@
 #include <iterator>
 #include <map>
 #ifdef __STDC_HOSTED__
-#include <sstream>
+# include <sstream>
 #else
-#include <strstream>
+# include <strstream>
+#endif
+#ifdef HAVE_LIBXML
+# include <libxml/encoding.h>
+# include <libxml/xmlwriter.h>
+# include <libxml/debugXML.h>
+# include "xml.h"
 #endif
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-#include <libxml/debugXML.h>
 #include "database.h"
 #include "log.h"
 #include "err.h"
-#include "xml.h"
 #include "msgs.h"
 #include "tcputil.h"
 #include "tcpip.h"
 
 using namespace std;
 Msgs::net_mode_e  Msgs::_net_mode;
-std::map<const unsigned char *, Msgs::methodPtr_t> Msgs::_methods;
-std::map<const unsigned char *, std::string> Msgs::_cache;
+std::map<const char *, Msgs::methodPtr_t> Msgs::_methods;
+std::map<const char *, std::string> Msgs::_cache;
 
 #define MY_ENCODING "ISO-8859-1"
 
@@ -201,96 +203,96 @@ Msgs::init(void)
     DEBUGLOG_REPORT_FUNCTION;
 
     // Top level node of the message
-    _methods[BAD_CAST "powerguru"] =      &Msgs::powerguruProcess;
+    _methods[ "powerguru"] =      &Msgs::powerguruProcess;
   
     // initialization message
-    _methods[BAD_CAST "helo"] =           &Msgs::heloProcess;
-    _methods[BAD_CAST "client"] =         &Msgs::clientProcess;
-    _methods[BAD_CAST "server"] =         &Msgs::serverProcess;
+    _methods[ "helo"] =           &Msgs::heloProcess;
+    _methods[ "client"] =         &Msgs::clientProcess;
+    _methods[ "server"] =         &Msgs::serverProcess;
   
     // Meter readings
-    _methods[BAD_CAST "meters"] =         &Msgs::metersProcess;
-    _methods[BAD_CAST "charge-mps"] =     &Msgs::chargeAmpsProcess;
-    _methods[BAD_CAST "load-amps"] =      &Msgs::loadAmpsProcess;
-    _methods[BAD_CAST "pv-amps"] =        &Msgs::pvAmpsProcess;
-    _methods[BAD_CAST "pv-volts"] =       &Msgs::pvVoltsProcess;
-    _methods[BAD_CAST "daily-kwh"] =      &Msgs::dailyKwhProcess;
-    _methods[BAD_CAST "hertz"] =          &Msgs::hertzProcess;
-    _methods[BAD_CAST "battery-volts"] =  &Msgs::batteryVoltsProcess;
-    _methods[BAD_CAST "buy-amps"] =       &Msgs::buyAmpsProcess;
-    _methods[BAD_CAST "sell-amps"] =      &Msgs::sellAmpsProcess;
-    _methods[BAD_CAST "ac-volts-out"] =   &Msgs::acVoltsOutProcess;
-    _methods[BAD_CAST "ac1-volts-in"] =   &Msgs::ac1InProcess;
-    _methods[BAD_CAST "ac2-volts-in"] =   &Msgs::ac2InProcess;
+    _methods[ "meters"] =         &Msgs::metersProcess;
+    _methods[ "charge-mps"] =     &Msgs::chargeAmpsProcess;
+    _methods[ "load-amps"] =      &Msgs::loadAmpsProcess;
+    _methods[ "pv-amps"] =        &Msgs::pvAmpsProcess;
+    _methods[ "pv-volts"] =       &Msgs::pvVoltsProcess;
+    _methods[ "daily-kwh"] =      &Msgs::dailyKwhProcess;
+    _methods[ "hertz"] =          &Msgs::hertzProcess;
+    _methods[ "battery-volts"] =  &Msgs::batteryVoltsProcess;
+    _methods[ "buy-amps"] =       &Msgs::buyAmpsProcess;
+    _methods[ "sell-amps"] =      &Msgs::sellAmpsProcess;
+    _methods[ "ac-volts-out"] =   &Msgs::acVoltsOutProcess;
+    _methods[ "ac1-volts-in"] =   &Msgs::ac1InProcess;
+    _methods[ "ac2-volts-in"] =   &Msgs::ac2InProcess;
   
     // Status messages on the system
-    _methods[BAD_CAST "status"] = &Msgs::statusProcess;
-    _methods[BAD_CAST "version"] = &Msgs::statusProcess;
-    _methods[BAD_CAST "revision"] = &Msgs::statusProcess;
-    _methods[BAD_CAST "opmode"] = &Msgs::statusProcess;
-    _methods[BAD_CAST "errormode"] = &Msgs::statusProcess;
-    _methods[BAD_CAST "warningmode"] = &Msgs::statusProcess;
+    _methods[ "status"] = &Msgs::statusProcess;
+    _methods[ "version"] = &Msgs::statusProcess;
+    _methods[ "revision"] = &Msgs::statusProcess;
+    _methods[ "opmode"] = &Msgs::statusProcess;
+    _methods[ "errormode"] = &Msgs::statusProcess;
+    _methods[ "warningmode"] = &Msgs::statusProcess;
 
     // Configuration settings
-    _methods[BAD_CAST "config"] = &Msgs::configProcess;
-    _methods[BAD_CAST "generator"] = &Msgs::configProcess;
-    _methods[BAD_CAST "grid"] = &Msgs::configProcess;
-    _methods[BAD_CAST "buy"] = &Msgs::configProcess;
-    _methods[BAD_CAST "sell"] = &Msgs::configProcess;
-    _methods[BAD_CAST "start"] = &Msgs::configProcess;
-    _methods[BAD_CAST "end"] = &Msgs::configProcess;
+    _methods[ "config"] = &Msgs::configProcess;
+    _methods[ "generator"] = &Msgs::configProcess;
+    _methods[ "grid"] = &Msgs::configProcess;
+    _methods[ "buy"] = &Msgs::configProcess;
+    _methods[ "sell"] = &Msgs::configProcess;
+    _methods[ "start"] = &Msgs::configProcess;
+    _methods[ "end"] = &Msgs::configProcess;
 
     // Command messages
-    _methods[BAD_CAST "command"] = &Msgs::commandProcess;
-//   _methods[BAD_CAST "auxilary"] = &Msgs::commandAuxilaryProcess;
-//   _methods[BAD_CAST "relay"] = &Msgs::commandRelayProcess;
-//   _methods[BAD_CAST "poll"] = &Msgs::commandPollProcess;;
-//   _methods[BAD_CAST "inverter"] = &Msgs::commandInverterProcess;;
-//   _methods[BAD_CAST "charger"] = &Msgs::commandChargerProcess;;
-    // _methods[BAD_CAST "restart"] = &Msgs::commandRestartProcess;;
-    _methods[BAD_CAST "auxilary"] = &Msgs::commandProcess;
-    _methods[BAD_CAST "relay"] = &Msgs::commandProcess;
-    _methods[BAD_CAST "poll"] = &Msgs::commandProcess;
-    _methods[BAD_CAST "inverter"] = &Msgs::commandProcess;
-    _methods[BAD_CAST "charger"] = &Msgs::commandProcess;
+    _methods[ "command"] = &Msgs::commandProcess;
+//   _methods[ "auxilary"] = &Msgs::commandAuxilaryProcess;
+//   _methods[ "relay"] = &Msgs::commandRelayProcess;
+//   _methods[ "poll"] = &Msgs::commandPollProcess;;
+//   _methods[ "inverter"] = &Msgs::commandInverterProcess;;
+//   _methods[ "charger"] = &Msgs::commandChargerProcess;;
+    // _methods[ "restart"] = &Msgs::commandRestartProcess;;
+    _methods[ "auxilary"] = &Msgs::commandProcess;
+    _methods[ "relay"] = &Msgs::commandProcess;
+    _methods[ "poll"] = &Msgs::commandProcess;
+    _methods[ "inverter"] = &Msgs::commandProcess;
+    _methods[ "charger"] = &Msgs::commandProcess;
   
     //  _methods[""] = &Msgs::unimplementedProcess;
 
     // preload a few values
     if (_net_mode == DAEMON) {
-        _cache[BAD_CAST "version"] = VERSION;
-        _cache[BAD_CAST "revision"] = VERSION;
-//     _cache[BAD_CAST "opmode"] = "unknown";
-//     _cache[BAD_CAST "errormode"] = "unknown";
-//     _cache[BAD_CAST "warningmode"] = "unknown";
+        _cache[ "version"] = VERSION;
+        _cache[ "revision"] = VERSION;
+//     _cache[ "opmode"] = "unknown";
+//     _cache[ "errormode"] = "unknown";
+//     _cache[ "warningmode"] = "unknown";
 
         // FIXME: fake meter values!
         // Meters
-        _cache[BAD_CAST "battery-volts"] = "88888888";
-        _cache[BAD_CAST "charge-amps"] = "777777777";
-        _cache[BAD_CAST "load-amps"] = "66666666";
-        _cache[BAD_CAST "pv-amps"] = "55555555";
-        _cache[BAD_CAST "sell-amps"] = "444444444444";
+        _cache[ "battery-volts"] = "88888888";
+        _cache[ "charge-amps"] = "777777777";
+        _cache[ "load-amps"] = "66666666";
+        _cache[ "pv-amps"] = "55555555";
+        _cache[ "sell-amps"] = "444444444444";
     }
   
     return SUCCESS;
 }
 
 std::string
-Msgs::cacheGet(const unsigned char * name) {
+Msgs::cacheGet(const char * name) {
     // DEBUGLOG_REPORT_FUNCTION;
 #if 1
-    const unsigned char         *tag;
+    const char         *tag;
     string                str;
   
     _body.str("");
-    std::map<const unsigned char *, string>::const_iterator it;
+    std::map<const char *, string>::const_iterator it;
     for (it = _cache.begin(); it != _cache.end(); it++) {
         //entry = it->second;
         tag = it->first;
         str  = it->second;
         _body.str("");
-        if (xmlStrcmp(tag, name) == 0) {
+        if (strcmp(tag, name) == 0) {
             if (str.size() != 0) {
                 _body << " Has data: " << str;
             } else {
@@ -309,7 +311,7 @@ Msgs::cacheGet(const unsigned char * name) {
 }
 
 retcode_t
-Msgs::cacheAdd(const unsigned char * name, string str)
+Msgs::cacheAdd(const char * name, string str)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     _cache[name] = str;
@@ -321,7 +323,7 @@ Msgs::cacheAdd(const unsigned char * name, string str)
 
 // Add a function for handling an XML tag to the list.
 void
-Msgs::methodSet(const unsigned char * name, methodPtr_t func)
+Msgs::methodSet(const char * name, methodPtr_t func)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     _methods[name] = func;
@@ -329,14 +331,14 @@ Msgs::methodSet(const unsigned char * name, methodPtr_t 
func)
 
 // Get the function for an XML tag from the list.
 Msgs::methodPtr_t
-Msgs::methodGet(const unsigned char * name)
+Msgs::methodGet(const char * name)
 {
     //DEBUGLOG_REPORT_FUNCTION;
 #if 1
-    const unsigned char         *str;
+    const char         *str;
     Msgs::methodPtr_t     ptr;
   
-    std::map<const unsigned char *, Msgs::methodPtr_t>::const_iterator it;
+    std::map<const char *, Msgs::methodPtr_t>::const_iterator it;
     for (it = _methods.begin(); it != _methods.end(); it++) {
         //entry = it->second;
         str = it->first;
@@ -349,7 +351,7 @@ Msgs::methodGet(const unsigned char * name)
         }
         //     dbglogfile << "Looking for method for XML Tag \"" << 
name.c_str()
         //                << "\" has " << _body.str().c_str() << endl;
-        if (xmlStrcmp(str, name) == 0) {
+        if (strcmp(str, name) == 0) {
             return ptr;
         }
     }
@@ -362,7 +364,7 @@ Msgs::methodGet(const unsigned char * name)
 
 // Call the function to process an XML node
 retcode_t
-Msgs::methodProcess(const unsigned char *name, XMLNode *node)
+Msgs::methodProcess(const char *name, XMLNode *node)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     //(this->*_methods.find(name)(node); 
@@ -374,12 +376,12 @@ void
 Msgs::methodsDump(void)
 {
     DEBUGLOG_REPORT_FUNCTION;
-    const unsigned char         *name;
+    const char         *name;
     Msgs::methodPtr_t     ptr;
   
     dbglogfile << "We have " << (int)_methods.size() << " in function table" 
<< endl;
   
-    std::map<const unsigned char *, Msgs::methodPtr_t>::const_iterator it;
+    std::map<const char *, Msgs::methodPtr_t>::const_iterator it;
     for (it = _methods.begin(); it != _methods.end(); it++) {
         name = it->first;
         ptr  = it->second;
@@ -399,12 +401,12 @@ void
 Msgs::cacheDump(void)
 {
     DEBUGLOG_REPORT_FUNCTION;
-    const unsigned char         *name;
+    const char         *name;
     string                data;
   
     dbglogfile << "We have " << (int)_cache.size() << " items in the cache" << 
endl;
   
-    std::map<const unsigned char *, string>::const_iterator it;
+    std::map<const char *, string>::const_iterator it;
     for (it = _cache.begin(); it != _cache.end(); it++) {
         name = it->first;
         data  = it->second;
@@ -435,8 +437,8 @@ Msgs::unimplementedProcess(XMLNode *xml)
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"" << _version << "\">";
     _body << "<status><warningmode><";
-    _body << BAD_CAST xml->nameGet();
-    _body << ">unimplemented</" << BAD_CAST xml->nameGet();
+    _body <<  xml->nameGet();
+    _body << ">unimplemented</" <<  xml->nameGet();
     _body <<  "></warningmode>" << "</status>"; 
     _body << "</powerguru>";
     _body << ends;
@@ -453,7 +455,7 @@ Msgs::process(XMLNode *xml)
 {
     DEBUGLOG_REPORT_FUNCTION;
     methodPtr_t   fptr;
-    const unsigned char *str;
+    const char *str;
     retcode_t     ret;
     int           i;
 
@@ -538,7 +540,7 @@ Msgs::statusCreate(meter_data_t *md)
     int rc;
     xmlTextWriterPtr writer;
     xmlBufferPtr buf;
-    unsigned char *tmp;
+    char *tmp;
   
     if ((buf = xmlBufferCreate()) == NULL) {
         printf("testXmlwriterMemory: Error creating the xml buffer\n");
@@ -558,21 +560,21 @@ Msgs::statusCreate(meter_data_t *md)
         return "";
     }
   
-    if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "powerguru")) < 0) {
+    if ((rc = xmlTextWriterStartElement(writer,  "powerguru")) < 0) {
         printf
             ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
         return "";
     }
   
-    if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "status")) < 0) {
+    if ((rc = xmlTextWriterStartElement(writer,  "status")) < 0) {
         printf
             ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
         return "";
     }
     
     /* Add an attribute with name "version" and value "1.0" to status. */
-    if ((rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
-                                          BAD_CAST "1.0")) < 0) {
+    if ((rc = xmlTextWriterWriteAttribute(writer,  "version",
+                                           "1.0")) < 0) {
         printf
             ("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
         return "";
@@ -688,7 +690,7 @@ Msgs::metersRequestCreate(xml_meters_e val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const unsigned char * type, int val) {
+Msgs::metersResponseCreate(const char * type, int val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -703,7 +705,7 @@ Msgs::metersResponseCreate(const unsigned char * type, int 
val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const unsigned char *type, float val) {
+Msgs::metersResponseCreate(const char *type, float val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -718,7 +720,7 @@ Msgs::metersResponseCreate(const unsigned char *type, float 
val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const unsigned char *type, string val) {
+Msgs::metersResponseCreate(const char *type, string val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -894,7 +896,7 @@ Msgs::requestCreate(xml_command_e tag)
 
 
 std::string
-Msgs::responseCreate(xml_msg_e type, const unsigned char *tag, string val)
+Msgs::responseCreate(xml_msg_e type, const char *tag, string val)
 {
     DEBUGLOG_REPORT_FUNCTION;
     string str;
@@ -959,7 +961,7 @@ Msgs::print_msg(std::string msg)
         "\r\n\t\t\t\t\t",
     };
   
-    xmlDebugDumpString(stderr, (const unsigned char *)msg.c_str());
+    xmlDebugDumpString(stderr, (const xmlChar *)msg.c_str());
     //  cerr << "++++++++++++++++++++++" << endl;
   
     // Strip off the DTD header, as we're not bothering to validate
@@ -1007,23 +1009,23 @@ Msgs::statusProcess(XMLNode *node)
 {
     DEBUGLOG_REPORT_FUNCTION;
     //  XMLNode *child;
-    //  unsigned int i;
+    //  xmlChar i;
     string str;
     _body.str("");
     _body << _version;
 
-    // dbglogfile << BAD_CAST node->valueGet() << endl;
+    // dbglogfile <<  node->valueGet() << endl;
   
     if (_net_mode == DAEMON) {
-        if (xmlStrcmp(node->valueGet(), BAD_CAST "sysversion") == 0) {
+        if (strcmp(node->valueGet(),  "sysversion") == 0) {
             str = responseCreate(STATUS, node->valueGet(), 
_body.str().c_str());
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "revision") == 0) {
+        } else if (strcmp(node->valueGet(),  "revision") == 0) {
             str = responseCreate(STATUS, node->valueGet(), "0.0");
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "opmode") == 0) {
+        } else if (strcmp(node->valueGet(),  "opmode") == 0) {
             str = responseCreate(STATUS, node->valueGet(), "none");
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "warningmode") == 0) {
+        } else if (strcmp(node->valueGet(),  "warningmode") == 0) {
             str = responseCreate(STATUS, node->valueGet(), "none");    
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "errormode") == 0) {
+        } else if (strcmp(node->valueGet(),  "errormode") == 0) {
             str = responseCreate(STATUS, node->valueGet(), "none");
         }
     
@@ -1035,20 +1037,20 @@ Msgs::statusProcess(XMLNode *node)
     }
 
     if (_net_mode == CLIENT) {
-        if (xmlStrcmp(node->nameGet(), BAD_CAST "status") == 0) {
+        if (strcmp(node->nameGet(),  "status") == 0) {
             return SUCCESS;
         }
 
 #if 0
-        if        (xmlStrcmp(node->nameGet(), BAD_CAST "revision") == 0) {
+        if        (strcmp(node->nameGet(),  "revision") == 0) {
             //cerr << "VER" << endl;
-        } else if (xmlStrcmp(node->nameGet(), BAD_CAST "sysversion") == 0) {
+        } else if (strcmp(node->nameGet(),  "sysversion") == 0) {
             //cerr << "REV" << endl;
-        } else if (xmlStrcmp(node->nameGet(), BAD_CAST "opmode") == 0) {
+        } else if (strcmp(node->nameGet(),  "opmode") == 0) {
             //cerr << "OP" << endl;
-        } else if (xmlStrcmp(node->nameGet(), BAD_CAST "warningmode") == 0) {
+        } else if (strcmp(node->nameGet(),  "warningmode") == 0) {
             //cerr << "WARN" << endl;
-        } else if (xmlStrcmp(node->nameGet(), BAD_CAST "errormode") == 0) {
+        } else if (strcmp(node->nameGet(),  "errormode") == 0) {
             //cerr << "ERROR" << endl;
         }
 #endif
@@ -1127,14 +1129,14 @@ Msgs::serverProcess(XMLNode *node)
         if ((attr = node->attribGet(0))) {
             dbglogfile << "\tAttribute is \"" << attr->nameGet()
                        << "\" with a value of " << attr->valueGet() << endl;
-            if (xmlStrcmp(attr->valueGet(), (const unsigned char 
*)_thisip.c_str()) != 0) {
+            if (strcmp(attr->valueGet(), (const char *)_thisip.c_str()) != 0) {
                 dbglogfile << "WARNING: IP's don't match!!!!" << endl;
                 return ERROR;
             }
         }
     }
 
-    if (xmlStrcmp(node->valueGet(), (const unsigned char *)_thishost.c_str()) 
!= 0) {
+    if (strcmp(node->valueGet(), (const char *)_thishost.c_str()) != 0) {
         dbglogfile << "WARNING: Host's don't match!!!!" << endl;
         return ERROR;
     }
@@ -1157,7 +1159,7 @@ Msgs::clientProcess(XMLNode *node)
             if ((attr = node->attribGet(0))) {
                 dbglogfile << "\tAttribute is \"" << attr->nameGet()
                            << "\" with a value of " << attr->valueGet() << 
endl;
-                if (xmlStrcmp(attr->valueGet(), (const unsigned char 
*)_remoteip.c_str()) != 0) {
+                if (strcmp(attr->valueGet(), (const char *)_remoteip.c_str()) 
!= 0) {
                     dbglogfile << "WARNING: IP's don't match!!!!" << endl;
                     return ERROR;
                 }
@@ -1166,7 +1168,7 @@ Msgs::clientProcess(XMLNode *node)
     }
 
     if (_remotehost.size() != 0) {
-        if (xmlStrcmp(node->valueGet(), (const unsigned char 
*)_remotehost.c_str()) != 0) {
+        if (strcmp(node->valueGet(), (const char *)_remotehost.c_str()) != 0) {
             dbglogfile << "WARNING: Host's don't match!!!!" << endl;
             return ERROR;
         }
@@ -1192,7 +1194,7 @@ Msgs::powerguruProcess(XMLNode *node)
         if ((attr = node->attribGet(0))) {
 //       dbglogfile << "\tAttribute is \"" << attr->nameGet().c_str()
 //                  << "\" with a value of " << attr->valueGet().c_str() << 
endl;
-            if (xmlStrcmp((const unsigned char *)_body.str().c_str(), 
attr->valueGet()) != 0) {
+            if (strcmp((const char *)_body.str().c_str(), (const 
char*)attr->valueGet()) != 0) {
                 dbglogfile << "Versions in header don't match!" << endl;
             } else {
                 dbglogfile << "Versions in header match" << endl;        
@@ -1235,13 +1237,15 @@ Msgs::loadAmpsProcess(XMLNode *node) {
     
         return SUCCESS;
     }
-  
+
+#if 0
     if (_net_mode == DAEMON) {
         string str = metersResponseCreate(node->valueGet(), 
_cache[node->nameGet()]);
     
         return SUCCESS;
     }
-
+#endif
+    
     return SUCCESS;
 }
 
@@ -1322,13 +1326,15 @@ Msgs::batteryVoltsProcess(XMLNode *node) {
     
         return SUCCESS;
     }
-  
+
+#if 0
     if (_net_mode == DAEMON) {
         string str = metersResponseCreate(node->valueGet(), 
_cache[node->nameGet()]);
     
         return SUCCESS;
     }
-  
+#endif
+    
     return ERROR;
 }
 
@@ -1440,19 +1446,19 @@ Msgs::commandProcess(XMLNode *node)
     _body.str("");
     _body << _version;
 
-    // dbglogfile << BAD_CAST node->valueGet() << endl;
-  
+    // dbglogfile <<  node->valueGet() << endl;
+
+#if 0
     if (_net_mode == DAEMON) {
-        if (xmlStrcmp(node->valueGet(), BAD_CAST "auxilary") == 0) {
+        if (strcmp(node->value Get(), "auxilary") == 0) {
             str = responseCreate(COMMAND, node->valueGet(), "0.0");
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "relay") == 0) {
+        } else if (strcmp(node->valueGet(), "relay") == 0) {
             str = responseCreate(COMMAND, node->valueGet(), "none");
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "poll") == 0) {
+        } else if (strcmp(node->valueGet(), "poll") == 0) {
             str = responseCreate(COMMAND, node->valueGet(), "inverter");    
-        } else if (xmlStrcmp(node->valueGet(), BAD_CAST "") == 0) {
+        } else if (strcmp(node->valueGet(), "") == 0) {
             str = responseCreate(COMMAND, node->valueGet(), "charger");
         }
-    
         if (writeNet(str)) {
             return ERROR;
         } else {
@@ -1461,16 +1467,16 @@ Msgs::commandProcess(XMLNode *node)
     }
 
     if (_net_mode == CLIENT) {
-        if (xmlStrcmp(node->nameGet(), BAD_CAST "command") == 0) {
+        if (strcmp(node->nameGet(), "command") == 0) {
             return SUCCESS;
         }
-
-
         cacheAdd(node->nameGet(), (const char*)node->valueGet());
         dbglogfile << "tag \"" << node->nameGet() << "\" has a value of: " << 
node->valueGet() << endl;
     
         return SUCCESS;
     }
+#endif
+
     return ERROR;  
 }
 
diff --git a/lib/msgs.h b/lib/msgs.h
index 878d423..a69061d 100644
--- a/lib/msgs.h
+++ b/lib/msgs.h
@@ -37,7 +37,9 @@
 #include "database.h"
 #include "log.h"
 #include "err.h"
-#include "xml.h"
+#ifdef HAVE_LIBXML
+# include "xml.h"
+#endif
 #include "tcpip.h"
 
 class Msgs : public Tcpip {
@@ -163,11 +165,11 @@ public:
     std::string metersRequestCreate(xml_meters_e type);
 
     // This formats a response from the daemon to the client
-    std::string metersResponseCreate(const unsigned char *tag, int val);
-    std::string metersResponseCreate(const unsigned char *tag, float val);
-    std::string metersResponseCreate(const unsigned char *tag, std::string);
+    std::string metersResponseCreate(const char *tag, int val);
+    std::string metersResponseCreate(const char *tag, float val);
+    std::string metersResponseCreate(const char *tag, std::string);
 
-    std::string responseCreate(xml_msg_e type, const unsigned char *tag, 
std::string);
+    std::string responseCreate(xml_msg_e type, const char *tag, std::string);
   
     std::string requestCreate(xml_meters_e tag);
     std::string requestCreate(xml_status_e tag);
@@ -177,13 +179,13 @@ public:
     std::string packet(void) { return _body.str(); }
     void print_msg(std::string msg);
 
-    void methodSet(const unsigned char *name, methodPtr_t func);
-    methodPtr_t methodGet(const unsigned char *name);
-    retcode_t methodProcess(const unsigned char *name, XMLNode *node);
+    void methodSet(const char *name, methodPtr_t func);
+    methodPtr_t methodGet(const char *name);
+    retcode_t methodProcess(const char *name, XMLNode *node);
     void methodsDump(void);
 
-    std::string cacheGet(const unsigned char *name);
-    retcode_t cacheAdd(const unsigned char *name, std::string);
+    std::string cacheGet(const char *name);
+    retcode_t cacheAdd(const char *name, std::string);
     void cacheDump(void);
 
     std::string thisIPGet(void) { return _thisip; };
@@ -195,8 +197,8 @@ public:
   
 private:
     float               _version;
-    static std::map<const unsigned char *, methodPtr_t> _methods;
-    static std::map<const unsigned char *, std::string> _cache;
+    static std::map<const char *, methodPtr_t> _methods;
+    static std::map<const char *, std::string> _cache;
     static net_mode_e   _net_mode;
 #ifdef __STDC_HOSTED__
     std::ostringstream  _body;
diff --git a/lib/tcpip.cc b/lib/tcpip.cc
index db9d0cb..7ffab08 100644
--- a/lib/tcpip.cc
+++ b/lib/tcpip.cc
@@ -36,15 +36,15 @@
 #include <iostream>
 #include <sys/param.h>
 #include <fcntl.h>
-// #ifdef HAVE_LIBXML
+#ifdef HAVE_LIBXML
 // # include <libxml/encoding.h>
 // # include <libxml/xmlwriter.h>
 // # include <libxml/debugXML.h>
-// #endif
+# include "xml.h"
+#endif
 
 #include "tcpip.h"
 #include "tcputil.h"
-#include "xml.h"
 #include "log.h"
 #include "err.h"
 
@@ -652,7 +652,7 @@ Tcpip::toggleDebug(bool val)
 
 // Return true if there is data in the socket, otherwise return false.
 retcode_t
-Tcpip::anydata(vector<const xmlChar *> &msgs)
+Tcpip::anydata(vector<const unsigned char *> &msgs)
 {
     DEBUGLOG_REPORT_FUNCTION;
     //printf("%s: \n", __FUNCTION__);
@@ -662,7 +662,7 @@ Tcpip::anydata(vector<const xmlChar *> &msgs)
 // This waits for data on the socket, and on stdin. This way we can sit
 // here in a kernel sleep instead of polling all devices.
 retcode_t
-Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
+Tcpip::anydata(int fd, vector<const unsigned char *> &msgs)
 {
     DEBUGLOG_REPORT_FUNCTION;
     fd_set                fdset;
@@ -747,7 +747,7 @@ Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
         ptr = buf;
         // If we get a single XML message, do less work
         if (ret == cr + 1) {
-            adjusted_size = memadjust(ret + 1);
+            // adjusted_size = memadjust(ret + 1); FIXME:
             packet = new char[adjusted_size];
             //printf("Packet size is %d at %p\n", ret + 1, packet);
             memset(packet, 0, adjusted_size);
@@ -756,8 +756,8 @@ Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
             if (eom) {
                 *eom = 0;
             }
-            //    msgs[index] = (const xmlChar *)packet;
-            msgs.push_back((const xmlChar *)packet);
+            //    msgs[index] = (const unsigned char *)packet;
+            msgs.push_back((const unsigned char *)packet);
             //      msgs[index+1] = 0;
             //printf("%d: Pushing Packet of size %d at %p\n", __LINE__, 
strlen(packet), packet);
             //processing(false);
@@ -772,7 +772,7 @@ Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
                 //processing(false);
                 printf("%s: The remainder is: \"%s\"\n", __FUNCTION__, 
leftover);
                 printf("%s: The rest of the message is: \"%s\"\n", 
__FUNCTION__, ptr);
-                adjusted_size = memadjust(cr + strlen(leftover) + 1);
+                // adjusted_size = memadjust(cr + strlen(leftover) + 1); FIXME:
                 packet = new char[adjusted_size];
                 memset(packet, 0, adjusted_size);
                 strcpy(packet, leftover);
@@ -786,7 +786,7 @@ Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
                 delete leftover;
                 leftover = 0;
             } else {
-                adjusted_size = memadjust(cr + 1);
+                // adjusted_size = memadjust(cr + 1); FIXME:
                 packet = new char[adjusted_size];
                 memset(packet, 0, adjusted_size);
                 strcpy(packet, ptr);
@@ -800,8 +800,8 @@ Tcpip::anydata(int fd, vector<const xmlChar *> &msgs)
                 }
                 //printf("Allocating new packet at %p\n", packet);
                 //data.push_back(packet);
-                //        msgs[index++] = (const xmlChar *)packet;
-                msgs.push_back((const xmlChar *)packet);
+                //        msgs[index++] = (const unsigned char *)packet;
+                msgs.push_back((const unsigned char *)packet);
             } else {
                 if (*packet == *ptr) {
                     // dbglogfile << "Read all XML messages in packet " << 
packet << endl;
diff --git a/lib/xml.cc b/lib/xml.cc
index 18295ee..1f93df9 100644
--- a/lib/xml.cc
+++ b/lib/xml.cc
@@ -30,6 +30,7 @@
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/xmlreader.h>
+#include <libxml/xmlstring.h>
 
 #include "xml.h"
 #include "log.h"
@@ -45,11 +46,11 @@ XMLAttr::XMLAttr() : _name(0), _value(0)
     // DEBUGLOG_REPORT_FUNCTION;
 }
 
-const xmlChar *
+const char *
 XMLAttr::nameGet(void)
 {
     // DEBUGLOG_REPORT_FUNCTION;
-    return _name;
+    return (const char *)_name;
 }
 
 void
@@ -59,11 +60,11 @@ XMLAttr::nameSet(const xmlChar *name)
     _name = name;
 }
 
-const xmlChar *
+const char *
 XMLAttr::valueGet(void)
 {
     // DEBUGLOG_REPORT_FUNCTION;
-    return _value;
+    return (const char *)_value;
 }
 
 void
@@ -155,11 +156,11 @@ XMLNode::operator = (XMLNode *node)
     return this;
 }
 
-const xmlChar *
+const char *
 XMLNode::nameGet(void)
 {
     // DEBUGLOG_REPORT_FUNCTION;
-    return _name;
+    return (const char *)_name;
 }
 
 void
@@ -169,11 +170,11 @@ XMLNode::nameSet(const xmlChar *name)
     _name = name;
 }
 
-const xmlChar *
+const char *
 XMLNode::valueGet(void)
 {
     // DEBUGLOG_REPORT_FUNCTION;
-    return _value;
+    return (const char *)_value;
 }
 
 void
@@ -645,10 +646,10 @@ XML::hasChildren(void)
     return (_nodes.childrenSize() > 0)? true : false;
 }
 
-const xmlChar *
+const char *
 XML::nodeNameGet(void)
 {
-    return _nodes.nameGet();
+    return (const char *)_nodes.nameGet();
 }
 
 int
diff --git a/lib/xml.h b/lib/xml.h
index 398eeb0..549ef7b 100644
--- a/lib/xml.h
+++ b/lib/xml.h
@@ -26,12 +26,11 @@
 
 #include <cstring>
 #include <vector>
-#ifdef HAVE_LIBXML
-# include <libxml/xmlmemory.h>
-# include <libxml/parser.h>
-# include <libxml/xmlreader.h>
-#endif
-
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlstring.h>
+#include "xml.h"
 #include "log.h"
 #include "err.h"
 
@@ -40,9 +39,9 @@ class XMLAttr {
 public:
   XMLAttr();
   ~XMLAttr();
-  const xmlChar *nameGet(void);
+  const char *nameGet(void);
   void nameSet(const xmlChar *name);
-  const xmlChar *valueGet(void);
+  const char *valueGet(void);
   void valueSet(const xmlChar *val);
  private:
   const xmlChar *_name;
@@ -61,10 +60,10 @@ public:
   XMLNode *operator = (XMLNode &node);
   XMLNode *operator = (XMLNode *node);
 
-  const xmlChar *nameGet(void);
+  const char *nameGet(void);
   //  void nameSet(std::string name);
   void nameSet(const xmlChar *name);
-  const xmlChar *valueGet(void);
+  const char *valueGet(void);
   //  void valueSet(std::string val);
   void valueSet(const xmlChar *val);
   
@@ -101,7 +100,7 @@ class XML {
   bool hasChildren(void);
   XMLNode *extractNode(xmlNodePtr node, bool mem);
   XMLNode *processNode(xmlTextReaderPtr reader, XMLNode *node);
-  const xmlChar *nodeNameGet(void);
+  const char *nodeNameGet(void);
   int size(void);  
   XMLNode *operator [] (int x);
   XML *operator = (XMLNode *node);

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=9f7f37c2ca5a53212d7273fd06b58bd37d40af21


commit 9f7f37c2ca5a53212d7273fd06b58bd37d40af21
Author: Rob Savoye <address@hidden>
Date:   Sun Nov 18 10:20:46 2018 -0700

    Silence warning about missing data support

diff --git a/lib/database.h b/lib/database.h
index 9c566a1..3f88c59 100644
--- a/lib/database.h
+++ b/lib/database.h
@@ -35,8 +35,8 @@
 #ifdef HAVE_MYSQL
 #include <mysql/errmsg.h>
 #include <mysql/mysql.h>
-#else
-#warning "You need to install MySQL for data base support"
+//#else
+//#warning "You need to install MySQL for data base support"
 #endif
 
 // This shuts up warnings about these constants not being used.

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=e5f008f4a10deee6a8758feffa01c1da3898a5ce


commit e5f008f4a10deee6a8758feffa01c1da3898a5ce
Author: Rob Savoye <address@hidden>
Date:   Sun Nov 18 10:19:25 2018 -0700

    Make database usage configurable

diff --git a/daemon/main.cc b/daemon/main.cc
index c43ed24..71a9a40 100644
--- a/daemon/main.cc
+++ b/daemon/main.cc
@@ -87,7 +87,9 @@ main(int argc, char *argv[])
     bool client;
     retcode_t   ret;
 
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
     Database pdb;
+#endif
     //    XantrexUI ui;
     //    Console con;
 
@@ -128,6 +130,7 @@ main(int argc, char *argv[])
     // the command line arguments.
     RCinitFile config;
     config.load_files();
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
     if (config.dbhostGet().size() > 0) {
         pdb.dbHostSet(config.dbhostGet());
     }
@@ -140,6 +143,7 @@ main(int argc, char *argv[])
     if (config.dbpasswdGet().size() > 0) {    
         pdb.dbPasswdSet(config.dbpasswdGet());
     }
+#endif
 
     if (config.deviceGet().size() > 0) {    
         filespec = (char *)config.deviceGet().c_str();
@@ -209,6 +213,7 @@ main(int argc, char *argv[])
               break;
 
               // Specify database host machine.
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
           case 'm':
               pdb.dbHostSet(optarg);
               break;
@@ -226,7 +231,7 @@ main(int argc, char *argv[])
           case 'w':
               pdb.dbPasswdSet(optarg);
               break;
-
+#endif
           case 'c':
               client = true;
               daemon = false;
@@ -245,13 +250,14 @@ main(int argc, char *argv[])
     }
 
     // Open the network connection to the database.
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
     if (use_db) {
         if (!pdb.openDB()) {
             dbglogfile << "ERROR: Couldn't open database!" << endl;
             exit(1);
         }
     }
-
+#endif
     // Start the SNMP daemon support.
 #ifdef USE_SNMP
     if (snmp) {
@@ -271,11 +277,12 @@ main(int argc, char *argv[])
         outback outdev(filespec);
         if (poll) {
             // outdev.poll();
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
         } else {
             if (outdev.main(con, pdb) == ERROR) {
                 dbglogfile << "ERROR: Main Loop exited with an error!" << endl;
             }
-        
+#endif
         }
         con.Reset();
         con.Close();
@@ -318,10 +325,11 @@ main(int argc, char *argv[])
                       break;
                 };
 #endif
-          
+
                 vector<meter_data_t *> data = ui.PollMeters(1);
 //           ui.MenuHeadingPlus();
 //           ui.MenuHeadingMinus();          
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
                 pdb.queryInsert(data);
 #if 0
                 for (i=0; i<data->size(); i++) {
@@ -338,6 +346,7 @@ main(int argc, char *argv[])
                     //delete data[i];
                 }
 #endif
+#endif
                 //sleep(1);
                 cout << endl;
             }
@@ -347,12 +356,14 @@ main(int argc, char *argv[])
         exit(0);
     }
 
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
     if (use_db) {
         if (!pdb.closeDB()) {
             dbglogfile << "ERROR: Couldn't open database!" << endl;
             exit(1);
         }
     }
+#endif
     
     // Network daemon/client mode. Normally we're a network daemon that
     // responses to requests by a remote client. Many house networks

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=eb87faa92cdc05f8558e60f457936ae0192e22b6


commit eb87faa92cdc05f8558e60f457936ae0192e22b6
Author: Rob Savoye <address@hidden>
Date:   Sat Nov 17 21:07:04 2018 -0700

    Make all internallibraies convieience (static) ones.

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 8a09dce..5104c64 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -20,32 +20,28 @@
 
 AUTOMAKE_OPTIONS = # dejagnu
 
-if BUILD_SNMP
-  SNMP_LA = ../snmp/libpgsnmp.la
-  SNMP_FILES = $(SNMP_LA) $(SNMP_LIBS)
-  SNMP_INCLUDES =  -I$(SNMP_CFLAGS)
-  SNMP_DIR = -L../snmp
-else
-  SNMP_LA = 
-  SNMP_FILES = 
-  SNMP_INCLUDES = 
-  SNMP_DIR = 
+pgd_CPPFLAGS = -Wall -I$(top_srcdir)/lib -I$(top_srcdir)/devices
+pgd_LDADD = ../devices/libpdev.la ../lib/libpguru.la 
+
+if BUILD_LIBXML
+pgd_CPPFLAGS += $(LIBXML_CPPFLAGS)
+pgd_LDADD += $(LIBXML_LIBS)
 endif
 
-AM_CPPFLAGS = -Wall -I$(top_srcdir)/lib $(MARIADB_CFLAGS) ${POSTGRESQL_CFLAGS} 
$(SNMP_INCLUDES) $(XML_CPPFLAGS) $(CPPFLAGS)
+if BUILD_SNMP
+pgd_LDADD += ../snmp/libpgsnmp.la $(SNMP_LIBS)
+endif
 
 bin_PROGRAMS = pgd
 
 pgd_SOURCES = main.cc
-pgd_LDFLAGS = -export-dynamic -static -L../lib $(SNMP_DIR)
-pgd_LDADD =  -lpguru $(MARIADB_LIBS) ${POSTGRESQL_LIBS} $(XML_LIBS) 
$(SNMP_FILES) #-lpgsnmp
-pgd_DEPENDENCIES = ../lib/libpguru.la $(SNMP_LA) ../lib/libpguru.la # 
$(LIBXML_LA)
+pgd_LDFLAGS = -export-dynamic -ldl
 
-MUDFLAP_OPT = -fmudflap
-MUDFLAP_LIB =  /usr/local/lib/libmudflap.so
+# MUDFLAP_OPT = -fmudflap
+# MUDFLAP_LIB =  /usr/local/lib/libmudflap.so
 
 # Rebuild with GCC 4.x Mudflap support
-mudflap:
-       @echo "Rebuilding with GCC Mudflap support"
-       $(MAKE) CXXFLAGS="$(CXXFLAGS) $(MUDFLAP_OPT)" LIBS="$(LIBS) 
$(MUDFLAP_LIB)"
+# mudflap:
+#      @echo "Rebuilding with GCC Mudflap support"
+#      $(MAKE) CXXFLAGS="$(CXXFLAGS) $(MUDFLAP_OPT)" LIBS="$(LIBS) 
$(MUDFLAP_LIB)"
 
diff --git a/devices/Makefile.am b/devices/Makefile.am
index b82f5a0..5af437f 100644
--- a/devices/Makefile.am
+++ b/devices/Makefile.am
@@ -23,7 +23,7 @@ AUTOMAKE_OPTIONS =
 # __USLC__ makes MySQL++ use the std namespace
 AM_CXXFLAGS = -g -D__USLC__
 
-lib_LTLIBRARIES = libpdev.la
+noinst_LTLIBRARIES = libpdev.la
 
 # The list of tty's to use by default
 address@hidden@
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bc727be..1beab0b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -23,7 +23,7 @@ AUTOMAKE_OPTIONS =
 # __USLC__ makes MySQL++ use the std namespace
 AM_CXXFLAGS = -g -D__USLC__
 
-lib_LTLIBRARIES = libpguru.la
+noinst_LTLIBRARIES = libpguru.la
 
 # The list of tty's to use by default
 address@hidden@
@@ -35,11 +35,10 @@ libpguru_la_CPPFLAGS =      -I$(top_srcdir)
 libpguru_la_LIBDADD =
 
 if BUILD_LIBXML
-XML_FILES = xml.cc xml.h
+XML_FILES = xml.cc xml.h msgs.cc msgs.h
 libpguru_la_CPPFLAGS += $(LIBXML_CPPFLAGS)
 libpguru_la_LIBDADD += $(LIBXML_LIBS)
 endif
-# libpguru_la_CPPFLAGS = $(LIBXML_CPPFLAGS)
 
 if BUILD_SNMP
 SNMP_FILES = snmp.cc snmp.h
@@ -62,7 +61,6 @@ libpguru_la_SOURCES = \
        proc.cc proc.h \
        err.cc err.h \
        log.cc log.h \
-       sem.cc sem.h \
        rc.cc rc.h \
        serial.cc serial.h \
        console.cc console.h \
@@ -73,8 +71,8 @@ libpguru_la_SOURCES = \
        $(MARIADB_FILES) \
        $(XML_FILES) \
        tcputil.cc tcputil.h \
-       tcpip.cc tcpip.h \
-       msgs.cc msgs.h
+       tcpip.cc tcpip.h
+#      sem.cc sem.h
 
 include_HEADERS = \
        proc.h \
@@ -86,6 +84,7 @@ include_HEADERS = \
        log.h \
        tcputil.h \
        tcpip.h \
+       msgs.h \
        xml.h
 
 #libpguru_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/snmp/Makefile.am b/snmp/Makefile.am
index bddd402..fb39bfb 100644
--- a/snmp/Makefile.am
+++ b/snmp/Makefile.am
@@ -17,7 +17,7 @@
 
 AUTOMAKE_OPTIONS = 
 
-lib_LTLIBRARIES = libpgsnmp.la
+noinst_LTLIBRARIES = libpgsnmp.la
 
 libpgsnmp_la_SOURCES = \
        powerguru.h powerguru.c

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=b18da55860579c8c66858b35b60df5949730a84b


commit b18da55860579c8c66858b35b60df5949730a84b
Author: Rob Savoye <address@hidden>
Date:   Sat Nov 17 13:38:04 2018 -0700

    Improve sysroot handling

diff --git a/configure.ac b/configure.ac
index 5749b98..ab96daf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,22 +95,22 @@ dnl AC_PROG_AR
 AC_CHECK_TOOL(AR, ar)
 AC_PATH_PROG(DEJAGNU, runtest)
 
+sysroot="${sysroot:-`${CXX} -print-sysroot`}"
 AC_ARG_WITH(sysroot,
   AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
   sysroot=${withval};
   cross_compiling=yes)
 
 with_top_level=""
-sysroot="${sysroot:-`${CXX} -print-sysroot`}"
 if test x"${cross_compiling}" = xyes; then
   AC_MSG_CHECKING([For a usable sysroot])
   dnl Check if /usr isn't part of the specified path
-  if test ! -d ${sysroot}/usr; then
+  if test -d ${sysroot}/usr; then
     sysroot=${withval}/usr
   else 
     dnl Check if the specified path supplies /usr
     if test -d ${sysroot}/usr/include; then
-      sysroot=${withval}
+      sysroot=${sysroot}
     else
       AC_MSG_ERROR([Specified sysroot \"${sysroot}\" doesn't exist!])
     fi
@@ -119,6 +119,7 @@ if test x"${cross_compiling}" = xyes; then
     LDFLAGS="--sysroot=${sysroot}"
   fi
   AC_MSG_RESULT([${sysroot}])
+  AC_SUBST(sysroot)
 fi
 
 dnl When cross compiling, limit the search directories cause otherwise
@@ -293,7 +294,7 @@ sim/Makefile
 devices/Makefile
 snmp/Makefile
 client/Makefile
-po/Makefile.in
+po/Makefile
 doc/Makefile
 doc/C/Makefile
 testsuite/Makefile

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=67ebdb7b39470c8510f56b3ad4fc8fd242e74f92


commit 67ebdb7b39470c8510f56b3ad4fc8fd242e74f92
Author: Rob Savoye <address@hidden>
Date:   Sat Nov 17 13:24:17 2018 -0700

    build device support separtely now

diff --git a/devices/Makefile.am b/devices/Makefile.am
new file mode 100644
index 0000000..b82f5a0
--- /dev/null
+++ b/devices/Makefile.am
@@ -0,0 +1,56 @@
+# 
+# Copyright (C) 2005, 2006, 2007, 2008,        2009, 2010, 2011
+#      Free Software Foundation, Inc.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+AUTOMAKE_OPTIONS = 
+
+#DL_LIB = @DL_LIB@
+#LIBLTDL = @LIBLTDL@
+# __USLC__ makes MySQL++ use the std namespace
+AM_CXXFLAGS = -g -D__USLC__
+
+lib_LTLIBRARIES = libpdev.la
+
+# The list of tty's to use by default
address@hidden@
+
+# These headers get installed
+# include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
+
+libpdev_la_CPPFLAGS = -I$(top_srcdir)/lib -I..
+
+if BUILD_SNMP
+SNMP_FILES = snmp.cc snmp.h
+libpdev_la_CPPFLAGS += -I$(top_srcdir)/snmp
+libpdev_la_LIBDADD =  $(SNMP_LIBS) ../snmp/libpgsnmp.la
+endif
+
+libpdev_la_SOURCES = \
+       xantrex-trace.cc xantrex-trace.h \
+       xanbus.cc xanbus.h \
+       outbackpower.cc outbackpower.h
+
+include_HEADERS = \
+       xantrex-trace.h \
+       outbackpower.h \
+       xanbus.h
+
+#libpdev_la_LDFLAGS = -module -avoid-version -no-undefined
+
+clean-hook:
+       -rm -f core.*
+

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=a7984d93f7c815fc830916063bf9e5119c287161


commit a7984d93f7c815fc830916063bf9e5119c287161
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:59:57 2018 -0700

    Fix to work with alternate sysroots

diff --git a/configure.ac b/configure.ac
index a24b679..5749b98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,32 @@ dnl AC_PROG_AR
 AC_CHECK_TOOL(AR, ar)
 AC_PATH_PROG(DEJAGNU, runtest)
 
+AC_ARG_WITH(sysroot,
+  AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
+  sysroot=${withval};
+  cross_compiling=yes)
+
+with_top_level=""
+sysroot="${sysroot:-`${CXX} -print-sysroot`}"
+if test x"${cross_compiling}" = xyes; then
+  AC_MSG_CHECKING([For a usable sysroot])
+  dnl Check if /usr isn't part of the specified path
+  if test ! -d ${sysroot}/usr; then
+    sysroot=${withval}/usr
+  else 
+    dnl Check if the specified path supplies /usr
+    if test -d ${sysroot}/usr/include; then
+      sysroot=${withval}
+    else
+      AC_MSG_ERROR([Specified sysroot \"${sysroot}\" doesn't exist!])
+    fi
+    CXXFLAGS="--sysroot=${sysroot}"
+    CFLAGS="--sysroot=${sysroot}"
+    LDFLAGS="--sysroot=${sysroot}"
+  fi
+  AC_MSG_RESULT([${sysroot}])
+fi
+
 dnl When cross compiling, limit the search directories cause otherwise
 dnl we may get the host headers or libraries by accident. These values
 dnl are exported, so all the other configure tests in macros/*.m4 use
@@ -112,8 +138,8 @@ if test x$cross_compiling = xyes; then
   if test x"${pkgroot}" = x"/usr"; then
     export pkgroot=""
   fi
-  export incllist="`eval echo ${with_top_level}/include 
${pkgroot}/${host_alias}/include ${pkgroot}/include`"
-  export libslist="`eval echo ${with_top_level}/lib 
${pkgroot}/${host_alias}/lib ${pkgroot}/lib64 ${pkgroot}/lib32 ${pkgroot}/lib`"
+  export incllist="`eval echo ${sysroot}/include 
${pkgroot}/${host_alias}/include ${pkgroot}/include`"
+  export libslist="`eval echo ${sysroot}/lib ${pkgroot}/${host_alias}/lib 
${pkgroot}/lib64 ${pkgroot}/lib32 ${pkgroot}/lib`"
   export pathlist="`eval echo ${pkgroot}/${host_alias}/bin:${pkgroot}/bin`"
   npapi=no
 else
@@ -128,33 +154,15 @@ else
 fi
 AM_CONDITIONAL(CROSS_COMPILING, [ test x$cross_compiling = xyes ])
 
-AC_ARG_WITH(sysroot,
-  AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
-  with_top_level=${withval};
-  cross_compiling=yes)
-
-with_top_level=""
-if test x"${cross_compiling}" = xyes; then
-  dnl Check if /usr isn't part of the specified path
-  if test -d ${with_top_level}/usr; then
-    with_top_level=${withval}/usr
-  else 
-    dnl Check if the specified path supplies /usr
-    if test -d ${with_top_level}/include; then
-      with_top_level=${withval}
-    else
-      AC_MSG_ERROR([Specified sysroot \"${with_top_level}/include\" doesn't 
exist!])
-    fi
-  fi
-fi
-
 save_LDFLAGS="${LDFLAGS}"
+save_CXXFLAGS="${CXXFLAGS}"
+save_CPPFLAGS="${CPPFLAGS}"
 save_CFLAGS="${CFLAGS}"
-dnl CFLAGS="${CFLAGS} -Wall -Werror `${CXX} -print-sysroot`/usr/include"
+
 CFLAGS="${save_CFLAGS} -Wall -Werror"
 
 # dnl libxml2's headers are sometimes in a libxml2 directory, but not always
-CPPFLAGS="-I`${CXX} -print-sysroot`/usr/include/libxml2"
+CPPFLAGS="-I${sysroot}/usr/include/libxml2"
 AC_MSG_CHECKING([For libxml2 development files])
 AC_TRY_COMPILE([#include <libxml/xmlstring.h>], [
   xmlChar foo = 'x';
@@ -166,13 +174,18 @@ AC_TRY_COMPILE([#include <libxml/xmlstring.h>], [
 AC_MSG_RESULT([${has_libxml}])
 if test x"${has_libxml}" = x"true"; then
   AC_DEFINE([HAVE_LIBXML], [1], [Has libxml2 development files])
-  LIBS="${LIBS} -lxml2"
+  LIBXML_LIBS="-lxml2"
+  LIBXML_CPPFLAGS="-I${sysroot}/usr/include/libxml2"
+  AC_SUBST(LIBXML_CPPFLAGS)
+  AC_SUBST(LIBXML_LIBS)
 fi
 AM_CONDITIONAL(BUILD_LIBXML, [ test x${has_libxml} = xtrue ])
 dnl GNU_PKG_FIND(libxml2, [libxml/xmlstring.h], [libxml2], xmlNewReference)
 
 dnl libpq. FIXME: add libpqcxx
+db=mariadb
 LDFLAGS="${save_LDFLAGS} -lpq"
+CPPFLAGS="-I${sysroot}/usr/include/postgresql/9.6/server/libpq"
 AC_MSG_CHECKING([For postgresql development files])
 AC_TRY_COMPILE([#include <libpq-fe.h>], [
   PQpass(0);
@@ -183,7 +196,11 @@ AC_TRY_COMPILE([#include <libpq-fe.h>], [
 AC_MSG_RESULT([${has_libpq}])
 if test x"${has_libpq}" = x"true"; then
   AC_DEFINE([HAVE_LIBPQ], [1], [Has postgresql development files])
-  LIBS="${LIBS} -lpq"
+  LIBPQ_LIBS="-lpq"
+  LIBPQ_CPPFLAGS="-I${sysroot}/usr/include/postgresql/9.6/server/libpq"
+  db=postgresql
+  AC_SUBST(LIBPQ_CPPFLAGS)
+  AC_SUBST(LIBPQ_LIBS)
 fi
 AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${has_libpq} = xtrue ])
 
@@ -194,7 +211,7 @@ AC_DEFINE([HAVE_STRCASESTR], [1], [ Has strcasestr defined 
])
 AC_DEFINE([HAVE_IN_ADDR_T], [1], [ Has typedef in_addr_t])
 
 CFLAGS="${save_CFLAGS} -Wall"
-LDFLAGS="${save_LDFLAGS} -lnetsnmp"
+LDFLAGS="${save_LDFLAGS} -lnetsnmp -lnetsnmpagent"
 AC_MSG_CHECKING([For Net SNMP development files])
 AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>
 #include <net-snmp/types.h>], [
@@ -206,13 +223,19 @@ AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>
 AC_MSG_RESULT([${has_snmp}])
 if test x"${has_snmp}" = x"true"; then
   AC_DEFINE([HAVE_SNMP], [1], [Has Net SNMP development files])
-  LIBS="${LIBS} -lnetsnmp"
+  SNMP_LIBS="-lnetsnmp -lnetsnmpagent"
+  AC_SUBST(SNMP_LIBS)
 fi
 AM_CONDITIONAL(BUILD_SNMP, [ test x${has_snmp} = xtrue ])
 
 dnl mariadb development files
 dnl FIXME
 
+LDFLAGS="${save_LDFLAGS}"
+CXXFLAGS="${save_CXXFLAGS}"
+CPPFLAGS="${save_CPPFLAGS}"
+CFLAGS="${save_CFLAGS}"
+
 dnl These are for MinGW or Cygwin support.
 AC_EXEEXT
 AC_CHECK_TOOL(DLLTOOL, dlltool)
@@ -267,6 +290,7 @@ Makefile
 lib/Makefile
 daemon/Makefile
 sim/Makefile
+devices/Makefile
 snmp/Makefile
 client/Makefile
 po/Makefile.in

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=0162045baa5bb1ab27a9b8672305571f2e50cf8d


commit 0162045baa5bb1ab27a9b8672305571f2e50cf8d
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:59:12 2018 -0700

    Use <cstring> instead of <string>.

diff --git a/sim/Makefile.am b/sim/Makefile.am
index e4c016c..91e4fe0 100644
--- a/sim/Makefile.am
+++ b/sim/Makefile.am
@@ -21,10 +21,10 @@ AUTOMAKE_OPTIONS =
 PGURU = ../lib/libpguru.la
 noinst_PROGRAMS = osim # xsim
 
-AM_CPPFLAGS = -I$(top_srcdir)/lib  $(XML_CPPFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/lib  $(LIBXML_CPPFLAGS)
 
 osim_SOURCES = fakeuart.cc fakeuart.h osim.cc
-osim_LDADD =  $(PGURU) $(MYSQL_LIBS) $(XML_LIBS)  $(SNMP_LIBS) -lpthread
+osim_LDADD =  $(PGURU)  $(SNMP_LIBS) -lpthread
 if BUILD_SNMP
 osim_LDADD += ../snmp/libpgsnmp.la
 endif
diff --git a/sim/fakeuart.cc b/sim/fakeuart.cc
index be4a505..8b88596 100644
--- a/sim/fakeuart.cc
+++ b/sim/fakeuart.cc
@@ -16,7 +16,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#include <string>
+#include <cstring>
 #include <unistd.h>
 
 #include "log.h"
@@ -30,7 +30,7 @@
 #include <termios.h>
 #include <iostream>
 #include <iomanip>
-#include <string>
+#include <cstring>
 #include <fstream>
 
 using namespace std;
diff --git a/sim/fakeuart.h b/sim/fakeuart.h
index 644205a..6dba897 100644
--- a/sim/fakeuart.h
+++ b/sim/fakeuart.h
@@ -18,7 +18,7 @@
 #ifndef __FAKEUART_H__
 #define __FAKEUART_H__
 
-#include <string>
+#include <cstring>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
diff --git a/sim/osim.cc b/sim/osim.cc
index ba8cbcd..3f37339 100644
--- a/sim/osim.cc
+++ b/sim/osim.cc
@@ -21,12 +21,12 @@
 # include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include <vector>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <string>
+#include <cstring>
 #include <iostream>
 #include <fstream>
 

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=1ab1416e07c6d8e2a15f43c7857216ae8f560133


commit 1ab1416e07c6d8e2a15f43c7857216ae8f560133
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:58:53 2018 -0700

    Use <cstring> instead of <string>.

diff --git a/daemon/main.cc b/daemon/main.cc
index a3e46bf..c43ed24 100644
--- a/daemon/main.cc
+++ b/daemon/main.cc
@@ -15,18 +15,12 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#include <net-snmp/net-snmp-config.h>
 #ifdef HAVE_CONFIG_H
-# undef PACKAGE_VERSION
-# undef PACKAGE_TARNAME
-# undef PACKAGE_STRING
-# undef PACKAGE_NAME
-# undef PACKAGE_BUGREPORT
 // This is generated by autoconf.
 # include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include <vector>
 #include <stdlib.h>
 #include <unistd.h>

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=97b72db1b3446761ecc5b21dc9b1c64e16d80eb5


commit 97b72db1b3446761ecc5b21dc9b1c64e16d80eb5
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:58:10 2018 -0700

    Improve conditional buildig to work when cross compiled.

diff --git a/client/Makefile.am b/client/Makefile.am
index dae1049..f3e72dd 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -19,17 +19,21 @@
 ## Process this file with automake to generate Makefile.in
 AUTOMAKE_OPTIONS = 
 
-PGURU = ../lib/libpguru.la
 bin_PROGRAMS = pguru 
 
-AM_CPPFLAGS = -I$(top_srcdir)/lib $(XML_CPPFLAGS)
+pguru_CPPFLAGS = -I$(top_srcdir)/lib
 
 pguru_SOURCES = cmd.cc
-pguru_LDADD = $(PGURU) $(XML_LIBS) $(MYSQL_LIBS) -lpthread $(SNMP_LIBS)
-if BUILD_SNMP
-pguru_LDADD += ../snmp/libpgsnmp.la
+pguru_LDADD = ../lib/libpguru.la -ldl
+
+if BUILD_LIBXML
+pguru_CPPFLAGS += ${LIBXML_CPPFLAGS}
+pguru_LDADD += ${LIBXML_LIBS}
 endif
 
-pguru_DEPENDENCIES = $(PGURU)
+if BUILD_SNMP
+pguru_LDADD += ../snmp/libpgsnmp.la $(SNMP_LIBS)
+endif
 
+# pguru_DEPENDENCIES = ../lib/libpguru.la
 
diff --git a/client/cmd.cc b/client/cmd.cc
index 7e15a40..857f9c5 100644
--- a/client/cmd.cc
+++ b/client/cmd.cc
@@ -33,15 +33,15 @@
 #include <sys/types.h>
 #include <cstdio>
 #include <iostream>
-#ifdef HAVE_LIBXML
-# include <libxml/encoding.h>
-# include <libxml/xmlwriter.h>
-# include <libxml/debugXML.h>
-#endif
+// #ifdef HAVE_LIBXML
+// # include <libxml/encoding.h>
+// # include <libxml/xmlwriter.h>
+// # include <libxml/debugXML.h>
+// #endif
+//#include "xml.h"
 #include "tcpip.h"
 #include "console.h"
 #include "msgs.h"
-#include "xml.h"
 
 using namespace std;
 extern LogFile dbglogfile;

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=492f9262f418331da9fec65fa5a79754ada731f0


commit 492f9262f418331da9fec65fa5a79754ada731f0
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:57:26 2018 -0700

    Add new devices directory, ad target to dump config info

diff --git a/Makefile.am b/Makefile.am
index 7a00863..73fdfdf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,7 +30,7 @@ SUBDIRS += snmp $(STD_DIRS) #src
 endif
 
 # These are built now, as they depend on the the libraries
-SUBDIRS += daemon client # testsuite
+SUBDIRS += devices client daemon # testsuite
 
 # this is an optional build directory
 if BUILD_SIM
@@ -40,8 +40,6 @@ endif
 EXTRA_DIST = \
        autogen.sh \
        powerguru.sql \
-       powerguru.glade2 \
-       powerguru.glade2p \
        doc/C/topic.dat \
        doc/C/xantrex.xml \
        doc/C/outback.xml \
@@ -50,6 +48,8 @@ EXTRA_DIST = \
        po/Makefile.in.in \
        po/POTFILES.in \
        web
+#      powerguru.glade2
+#      powerguru.glade2p
 
 #install-data-local:
 #      @$(NORMAL_INSTALL)
@@ -94,3 +94,18 @@ deb debian: dist-bzip2 $(srcdir)/debian/rules
 mudflap:
        @echo "Rebuilding with GCC Mudflap support"
        $(MAKE) CXXFLAGS="$(CXXFLAGS) -fmudflap" LDFLAGS="$(LDFLAGS) -lmudflap"
+
+dump:
+       @echo "Dumping configure options"
+if BUILD_SNMP
+       @echo " Building with net-snmp"
+endif
+if BUILD_LIBXML
+       @echo " Building with libxml2"
+endif
+if BUILD_MARIADB
+       @echo " Building with mariadb"
+endif
+if BUILD_POSTGRESQL
+       @echo " Building with Postgresql"
+endif

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=55b3555870e7802a971b3594f0c2e5f13d75a72f


commit 55b3555870e7802a971b3594f0c2e5f13d75a72f
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:56:17 2018 -0700

    Use <cstring> instead of <string>. Move devices to from ne directory

diff --git a/lib/Makefile.am b/lib/Makefile.am
index 122c761..bc727be 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -31,31 +31,31 @@ address@hidden@
 # These headers get installed
 # include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
 
-AM_CPPFLAGS = -Wall \
-       -I$(srcdir) \
-       -I$(top_srcdir)/snmp \
-       -I.. $(XML_CPPFLAGS)
-#      $(MARIADB_CFLAGS) \
-#      ${POSTGRESQL_CFLAGS)
+libpguru_la_CPPFLAGS = -I$(top_srcdir)
+libpguru_la_LIBDADD =
 
 if BUILD_LIBXML
-SNMP_FILES = xml.cc xml.h
-libpguru_la_LIBDADD =  $(SNMP_LIBS) -lxml2
+XML_FILES = xml.cc xml.h
+libpguru_la_CPPFLAGS += $(LIBXML_CPPFLAGS)
+libpguru_la_LIBDADD += $(LIBXML_LIBS)
 endif
+# libpguru_la_CPPFLAGS = $(LIBXML_CPPFLAGS)
 
 if BUILD_SNMP
 SNMP_FILES = snmp.cc snmp.h
-libpguru_la_LIBDADD =  $(SNMP_LIBS) ../snmp/libpgsnmp.la
+libpguru_la_CPPFLAGS += -I$(top_srcdir)/snmp
+libpguru_la_LIBDADD += $(SNMP_LIBS) ../snmp/libpgsnmp.la
 endif
 
 if BUILD_MARIADB
 MARIADB_FILES = mariadb.cc
-libpguru_la_LIBDADD =  $(MARIADB_LIBS)
+libpguru_la_LIBDADD += $(MARIADB_LIBS)
 endif
 
 if BUILD_POSTGRESQL
 LIBPQ_FILES = postgresql.cc
-libpguru_la_LIBDADD =  $(LIBPQ_LIBS)
+libpguru_la_CPPFLAGS += ${LIBPQ_CPPFLAGS}
+libpguru_la_LIBDADD +=  $(LIBPQ_LIBS)
 endif
 
 libpguru_la_SOURCES = \
@@ -66,24 +66,19 @@ libpguru_la_SOURCES = \
        rc.cc rc.h \
        serial.cc serial.h \
        console.cc console.h \
-       xantrex-trace.cc xantrex-trace.h \
-       xanbus.cc xanbus.h \
-       outbackpower.cc outbackpower.h \
        menuitem.cc menuitem.h \
-       database.h\
+       database.h \
        $(SNMP_FILES) \
        $(LIBPQ_FILES) \
        $(MARIADB_FILES) \
+       $(XML_FILES) \
        tcputil.cc tcputil.h \
        tcpip.cc tcpip.h \
-       msgs.cc msgs.h \
-       $(XML_FILES)
+       msgs.cc msgs.h
 
 include_HEADERS = \
        proc.h \
        serial.h \
-       xantrex-trace.h \
-       outbackpower.h \
        menuitem.h \
        database.h \
        console.h \
diff --git a/lib/console.cc b/lib/console.cc
index de2557c..7f3b475 100644
--- a/lib/console.cc
+++ b/lib/console.cc
@@ -19,7 +19,7 @@
 // This sets up a console for user interaction, and defaults to using
 // standard in.
 
-#include <string>
+#include <cstring>
 #include <cstdio>
 
 #include "err.h"
diff --git a/lib/console.h b/lib/console.h
index f5ad8aa..9709b9d 100644
--- a/lib/console.h
+++ b/lib/console.h
@@ -22,7 +22,7 @@
 // This sets up a console for user interaction, and defaults to using
 // standard in.
 
-#include <string>
+#include <cstring>
 #include <vector>
 #include <cstdio>
 #include <termios.h>
diff --git a/lib/database.h b/lib/database.h
index 0aa2535..9c566a1 100644
--- a/lib/database.h
+++ b/lib/database.h
@@ -25,7 +25,7 @@
 #endif
 
 #include <iostream> 
-#include <string>
+#include <cstring>
 #include <list>
 #include <iomanip> 
 #include <vector>
diff --git a/lib/err.cc b/lib/err.cc
index 1558271..7ebb599 100644
--- a/lib/err.cc
+++ b/lib/err.cc
@@ -23,7 +23,7 @@
 
 #include <stdio.h>
 #include <errno.h>
-#include <string>
+#include <cstring>
 
 #include <iostream>
 #include <iomanip>
diff --git a/lib/err.h b/lib/err.h
index 732b87a..979422e 100644
--- a/lib/err.h
+++ b/lib/err.h
@@ -116,7 +116,7 @@ static inline void SETERR(struct errcond *x, const char *y, 
int z) {
 };
 
 #ifdef __cplusplus
-#include <string>
+#include <cstring>
 #include <iostream>
 
 #define WARNMSG (sys_nerr+1)
diff --git a/lib/gdb.h b/lib/gdb.h
index 2994390..10b426d 100644
--- a/lib/gdb.h
+++ b/lib/gdb.h
@@ -16,7 +16,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#include <string>
+#include <cstring>
 
 class gdb {
 public:
diff --git a/lib/log.cc b/lib/log.cc
index 9495cc3..c2eb449 100644
--- a/lib/log.cc
+++ b/lib/log.cc
@@ -1,6 +1,6 @@
 #include <iomanip>
 #include <fstream>
-#include <string>
+#include <cstring>
 // #include <strstream>
 
 using namespace std;
diff --git a/lib/log.h b/lib/log.h
index d8346cc..f374efd 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -42,7 +42,7 @@
 
 #include <iostream>
 #include <iomanip>
-#include <string>
+#include <cstring>
 #include <fstream>
 
 // the default name for the debug log
diff --git a/lib/mariadb.cc b/lib/mariadb.cc
index 1ff56af..36e42bc 100644
--- a/lib/mariadb.cc
+++ b/lib/mariadb.cc
@@ -21,7 +21,7 @@
 #include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include <iostream>
 #include <iomanip> 
 #include <vector>
diff --git a/lib/menuitem.cc b/lib/menuitem.cc
index 20899f4..47d012a 100644
--- a/lib/menuitem.cc
+++ b/lib/menuitem.cc
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include <cstdlib>
-#include <string>
+#include <cstring>
 #include <map>
 #include <vector>
 #include <sstream>
diff --git a/lib/menuitem.h b/lib/menuitem.h
index 9cdb712..41c8fe5 100644
--- a/lib/menuitem.h
+++ b/lib/menuitem.h
@@ -21,7 +21,7 @@
 
 #include <map>
 #include <vector>
-#include <string>
+#include <cstring>
 #include <sstream>
 
 #include "err.h"
diff --git a/lib/msgs.cc b/lib/msgs.cc
index 26c0de7..099f37e 100644
--- a/lib/msgs.cc
+++ b/lib/msgs.cc
@@ -23,7 +23,7 @@
 
 #include <iostream>
 #include <fstream>
-#include <string>
+#include <cstring>
 #include <iterator>
 #include <map>
 #ifdef __STDC_HOSTED__
@@ -44,8 +44,8 @@
 
 using namespace std;
 Msgs::net_mode_e  Msgs::_net_mode;
-std::map<const xmlChar *, Msgs::methodPtr_t> Msgs::_methods;
-std::map<const xmlChar *, std::string> Msgs::_cache;
+std::map<const unsigned char *, Msgs::methodPtr_t> Msgs::_methods;
+std::map<const unsigned char *, std::string> Msgs::_cache;
 
 #define MY_ENCODING "ISO-8859-1"
 
@@ -277,14 +277,14 @@ Msgs::init(void)
 }
 
 std::string
-Msgs::cacheGet(const xmlChar * name) {
+Msgs::cacheGet(const unsigned char * name) {
     // DEBUGLOG_REPORT_FUNCTION;
 #if 1
-    const xmlChar         *tag;
+    const unsigned char         *tag;
     string                str;
   
     _body.str("");
-    std::map<const xmlChar *, string>::const_iterator it;
+    std::map<const unsigned char *, string>::const_iterator it;
     for (it = _cache.begin(); it != _cache.end(); it++) {
         //entry = it->second;
         tag = it->first;
@@ -309,7 +309,7 @@ Msgs::cacheGet(const xmlChar * name) {
 }
 
 retcode_t
-Msgs::cacheAdd(const xmlChar * name, string str)
+Msgs::cacheAdd(const unsigned char * name, string str)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     _cache[name] = str;
@@ -321,7 +321,7 @@ Msgs::cacheAdd(const xmlChar * name, string str)
 
 // Add a function for handling an XML tag to the list.
 void
-Msgs::methodSet(const xmlChar * name, methodPtr_t func)
+Msgs::methodSet(const unsigned char * name, methodPtr_t func)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     _methods[name] = func;
@@ -329,14 +329,14 @@ Msgs::methodSet(const xmlChar * name, methodPtr_t func)
 
 // Get the function for an XML tag from the list.
 Msgs::methodPtr_t
-Msgs::methodGet(const xmlChar * name)
+Msgs::methodGet(const unsigned char * name)
 {
     //DEBUGLOG_REPORT_FUNCTION;
 #if 1
-    const xmlChar         *str;
+    const unsigned char         *str;
     Msgs::methodPtr_t     ptr;
   
-    std::map<const xmlChar *, Msgs::methodPtr_t>::const_iterator it;
+    std::map<const unsigned char *, Msgs::methodPtr_t>::const_iterator it;
     for (it = _methods.begin(); it != _methods.end(); it++) {
         //entry = it->second;
         str = it->first;
@@ -362,7 +362,7 @@ Msgs::methodGet(const xmlChar * name)
 
 // Call the function to process an XML node
 retcode_t
-Msgs::methodProcess(const xmlChar *name, XMLNode *node)
+Msgs::methodProcess(const unsigned char *name, XMLNode *node)
 {
     // DEBUGLOG_REPORT_FUNCTION;
     //(this->*_methods.find(name)(node); 
@@ -374,12 +374,12 @@ void
 Msgs::methodsDump(void)
 {
     DEBUGLOG_REPORT_FUNCTION;
-    const xmlChar         *name;
+    const unsigned char         *name;
     Msgs::methodPtr_t     ptr;
   
     dbglogfile << "We have " << (int)_methods.size() << " in function table" 
<< endl;
   
-    std::map<const xmlChar *, Msgs::methodPtr_t>::const_iterator it;
+    std::map<const unsigned char *, Msgs::methodPtr_t>::const_iterator it;
     for (it = _methods.begin(); it != _methods.end(); it++) {
         name = it->first;
         ptr  = it->second;
@@ -399,12 +399,12 @@ void
 Msgs::cacheDump(void)
 {
     DEBUGLOG_REPORT_FUNCTION;
-    const xmlChar         *name;
+    const unsigned char         *name;
     string                data;
   
     dbglogfile << "We have " << (int)_cache.size() << " items in the cache" << 
endl;
   
-    std::map<const xmlChar *, string>::const_iterator it;
+    std::map<const unsigned char *, string>::const_iterator it;
     for (it = _cache.begin(); it != _cache.end(); it++) {
         name = it->first;
         data  = it->second;
@@ -453,7 +453,7 @@ Msgs::process(XMLNode *xml)
 {
     DEBUGLOG_REPORT_FUNCTION;
     methodPtr_t   fptr;
-    const xmlChar *str;
+    const unsigned char *str;
     retcode_t     ret;
     int           i;
 
@@ -538,7 +538,7 @@ Msgs::statusCreate(meter_data_t *md)
     int rc;
     xmlTextWriterPtr writer;
     xmlBufferPtr buf;
-    xmlChar *tmp;
+    unsigned char *tmp;
   
     if ((buf = xmlBufferCreate()) == NULL) {
         printf("testXmlwriterMemory: Error creating the xml buffer\n");
@@ -688,7 +688,7 @@ Msgs::metersRequestCreate(xml_meters_e val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const xmlChar * type, int val) {
+Msgs::metersResponseCreate(const unsigned char * type, int val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -703,7 +703,7 @@ Msgs::metersResponseCreate(const xmlChar * type, int val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const xmlChar *type, float val) {
+Msgs::metersResponseCreate(const unsigned char *type, float val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -718,7 +718,7 @@ Msgs::metersResponseCreate(const xmlChar *type, float val) {
 }
 
 std::string
-Msgs::metersResponseCreate(const xmlChar *type, string val) {
+Msgs::metersResponseCreate(const unsigned char *type, string val) {
     DEBUGLOG_REPORT_FUNCTION;
     _body.str("");                // erase the current string
     _body << "<powerguru version=\"";
@@ -894,7 +894,7 @@ Msgs::requestCreate(xml_command_e tag)
 
 
 std::string
-Msgs::responseCreate(xml_msg_e type, const xmlChar *tag, string val)
+Msgs::responseCreate(xml_msg_e type, const unsigned char *tag, string val)
 {
     DEBUGLOG_REPORT_FUNCTION;
     string str;
@@ -959,7 +959,7 @@ Msgs::print_msg(std::string msg)
         "\r\n\t\t\t\t\t",
     };
   
-    xmlDebugDumpString(stderr, (const xmlChar *)msg.c_str());
+    xmlDebugDumpString(stderr, (const unsigned char *)msg.c_str());
     //  cerr << "++++++++++++++++++++++" << endl;
   
     // Strip off the DTD header, as we're not bothering to validate
@@ -1090,7 +1090,7 @@ Msgs::metersProcess(XMLNode *node)
 
     if(_net_mode == DAEMON) {
         //cacheDump();
-        //    const xmlChar *xxx = node->nameGet();
+        //    const unsigned char *xxx = node->nameGet();
         string value = cacheGet(node->valueGet());
         dbglogfile << "value for \"" << node->valueGet() << "\" is " << 
value.c_str() << endl;
         if (value.size() == 0) {
@@ -1127,14 +1127,14 @@ Msgs::serverProcess(XMLNode *node)
         if ((attr = node->attribGet(0))) {
             dbglogfile << "\tAttribute is \"" << attr->nameGet()
                        << "\" with a value of " << attr->valueGet() << endl;
-            if (xmlStrcmp(attr->valueGet(), (const xmlChar *)_thisip.c_str()) 
!= 0) {
+            if (xmlStrcmp(attr->valueGet(), (const unsigned char 
*)_thisip.c_str()) != 0) {
                 dbglogfile << "WARNING: IP's don't match!!!!" << endl;
                 return ERROR;
             }
         }
     }
 
-    if (xmlStrcmp(node->valueGet(), (const xmlChar *)_thishost.c_str()) != 0) {
+    if (xmlStrcmp(node->valueGet(), (const unsigned char *)_thishost.c_str()) 
!= 0) {
         dbglogfile << "WARNING: Host's don't match!!!!" << endl;
         return ERROR;
     }
@@ -1157,7 +1157,7 @@ Msgs::clientProcess(XMLNode *node)
             if ((attr = node->attribGet(0))) {
                 dbglogfile << "\tAttribute is \"" << attr->nameGet()
                            << "\" with a value of " << attr->valueGet() << 
endl;
-                if (xmlStrcmp(attr->valueGet(), (const xmlChar 
*)_remoteip.c_str()) != 0) {
+                if (xmlStrcmp(attr->valueGet(), (const unsigned char 
*)_remoteip.c_str()) != 0) {
                     dbglogfile << "WARNING: IP's don't match!!!!" << endl;
                     return ERROR;
                 }
@@ -1166,7 +1166,7 @@ Msgs::clientProcess(XMLNode *node)
     }
 
     if (_remotehost.size() != 0) {
-        if (xmlStrcmp(node->valueGet(), (const xmlChar *)_remotehost.c_str()) 
!= 0) {
+        if (xmlStrcmp(node->valueGet(), (const unsigned char 
*)_remotehost.c_str()) != 0) {
             dbglogfile << "WARNING: Host's don't match!!!!" << endl;
             return ERROR;
         }
@@ -1192,7 +1192,7 @@ Msgs::powerguruProcess(XMLNode *node)
         if ((attr = node->attribGet(0))) {
 //       dbglogfile << "\tAttribute is \"" << attr->nameGet().c_str()
 //                  << "\" with a value of " << attr->valueGet().c_str() << 
endl;
-            if (xmlStrcmp((const xmlChar *)_body.str().c_str(), 
attr->valueGet()) != 0) {
+            if (xmlStrcmp((const unsigned char *)_body.str().c_str(), 
attr->valueGet()) != 0) {
                 dbglogfile << "Versions in header don't match!" << endl;
             } else {
                 dbglogfile << "Versions in header match" << endl;        
diff --git a/lib/msgs.h b/lib/msgs.h
index 35ae275..878d423 100644
--- a/lib/msgs.h
+++ b/lib/msgs.h
@@ -26,7 +26,7 @@
 
 #include <iostream>
 #include <fstream>
-#include <string>
+#include <cstring>
 #include <map>
 #ifdef __STDC_HOSTED__
 #include <sstream>
@@ -163,11 +163,11 @@ public:
     std::string metersRequestCreate(xml_meters_e type);
 
     // This formats a response from the daemon to the client
-    std::string metersResponseCreate(const xmlChar *tag, int val);
-    std::string metersResponseCreate(const xmlChar *tag, float val);
-    std::string metersResponseCreate(const xmlChar *tag, std::string);
+    std::string metersResponseCreate(const unsigned char *tag, int val);
+    std::string metersResponseCreate(const unsigned char *tag, float val);
+    std::string metersResponseCreate(const unsigned char *tag, std::string);
 
-    std::string responseCreate(xml_msg_e type, const xmlChar *tag, 
std::string);
+    std::string responseCreate(xml_msg_e type, const unsigned char *tag, 
std::string);
   
     std::string requestCreate(xml_meters_e tag);
     std::string requestCreate(xml_status_e tag);
@@ -177,13 +177,13 @@ public:
     std::string packet(void) { return _body.str(); }
     void print_msg(std::string msg);
 
-    void methodSet(const xmlChar *name, methodPtr_t func);
-    methodPtr_t methodGet(const xmlChar *name);
-    retcode_t methodProcess(const xmlChar *name, XMLNode *node);
+    void methodSet(const unsigned char *name, methodPtr_t func);
+    methodPtr_t methodGet(const unsigned char *name);
+    retcode_t methodProcess(const unsigned char *name, XMLNode *node);
     void methodsDump(void);
 
-    std::string cacheGet(const xmlChar *name);
-    retcode_t cacheAdd(const xmlChar *name, std::string);
+    std::string cacheGet(const unsigned char *name);
+    retcode_t cacheAdd(const unsigned char *name, std::string);
     void cacheDump(void);
 
     std::string thisIPGet(void) { return _thisip; };
@@ -195,8 +195,8 @@ public:
   
 private:
     float               _version;
-    static std::map<const xmlChar *, methodPtr_t> _methods;
-    static std::map<const xmlChar *, std::string> _cache;
+    static std::map<const unsigned char *, methodPtr_t> _methods;
+    static std::map<const unsigned char *, std::string> _cache;
     static net_mode_e   _net_mode;
 #ifdef __STDC_HOSTED__
     std::ostringstream  _body;
diff --git a/lib/outbackpower.cc b/lib/outbackpower.cc
deleted file mode 100644
index b61f2a9..0000000
--- a/lib/outbackpower.cc
+++ /dev/null
@@ -1,718 +0,0 @@
-// 
-// Copyright (C) 2005, 2006 - 2018
-//      Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "err.h"
-#include "log.h"
-#include "console.h"
-#include "outbackpower.h"
-#include "database.h"
-
-using namespace std;
-using namespace outbackpower;
-
-const int PACKET_SIZE = 49;
-
-outback::outback() : _type(OUTBACK_NONE), _address('x'),_inverter_current(0), 
_charge_current(0), _buy_current(0), _pv_current(0), _sell_current(0), 
_AC_input_voltage(0), _AC_output_voltage(0), _pv_input_voltage(0), 
_battery_voltage(0), _daily_kwh(0), _operating_mode(SUPPORT), _AC_mode(NO_AC), 
_misc_byte(RESERVE1), _aux_mode(DISABLED),_charge_mode(SILENT_MODE), 
_error_mode(NO_ERROR), _warning_mode(NO_WARNING), _checksum(0)
-{
-    DEBUGLOG_REPORT_FUNCTION;  
-}
-
-outback::outback(string filespec) :  _type(OUTBACK_NONE), 
_address('x'),_inverter_current(0),_charge_current(0), _buy_current(0), 
_pv_current(0), _sell_current(0), _AC_input_voltage(0), _AC_output_voltage(0), 
_pv_input_voltage(0), _battery_voltage(0), _daily_kwh(0), 
_operating_mode(SUPPORT), _AC_mode(NO_AC), _misc_byte(RESERVE1), 
_aux_mode(DISABLED), _charge_mode(SILENT_MODE), _error_mode(NO_ERROR), 
_warning_mode(NO_WARNING), _checksum(0)
-
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    commInit(filespec);
-}
-
-outback::outback(const char *filespec) : _type(OUTBACK_NONE), 
_address('x'),_inverter_current(0),_charge_current(0), _buy_current(0), 
_pv_current(0), _sell_current(0), _AC_input_voltage(0), _AC_output_voltage(0), 
_pv_input_voltage(0), _battery_voltage(0), _daily_kwh(0), 
_operating_mode(SUPPORT), _AC_mode(NO_AC), _misc_byte(RESERVE1), 
_aux_mode(DISABLED), _charge_mode(SILENT_MODE), _error_mode(NO_ERROR), 
_warning_mode(NO_WARNING), _checksum(0)
-
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    commInit(filespec);
-}
-
-outback::~outback()
-{
-}
-
-// Read from the serial port
-const char *
-outback::readSerial()
-{
-    // DEBUGLOG_REPORT_FUNCTION;
-
-    int ret;
-    char *buf = new char[PACKET_SIZE+1];
-  
-    memset(buf, 0, PACKET_SIZE+1);
-
-    ret = Read(buf, PACKET_SIZE);
-  
-    if (ret > 0) {
-        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buf << "\t" << 
buf << endl;
-        return buf;
-    }
-
-    //  calcChecksum(packet);
-
-    return "";
-}
-
-retcode_t
-outback::commInit(string filespec)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    if (filespec.size() == 0) {
-        dbglogfile << "ERROR: no serial device specified!" << endl;
-        exit(0);
-    }    
-
-#if 0
-    Open(filespec);
-#else
-    try {
-        Open(filespec);
-    }
-    catch (ErrCond catch_err) {
-        dbglogfile << catch_err << endl;
-        exit(1);
-    }
-#endif
-  
-    return commInit(GetFD());
-}
-
-retcode_t
-outback::commInit(int fd)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    SetRaw();
-    SetBaud(B19200);
-  
-#if 0
-    termios thistty;
-    tcgetattr(GetFD(), &thistty);
-    thistty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-    thistty.c_oflag &= ~(OPOST|~ONLCR);
-    thistty.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-    thistty.c_cflag &= ~(CSIZE|PARENB|HUPCL);
-    thistty.c_cflag |= CREAD;
-    //thistty.c_cflag |= CS8;
-    thistty.c_cc[VMIN] = 1;
-    thistty.c_cc[VTIME] = 100;
-    tcsetattr(GetFD(), TCSANOW, &thistty);
-#endif
-    SetDTR(true);
-
-    return SUCCESS;
-}
-
-// The main loop for an outback device
-retcode_t
-outback::main()
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    Console con;
-    Database db;
-    return main(con, db);
-}
-
-retcode_t
-outback::main(Console &con, Database &db)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    string str;
-    int ch;
-  
-    while ((ch = con.Getc()) != 'q') {
-        if (ch > 0){                // If we have something, process it
-            //con.Putc (ch);          // echo inputted character to screen
-      
-            switch (ch) {
-                // Toggle the DTR state, which is as close as we get to
-                // flow control.
-              case 'd':
-                  SetDTR(false);
-                  break;
-              case 'D':
-                  SetDTR(true);
-                  break;
-              case 'Q':
-              case 'q':
-                  return SUCCESS;
-                  break;
-              case '?':
-                  con.Puts("PowerGuru - Outback Mode\r\n");
-                  con.Puts("\t? - help\r\n");
-                  con.Puts("\tq - Quit\r\n");
-                  con.Puts("\tQ - Quit\r\n");
-                  // sleep(2); FIXME
-              default:
-                  break;
-            };
-        }
-    
-        str = readSerial();
-        if (str.size() > 0) {
-            // con.Puts(str); con.Puts("\r\n");
-            calcChecksum(str.c_str());
-            {
-                parse(str.c_str());
-                meter_data_t md;
-                exportMeterData(&md);
-                db.queryInsert(&md);
-            }
-            str.erase();
-        }
-    }
-  
-    return SUCCESS;
-}
-
-// Send a command to the master FX inverter. Each command is a single
-// character, but is sent twice for error handling.
-retcode_t
-outback::sendFXCommand(fx_commands_t cmd) 
-{
-    char buf[3];
-    memset(buf,0, 3);
-    buf[0] = buf[1] = cmd;
-
-    if (Write(buf, 2) != 2) {
-        return ERROR;
-    }
-
-    return SUCCESS;
-}
-
-// Parse the ASCII packet into numerical data.
-//
-// A packet from an Outback Power systems device is a 49 bytes ASCII
-// string representing numerical data. It is framed by a LF character
-// (0x0a) to start, and a CR (0x0d) to end it. Each field is separated
-// by commas, but we can ignore those. The checksum is a simply the
-// addition of all the characters in the message.
-retcode_t outback::parse(const char *data)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    string packet = data;
-  
-    // The address is byte 1
-    _address = packet[1];
-    if ((_address >= '0') && (_address <= '9')) {
-        _type = OUTBACK_FX;
-    } else if ((_address >= 'A') && (_address <= 'K')) {
-        _type = OUTBACK_MX;
-    } else {
-        dbglogfile << "ERROR: bad address in packet!" << endl;
-        return ERROR;
-    }
-
-    _type = OUTBACK_MX;           // FIXME: 
-  
-    // The inverter current is bytes 4 & 4 on an FX, but unused on the MX.
-    _inverter_current = strtol(packet.substr(3,2).c_str(), NULL, 0);
-  
-    // The charger current is bytes 7 & 8.
-    _charge_current = strtol(packet.substr(6,2).c_str(), NULL, 0);
-
-    // Bytes 9 & 10 are the Buy current on an FX, and the PV current on
-    // an MX.
-    if (_type == OUTBACK_FX) {
-        _buy_current = strtol(packet.substr(9,2).c_str(), NULL, 0);
-    } else {
-        _pv_current = strtol(packet.substr(9,2).c_str(), NULL, 0);;
-    }   
-  
-    // Bytes 13, 14, & 15 are the AC Input Voltage on an FX, and the PV
-    // input voltage on an MX.
-    if (_type == OUTBACK_FX) {
-        _AC_input_voltage = strtol(packet.substr(13,3).c_str(), NULL, 0);
-    } else {
-        _pv_input_voltage = strtol(packet.substr(13,3).c_str(), NULL, 0);
-    }
-
-    // Bytes 16, 17, & 18 are the AC Output Voltage on an FX, and the
-    // Daily Kilowatts on an MX.
-    if (_type == OUTBACK_FX) {
-        _AC_output_voltage = strtol(packet.substr(16,3).c_str(), NULL, 0);
-    } else {
-        _daily_kwh = strtol(packet.substr(16,3).c_str(), NULL, 0);
-    }
-
-    // Bytes 20 & 21 are the Sell current on an FX, but unused on an MX.
-    if (_type == OUTBACK_FX) {
-        _sell_current = strtol(packet.substr(20,2).c_str(), NULL, 0);
-    }
-
-    // Bytes 23 & 24 are the Operating Mode on an FX, but is the AUX Mode
-    // on an MX.
-    if (_type == OUTBACK_FX) {
-        _operating_mode = 
static_cast<op_mode_t>(strtol(packet.substr(23,2).c_str(), NULL, 0));
-    } else {
-        _aux_mode = 
static_cast<aux_mode_t>(strtol(packet.substr(23,2).c_str(), NULL, 0));
-    }
-  
-    // Bytes 26, 27, & 28 are the Error Mode, but is unimplemented on
-    // the MX at this time. (2005/7/12)
-    if (_type == OUTBACK_FX) {
-        _error_mode = 
static_cast<error_mode_t>(strtol(packet.substr(13,3).c_str(), NULL, 0));
-    }
-
-    // Bytes 30 & 31 are the AC Mode on an FX, but is the Charger Mode
-    // on an MX.
-    if (_type == OUTBACK_FX) {
-        _AC_mode = static_cast<AC_mode_t>(strtol(packet.substr(30,2).c_str(), 
NULL, 0));
-    } else {
-        _charge_mode = 
static_cast<charge_mode_t>(strtol(packet.substr(30,2).c_str(), NULL, 0));
-    }
-  
-    // Bytes 33, 34, & 35 are the battery voltage.
-    _battery_voltage = strtol(packet.substr(33,3).c_str(), NULL, 0);
-
-    // Bytes 37, 38, & 39 are the Misc Byte on an FX, but are unused on
-    // an MX.
-    if (_type == OUTBACK_FX) {
-        _misc_byte = 
static_cast<misc_byte_t>(strtol(packet.substr(37,3).c_str(), NULL, 0));
-    }
-
-    // Bytes 41, 42, & 43 are the Warning Mode on an FX, but unused on an MX.
-    if (_type == OUTBACK_FX) {
-        _warning_mode = 
static_cast<warning_mode_t>(strtol(packet.substr(13,3).c_str(), NULL, 0));
-    }
-
-    // Bytes 45, 46, & 47 are the packet checksum.
-    _checksum = strtol(packet.substr(45,3).c_str(), NULL, 0);
-
-    dump();
-  
-    return SUCCESS;
-}
-
-//
-void
-outback::dump()
-{
-    switch (_type) {
-      case OUTBACK_MX:
-          dbglogfile << "Outback Power Systems MX Charge Controller" << endl;
-          break;
-      case OUTBACK_FX:
-          dbglogfile << "Outback Power Systems FX inverter" << endl;
-          break;
-      case OUTBACK_NONE:
-      default:
-          dbglogfile << "Outback Power Systems, no type specified!" << endl;
-          break;
-    };
-  
-    // The address of the unit.
-    string addr;
-    addr = "Unit #";
-    if ((_address >= '0') && (_address <= '9')) {
-        addr += _address;
-    } else if ((_address >= 'A') && (_address <= 'K')) {
-        addr += _address;
-    }
-    dbglogfile << "The address is: " << addr.c_str() << endl;
-
-    // Amperage readings. These range from 0-99 in 1 amp increments
-    if (_inverter_current) {
-        dbglogfile << "Inverter current is: " << _inverter_current << endl;
-    }
-
-    if (_charge_current) {
-        dbglogfile << "Charge current is: " << _charge_current << " Amps" << 
endl;
-    }
-    if (_buy_current) {
-        dbglogfile << "Buy current is: " <<  _buy_current << " Amps" << endl;
-    }
-    if (_pv_current) {
-        dbglogfile << "PV current is: " <<  _pv_current << " Amps" << endl;
-    }
-    if (_sell_current) {
-        dbglogfile << "Sell current is: " <<  _sell_current << " Amps" << endl;
-    }
-
-    // Voltage readings. These range from 0-256. If the Misc Mode bit is
-    // set, then this number is multiplied by 2.
-    if (_AC_input_voltage) {
-        dbglogfile << "AC Input voltage is: " << _AC_input_voltage << " VAC" 
<< endl;
-    }
-    if (_AC_output_voltage) {
-        dbglogfile << "AC Output voltage is: " << _AC_output_voltage << " VAC" 
<< endl;
-    }
-    // one volt increments, ignore the misc Byte. FIXME: Do we devide this by 
2 ?
-    if (_pv_input_voltage) {
-        dbglogfile << "PV Input voltage is: " << _pv_input_voltage/2 << " VDC" 
<< endl;
-    }
-  
-    // the resolution is 0.1 volts for a 12VDC system, 0.2 volts for a
-    // 24VDC system, and 0.4 for a 48 volt system.
-    if (_battery_voltage) {
-        dbglogfile << "Battery voltage is: " << _battery_voltage/10
-                   << "." << _battery_voltage%10 << " VDC" << endl;
-    }
-    // The total kilowatts used daily. This ranges from 0-999, with the
-    // last digit being the fraction. ie... 99 = 99.9.
-    if (_daily_kwh) {
-        dbglogfile << "The daily Kilowatts used is: " << _daily_kwh/10
-                   << "." << _daily_kwh%10 << " KW" << endl;
-    }
-
-    // Modes. Not all modes are currently implemented on the MX
-    // series. All the modes range from 0-99 except for the error and
-    // warning modes which range from 0-256.
-    dbglogfile << "The operating mode is: ";
-    switch (_operating_mode){
-      case INV_OFF:
-          dbglogfile << "Inverter OFF" << endl;
-          break;
-      case INV_SEARCH:
-          dbglogfile << "Inverter SEARCH" << endl;
-          break;
-      case INV_ON:
-          dbglogfile << "Inverter ON" << endl;    
-          break;
-      case CHARGE:
-          dbglogfile << "Charge" << endl;
-          break;
-      case SILENT:
-          dbglogfile << "Silent" << endl;
-          break;
-      case FLOAT:
-          dbglogfile << "Float" << endl;
-          break;
-      case EQ:
-          dbglogfile << "Equalize" << endl;
-          break;
-      case CHARGER_OFF:
-          dbglogfile << "Charger Off" << endl;
-          break;
-      case SUPPORT:
-          dbglogfile << "Support" << endl;
-          break;
-      case SELL_ON:
-          dbglogfile << "Sell On" << endl;
-          break;
-      case PASS_THRU:
-          dbglogfile << "Pass Thru" << endl;
-          break;
-      case FX_ERR:
-          dbglogfile << "FX Error" << endl;
-          break;
-      case AGS_ERR:
-          dbglogfile << "AGS Error" << endl;
-          break;
-      case COM_ERR:
-          dbglogfile << "Communications Error" << endl;
-          break;
-      default:
-          dbglogfile << "No operating mode!" << endl;
-          break;
-    };
-  
-    dbglogfile << "The AC mode is: \t";
-    switch (_AC_mode) {
-      case NO_AC:
-          dbglogfile << "No AC" << endl;
-          break;
-      case AC_DROP:
-          dbglogfile << "AC Dropped" << endl;
-          break;
-      case AC_USE:
-          dbglogfile << "AC In Use" << endl;    
-          break;
-      default:
-          dbglogfile << "No AC mode!" << endl;
-          break;
-    };
-
-    dbglogfile << "The Misc Byte is: \t";
-    switch (_misc_byte) {
-      case 0:
-          dbglogfile << "No Misc byte" << endl;
-      case AC_UNIT:
-          dbglogfile << "AC Unit" << endl;
-          break;
-      case AUX_OUT_ON:
-          dbglogfile << "Aux Mode On set" << endl;
-          break;
-      default:
-          dbglogfile << "Reserved" << endl;
-          break;
-    };
-
-    dbglogfile << "The Aux mode is: \t";
-    switch (_aux_mode) {
-      case DISABLED:
-          dbglogfile << "Aux Mode Disabled" << endl;
-          break;
-      case DIVERSION:
-          dbglogfile << "Diversion" << endl;
-          break;
-      case REMOTE:
-          dbglogfile << "Remote" << endl;
-          break;
-      case MANUAL:
-          dbglogfile << "Manual" << endl;
-          break;
-      case VENT_FAN:
-          dbglogfile << "Vent Fan" << endl;
-          break;
-      case PV_TRIGGER:
-          dbglogfile << "PV Trigger" << endl;
-          break;
-      default:
-          dbglogfile << "No AUX mode set" << endl;
-          break;
-    };
-
-    dbglogfile << "The charge mode is: \t";
-    switch (_charge_mode) {
-      case SILENT_MODE:
-          dbglogfile << "Silent Charge mode" << endl;
-          break;
-      case FLOAT_MODE:
-          dbglogfile << "Float Charge mode" << endl;
-          break;
-      case BULK_MODE:
-          dbglogfile << "Bulk Charge mode" << endl;
-          break;
-      case ABSORB_MODE:
-          dbglogfile << "Absorb Charge mode" << endl;
-          break;
-      case EQ_MODE:
-          dbglogfile << "Equalization Charge mode" << endl;
-          break;
-      default:
-          dbglogfile << "No Charge mode" << endl;
-          break;
-    };
-
-    dbglogfile << "The error mode is: \t";
-    switch (_error_mode) {
-      case NO_ERROR:
-          dbglogfile << "No error" << endl;
-          break;
-      case LOW_VAC:
-          dbglogfile << "ERROR: Low Volts AC" << endl;
-          break;
-      case STACKING:
-          dbglogfile << "ERROR: Stacking" << endl;
-          break;
-      case OVER_TEMP:
-          dbglogfile << "ERROR: Over Temperature" << endl;
-          break;
-      case LOW_BATT:
-          dbglogfile << "ERROR: Low Battery" << endl;
-          break;
-      case PHASE_LOSS:
-          dbglogfile << "ERROR: Phase Loss" << endl;
-          break;
-      case HIGH_BATT:
-          dbglogfile << "ERROR: High Battery" << endl;
-          break;
-      case SHORT:
-          dbglogfile << "ERROR: Short" << endl;
-          break;
-      case BACKFEED:
-          dbglogfile << "ERROR: Backfeed" << endl;
-          break;
-      default:
-          dbglogfile << "No error mode" << endl;
-          break;
-    };
-
-    dbglogfile << "The warning mode is: \t";
-    switch (_warning_mode) {
-      case NO_WARNING:
-          dbglogfile << "No warning" << endl;
-          break;
-      case AC_IN_FREQ_HIGH:
-          dbglogfile << "WARNING: Input Frequency High" << endl;
-          break;
-      case AC_IN_FREQ_LOW:
-          dbglogfile << "WARNING: Input Frequency Low" << endl;
-          break;
-      case IN_VAC_HIGH:
-          dbglogfile << "WARNING: Input Volts AC High" << endl;
-          break;
-      case IN_VAC_LOW:
-          dbglogfile << "WARNING: Input Volts AC low" << endl;
-          break;
-      case BUY_IN_SIZE:
-          dbglogfile << "WARNING: Buy in size" << endl;
-          break;
-      case TEMP_FAILED:
-          dbglogfile << "WARNING: Temperature Failure" << endl;
-          break;
-      case COMM_ERROR:
-          dbglogfile << "WARNING: Communications error" << endl;
-          break;
-      case FAN_FAILURE:
-          dbglogfile << "WARNING: Fan Failure" << endl;
-          break;
-      default:
-          dbglogfile << "No warning mode" << endl;
-          break;
-    };
-}
-
-// Calculate the checksum for a packet and see if it matches.
-retcode_t
-outback::calcChecksum(const char *packet)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    const char *ptr = packet;
-    int index = 45;
-    int chk_field = 0;
-    int checksum = 0;
-    int elem = 0;
-
-    // extract the checksum field from the packet. Also strip off any
-    // leading zeros, as this makes strtol() thinks it's octal by
-    // mistake.
-    char chk[4];
-    memset(chk,0, 4);
-    while (index <= 47) {
-        if (packet[index] != '0') {
-            chk[elem++] = packet[index];
-        }
-        index++;
-    }
-  
-    // Convert the checksum to a number
-    chk_field = strtol(chk, NULL, 0);
-  
-    do {
-        if (*ptr == ',') {
-            ptr++;
-            continue;
-        }
-        if (*ptr == '*') {
-            ptr++;
-            continue;
-        }
-        checksum+= (*ptr++) - '0';
-    } while ((ptr - packet) <= 44); // Don't add the checksum itself
-
-    //dbglogfile << "Transmitted checksum for packet is: " << chk << endl;
-    //dbglogfile << "Calculated checksum for packet is: " << checksum << endl;
-
-    // See if the calculated checksum matches the checksum from the
-    // packet checksum field. (the last 3 bytes before the CR terminator)
-    if (checksum != chk_field) {
-        dbglogfile << "ERROR: Checksums don't match!" << endl;
-        return ERROR;
-    }
-  
-    return SUCCESS;
-}
-
-
-//CREATE TABLE `meters` (
-//  `unit` int(11) NOT NULL default '0',
-//  `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update 
CURRENT_TIMESTAMP,
-//  `charge_amps` int(11) NOT NULL default '0',
-//  `ac_load_amps` int(11) NOT NULL default '0',
-//  `battery_volts` float NOT NULL default '0',
-//  `ac_volts_out` float NOT NULL default '0',
-//  `ac1_volts_in` float NOT NULL default '0',
-//  `ac2_volts_in` float NOT NULL default '0',
-//  `buy_amps` int(11) NOT NULL default '0',
-//  `sell_amps` int(11) NOT NULL default '0',
-//  `daily_kwh` float NOT NULL default '0',
-//  `hertz` int(11) NOT NULL default '0',
-//  `battery_tempcomp` float NOT NULL default '0'
-//) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Stores data from data 
logging output';
-meter_data_t *
-outback::exportMeterData(meter_data_t *data)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    // The unit number for the device
-    data->unit = _address;
-  
-    // The type of the device
-    switch (_type) {
-      case OUTBACK_MX:
-          data->type = MX_OUTBACK;
-          data->unit = _address - '0';
-          break;
-      case OUTBACK_FX:
-          data->type = FX_OUTBACK;
-          data->unit = _address - 'A';
-          break;
-      case SW_XANTREX:
-      default:
-          break;
-    };
-  
-    // The amperage being put into the batteries
-    data->charge_amps = _charge_current;
-    // The load in amps
-    data->ac_load_amps = _inverter_current;
-    // Actual Battery Voltage
-    data->battery_volts = _battery_voltage/10.0;
-    // Battery Voltage temperature compensated. This isn't used by
-    // Outback products.
-    data->tempcomp_volts = 0;
-    // The voltage the inverter is producing
-    data->ac_volts_out = _AC_output_voltage;
-    // Grid AC input
-    data->ac1_volts_in = _AC_input_voltage;
-    // The AC current taken from the Grid and used to charge the batteries.
-    data->buy_amps = _buy_current;
-    // The AC current the batteries are putting into the grid.
-    data->sell_amps = _sell_current;
-    // The daily kilowatts put into the batteries from the PV source.
-    data->daily_kwh = _daily_kwh/10.0;
-    // The frequency in hertz. This doesn't exist on an Outback, but does on
-    // a Xantrex. It should always be 60 though, so we set it so other
-    // software can handle this  the same way.
-    data->hertz = 60;
-    // The generator is AC2 on a Xantrex, but doesn't have a separete
-    // input on an Outback.
-    data->ac2_volts_in = 0.0;
-    // The current coming in from the PV panels before MPPT
-    data->pv_amps_in = _pv_current;
-    // The Voltage coming in from the PV panels before MPPT
-    data->pv_volts_in = _pv_input_voltage;
-
-  
-    return data;
-}
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
diff --git a/lib/outbackpower.h b/lib/outbackpower.h
deleted file mode 100644
index 349a6ae..0000000
--- a/lib/outbackpower.h
+++ /dev/null
@@ -1,364 +0,0 @@
-// 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
-//      Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifndef __OUTBACK_POWER_H__
-#define __OUTBACK_POWER_H__
-
-// This is generated by autoconf
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string>
-#include "serial.h"
-#include "console.h"
-#include "database.h"
-
-// The outback has two variations on protocols, one for the FX
-// inverter series, and the other for the MX charge controller
-// series. Each packet is 49 bytes, and is transmitted as ASCII
-// numerals for portability, with an ASCII comma character
-// seperating each field.
-namespace outbackpower
-{
-
-// Outback FX Inverter protocol
-struct outback_fx
-{
-    char start;                   // 1. This is an ASCII(10) New Line character
-    // denoting the start of the status page.
-    char address;                 // 2. This is the Inverter address.
-    char comma1;                  // 3. ASCII(44) a comma as a data separator.
-    char inverter_current[2];     // 4. High byte of Inverter current.
-    // 5. Low byte of Inverter current.
-    char comma2;                  // 6. ASCII(44) a comma as a data separator.
-    char charger_current[2];      // 7. High byte of Charger current..
-    // 8. Low byte of Charger current.
-    char comma3;                  // 9. ASCII(44) a comma as a data separator.
-    char buy_current[2];          // 10. High byte of Buy current..
-    // 11. Low byte of Buy current.
-    char comma4;                  // 12. ASCII(44) a comma as a data separator.
-    char ac_input_voltage[3];     // 13. High byte of the AC input voltage.
-    // 14. Middle byte of AC input voltage.
-    // 15. Low byte of AC input voltage.
-    char comma5;                  // 16. ASCII(44) a comma as a data separator.
-    char ac_output_voltage[3];    // 17. High byte of the AC output voltage.
-    // 18. Middle byte of AC output voltage.
-    // 19. Low byte of AC output voltage.
-    char comma6;                  // 20. ASCII(44) a comma as a data separator.
-    char sell_current[2];         // 21. High byte of Sell current.
-    // 22. Low byte of Sell current.
-    char comma7;                  // 23. ASCII(44) a comma as a data separator.
-    char operating_mode[2];       // 24. High byte of FX operating mode.
-    // 25. Low byte of FX operating mode.
-    char comma8;                  // 26. ASCII(44) a comma as a data separator.
-    char error_mode[3];           // 27. High byte of FX Error mode.
-    // 28. Middle byte of FX Error mode.
-    // 29. Low byte of FX Error mode.
-    char comma9;                  // 30. ASCII(44) a comma as a data separator.
-    char ac_mode[2];              // 31. High byte of FX AC mode.
-    // 32. Low byte of FX AC mode
-    char comma10;                 // 33. ASCII(44) a comma as a data separator.
-    char battery_voltage[3];      // 34. High byte of FX battery voltage.
-    // 35. Middle byte of FX battery voltage.
-    // 36. Low byte of FX battery voltage.
-    char comma11;                 // 37. ASCII(44) a comma as a data separator.
-    char misc[3];                 // 38. High byte of FX Misc.
-    // 39. Middle byte of FX Misc.
-    // 40. Low byte of FX Misc.
-    char comma12;                 // 41. ASCII(44) a comma as a data separator.
-    char warning_mode[3];         // 42. High byte of FX Warning mode.
-    // 43. Middle byte of FX Warning mode.
-    // 44. Low byte of FX Warning mode.
-    char comma13;                 // 45. ASCII(44) a comma as a data separator.
-    char checksum[3];             // 46. High byte of Chksum.
-    // 47. Middle byte of Chksum.
-    // 48. Low byte of Chksum.
-    char end;                     // 49. ASCII(13) carriage return. Denotes 
end of status page.*
-
-};
-
-// Outback MX charger controller protocol
-
-struct outback_mx
-{
-    char start;                   // 1. This is an ASCII(10) New Line character
-    // denoting the start of the status page.
-    char address;                 // 2. This is the MX address.
-    char comma1;                  // 3. ASCII(44) a comma as a data separator.
-    char unused1[2];              // 4. Unused, ASCII(48).
-    // 5. Unused, ASCII(48).
-    char comma2;                  // 6. ASCII(44) a comma as a data separator.
-    char charger_current[2];      // 7. High byte of Charger current.
-    // 8. Low byte of Charger current.
-    char comma3;                  // 9. ASCII(44) a comma as a data separator.
-    char pv_current[2];           // 10. High byte of PV current.
-    // 11. Low byte of PV current.
-    char comma4;                  // 12. ASCII(44) a comma as a data separator.
-    char pv_input_voltage[3];     // 13. High byte of the PV input voltage.
-    // 14. Middle byte of PV input voltage.
-    // 15. Low byte of PV input voltage.
-    char comma5;                  // 16. ASCII(44) a comma as a data separator.
-    char daily_kwh[3];            // 17. High byte of Daily KWH.
-    // 18. Middle byte of Daily KWH.
-    // 19. Low byte of Daily KWH.
-    char comma6;                  // 20. ASCII(44) a comma as a data separator.
-    char unused2[2];              // 21. Unused, ASCII(48).
-    // 22. Unused, ASCII(48).
-    char comma7;                  // 23. ASCII(44) a comma as a data separator.
-    char aux_mode[2];             // 24. High byte of MX Aux mode.
-    // 25. Low byte of MX Aux mode.
-    char comma8;                  // 26. ASCII(44) a comma as a data separator.
-    char error_mode[3];           // 27. High byte of MX Error mode.
-    // 28. Middle byte of MX Error mode.
-    // 29. Low byte of MX Error mode.
-    char comma9;                  // 30. ASCII(44) a comma as a data separator.
-    char charger_mode[2];         // 31. High byte of MX charger mode.
-    // 32. Low byte of MX charger mode.
-    char comma10;                 // 33. ASCII(44) a comma as a data separator.
-    char battery_voltage[3];      // 34. High byte of MX battery voltage.
-    // 35. Middle byte of MX battery voltage.
-    // 36. Low byte of MX battery voltage.
-    char comma11;                 // 37. ASCII(44) a comma as a data separator.
-    char unused3[3];              // 38. Unused, ASCII(48).
-    // 39. Unused, ASCII(48).
-    // 40. Unused, ASCII(48).
-    char comma12;                 // 41. ASCII(44) a comma as a data separator.
-    char unused4[3];              // 42. Unused, ASCII(48).
-    // 43. Unused, ASCII(48)
-    // 44. Unused, ASCII(48).
-    char comma13;                 // 45. ASCII(44) a comma as a data separator.
-    char checksum[3];             // 46. High byte of Chksum.
-    // 47. Middle byte of Chksum.
-    // 48. Low byte of Chksum.
-    char end;                     // 49. ASCII(13) carriage return. Denotes 
end of status page.
-};
-
-// Voltages on an Outback need to be scaled based on the battery voltage.
-typedef enum {
-    CONVERT_12VDC = 1,
-    CONVERT_24VDC = 2,
-    CONVERT_48VDC = 4
-} voltage_conversion_t;
-
-
-// Bit masks for warning messages
-typedef enum {
-    NO_WARNING      = 0,
-    AC_IN_FREQ_HIGH = 1,
-    AC_IN_FREQ_LOW  = 1 << 1,
-    IN_VAC_HIGH     = 1 << 2,
-    IN_VAC_LOW      = 1 << 3,
-    BUY_IN_SIZE     = 1 << 4,
-    TEMP_FAILED     = 1 << 5,
-    COMM_ERROR      = 1 << 6,
-    FAN_FAILURE     = 1 << 7
-} warning_mode_t;
-
-// Bit masks for error messages
-typedef enum {
-    NO_ERROR   = 0,
-    LOW_VAC    = 1,
-    STACKING   = 1 << 1,
-    OVER_TEMP  = 1 << 2,
-    LOW_BATT   = 1 << 3,
-    PHASE_LOSS = 1 << 4,
-    HIGH_BATT  = 1 << 5,
-    SHORT      = 1 << 6,
-    BACKFEED   = 1 << 7
-} error_mode_t;
-
-// "Misc" field bit masks
-typedef enum {
-    AC_UNIT    = 1,
-    RESERVE1   = 1 << 1,
-    RESERVE2   = 1 << 2,
-    RESERVE3   = 1 << 3,
-    RESERVE4   = 1 << 4,
-    RESERVE5   = 1 << 5,
-    RESERVE6   = 1 << 6,
-    AUX_OUT_ON = 1 << 7
-} misc_byte_t;
-
-// These are the numeric equivalents for the ASCII representation
-typedef enum {
-    INV_OFF     = 0,
-    INV_SEARCH  = 1,
-    INV_ON      = 2,
-    CHARGE      = 3,
-    SILENT      = 4,
-    FLOAT       = 5,
-    EQ          = 6,
-    CHARGER_OFF = 7,
-    SUPPORT     = 8,
-    SELL_ON     = 9,
-    PASS_THRU   = 10,
-    FX_ERR      = 90,
-    AGS_ERR     = 91,
-    COM_ERR     = 92
-} op_mode_t;
-
-typedef enum {
-    DISABLED    = 0,
-    DIVERSION   = 1,
-    REMOTE      = 2,
-    MANUAL      = 3,
-    VENT_FAN    = 4,
-    PV_TRIGGER  = 5
-} aux_mode_t;
-
-typedef enum {
-    SILENT_MODE = 0,
-    FLOAT_MODE  = 1,
-    BULK_MODE   = 2,
-    ABSORB_MODE = 3,
-    EQ_MODE     = 4
-} charge_mode_t;
-
-typedef enum {
-    NO_AC = 0,
-    AC_DROP = 1,
-    AC_USE = 2  
-} AC_mode_t ;
-
-// When sending the command, each of these bytes needs to be sent twice
-typedef enum {
-    ON          = 'O',
-    SEARCH      = 'S',
-    OFF         = 'F',
-    USE         = 'U',
-    DROP        = 'D',
-    AUX_ON      = 'Z',
-    AUX_OFF     = 'X'
-} fx_commands_t;
-
-typedef enum {
-    OUTBACK_NONE,
-    OUTBACK_MX,
-    OUTBACK_FX
-} outback_type_t;
-
-class outback : public Serial
-{
-public:
-    outback();
-    outback(const char *filespec);
-    outback(std::string filespec);
-    ~outback();
-    // Set up the object with data from the packet.
-    retcode_t parse(const char *packet);
-
-    // Initialize the serial port
-    retcode_t commInit(std::string);
-    retcode_t commInit(int fd);
-
-    // The main loop for an outback device
-    retcode_t main();
-    retcode_t main(Console &con);
-    retcode_t main(Console &con, Database &db);
-  
-    // calculate the ASCII packet
-    retcode_t calcChecksum(const char *packet);  
-
-    // Get the type of device
-    outback_type_t typeGet();
-  
-    // Get the address of the unit.
-    char addressGet() { return _address; }
-  
-    // Get the current readings
-    int inverterCurrentGet()        { return _inverter_current; };
-    int chargerCurrentGet()         { return _charge_current; };
-    int buyCurrentGet()             { return _buy_current; };
-    int pvCurrentGet()              { return _pv_current; };
-    int sellCurrentGet()            { return _sell_current; };
-  
-    // Get the voltage readings
-    int pvInputVoltageGet()         { return _pv_input_voltage; };
-    int ACInputVoltageGet()         { return _AC_input_voltage; };
-    int ACOutputVoltageGet()        { return _AC_output_voltage; };
-    int batteryVoltageGet()         { return _battery_voltage; };
-
-    // Get the modes
-    op_mode_t operatingModeGet()    { return _operating_mode; };
-    error_mode_t errorModeGet()     { return _error_mode; };
-    warning_mode_t warningModeGet() { return _warning_mode; };
-    AC_mode_t ACModeGet()           { return  _AC_mode; };
-    misc_byte_t miscByteGet()       { return _misc_byte; };
-    aux_mode_t auxModeGet()         { return _aux_mode; };
-    charge_mode_t chargeModeGet()   { return _charge_mode; };
-
-    // Read from the serial port
-    const char *readSerial();
-
-    // Write an FX command to the serial port
-    retcode_t sendFXCommand(fx_commands_t cmd);
-
-    void dump();
-
-    meter_data_t *exportMeterData(meter_data_t *data);
-  
-private:
-    outback_type_t _type;
-    // The address of the unit.
-    char _address;
-
-    // Amperage readings. These range from 0-99 in 1 amp increments
-    int _inverter_current;
-    int _charge_current;
-    int _buy_current;
-    int _pv_current;
-    int _sell_current;
-
-    // Voltage readings. These range from 0-256. If the Misc Mode bit is
-    // set, then this number is multiplied by 2.
-    int _AC_input_voltage;
-    int _AC_output_voltage;
-    // one volt increments, ignore the misc Byte
-    int _pv_input_voltage;
-    // the resolution is 0.1 volts for a 12VDC system, 0.2 volts for a
-    // 24VDC system, and 0.4 for a 48 volt system.
-    int _battery_voltage;
-    // The total kilowatts used daily. This ranges from 0-999, with the
-    // last digit being the fraction. ie... 99 = 99.9.
-    int _daily_kwh;
-
-    // Modes. Not all modes are currently implemented on the MX
-    // series. All the modes range from 0-99 except for the error and
-    // warning modes which range from 0-256.
-    op_mode_t _operating_mode;
-    AC_mode_t _AC_mode;
-    misc_byte_t _misc_byte;
-    aux_mode_t _aux_mode;
-    charge_mode_t _charge_mode;
-
-    error_mode_t _error_mode;
-    warning_mode_t _warning_mode;
-    int _checksum;
-};
-
-// end of namespace outback
-}
-
-// __OUTBACK_POWER_H__
-#endif
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
diff --git a/lib/postgresql.cc b/lib/postgresql.cc
index 7c4cf06..45a908f 100644
--- a/lib/postgresql.cc
+++ b/lib/postgresql.cc
@@ -21,7 +21,7 @@
 #include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include <iostream>
 #include <iomanip> 
 #include <vector>
diff --git a/lib/proc.cc b/lib/proc.cc
index 2976186..8e01a6e 100644
--- a/lib/proc.cc
+++ b/lib/proc.cc
@@ -21,7 +21,7 @@
 #include <cstdio>
 #include <unistd.h>
 #include <fcntl.h>
-#include <string>
+#include <cstring>
 #include <cstring>
 #include <cstdlib>
 #include <signal.h>
diff --git a/lib/proc.h b/lib/proc.h
index 2006c4c..c768941 100644
--- a/lib/proc.h
+++ b/lib/proc.h
@@ -16,7 +16,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#include <string>
+#include <cstring>
 #include <map>
 
 class Proc {
diff --git a/lib/rc.cc b/lib/rc.cc
index 1533bdd..9f31fd3 100644
--- a/lib/rc.cc
+++ b/lib/rc.cc
@@ -24,7 +24,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <string>
+#include <cstring>
 #include <iostream>
 #include <fstream>
 
diff --git a/lib/rc.h b/lib/rc.h
index df84501..33bd893 100644
--- a/lib/rc.h
+++ b/lib/rc.h
@@ -24,7 +24,7 @@
 # include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include "err.h"
 
 namespace rcinit {
diff --git a/lib/sem.cc b/lib/sem.cc
index c26d3f9..88b007d 100644
--- a/lib/sem.cc
+++ b/lib/sem.cc
@@ -76,7 +76,7 @@
 // 
 
 
-#include <string>
+#include <cstring>
 #include <map>
 #include "sem.h"
 #include <iostream>
diff --git a/lib/sem.h b/lib/sem.h
index 33f1c8a..16b3b1a 100644
--- a/lib/sem.h
+++ b/lib/sem.h
@@ -103,7 +103,7 @@ extern "C" {
 #include <semaphore.h>
 }
 
-#include <string>
+#include <cstring>
 #include <map>
 
 #define MEMBERS 1
diff --git a/lib/serial.cc b/lib/serial.cc
index 40a759d..5497dde 100644
--- a/lib/serial.cc
+++ b/lib/serial.cc
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <termios.h>
 
-#include <string>
+#include <cstring>
 #include <fstream>
 #include <ostream>
 #include <iostream>
diff --git a/lib/serial.h b/lib/serial.h
index b56a40d..d25d8fe 100644
--- a/lib/serial.h
+++ b/lib/serial.h
@@ -25,7 +25,7 @@
 #endif
 
 // System include files
-#include <string>
+#include <cstring>
 #include <vector>
 #include <fstream>
 #include <ostream>
diff --git a/lib/sharedlib.cc b/lib/sharedlib.cc
index 45e198c..e24fb68 100644
--- a/lib/sharedlib.cc
+++ b/lib/sharedlib.cc
@@ -18,7 +18,7 @@
 
 #include <sys/stat.h>
 #include <unistd.h>
-#include <string>
+#include <cstring>
 #include <ltdl.h>
 #include <dlfcn.h>
 
diff --git a/lib/sharedlib.h b/lib/sharedlib.h
index ff01970..5a32298 100644
--- a/lib/sharedlib.h
+++ b/lib/sharedlib.h
@@ -19,7 +19,7 @@
 #ifndef __SHAREDLIB__
 #define __SHAREDLIB__
 
-#include <string>
+#include <cstring>
 #include <ltdl.h>
 
 #include "log.h"
diff --git a/lib/snmp.h b/lib/snmp.h
index 4713cf6..98e4a65 100644
--- a/lib/snmp.h
+++ b/lib/snmp.h
@@ -74,7 +74,7 @@
 #include <net-snmp/agent/net-snmp-agent-includes.h>
 #include <net-snmp/agent/scalar.h>
 
-#include <string>
+#include <cstring>
 #include "err.h"
 
 class SnmpClient
diff --git a/lib/tcpip.cc b/lib/tcpip.cc
index 61e5d2b..db9d0cb 100644
--- a/lib/tcpip.cc
+++ b/lib/tcpip.cc
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <cstdlib>
 #include <cstdio>
-#include <string>
+#include <cstring>
 #include <vector>
 #include <iostream>
 #include <sys/param.h>
diff --git a/lib/tcpip.h b/lib/tcpip.h
index b7032e5..24fafd9 100644
--- a/lib/tcpip.h
+++ b/lib/tcpip.h
@@ -29,7 +29,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 //#include <netdb.h>
-#include <string>
+#include <cstring>
 #include <vector>
 // #ifdef HAVE_LIBXML
 // # include <libxml/encoding.h>
diff --git a/lib/tcputil.h b/lib/tcputil.h
index b3cb2f1..250b20b 100644
--- a/lib/tcputil.h
+++ b/lib/tcputil.h
@@ -30,7 +30,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
-#include <string>
+#include <cstring>
 #include <vector>
 
 #include "log.h"
diff --git a/lib/xanbus.cc b/lib/xanbus.cc
deleted file mode 100644
index a81eeb7..0000000
--- a/lib/xanbus.cc
+++ /dev/null
@@ -1,1682 +0,0 @@
-// 
-// Copyright (C) 2011 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "err.h"
-#include "log.h"
-#include "console.h"
-#include "xanbus.h"
-#include "database.h"
-
-using namespace std;
-
-static std::string menudisp;
-static char buffy[100];
-
-extern LogFile dbglogfile;
-
-const XanbusUI::cmd_data_t xanbus[] = {
-    { XanbusUI::XanbusUI::XACCESS, "ACCESS", false },
-    { XanbusUI::XanbusUI::BACKLIGHT, "BACKLIGHT", false },
-    { XanbusUI::CONT, "CONT", false },
-    { XanbusUI::CUSTOM11_QUERY, "CUSTOM11?", true },
-    { XanbusUI::CUSTOM12_QUERY, "CUSTOM12?", true },
-    { XanbusUI::CUSTOM11ERASE, "CUSTOM11ERASE", false },
-    { XanbusUI::CUSTOM12ERASE, "CUSTOM12ERASE", false },
-    { XanbusUI::CUSTOM21, "CUSTOM21", true },
-    { XanbusUI::CUSTOM22, "CUSTOM22", true },
-    { XanbusUI::CUSTOM21_QUERY, "CUSTOM21?", true },
-    { XanbusUI::CUSTOM22_QUERY, "CUSTOM22?", true },
-    { XanbusUI::CUSTOM21ERASE, "CUSTOM21ERASE", true },
-    { XanbusUI::CUSTOM22ERASE, "CUSTOM22ERASE", true },
-    { XanbusUI::DCCOMPLEV_QUERY, "DCCOMPLEV?", true },
-    { XanbusUI::DCDC_QUERY, "DCDC?", true },
-    { XanbusUI::DERATELIMIT_QUERY, "DERATELIMIT?", true },
-    { XanbusUI::ERR_QUERY, "ERR?", true },
-    { XanbusUI::FAULTACTIVE_QUERY, "FAULTACTIVE?", true },
-    { XanbusUI::FAULTGND_QUERY, "FAULTGND?", true },
-    { XanbusUI::FAULTLAST_QUERY, "FAULTLAST?", true },
-    { XanbusUI::FAULTLOG_QUERY, "FAULTLOG?", true },
-    { XanbusUI::FREQ_QUERY, "FREQ?", true },
-    { XanbusUI::FWHW_QUERY, "FWHW?", true },
-    { XanbusUI::IDN_QUERY, "IDN?", true },
-    { XanbusUI::IIN_QUERY, "IIN?", true },
-    { XanbusUI::INV_QUERY, "INV?", true },
-    { XanbusUI::IOUT_QUERY, "IOUT?", true },
-    { XanbusUI::KNOCK, "KNOCK", true },
-    { XanbusUI::KWHLIFE_QUERY, "KWHLIFE?", true },
-    { XanbusUI::KWHLIFESYS_QUERY, "KWHLIFESYS?", true },
-    { XanbusUI::KWHTODAY_QUERY, "KWHTODAY?", true },
-    { XanbusUI::KWHTODAYSYS_QUERY, "KWHTODAYSYS?", true },
-    { XanbusUI::XKWHTODAY_QUERY, "XKWHTODAY?", true },
-    { XanbusUI::MEASENGY_QUERY, "MEASENGY?", true },
-    { XanbusUI::MEASENGYSYS_QUERY, "MEASENGYSYS?", true },
-    { XanbusUI::MEASICMM_QUERY, "MEASICMM?", true },
-    { XanbusUI::MEASIN_QUERY, "MEASIN?", true },
-    { XanbusUI::MEASOUT_QUERY, "MEASOUT?", true },
-    { XanbusUI::MEASRAW_QUERY, "MEASRAW?", true },
-    { XanbusUI::MEASTEMP_QUERY, "MEASTEMP?", true },
-    { XanbusUI::MEMFREE_QUERY, "MEMFREE?", true },
-    { XanbusUI::MODELID_QUERY, "MODELID?", true },
-    { XanbusUI::MODELSTR_QUERY, "MODELSTR?", true },
-    { XanbusUI::MONPARAM_QUERY, "MONPARAM?", true },
-    { XanbusUI::MONALL_QUERY, "MONALL?", true },
-    { XanbusUI::MONAUXPARAM_QUERY, "MONAUXPARAM?", true },
-    { XanbusUI::MONENS_QUERY, "MONENS?", true },
-    { XanbusUI::MONENSPARAM_QUERY, "MONENSPARAM?", true },
-    { XanbusUI::MONEXT_QUERY, "MONEXT?", true },
-    { XanbusUI::MONEXTPARAM_QUERY, "MONEXTPARAM?", true },
-    { XanbusUI::MONFB_QUERY, "MONFB?", true },
-    { XanbusUI::MONFBPARAM_QUERY, "MONFBPARAM?", true },
-    { XanbusUI::MONGND_QUERY, "MONGND?", true },
-    { XanbusUI::MONGNDPARAM_QUERY, "MONGNDPARAM?", true },
-    { XanbusUI::MONGRID_QUERY, "MONGRID?", true },
-    { XanbusUI::MONGRIDPARAM_QUERY, "MONGRIDPARAM?", true },
-    { XanbusUI::MONTEMP_QUERY, "MONTEMP?", true },
-    { XanbusUI::MONTEMPPARAM_QUERY, "MONTEMPPARAM?", true },
-    { XanbusUI::MONOVPARAM_QUERY, "MONOVPARAM?", true },
-    { XanbusUI::MONUVPARAM_QUERY, "MONUVPARAM?", true },
-    { XanbusUI::MONVIN_QUERY, "MONVIN?", true },
-    { XanbusUI::MPPT_QUERY, "MPPT?", true },
-    { XanbusUI::MPPTDBG_QUERY, "MPPTDBG?", true },
-    { XanbusUI::MPPTLEV_QUERY, "MPPTLEV?", true },
-    { XanbusUI::MPPTLEVM_QUERY, "MPPTLEVM?", true },
-    { XanbusUI::MPPTOFFSET_QUERY, "MPPTOFFSET?", true },
-    { XanbusUI::MPPTSTAT_QUERY, "MPPTSTAT?", true },
-    { XanbusUI::NVMEMSPACE_QUERY, "NVMEMSPACE?", true },
-    { XanbusUI::OFFSET_QUERY, "OFFSET?", true },
-    { XanbusUI::OLDERLIM_QUERY, "OLDERLIM?", true },
-    { XanbusUI::PDCMPPT_QUERY, "PDCMPPT?", true },
-    { XanbusUI::PIN_QUERY, "PIN?", true },
-    { XanbusUI::POUT_QUERY, "POUT?", true },
-    { XanbusUI::POUTSYS_QUERY, "POUTSYS?", true },
-    { XanbusUI::PROD_QUERY, "PROD?", true },
-    { XanbusUI::POWLIMIT_QUERY, "POWLIMIT?", true },
-    { XanbusUI::POWSEQ_QUERY, "POWSEQ?", true },
-    { XanbusUI::POWSEQCLR, "POWSEQCLR", true },
-    { XanbusUI::QUEUED_QUERY, "QUEUED?", true },
-    { XanbusUI::RECTIME_QUERY, "RECTIME?", true },
-    { XanbusUI::RELAY_QUERY, "RELAY?", true },
-    { XanbusUI::RIPCOMP_QUERY, "RIPCOMP?", true },
-    { XanbusUI::ROM_QUERY, "ROM?", true },
-    { XanbusUI::SCALE_QUERY, "SCALE?", true },
-    { XanbusUI::SCID_QUERY, "SCID?", true },
-    { XanbusUI::SCROLL, "SCROLL", true },
-    { XanbusUI::STANDBY, "STANDBY", true },
-    { XanbusUI::STANDBY_QUERY, "STANDBY?", true },
-    { XanbusUI::TEMPLIMIT_QUERY, "TEMPLIMIT?", true },
-    { XanbusUI::TEMPLIMITSTEP_QUERY, "TEMPLIMITSTEP?", true },
-    { XanbusUI::TIME_QUERY, "TIME?", true },
-    { XanbusUI::VDCREF_QUERY, "VDCREF?", true },
-    { XanbusUI::VIN_QUERY, "VIN?", true },
-    { XanbusUI::XBADX_QUERY, "XBADX?", true }
-};
-
-XanbusUI::XanbusUI(void)
-{
-    SetDefaultValues();  
-}
-
-XanbusUI::~XanbusUI(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-string &
-XanbusUI::ReadSerial(void)
-{
-    int ret;
-    //DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-
-#if 0 
-    int retries = 1;
-  
-    while (retries--) {
-        if (ret = Read((char *)&buffy, 99) < 0) {
-            //dbglogfile << "FIXME: " << retries << "\t" << buffy << endl;
-            //ret = Read((char *)&buffy, 100);
-            continue;
-        } else {
-            break;
-        }
-    }
-#else
-    ret = Read((char *)&buffy, 100);
-#endif
-  
-    if (ret > 0) {
-        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buffy << "\t" 
<< buffy << endl;
-        menudisp = buffy;
-    } else {
-        menudisp.erase();
-    }
-  
-    return menudisp;
-}
-
-string
-XanbusUI::GetLabel() {
-    //DEBUGLOG_REPORT_FUNCTION;
-
-    dbglogfile << "menuheading: " << menuheading << " menuitem:" << menuitem 
<< endl;
-  
-    MenuItem ti = GetItem(menuheading, menuitem);
-  
-    return ti.GetLabel();
-}
-
-string &
-XanbusUI::WriteSerial(const char *buf, int nbytes)
-{
-    int ret;
-  
-    //DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    ret = Write(buf, nbytes);
-    //dbglogfile << "FIXME" << buffy << endl;
-    ret = Read(buffy, nbytes);
-  
-    menudisp = buffy;
-    return menudisp;
-}
-
-// This selects which inverter we want to control
-string &
-XanbusUI::SelectInverter(int x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-
-    Write((char *)&x, 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-// These methods all go with the Xantrex display buttons
-string &
-XanbusUI::MenuHeadingMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    //memset(buffy, 0, 100);
-  
-    Write("L", 1);
-    //Read((char *)&buffy, 100);
-    menudisp = ReadSerial();
-    //dbglogfile << "FIXME" << menudisp << endl;
-
-    //cerr << "FIXMEh-: \"" << menudisp  << "\"" << endl;
-    //cerr << "FIXMEh-: \"" << GetLabel() << "\"" << endl;
-
-    if (menuheading > 1) {
-        menuheading--;
-    }
-    menuitem = 0;
-
-    if (menudisp.find(GetLabel()) == string::npos) {
-        dbglogfile << "Heading Minus didn't Match!!" << menuheading << endl;  
-    } else {
-        dbglogfile << "Heading Minus Matched!!" << endl;
-    }
-
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::MenuHeadingPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    //memset(buffy, 0, 100);
-    MenuItem mi;
-  
-    Write("R", 1);
-  
-    //Read((char *)&buffy, 100);
-    menudisp = ReadSerial();
-    //mi = GetItem();
-
-    //dbglogfile << menudisp << endl;
-
-    menuheading++;
-    menuitem = 0;
-
-    //cerr << "FIXMEh+: \"" << menudisp  << "\"" << endl;
-    //cerr << "FIXMEh+: \"" << GetLabel() << "\"" << endl;
-  
-    if (menudisp.find(GetLabel()) == string::npos) {
-        dbglogfile << "Heading Plus didn't Match!!" << endl;  
-    } else {
-        dbglogfile << "Heading Plus Matched!!" << endl;
-    }
-
-
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-// This decends through the sub menu items of a heading
-string &
-XanbusUI::MenuItemMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int retries = 5;
-    string label;
-  
-    //memset(buffy, 0, 100);
-  
-    //Write("D", 1);
-    //Read((char *)&buffy, 100);
-    //menudisp = ReadSerial();
-    //dbglogfile << menudisp << endl;
-
-    menuitem++;
-
-    //cerr << "FIXME-I: \"" << menuheading << "," << menuitem << "\"" << endl;
-    while (retries--) {
-        Write("D", 1);
-        menudisp = ReadSerial();
-        //Flush();
-        //cerr << "FIXMEi-: \"" << menudisp  << "\"" << endl;
-        //cerr << "FIXMEi-: \"" << GetLabel() << "\"" << endl;
-
-        label = GetLabel();
-        if (label.size()) {
-            if (menudisp.find(label) == string::npos) {
-                dbglogfile << "Item Minus didn't Match!!" << endl;
-            } else {
-                dbglogfile << "Item Minus Matched!!" << endl;
-                break;
-            }
-        }
-    }
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::MenuItemPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int retries = 5;
-
-    //memset(buffy, 0, 100);
-  
-    //Write("U", 1);
-    //Read((char *)&buffy, 100);
-    //menudisp = ReadSerial();
-    //dbglogfile << menudisp << endl;
-    //menudisp = buffy;
-    if (menuitem > 1)
-        menuitem--;
-
-    //  if (strcmp(label.c_str(), buffy) == 0)
-    //    dbglogfile << "AAAAHHHHHHH" << endl;
-  
-    while (retries--) {
-        Write("U", 1);
-        menudisp = ReadSerial();
-        //Flush();
-
-        //cerr << "FIXMEi+: \"" << menudisp  << "\"" << endl;
-        //cerr << "FIXMEi+: \"" << GetLabel() << "\"" << endl;
-
-        if (menudisp.find(GetLabel()) == string::npos) {
-            dbglogfile << "Item Plus didn't Match!!" << endl;
-        } else {
-            dbglogfile << "Item Plus Matched!!" << endl;
-            break;
-        }
-    }
-
-    //  if (menudisp != label)
-    //  dbglogfile << "FIXME: Wrong Item " << menuheading << ":" << menuitem 
<< menudisp << "\t" << label << endl;
-    
-    return menudisp;
-}
-
-string &
-XanbusUI::SetPointMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("-", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::SetPointPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("+", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::Inverter(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("|", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::Generator(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("G", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::SetupMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("\003", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menuheading = 8;
-    menuitem = 0;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::LedStatus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("?", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;  
-}
-
-string &
-XanbusUI::Version(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("V", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XanbusUI::SetTerminalMode(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("T", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-#if 0
-// These methods are for switching menu modes
-retcode_t
-XanbusUI::GotoSetupMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-retcode_t
-XanbusUI::GotoUserMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-string &
-XanbusUI::UserMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-#endif
-
-// This method takes us to the beginning of the menu headers and items
-// This corresponds then to being in the Inverter Mode header of the
-// User menu.
-retcode_t
-XanbusUI::GotoMenuStart(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int i;
-    for (i=0; i<22; i++) {
-        // Don't use MenuheadingMinus, as it gets all confused
-        Write("L", 1);
-        menudisp = ReadSerial();
-        if (menudisp.find("Inverter", 0) != string::npos) {
-            break;
-        }
-    }
-  
-    menuheading = 1;
-    menuitem = 0;
-    dbglogfile << "At Start Of Menu" << endl;
-  
-    return SUCCESS;
-}
-
-// These methods manipulate values
-retcode_t
-XanbusUI::SetFloatValue(float )
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    cerr << "ERROR: unimplemented!" << endl;
-    return ERROR;
-}
-
-float
-XanbusUI::GetFloatValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    return atof(GetValue(str).c_str());
-}
-
-retcode_t
-XanbusUI::SetIntValue(int x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    cerr << "ERROR: unimplemented!" << endl;
-    return ERROR;
-}
-
-int
-XanbusUI::GetIntValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    return atoi(GetValue(str).c_str());
-}
-
-bool
-XanbusUI::GetBoolValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    string tmpstr = GetValue(str).c_str();
-  
-    if (tmpstr == "NO" || tmpstr == "OFF")
-        return false;
-    else
-        return true;
-}
-
-string &
-XanbusUI::GetValue (std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos, pos2;
-    //string value;
-    int i = 0;
-    string lookfor;
-
-    //cout << "The Raw value string is: " << str << endl;
-
-#if 0
-    pos = str.find("-00", str.length());
-    if (pos != string::npos) {
-        str.erase(pos, str.length() - pos);
-    }
-#endif
-  
-    do {
-        lookfor = " ";
-        char j = '0' + i;
-        lookfor += j;
-        pos = str.find(lookfor, 0);
-        lookfor.erase();
-    } while ((pos == string::npos) && (i++ < 10));
-  
-    pos2 = str.find(' ', pos+1);
-    if (pos2 == string::npos) {
-        pos2 = pos + 4;
-    }
-  
-    str = str.substr(pos+1, pos2 - pos);
-
-#if 0
-    if (pos != string::npos) {
-        // We want just the last data item, which is the value
-        value = str.substr(pos+1, str.length() - pos);
-        str = value;
-    } else {
-        str.erase();
-    }
-#endif
-  
-    return str;
-}
-
-vector<string> *
-XanbusUI::GetValues (std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos;
-    string value;
-    vector<string> *array;
-
-    array = new vector<string>;
-
-    //cout << "The Raw values string is: " << str << endl;
-
-    do {
-        pos = str.find("-00", str.length());
-        if (pos != string::npos) {
-            str.erase(pos, str.length() - pos);
-        }
-    
-        // Find the last space in the string
-        pos = str.rfind(' ' , str.length());
-    
-        if (pos != string::npos) {
-            // We want just the last data item, which is the value
-            value = str.substr(pos+1, str.length() - pos);
-            str = value;
-            array->push_back(value);
-        } else {
-            str.erase();
-        }
-    } while (pos != string::npos);
-  
-  
-    return array;
-}
-
-std::string
-XanbusUI::GetLabel(std::string &x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos;
-
-    // Find the last space in the string
-    pos = x.rfind(' ' , x.length());
-    //pos = x.rfind('\t' , x.length());
-
-    if (pos != string::npos) {
-        return x.substr(0, pos);
-    }
-  
-    return x;
-}
-
-
-string &
-XanbusUI::GotoMenuItem(int mh, int mi)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string tmpstr;
-    int i;
-    MenuItem item;
-  
-    GotoMenuStart();
-
-    item = GetItem(mh, mi);
-    for (i=0; i < mh-1; i++) {
-        menudisp = MenuHeadingPlus();
-    }
-  
-    for (i=0; i < mi-1; i++) {
-        menudisp = MenuItemMinus();
-    }
-
-    if (menudisp.find(item.GetLabel()) != string::npos) {
-        dbglogfile << "Didn't Match!!" << endl;  
-    }
-
-    //menudisp = CleanUpData(tmpstr);
-  
-    menuheading = mh;
-    menuitem = mi;
-
-    return menudisp;
-}
-
-//std::map<std::string, float> *
-//std::vector< std::map< std::string, float > >
-vector<meter_data_t *>
-XanbusUI::PollMeters(int loops)
-{
-    MenuItem      ti;
-    int           mh = 4;
-    int           mi = 1;
-    int           items = 7;                // the number of data items to get
-    float         fltval;
-    int           intval;
-    int           i;
-    string        str, label;
-    meter_data_t *downdata, *updata;
-    vector<meter_data_t *> meters;
-
-    //memset(buffy, 0, 100);
-
-    GotoMenuItem(mh, mi);
-    while (loops-- > 0) {
-        downdata = new meter_data_t;
-        memset(downdata, 0, sizeof(meter_data_t));
-    
-        for (i=mi; i<= mi+items; i++) {
-            str = MenuItemMinus();
-            fltval = 0.0;
-            intval = 0;
-            if (str.size() > 1) {
-                ti = GetItem();
-                if (ti.GetType() != MenuItem::INFO) {
-                    label = GetLabel(); 
-                    cout << "The Menu Item Label down is: " << label;
-                }
-                ti = GetItem();
-                if (ti.GetType() == MenuItem::FLOAT) {
-                    fltval = GetFloatValue(str);
-                    cout << ", with a float value is: " << fltval << endl;
-                }
-                if (ti.GetType() == MenuItem::INT) {
-                    intval = GetIntValue(str);
-                    cout << ", with an Integer value is: " << intval << endl;
-                }
-                if (ti.GetType() == MenuItem::INFO) {
-                    cout << ", an INFO statement  " << endl;
-                    break;
-                }
-                if (label.substr(0, 5) == "Input") {
-                    //downdata->
-                }
-                if (label.substr(0, 4) == "Load") {
-                    dbglogfile << "Matched label going down " << label;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->ac_load_amps = intval;
-                }
-                if (label.substr(8, 6) == "actual") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->battery_volts = fltval;
-                }
-                if (label.substr(8, 8) == "TempComp") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->tempcomp_volts = fltval;
-                }
-                if (label.substr(0, 8) == "Inverter") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->ac_volts_out = intval;
-                }
-                if (label.substr(0, 4) == "Grid") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->ac1_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Generator") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->ac2_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Read Freq") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->hertz = intval;
-                }
-            }
-        }
-
-        meters.push_back(downdata);
-        //MenuItemMinus();            // go one more, since the first thing
-        // we do is come back up one item.
-        updata = new meter_data_t;
-        memset(updata, 0, sizeof(meter_data_t));
-        //ptr2 = (float *)((char *)updata + 
sizeof(meter_data_t)-sizeof(float));
-        //*ptr2-- = downdata->hertz;
-    
-        // Now go up through the menu
-        for (i=mi+items; i>mi; i--) {
-            str = MenuItemPlus();
-            fltval = 0.0;
-            intval = 0;
-            if (str.size() > 0) {
-                label = GetLabel(); 
-                cout << "The Menu Item Label up is: " << label;
-                ti = GetItem();
-                if (ti.GetType() == MenuItem::FLOAT) {
-                    fltval = GetFloatValue(str);
-                    cout << ", with a float value is: " << fltval << endl;
-                }
-                if (ti.GetType() == MenuItem::INT) {
-                    intval = GetIntValue(str);
-                    cout << ", with an integer value is: " << intval << endl;
-                }
-                //Flush();
-                //_data.push(label, );
-                if (label.substr(0, 5) == "Input") {
-                    //updata->
-                }
-                if (label.substr(0, 4) == "Load ") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    updata->ac_load_amps = intval;
-                }
-                if (label.substr(8, 6) == "actual") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->battery_volts = fltval;
-                }
-                if (label.substr(8, 8) == "TempComp") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->tempcomp_volts = fltval;
-                }
-                if (label.substr(0, 8) == "Inverter") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    updata->ac_volts_out = intval;
-                }
-                if (label.substr(0, 4) == "Grid") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->ac1_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Generator") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->ac2_volts_in = fltval;
-                }
-                // Since this is the last and first reading, it doesn't really
-                // have time to change.
-                updata->hertz = downdata->hertz;
-//         if (label.substr(0, 9) == "Read Freq") {
-//           dbglogfile << "Matched label going up " << label << endl;
-//           dbglogfile << " value is: " << intval << endl;
-//           updata->hertz = intval;
-//         }
-            } // end of if str
-        } // end of for loop
-        meters.push_back(updata);
-    }
-    // Go back to the top
-//   for (i=items; i>=mi; i--) {
-//     MenuItemPlus();
-//   }
-  
-    MenuHeadingPlus();
-    MenuHeadingMinus();          
-  
-    return meters;
-}
-
-// This method takes the data as outputted by the Xantrex inverter,
-// and munges it to be a standard form with whitespace compressed,
-// newlines & carriage returns stripped out, etc... This is so
-// we can analyse the string data in a consistant fashion.
-std::string &
-XanbusUI::CleanUpData(std::string &str)
-{
-    unsigned int i;
-
-    menudisp.erase();
-    for (i=0; i< str.length(); i++) {
-        switch (str[i]) {
-            // we ignore these characters
-          case '\r':
-          case '\n':
-              break;
-              // compress multiple spaces to be just one
-          case ' ':
-              if (str[i+1] == ' ') {
-                  continue;
-              } else {
-                  menudisp += ' ';
-                  break;
-              }
-          default:
-              menudisp += str[i];
-        }
-    }
-
-    return menudisp;
-}
-
-void
-XanbusUI::SetDefaultValues(void)
-{
-
-    MenuItem mi;
-
-    // We know we always have 20 major menu headings
-    _items.resize(21);
-
-    mi.SetItem ("Top of Menu", 0);
-    _items[0].push_back(mi);
-
-    // Inverter Mode - Menu Heading #1
-    mi.SetItem ("Inverter Mode",                      1);
-    _items[1].push_back(mi);
-
-    mi.SetItem ("Set Inverter     OFF SRCH ON CHG",   1, 1, "SetVert"); // 
FIXME: enum
-    _items[1].push_back(mi);
-    mi.SetItem ("CHG avail. Only  in FLT mode",       1, 2);
-    _items[1].push_back(mi);
-    mi.SetItem ("Press red or     setpoint button",   1, 3);
-    _items[1].push_back(mi);
-    mi.SetItem ("to move.         Move cursor to",    1, 4);
-    _items[1].push_back(mi);
-    mi.SetItem ("Inverter OFF to  resetOverCurrent",  1, 5);
-    _items[1].push_back(mi);
-
-    // Generator Mode - Menu Headings #2
-    mi.SetItem ("Generator Mode",                     2);
-    _items[2].push_back(mi);
-    mi.SetItem ("Set Generator    OFF AUTO ON EQ",    2, 1, "SetGen"); // 
FIXME: enum
-    _items[2].push_back(mi);
-    mi.SetItem ("Gen under/over   speed",             2, 2, false, "GenSpeed");
-    _items[2].push_back(mi);  
-    mi.SetItem ("Generator start  error",             2, 3, false, "GenStart");
-    _items[2].push_back(mi);
-    mi.SetItem ("Generator sync   error",             2, 4, false, "GenSync");
-    _items[2].push_back(mi);
-    mi.SetItem ("Gen max run Time error",             2, 5, false, "GenMax");
-    _items[2].push_back(mi);
-    mi.SetItem ("Load Amp Start   ready",             2, 6, false, "LoadAmp");
-    _items[2].push_back(mi);
-    mi.SetItem ("Voltage Start    ready",             2, 7, false, 
"VoltStart");
-    _items[2].push_back(mi);
-    mi.SetItem ("Exercise Start   ready",             2, 8, false, 
"ExerStart");
-    _items[2].push_back(mi);
-  
-    // Xantrex Engineering - Menu Heading #3
-    // Xantrex was Trace, so this prompt varies depending on the
-    // software version on the inverter.
-    mi.SetItem ("Engineering",       3);
-    //mi.SetItem ("Trace            Engineering",       3);
-    _items[3].push_back(mi);
-    mi.SetItem ("Press reset now  for defaults",      3, 1);
-    _items[3].push_back(mi);
-    mi.SetItem ("Revision 4.01",                      3, 2, "XantrexRev");
-    _items[3].push_back(mi);
-    mi.SetItem ("5916 195th St NE Arlington, WA",     3, 3);
-    _items[3].push_back(mi);
-    mi.SetItem ("98223 USA",                          3, 4);
-    _items[3].push_back(mi);
-    mi.SetItem ("Ph  360-435-8826 Fax 360-435-2229",  3, 5);
-    _items[3].push_back(mi);
-
-    // Meters - Menu Heading #4
-    mi.SetItem ("Meters",                         4);
-    _items[4].push_back(mi);
-    mi.SetItem ("Inverter/charger amps AC",         4,  1, 0, "ChargerAmps");
-    _items[4].push_back(mi);
-    mi.SetItem ("Input            amps AC",         4,  2, 0, "InputAmps");
-    //mi.SetItem ("Input",                           4,  2, 0, "InputAmps");
-    _items[4].push_back(mi);
-    mi.SetItem ("Load             amps AC",         4,  3, 0, "LoadAmps");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Battery actual",                   4,  4, (float)25.1, 
"BattVolts");
-    mi.SetItem ("Battery actual   volts DC",        4,  4, (float)25.1, 
"BattVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Battery TempComp",                4,  5, (float)25.1, 
"TempComp");
-    mi.SetItem ("Battery TempComp volts DC",        4,  5, (float)25.1, 
"TempComp");
-    _items[4].push_back(mi);
-    mi.SetItem ("Inverter         volts AC",        4,  6, 0, "InvertVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Grid (AC1)",                       4,  7, 0, "GridVolts");
-    mi.SetItem ("Grid (AC1)       volts AC",                             4,  
7, 0, "GridVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Generator (AC2)",                  4,  8, 0, "GenVolts");
-    mi.SetItem ("Generator (AC2)  volts AC",                             4,  
8, 0, "GenVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Read Frequency",                   4,  9, 0, "ReadHertz");
-    mi.SetItem ("Read Frequency   Hertz",                           4,  9, 0, 
"ReadHertz");
-    _items[4].push_back(mi);
-    mi.SetItem ("AC1 & AC2 volts  valid only when", 4, 10);
-    _items[4].push_back(mi);
-    mi.SetItem ("inverter synced  to that input.",  4, 11);
-    _items[4].push_back(mi);
-    mi.SetItem ("Batt volt actual is used for",     4, 12);
-    _items[4].push_back(mi);
-    mi.SetItem ("LBCO,HBCO,LBX,   LBCI,sell volts", 4, 13);
-    _items[4].push_back(mi);
-    mi.SetItem ("and gen starting",                 4, 14);
-    _items[4].push_back(mi);
-    mi.SetItem ("Batt volt temp   comp is used,",   4, 15);
-    _items[4].push_back(mi);
-    mi.SetItem ("for float, bulk, eq & aux relays", 4, 16);
-    _items[4].push_back(mi);
-  
-    // Error Cause - Menu Heading #5
-    mi.SetItem ("Error Causes",                 5);
-    _items[5].push_back(mi);
-    mi.SetItem ("Over Current",                 5,  1, false, "OverCurrent");
-    _items[5].push_back(mi);
-    mi.SetItem ("Transformer      overtemp",    5,  2, false, "OverTemp");
-    _items[5].push_back(mi);
-    mi.SetItem ("Heatsink         overtemp",    5,  3, false, "HeatSink");
-    _items[5].push_back(mi);
-    mi.SetItem ("High Battery     voltage",     5,  4, false, "HighBatt");
-    _items[5].push_back(mi);
-    mi.SetItem ("Low Battery      voltage",     5,  5, false, "LowBatt");
-    _items[5].push_back(mi);
-    mi.SetItem ("Inverter breaker tripped",     5,  6, false, "Tripped");
-    _items[5].push_back(mi);
-    mi.SetItem ("Manual Off",                   5,  7, false, "ManualOff");
-    _items[5].push_back(mi);
-    mi.SetItem ("AC source wired  to output",   5,  8, false, "ACWired");
-    _items[5].push_back(mi);
-    mi.SetItem ("External error   (Stacked)",   5,  9, false, "ExtError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Generator start  error",       5, 10, false, "GenError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Generator sync   error",       5, 11, false, "SyncError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Gen maximum run  time error",  5, 12, false, "MaxRunError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Gen Under/Over   speed",       5, 13, false, "SpeedError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Inverter breaker tripped",     5, 14, false, "BreakerError");
-    _items[5].push_back(mi);
-  
-    // Time Of Day - Menu Heading #6
-    mi.SetItem ("Time of Day",                 6);
-    _items[6].push_back(mi);
-    mi.SetItem ("Time of Day      Set Clock hour", 6, 1, 0);
-    _items[6].push_back(mi);
-    mi.SetItem ("Set Clock minute",            6, 2, 0, "Minute");
-    _items[6].push_back(mi);
-    mi.SetItem ("Set Clock second",            6, 3, 0, "Second");
-    _items[6].push_back(mi);
-
-    // Generator timer - Menu Heading #7
-    mi.SetItem ("Generator Timer",           7);
-    _items[7].push_back(mi);
-    mi.SetItem ("Start Quiet      time h:m", 7, 1, 8 ); // FIXME: this should 
be a time
-    _items[7].push_back(mi);  
-    mi.SetItem ("End Quiet        time h:m", 7, 2, 8 ); // FIXME: this should 
be a time
-    _items[7].push_back(mi);
-
-    // End of User menus!
-    mi.SetItem ("END USER MENU", 8);
-    _items[8].push_back(mi);
-
-    // Inverter Setup - Menu heading #9
-    mi.SetItem ("Inverter Setup",               9);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Grid Usage",               9, 1); // FIXME: FLOAT
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Low battery  cut out VDC", 9, 2, (float)22.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set LBCO delay   minutes",     9, 3, 15);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Low battery  cut in VDC",  9, 4, (float)26.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set High battery cut out VDC", 9, 5, (float)32.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set search       watts",       9, 6, 48);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set search       spacing",     9, 7, 59);
-    _items[9].push_back(mi);
-
-    // Battery Charging - Menu heading #10
-    mi.SetItem ("Battery Charging",                10);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Bulk         volts DC",       10, 1, (float)28.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Absorption   time h:m",       10, 2, 2);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Float        volts DC",       10, 3, (float)26.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Equalize     volts DC",       10, 4, (float)28.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Equalize     time h:m",       10, 5, 2);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Max Charge   amps DC",        10, 6, 30);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Temp Comp    LeadAcid Nicad", 10, 7); // FIXME: LEADACID
-    _items[10].push_back(mi);
-
-    // AC Inputs - Menu heading #11
-    mi.SetItem ("AC Inputs",                       11);
-    _items[11].push_back(mi);
-    mi.SetItem ("inverter synced  to that input.", 11);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Grid (AC1)   amps AC",        11, 1, 60);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Gen (AC2)    amps AC",        11, 2, 30);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Input lower  limit VAC",      11, 3, 108);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Input upper  limit VAC",      11, 4, 132);
-    _items[11].push_back(mi);
-
-    // Generator Auto Start Setup - Menu heading #12
-    //  genauto.state = OFF;
-    mi.SetItem ("Gen Auto Start   setup",           12);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Start   amps AC",         12, 1, 33);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Start   delay min",       12, 2, 5);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Stop    delay min",       12, 3, 5);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 24 hr start  volts DC",        12, 4, (float)24.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 2 hr start   volts DC",        12, 5, (float)23.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 15 min start volts DC",        12, 6, (float)22.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Read LBCO 30 sec start VDC",       12, 7, 22);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Exercise     period days",     12, 8, 30);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Maximum run  time h:m",        12, 9, 8);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Max Run time to 0 to defeat.", 12, 10, 0);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Exercise to 0 to defeat.",     12, 11, 0);
-    _items[12].push_back(mi);
-    mi.SetItem ("See menu 9 to    to set LBCO.",    12, 12, 0);
-    _items[12].push_back(mi);
-
-    //Generator Starting Details - Menu heading #13
-    mi.SetItem ("Gen starting     details",      13);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set RY7 Function GlowStop Run", 13, 1, 0);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Gen warmup   seconds",      13, 2, 60);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Pre Crank    seconds",      13, 3, 10);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Max Cranking seconds",      13, 4, 10);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Post Crank   seconds",      13, 5, 30);
-    _items[13].push_back(mi);
-
-    // Auxilary relays - Menu heading #14
-    mi.SetItem ("Auxiliary Relays R9 R10 R11", 14);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 9      volts DC",       14, 1, 29);
-    _items[14].push_back(mi);
-    mi.SetItem ("R9 Hysteresis    volts DC",       14, 2, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 10     volts DC",       14, 3, (float)29.5);
-    _items[14].push_back(mi);
-    mi.SetItem ("R10 Hysteresis   volts DC",       14, 4, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 11     volts DC",       14, 5, 30);
-    _items[14].push_back(mi);
-    mi.SetItem ("R11 Hysteresis   volts DC",       14, 6, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Close on batt >  setpoint.",      14, 7);
-    _items[14].push_back(mi);
-    mi.SetItem ("Open  on  batt < setpoint - Hys", 14, 8);
-    _items[14].push_back(mi);
-    mi.SetItem ("Relays have 2    second delay on",14, 9);
-    _items[14].push_back(mi);
-    mi.SetItem ("Close, 0.1 sec   delay on open",  14, 10);
-    _items[14].push_back(mi);
-
-    // Bulk Charge Trigger Time - Menu heading #15
-    mi.SetItem ("Bulk Charge      Trigger Timer",   15);
-    _items[15].push_back(mi);              
-    mi.SetItem ("Set Start Bulk   time",            15, 1, 0);
-    _items[15].push_back(mi);              
-    mi.SetItem ("To disable timer set to 00:00",    15, 2);
-    _items[15].push_back(mi);              
-    mi.SetItem ("If grid timer    active set bulk", 15, 3);
-    _items[15].push_back(mi);              
-    mi.SetItem ("time after start charge time.",    15, 4);
-    _items[15].push_back(mi);              
-    mi.SetItem ("In SLT mode don't disable this",   15, 5);
-    _items[15].push_back(mi);              
-    mi.SetItem ("timer. It is the daily chg time.", 15, 6);
-    _items[15].push_back(mi);              
-
-    // Low Battery Transfer - Menu heading #16
-    mi.SetItem ("Low Battery      Transfer (LBX)",    16);
-    _items[16].push_back(mi);
-    mi.SetItem ("Set Low Battery  TransferVDC",       16, 1, (float)26.8);
-    _items[16].push_back(mi);
-    mi.SetItem ("Set Low Battery  cut in  VDC",       16, 2, (float)26);
-    _items[16].push_back(mi);
-    mi.SetItem ("See menu 9 to    enable LBX mode.",  16, 3);
-    _items[16].push_back(mi);
-    mi.SetItem ("Make sure LBX is above LBCO volts.", 16, 4);
-    _items[16].push_back(mi);
-
-    //  Battery Power Selling - Menu heading #17
-    mi.SetItem ("Battery Selling",                    17);
-    _items[17].push_back(mi);
-    mi.SetItem ("Set Battery Sell volts",             17, 1, (float)26.8);
-    _items[17].push_back(mi);
-    mi.SetItem ("Set Max Sell     amps",              17, 2, 30);
-    _items[17].push_back(mi);
-    mi.SetItem ("See menu 9 to    enable SELL mode.", 17, 3);
-    _items[17].push_back(mi);
-    mi.SetItem ("Make sure LBX is above LBCO volts.", 17, 4);
-    _items[17].push_back(mi);
-  
-    // Grid Usage Timer - Menu heading #18
-    mi.SetItem ("Grid Usage Timer",                 18);
-    _items[18].push_back(mi);
-    mi.SetItem ("Set Charge       time",            18,  1, 21); // FIXME: TIME
-    _items[18].push_back(mi);
-    mi.SetItem ("End Charge       time",            18,  2, 21); // FIXME: TIME
-    _items[18].push_back(mi);
-    mi.SetItem ("After Start      Charge time:",    18,  3);
-    _items[18].push_back(mi);
-    mi.SetItem ("SELL mode        charges battery.",18,  4);
-    _items[18].push_back(mi);
-    mi.SetItem ("FLT mode         charges battery", 18,  5);
-    _items[18].push_back(mi);
-    mi.SetItem ("After End Charge time:",           18,  6);
-    _items[18].push_back(mi);
-    mi.SetItem ("SELL mode sells  battery to AC1.", 18,  7);
-    _items[18].push_back(mi);
-    mi.SetItem ("FLT mode drops   AC1 and inverts", 18,  8);
-    _items[18].push_back(mi);
-    mi.SetItem ("Timer on when    start < > end;",  18,  9);
-    _items[18].push_back(mi);
-    mi.SetItem ("timer off when   start = end",     18, 10);
-    _items[18].push_back(mi);
-    mi.SetItem ("Sell and float   modes use timer", 18, 11);
-    _items[18].push_back(mi);
-    mi.SetItem ("SLT and LBX mode ignore timer",    18, 12);
-    _items[18].push_back(mi);
-  
-    // Information file battery - Menu Heading #19
-    mi.SetItem ("Information file battery",          19);
-    _items[19].push_back(mi);
-    mi.SetItem ("Batt temp comp   changes battery",  19, 1);
-    _items[19].push_back(mi);
-    mi.SetItem ("voltage reading  away from actual", 19, 2);
-    _items[19].push_back(mi);
-    mi.SetItem ("HBCO resets at:  6v/48, 3v/24 and", 19, 3);
-    _items[19].push_back(mi);
-    mi.SetItem ("1.5v/12v under   HBCO.",            19, 4);
-    _items[19].push_back(mi);
-    mi.SetItem ("LowBattTransfer  used in LBX, FLT", 19, 5);
-    _items[19].push_back(mi);
-    mi.SetItem ("Modes only. Goes back to battery",  19, 6);
-    _items[19].push_back(mi);
-    mi.SetItem ("at LowBattCutIn  (aka LBCI).",      19, 7);
-    _items[19].push_back(mi);
-    mi.SetItem ("For LBX mode set below LBCI so",    19, 8);
-    _items[19].push_back(mi);
-    mi.SetItem ("charger won't    cycle batteries",  19, 9);
-    _items[19].push_back(mi);
-    mi.SetItem ("up and down and  set LBCO below.",  19, 10);
-    _items[19].push_back(mi);
-  
-    // End of Setup - Menu Heading #20
-    mi.SetItem ("END SETUP MENU", 20);
-    _items[20].push_back(mi);
-}
-
-// Dump all the MenuItem data
-void
-XanbusUI::Dump (void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-
-    dbglogfile << "There are " << (int)_items.size() << " menu _items" << endl;
-
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            //it->Dump();
-            cout << it->GetHeaderIndex()
-                 << "," << it->GetItemIndex()
-                 << ": " << it->GetLabel() << endl;
-        }
-    }
-}
-
-void
-XanbusUI::DumpAliases (void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    string tmpstr;
-
-    cout << "Command Name\t\tMenu Item" << endl;
-    cout << "------------\t\t---------" << endl;
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            tmpstr = it->GetLabel();
-            if (it->GetAlias().size() > 0)
-                cout << it->GetAlias() << "  \t- " << CleanUpData(tmpstr) << 
endl;
-        }
-    }
-}
-
-MenuItem &
-XanbusUI::Match(string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    vector< MenuItem > arg;
-
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        arg = *mh;
-        for (it = arg.begin(); it != arg.end(); ++it) {
-            dbglogfile << "Matching \"" << it->GetAlias() << "\""
-                       << " against the argument \"" << str << "\"" << endl;
-            if (it->GetAlias() == str){
-                dbglogfile << "Matched " << it->GetLabel() << " !" << endl;
-                return *it;
-            }
-        }
-    }
-    // FIXME: this is a hack to set an error condition
-    str.erase();
-    return *it;
-}
-
-MenuItem &
-XanbusUI::GetItem(int x, int y)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    vector< MenuItem > arg;
-    string tmp;
-   
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            tmp = it->GetLabel();
-            if ((it->GetHeaderIndex() == x) && (it->GetItemIndex() == y)) {
-                return *it;
-            }
-        }
-    }
-
-    return *it;                  // FIXME: This probably isn't what we want
-}
-
-#if 0
-retcode_t
-XanbusUI::xantrex_main(Console &con);
-{
-
-#if 0
-    if (item.size() > 0) {
-        // See if the name is actually a specified index
-        if (item.find(":",0) != string::npos)
-            {
-                menuhead = atoi(item.substr(0, item.find(":",0)).c_str());
-                menuitem = atoi(item.substr(item.find(":",0) + 1, 2).c_str());
-            } else {
-            // lookup the alias to get the indexes
-            ti = ui.Match(item);
-            if (item.size() > 0) {
-                menuhead = ti->GetHeaderIndex();
-                menuitem = ti.GetItemIndex();
-            }
-        }
-    }
-#endif
-
-    // Go into console mode where we can type direct commands
-    // via the serial port. This just saves us from firing up
-    // kermit or minicom
-    if (console) {
-        Console con;
-        con.Open();
-        //ui.SetRaw();
-        while ((ch = con.Getc())!='q') {
-            if (ch > 0){             // If we have something, process it
-                if (echo)
-                    con.Putc (ch);          // echo inputted character to 
screen
-          
-                switch (ch) {
-                  case 'Q':
-                  case 'q':
-                      con.Reset();
-                      exit(0);
-                      break;
-                  case 'L':
-                      display = ui.MenuHeadingMinus();
-                      break;
-                  case 'R':
-                      display = ui.MenuHeadingPlus();
-                      break;
-                  case 'D':
-                      display = ui.MenuItemMinus();
-                      break;
-                  case 'U':
-                      display = ui.MenuItemPlus();
-                      break;
-                  case '+':
-                      display = ui.SetPointPlus();
-                      break;
-                  case '-':
-                      display = ui.SetPointMinus();
-                      break;
-                  case '|':
-                      display = ui.Inverter();
-                      break;
-                  case 'G':
-                      display = ui.Generator();
-                      break;
-                  case 'S':
-                      display = ui.SetupMenu();
-                      break;
-                  case 's':
-                      display = ui.GotoMenuStart();
-                      break;
-                  case '/':
-                      display = ui.LedStatus();
-                      break;
-                  case 'V':
-                      display = ui.Version();
-                      break;
-                  case 'T':
-                      display = ui.SetTerminalMode();
-                      break;
-                  case '?':
-                      con.Puts("PowerGuru - Xantrex mode\r\n");
-                      con.Puts("\t? - help\r\n");
-                      con.Puts("\tL - Menu Heading Minus\r\n");
-                      con.Puts("\tR - Menu Heading Plus\r\n");
-                      con.Puts("\tR - Menu Heading Plus\r\n");
-                      con.Puts("\tD - Menu Item Minus\r\n");
-                      con.Puts("\tU - Menu Item Plus\r\n");
-                      con.Puts("\t+ - Value Plus\r\n");
-                      con.Puts("\t- - Value Item Plus\r\n");
-
-                      con.Puts("\t| - Inverter Mode\r\n");
-                      con.Puts("\tG - Generator Mode\r\n");
-                      con.Puts("\tS - Setup Menu\r\n");
-                      con.Puts("\t/ - LED Status\r\n");
-                      con.Puts("\tV - Version\r\n");
-                      con.Puts("\tT - TerminalMode\r\n");
-                      con.Puts("\tQ - Quit\r\n");
-                  default:
-                      break;
-                };
-
-                //          display += "\r";
-                con.Putc('\r');
-                con.Puts(display);
-#if 0
-                switch (ui.GetDataType()) {
-                  case MenuItem::NONE:
-                  case MenuItem::MENUHEAD:
-                  case MenuItem::MENUITEM:
-                  case MenuItem::BOOL:
-                      if (ui.GetBoolValue() == false)
-                          dbglogfile << "\tBoolean value is: " << "OFF" ;
-                      else
-                          dbglogfile << "\tBoolean value is: " << "ON" ;      
-                      dbglogfile << endl;
-                      break;
-                  case MenuItem::INT:
-                      dbglogfile << "\tInteger value is: " << value.intval << 
endl;
-                      break;
-                  case MenuItem::FLOAT:
-                      cerr << "\tFIXME: Float value is: " << value.floatval << 
endl;
-                      break;
-                  case MenuItem::TIME:
-                      dbglogfile << "\tTime value is: " << value.timeval << 
endl;
-                      break;
-                  case MenuItem::EOL:
-                  case MenuItem::CLOCK:
-                  case MenuItem::ENUM:
-                  case MenuItem::DATE:
-                      dbglogfile << "\tFIXME: unsupported type! " << 
value.intval << endl;
-                      break;
-                  default:
-                      dbglogfile << "Data Type out of range";
-                      break;
-                };
-#endif
-            }
-
-            str += ui.ReadSerial();
-            if (str.size() > 0) {
-                con.Puts(str);
-                str.erase();
-            }
-        }
-    }
-    
-    // Get the value of a menu item
-    if (getitem){
-      
-        string str = ui.GotoMenuItem(menuhead, menuitem);
-        ti = ui.GetItem(menuhead, menuitem);
-        //    ui.Read((char *)&buffy, 100);
-        cerr << "Inverter returned: " << str << endl;
-
-        //      dbglogfile << "BREAK HERE" << endl;
-      
-        switch (ti.GetType()) {
-          case MenuItem::BOOL:
-              if (ui.GetBoolValue(str) == false)
-                  cout << "The Boolean value is: NO" << endl;
-              else
-                  cout << "The Boolean value is: YES" << endl;
-              break;
-          case MenuItem::INFO:
-              value = ui.GetValue(str);
-              cout << "The value is: " << value << endl;
-              break;
-          case MenuItem::INT:
-              intval = ui.GetIntValue(str);
-              cout << "The Integer value is: " << intval << endl;
-              break;
-          case MenuItem::FLOAT:
-              fltval= ui.GetFloatValue(str);
-              cout << "The Float value is: " << fltval << endl;
-              break;
-          case MenuItem::MENUHEAD:
-              cout << "The Menu Header is: " << "\"" <<
-                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-              break;
-          case MenuItem::MENUITEM:
-              cout << "The Menu Item is: " << "\"" <<
-                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-              break;
-          case MenuItem::TIME:
-              value = ui.GetValue(str);
-              cout << "The Time is: " << "\"" << value << endl;
-              break;
-          case MenuItem::EOL:
-              value = ui.GetValue(str);
-              cout << "The Time is: " << "\"" << value << endl;
-              break;
-          case MenuItem::CLOCK:
-              value = ui.GetValue(str);
-              cout << "The Clock value is: " << "\"" << value << endl;
-              break;
-          case MenuItem::ENUM:
-              value = ui.GetValue(str);
-              cout << "The Enum value is: " << "\"" << value << endl;
-              break;
-          case MenuItem::DATE:
-              value = ui.GetValue(str);
-              cout << "The Date is: " << "\"" << value << endl;
-              break;
-          default:
-              cout << "The value is: " << value << endl;
-              value = str;
-        };
-    } // endof getitem
-
-    // Monitor an item. This means grabs successive values and
-    // display them. This is for selections that constantly update
-    // the value.
-    if (monitor) {
-        string str = ui.GotoMenuItem(menuhead, menuitem);
-        ti = ui.GetItem(menuhead, menuitem);
-
-        cout << "The Menu Header is: " << "\"" <<
-            ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-      
-        do {
-            memset(buffy, 0, 100);        
-            ret = ui.Read((char *)&buffy, 100);
-            str = buffy;
-            if (ret < 0)            // there is no input yet, try again
-                continue;
-
-            // We got something, so extract the type, and process the
-            // value.
-            switch (ti.GetType()) {
-              case MenuItem::BOOL:
-                  if (ui.GetBoolValue(str) == false)
-                      cout << "\tThe Boolean value is: NO" << endl;
-                  else
-                      cout << "\tThe Boolean value is: YES" << endl;
-                  break;
-              case MenuItem::INFO:
-                  value = ui.GetValue(str);
-                  cout << "\tThe value is: " << value << endl;
-                  break;
-              case MenuItem::INT:
-                  intval = ui.GetIntValue(str);
-                  cout << "\tThe Integer value is: " << intval << endl;
-                  break;
-              case MenuItem::FLOAT:
-                  fltval= ui.GetFloatValue(str);
-                  cout << "\tThe Float value is: " << fltval << endl;
-                  break;
-              case MenuItem::MENUHEAD:
-                  cout << "\tThe Menu Header is: " << "\"" <<
-                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-                  break;
-              case MenuItem::MENUITEM:
-                  cout << "\tThe Menu Item is: " << "\"" <<
-                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-                  break;
-              default:
-                  cout << "\tThe value is: " << value << endl;
-                  value = str;
-            };
-        } while (ret); // endof monitor   
-    }
-}
-#endif
-
-meter_data_t *
-XanbusUI::exportMeterData(meter_data_t *data)
-{
-#if 0
-    // The unit number for the device
-    data->unit = _address;
-  
-    // The type of the device
-    switch (_type) {
-      case OUTBACK_MX:
-          data->type = MX_OUTBACK;
-          break;
-      case OUTBACK_FX:
-          data->type = FX_OUTBACK;
-          break;
-      case SW_XANTREX:
-      default:
-          break;
-    };
-  
-    // The amperage being put into the batteries
-    data->charge_amps = _charge_current;
-    // The load in amps
-    data->ac_load_amps = _inverter_current;
-    // Actual Battery Voltage
-    data->battery_volts = _battery_voltage;
-    // Battery Voltage temperature compensated. This isn't used by
-    // Outback products.
-    data->tempcomp_volts = 0;
-    // The voltage the inverter is producing
-    data->ac_volts_out = _AC_output_voltage;
-    // Grid AC input
-    data->ac1_volts_in = _AC_input_voltage;
-    // The AC current taken from the Grid and used to charge the batteries.
-    data->buy_amps = _buy_current;
-    // The AC current the batteries are putting into the grid.
-    data->sell_amps = _sell_current;
-    // The daily kilowatts put into the batteries from the PV source.
-    data->daily_kwh = _daily_kwh;
-    // The frequency in hertz. This doesn't exist on an Outback, but does on
-    // a Xantrex. It should always be 60 though, so we set it so other
-    // software can handle this  the same way.
-    data->hertz = 60;
-#endif
-
-    return data;
-}
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
diff --git a/lib/xanbus.h b/lib/xanbus.h
deleted file mode 100644
index a743866..0000000
--- a/lib/xanbus.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// 
-// Copyright (C) 2011 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifndef  __XANBUSUI_H__
-#define __XANBUSUI_H__
-
-#ifdef __cplusplus
-
-#include <string>
-#include <vector>
-#include <map>
-#include "err.h"
-#include <console.h>
-
-#include "serial.h"
-#include "menuitem.h"
-#include "database.h"
-
-class XanbusUI : public Serial
-{
-public:
-
-
-    
-    typedef enum {USERMENU, SETUPMENU} menu_e;
-    enum inverter_e {OFF, SRCH, ON, CHG};
-    enum invertsetup_e {FLOAT, SELL, SLT, LBX};
-    enum battery_e {NICAD, LEADACID, GEL};
-    enum genauto_e {UNINITIALIZED, RUNNING, IDLE};
-
-    typedef enum { XACCESS, ACCESS_QUERY, BACKLIGHT, CONT, CONT_QUERY,
-                   CUSTOM11_QUERY, CUSTOM12_QUERY, CUSTOM11ERASE,
-                   CUSTOM12ERASE, CUSTOM21, CUSTOM22, CUSTOM21_QUERY,
-                   CUSTOM22_QUERY, CUSTOM21ERASE, CUSTOM22ERASE,
-                   DCCOMPLEV_QUERY, DCDC_QUERY, DERATELIMIT_QUERY,
-                   ERR_QUERY, FAULTACTIVE_QUERY, FAULTGND_QUERY,
-                   FAULTLAST_QUERY, FAULTLOG_QUERY, FREQ_QUERY,
-                   FWHW_QUERY, IDN_QUERY, IIN_QUERY, INV_QUERY,
-                   IOUT_QUERY, KNOCK, KWHLIFE_QUERY, KWHLIFESYS_QUERY,
-                   KWHTODAY_QUERY, KWHTODAYSYS_QUERY, XKWHTODAY_QUERY,
-                   MEASENGY_QUERY, MEASENGYSYS_QUERY, MEASICMM_QUERY,
-                   MEASIN_QUERY, MEASOUT_QUERY, MEASRAW_QUERY, MEASTEMP_QUERY,
-                   MEMFREE_QUERY, MODELID_QUERY, MODELSTR_QUERY, 
MONPARAM_QUERY,
-                   MONALL_QUERY, MONAUXPARAM_QUERY, MONENS_QUERY,
-                   MONENSPARAM_QUERY, MONEXT_QUERY, MONEXTPARAM_QUERY,
-                   MONFB_QUERY, MONFBPARAM_QUERY, MONGND_QUERY,
-                   MONGNDPARAM_QUERY, MONGRID_QUERY, MONGRIDPARAM_QUERY,
-                   MONTEMP_QUERY, MONTEMPPARAM_QUERY, MONOVPARAM_QUERY,
-                   MONUVPARAM_QUERY, MONVIN_QUERY, MPPT_QUERY,
-                   MPPTDBG_QUERY, MPPTLEV_QUERY, MPPTLEVM_QUERY,
-                   MPPTOFFSET_QUERY, MPPTSTAT_QUERY, NVMEMSPACE_QUERY,
-                   OFFSET_QUERY, OLDERLIM_QUERY, PDCMPPT_QUERY, PIN_QUERY,
-                   POUT_QUERY, POUTSYS_QUERY, PROD_QUERY, POWLIMIT_QUERY,
-                   POWSEQ_QUERY, POWSEQCLR, QUEUED_QUERY, RECTIME_QUERY,
-                   RELAY_QUERY, RIPCOMP_QUERY, ROM_QUERY, SCALE_QUERY,
-                   SCID_QUERY, SCROLL, STANDBY, STANDBY_QUERY, TEMPLIMIT_QUERY,
-                   TEMPLIMITSTEP_QUERY, TIME_QUERY, VDCREF_QUERY, VIN_QUERY,
-                   XBADX_QUERY
-    } xanbus_command_e;
-
-
-    typedef struct {
-        xanbus_command_e type;
-        std::string      command;
-        bool             query;
-    } cmd_data_t;
-    
-    XanbusUI(void);
-    ~XanbusUI(void);
-    
-    // Dump all internal data to the console
-    void Dump (void);
-    void DumpAliases(void);
-    
-    // This selects which inverter we want to control
-    std::string &SelectInverter(int x);
-    
-    // Read from the serial port
-    std::string &ReadSerial(void);
-    
-    // Write to the serial port
-    std::string &WriteSerial(const char *buf, int nbytes);
-    
-    // These methods all go with the Xantrex display buttons
-    std::string &MenuHeadingMinus(void);
-    std::string &MenuHeadingPlus(void);
-    std::string &MenuItemMinus(void);
-    std::string &MenuItemPlus(void);
-    std::string &SetPointMinus(void);
-    std::string &SetPointPlus(void);
-    std::string &Inverter(void);
-    std::string &Generator(void);
-    std::string &SetupMenu(void);
-    std::string &LedStatus(void);
-    std::string &Version(void);
-    std::string &SetTerminalMode(void);
-    
-    std::vector<meter_data_t *> PollMeters(int loops);
-    //std::map<std::string, float> *PollMeters(int loops);
-    
-    // This method takes the data as outputted by the Xantrex inverter,
-    // and munges it to be a standard form with whitespace compressed,
-    // newlines & carriage returns stripped out, etc... This is so
-    // we can analyse the string data in a consistant fashion.
-    std::string &CleanUpData(std::string &str);
-    
-    meter_data_t *exportMeterData(meter_data_t *data);
-    
-#if 0
-    std::string &UserMenu(void);
-    // These methods are for switching menu modes
-  retcode_t GotoSetupMenu(void);
-    retcode_t GotoUserMenu(void);
-#endif
-    // This method takes us to the beginning of the menu headers and items
-    // This corresponds then to being in the Inverter Mode header of the
-    // User menu.
-    retcode_t GotoMenuStart(void);
-    std::string &GotoMenuItem(int mh, int mi);
-    
-    // These methods manipulate values
-    std::string &GetValue (std::string &x);
-    std::vector<std::string> *GetValues (std::string &str);
-    retcode_t SetFloatValue(float x);
-    float GetFloatValue(std::string &x);
-    retcode_t SetIntValue(int x);
-    int GetIntValue(std::string &x);
-    retcode_t SetBoolValue(bool x);
-    bool GetBoolValue(std::string &x);
-    std::string GetLabel(std::string &x);
-    // This method populates the menu item data to default values as per
-    // the Xantrex manual.
-    void SetDefaultValues (void);
-    
-    // This method tries to match the display with a menu item
-    // to verify we're where we think we are...
-    MenuItem &Match(std::string &str);
-    MenuItem &GetItem(int x, int y);
-    MenuItem &GetItem() { return GetItem(menuheading, menuitem); }
-    std::string GetLabel();
-    
-    retcode_t xantrex_main(Console& con);
- private:
-    std::vector< std::vector< MenuItem > > _items;
-    int menuheading;
-    int menuitem;
-    //  Serial uart;  
-};
-
-extern "C" {
-#else
-    
-    // Default object for C code. 
-    XanbusUI ui;
-    
-    /* This is the C API for this class. */
-    
-    const char *menu_heading_minus(void);
-    const char *menu_heading_plus(void);
-    const char *menu_item_minus(void);
-    const char *menu_item_mlus(void);
-    const char *set_point_minus(void);
-    const char *set_point_plus(void);
-    
-    const char *inverter(void);
-    const char *generator(void);
-    const char *setup_menu(void);
-    const char *led_status(void);
-    const char *version(void);
-    const char *set_terminal_mode(void);
-    
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-// end of __XANBUSUI_H__
-#endif
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
-
diff --git a/lib/xantrex-trace.cc b/lib/xantrex-trace.cc
deleted file mode 100644
index bb746a8..0000000
--- a/lib/xantrex-trace.cc
+++ /dev/null
@@ -1,1586 +0,0 @@
-// 
-// Copyright (C) 2005, 2006 - 2018
-//      Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "err.h"
-#include "log.h"
-#include "console.h"
-#include "xantrex-trace.h"
-#include "database.h"
-
-using namespace std;
-
-static std::string menudisp;
-static char buffy[100];
-
-extern LogFile dbglogfile;
-
-XantrexUI::XantrexUI(void)
-{
-    SetDefaultValues();  
-}
-
-XantrexUI::~XantrexUI(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-string &
-XantrexUI::ReadSerial(void)
-{
-    int ret;
-    //DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-
-#if 0 
-    int retries = 1;
-  
-    while (retries--) {
-        if (ret = Read((char *)&buffy, 99) < 0) {
-            //dbglogfile << "FIXME: " << retries << "\t" << buffy << endl;
-            //ret = Read((char *)&buffy, 100);
-            continue;
-        } else {
-            break;
-        }
-    }
-#else
-    ret = Read((char *)&buffy, 100);
-#endif
-  
-    if (ret > 0) {
-        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buffy << "\t" 
<< buffy << endl;
-        menudisp = buffy;
-    } else {
-        menudisp.erase();
-    }
-  
-    return menudisp;
-}
-
-string
-XantrexUI::GetLabel() {
-    //DEBUGLOG_REPORT_FUNCTION;
-
-    dbglogfile << "menuheading: " << menuheading << " menuitem:" << menuitem 
<< endl;
-  
-    MenuItem ti = GetItem(menuheading, menuitem);
-  
-    return ti.GetLabel();
-}
-
-string &
-XantrexUI::WriteSerial(const char *buf, int nbytes)
-{
-    int ret;
-  
-    //DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    ret = Write(buf, nbytes);
-    //dbglogfile << "FIXME" << buffy << endl;
-    ret = Read(buffy, nbytes);
-  
-    menudisp = buffy;
-    return menudisp;
-}
-
-// This selects which inverter we want to control
-string &
-XantrexUI::SelectInverter(int x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-
-    Write((char *)&x, 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-// These methods all go with the Xantrex display buttons
-string &
-XantrexUI::MenuHeadingMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    //memset(buffy, 0, 100);
-  
-    Write("L", 1);
-    //Read((char *)&buffy, 100);
-    menudisp = ReadSerial();
-    //dbglogfile << "FIXME" << menudisp << endl;
-
-    //cerr << "FIXMEh-: \"" << menudisp  << "\"" << endl;
-    //cerr << "FIXMEh-: \"" << GetLabel() << "\"" << endl;
-
-    if (menuheading > 1) {
-        menuheading--;
-    }
-    menuitem = 0;
-
-    if (menudisp.find(GetLabel()) == string::npos) {
-        dbglogfile << "Heading Minus didn't Match!!" << menuheading << endl;  
-    } else {
-        dbglogfile << "Heading Minus Matched!!" << endl;
-    }
-
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::MenuHeadingPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    //memset(buffy, 0, 100);
-    MenuItem mi;
-  
-    Write("R", 1);
-  
-    //Read((char *)&buffy, 100);
-    menudisp = ReadSerial();
-    //mi = GetItem();
-
-    //dbglogfile << menudisp << endl;
-
-    menuheading++;
-    menuitem = 0;
-
-    //cerr << "FIXMEh+: \"" << menudisp  << "\"" << endl;
-    //cerr << "FIXMEh+: \"" << GetLabel() << "\"" << endl;
-  
-    if (menudisp.find(GetLabel()) == string::npos) {
-        dbglogfile << "Heading Plus didn't Match!!" << endl;  
-    } else {
-        dbglogfile << "Heading Plus Matched!!" << endl;
-    }
-
-
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-// This decends through the sub menu items of a heading
-string &
-XantrexUI::MenuItemMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int retries = 5;
-    string label;
-  
-    //memset(buffy, 0, 100);
-  
-    //Write("D", 1);
-    //Read((char *)&buffy, 100);
-    //menudisp = ReadSerial();
-    //dbglogfile << menudisp << endl;
-
-    menuitem++;
-
-    //cerr << "FIXME-I: \"" << menuheading << "," << menuitem << "\"" << endl;
-    while (retries--) {
-        Write("D", 1);
-        menudisp = ReadSerial();
-        //Flush();
-        //cerr << "FIXMEi-: \"" << menudisp  << "\"" << endl;
-        //cerr << "FIXMEi-: \"" << GetLabel() << "\"" << endl;
-
-        label = GetLabel();
-        if (label.size()) {
-            if (menudisp.find(label) == string::npos) {
-                dbglogfile << "Item Minus didn't Match!!" << endl;
-            } else {
-                dbglogfile << "Item Minus Matched!!" << endl;
-                break;
-            }
-        }
-    }
-
-    //menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::MenuItemPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int retries = 5;
-
-    //memset(buffy, 0, 100);
-  
-    //Write("U", 1);
-    //Read((char *)&buffy, 100);
-    //menudisp = ReadSerial();
-    //dbglogfile << menudisp << endl;
-    //menudisp = buffy;
-    if (menuitem > 1)
-        menuitem--;
-
-    //  if (strcmp(label.c_str(), buffy) == 0)
-    //    dbglogfile << "AAAAHHHHHHH" << endl;
-  
-    while (retries--) {
-        Write("U", 1);
-        menudisp = ReadSerial();
-        //Flush();
-
-        //cerr << "FIXMEi+: \"" << menudisp  << "\"" << endl;
-        //cerr << "FIXMEi+: \"" << GetLabel() << "\"" << endl;
-
-        if (menudisp.find(GetLabel()) == string::npos) {
-            dbglogfile << "Item Plus didn't Match!!" << endl;
-        } else {
-            dbglogfile << "Item Plus Matched!!" << endl;
-            break;
-        }
-    }
-
-    //  if (menudisp != label)
-    //  dbglogfile << "FIXME: Wrong Item " << menuheading << ":" << menuitem 
<< menudisp << "\t" << label << endl;
-    
-    return menudisp;
-}
-
-string &
-XantrexUI::SetPointMinus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("-", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::SetPointPlus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("+", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::Inverter(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("|", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::Generator(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("G", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::SetupMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("\003", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menuheading = 8;
-    menuitem = 0;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::LedStatus(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("?", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;  
-}
-
-string &
-XantrexUI::Version(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("V", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-string &
-XantrexUI::SetTerminalMode(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    memset(buffy, 0, 100);
-  
-    Write("T", 1);
-    Read((char *)&buffy, 100);
-    dbglogfile << buffy << endl;
-
-    menudisp = buffy;
-    return menudisp;
-}
-
-#if 0
-// These methods are for switching menu modes
-retcode_t
-XantrexUI::GotoSetupMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-retcode_t
-XantrexUI::GotoUserMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-string &
-XantrexUI::UserMenu(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-}
-
-#endif
-
-// This method takes us to the beginning of the menu headers and items
-// This corresponds then to being in the Inverter Mode header of the
-// User menu.
-retcode_t
-XantrexUI::GotoMenuStart(void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    int i;
-    for (i=0; i<22; i++) {
-        // Don't use MenuheadingMinus, as it gets all confused
-        Write("L", 1);
-        menudisp = ReadSerial();
-        if (menudisp.find("Inverter", 0) != string::npos) {
-            break;
-        }
-    }
-  
-    menuheading = 1;
-    menuitem = 0;
-    dbglogfile << "At Start Of Menu" << endl;
-  
-    return SUCCESS;
-}
-
-// These methods manipulate values
-retcode_t
-XantrexUI::SetFloatValue(float )
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    cerr << "ERROR: unimplemented!" << endl;
-    return ERROR;
-}
-
-float
-XantrexUI::GetFloatValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    return atof(GetValue(str).c_str());
-}
-
-retcode_t
-XantrexUI::SetIntValue(int x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    cerr << "ERROR: unimplemented!" << endl;
-    return ERROR;
-}
-
-int
-XantrexUI::GetIntValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    return atoi(GetValue(str).c_str());
-}
-
-bool
-XantrexUI::GetBoolValue(std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    string tmpstr = GetValue(str).c_str();
-  
-    if (tmpstr == "NO" || tmpstr == "OFF")
-        return false;
-    else
-        return true;
-}
-
-string &
-XantrexUI::GetValue (std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos, pos2;
-    //string value;
-    int i = 0;
-    string lookfor;
-
-    //cout << "The Raw value string is: " << str << endl;
-
-#if 0
-    pos = str.find("-00", str.length());
-    if (pos != string::npos) {
-        str.erase(pos, str.length() - pos);
-    }
-#endif
-  
-    do {
-        lookfor = " ";
-        char j = '0' + i;
-        lookfor += j;
-        pos = str.find(lookfor, 0);
-        lookfor.erase();
-    } while ((pos == string::npos) && (i++ < 10));
-  
-    pos2 = str.find(' ', pos+1);
-    if (pos2 == string::npos) {
-        pos2 = pos + 4;
-    }
-  
-    str = str.substr(pos+1, pos2 - pos);
-
-#if 0
-    if (pos != string::npos) {
-        // We want just the last data item, which is the value
-        value = str.substr(pos+1, str.length() - pos);
-        str = value;
-    } else {
-        str.erase();
-    }
-#endif
-  
-    return str;
-}
-
-vector<string> *
-XantrexUI::GetValues (std::string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos;
-    string value;
-    vector<string> *array;
-
-    array = new vector<string>;
-
-    //cout << "The Raw values string is: " << str << endl;
-
-    do {
-        pos = str.find("-00", str.length());
-        if (pos != string::npos) {
-            str.erase(pos, str.length() - pos);
-        }
-    
-        // Find the last space in the string
-        pos = str.rfind(' ' , str.length());
-    
-        if (pos != string::npos) {
-            // We want just the last data item, which is the value
-            value = str.substr(pos+1, str.length() - pos);
-            str = value;
-            array->push_back(value);
-        } else {
-            str.erase();
-        }
-    } while (pos != string::npos);
-  
-  
-    return array;
-}
-
-std::string
-XantrexUI::GetLabel(std::string &x)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string::size_type pos;
-
-    // Find the last space in the string
-    pos = x.rfind(' ' , x.length());
-    //pos = x.rfind('\t' , x.length());
-
-    if (pos != string::npos) {
-        return x.substr(0, pos);
-    }
-  
-    return x;
-}
-
-
-string &
-XantrexUI::GotoMenuItem(int mh, int mi)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    string tmpstr;
-    int i;
-    MenuItem item;
-  
-    GotoMenuStart();
-
-    item = GetItem(mh, mi);
-    for (i=0; i < mh-1; i++) {
-        menudisp = MenuHeadingPlus();
-    }
-  
-    for (i=0; i < mi-1; i++) {
-        menudisp = MenuItemMinus();
-    }
-
-    if (menudisp.find(item.GetLabel()) != string::npos) {
-        dbglogfile << "Didn't Match!!" << endl;  
-    }
-
-    //menudisp = CleanUpData(tmpstr);
-  
-    menuheading = mh;
-    menuitem = mi;
-
-    return menudisp;
-}
-
-//std::map<std::string, float> *
-//std::vector< std::map< std::string, float > >
-vector<meter_data_t *>
-XantrexUI::PollMeters(int loops)
-{
-    MenuItem      ti;
-    int           mh = 4;
-    int           mi = 1;
-    int           items = 7;                // the number of data items to get
-    float         fltval;
-    int           intval;
-    int           i;
-    string        str, label;
-    meter_data_t *downdata, *updata;
-    vector<meter_data_t *> meters;
-
-    //memset(buffy, 0, 100);
-
-    GotoMenuItem(mh, mi);
-    while (loops-- > 0) {
-        downdata = new meter_data_t;
-        memset(downdata, 0, sizeof(meter_data_t));
-    
-        for (i=mi; i<= mi+items; i++) {
-            str = MenuItemMinus();
-            fltval = 0.0;
-            intval = 0;
-            if (str.size() > 1) {
-                ti = GetItem();
-                if (ti.GetType() != MenuItem::INFO) {
-                    label = GetLabel(); 
-                    cout << "The Menu Item Label down is: " << label;
-                }
-                ti = GetItem();
-                if (ti.GetType() == MenuItem::FLOAT) {
-                    fltval = GetFloatValue(str);
-                    cout << ", with a float value is: " << fltval << endl;
-                }
-                if (ti.GetType() == MenuItem::INT) {
-                    intval = GetIntValue(str);
-                    cout << ", with an Integer value is: " << intval << endl;
-                }
-                if (ti.GetType() == MenuItem::INFO) {
-                    cout << ", an INFO statement  " << endl;
-                    break;
-                }
-                if (label.substr(0, 5) == "Input") {
-                    //downdata->
-                }
-                if (label.substr(0, 4) == "Load") {
-                    dbglogfile << "Matched label going down " << label;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->ac_load_amps = intval;
-                }
-                if (label.substr(8, 6) == "actual") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->battery_volts = fltval;
-                }
-                if (label.substr(8, 8) == "TempComp") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->tempcomp_volts = fltval;
-                }
-                if (label.substr(0, 8) == "Inverter") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->ac_volts_out = intval;
-                }
-                if (label.substr(0, 4) == "Grid") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->ac1_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Generator") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    downdata->ac2_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Read Freq") {
-                    dbglogfile << "Matched label going down " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    downdata->hertz = intval;
-                }
-            }
-        }
-
-        meters.push_back(downdata);
-        //MenuItemMinus();            // go one more, since the first thing
-        // we do is come back up one item.
-        updata = new meter_data_t;
-        memset(updata, 0, sizeof(meter_data_t));
-        //ptr2 = (float *)((char *)updata + 
sizeof(meter_data_t)-sizeof(float));
-        //*ptr2-- = downdata->hertz;
-    
-        // Now go up through the menu
-        for (i=mi+items; i>mi; i--) {
-            str = MenuItemPlus();
-            fltval = 0.0;
-            intval = 0;
-            if (str.size() > 0) {
-                label = GetLabel(); 
-                cout << "The Menu Item Label up is: " << label;
-                ti = GetItem();
-                if (ti.GetType() == MenuItem::FLOAT) {
-                    fltval = GetFloatValue(str);
-                    cout << ", with a float value is: " << fltval << endl;
-                }
-                if (ti.GetType() == MenuItem::INT) {
-                    intval = GetIntValue(str);
-                    cout << ", with an integer value is: " << intval << endl;
-                }
-                //Flush();
-                //_data.push(label, );
-                if (label.substr(0, 5) == "Input") {
-                    //updata->
-                }
-                if (label.substr(0, 4) == "Load ") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    updata->ac_load_amps = intval;
-                }
-                if (label.substr(8, 6) == "actual") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->battery_volts = fltval;
-                }
-                if (label.substr(8, 8) == "TempComp") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->tempcomp_volts = fltval;
-                }
-                if (label.substr(0, 8) == "Inverter") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << intval << endl;
-                    updata->ac_volts_out = intval;
-                }
-                if (label.substr(0, 4) == "Grid") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->ac1_volts_in = fltval;
-                }
-                if (label.substr(0, 9) == "Generator") {
-                    dbglogfile << "Matched label going up " << label << endl;
-                    dbglogfile << " value is: " << fltval << endl;
-                    updata->ac2_volts_in = fltval;
-                }
-                // Since this is the last and first reading, it doesn't really
-                // have time to change.
-                updata->hertz = downdata->hertz;
-//         if (label.substr(0, 9) == "Read Freq") {
-//           dbglogfile << "Matched label going up " << label << endl;
-//           dbglogfile << " value is: " << intval << endl;
-//           updata->hertz = intval;
-//         }
-            } // end of if str
-        } // end of for loop
-        meters.push_back(updata);
-    }
-    // Go back to the top
-//   for (i=items; i>=mi; i--) {
-//     MenuItemPlus();
-//   }
-  
-    MenuHeadingPlus();
-    MenuHeadingMinus();          
-  
-    return meters;
-}
-
-// This method takes the data as outputted by the Xantrex inverter,
-// and munges it to be a standard form with whitespace compressed,
-// newlines & carriage returns stripped out, etc... This is so
-// we can analyse the string data in a consistant fashion.
-std::string &
-XantrexUI::CleanUpData(std::string &str)
-{
-    unsigned int i;
-
-    menudisp.erase();
-    for (i=0; i< str.length(); i++) {
-        switch (str[i]) {
-            // we ignore these characters
-          case '\r':
-          case '\n':
-              break;
-              // compress multiple spaces to be just one
-          case ' ':
-              if (str[i+1] == ' ') {
-                  continue;
-              } else {
-                  menudisp += ' ';
-                  break;
-              }
-          default:
-              menudisp += str[i];
-        }
-    }
-
-    return menudisp;
-}
-
-void
-XantrexUI::SetDefaultValues(void)
-{
-
-    MenuItem mi;
-
-    // We know we always have 20 major menu headings
-    _items.resize(21);
-
-    mi.SetItem ("Top of Menu", 0);
-    _items[0].push_back(mi);
-
-    // Inverter Mode - Menu Heading #1
-    mi.SetItem ("Inverter Mode",                      1);
-    _items[1].push_back(mi);
-
-    mi.SetItem ("Set Inverter     OFF SRCH ON CHG",   1, 1, "SetVert"); // 
FIXME: enum
-    _items[1].push_back(mi);
-    mi.SetItem ("CHG avail. Only  in FLT mode",       1, 2);
-    _items[1].push_back(mi);
-    mi.SetItem ("Press red or     setpoint button",   1, 3);
-    _items[1].push_back(mi);
-    mi.SetItem ("to move.         Move cursor to",    1, 4);
-    _items[1].push_back(mi);
-    mi.SetItem ("Inverter OFF to  resetOverCurrent",  1, 5);
-    _items[1].push_back(mi);
-
-    // Generator Mode - Menu Headings #2
-    mi.SetItem ("Generator Mode",                     2);
-    _items[2].push_back(mi);
-    mi.SetItem ("Set Generator    OFF AUTO ON EQ",    2, 1, "SetGen"); // 
FIXME: enum
-    _items[2].push_back(mi);
-    mi.SetItem ("Gen under/over   speed",             2, 2, false, "GenSpeed");
-    _items[2].push_back(mi);  
-    mi.SetItem ("Generator start  error",             2, 3, false, "GenStart");
-    _items[2].push_back(mi);
-    mi.SetItem ("Generator sync   error",             2, 4, false, "GenSync");
-    _items[2].push_back(mi);
-    mi.SetItem ("Gen max run Time error",             2, 5, false, "GenMax");
-    _items[2].push_back(mi);
-    mi.SetItem ("Load Amp Start   ready",             2, 6, false, "LoadAmp");
-    _items[2].push_back(mi);
-    mi.SetItem ("Voltage Start    ready",             2, 7, false, 
"VoltStart");
-    _items[2].push_back(mi);
-    mi.SetItem ("Exercise Start   ready",             2, 8, false, 
"ExerStart");
-    _items[2].push_back(mi);
-  
-    // Xantrex Engineering - Menu Heading #3
-    // Xantrex was Trace, so this prompt varies depending on the
-    // software version on the inverter.
-    mi.SetItem ("Engineering",       3);
-    //mi.SetItem ("Trace            Engineering",       3);
-    _items[3].push_back(mi);
-    mi.SetItem ("Press reset now  for defaults",      3, 1);
-    _items[3].push_back(mi);
-    mi.SetItem ("Revision 4.01",                      3, 2, "XantrexRev");
-    _items[3].push_back(mi);
-    mi.SetItem ("5916 195th St NE Arlington, WA",     3, 3);
-    _items[3].push_back(mi);
-    mi.SetItem ("98223 USA",                          3, 4);
-    _items[3].push_back(mi);
-    mi.SetItem ("Ph  360-435-8826 Fax 360-435-2229",  3, 5);
-    _items[3].push_back(mi);
-
-    // Meters - Menu Heading #4
-    mi.SetItem ("Meters",                         4);
-    _items[4].push_back(mi);
-    mi.SetItem ("Inverter/charger amps AC",         4,  1, 0, "ChargerAmps");
-    _items[4].push_back(mi);
-    mi.SetItem ("Input            amps AC",         4,  2, 0, "InputAmps");
-    //mi.SetItem ("Input",                           4,  2, 0, "InputAmps");
-    _items[4].push_back(mi);
-    mi.SetItem ("Load             amps AC",         4,  3, 0, "LoadAmps");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Battery actual",                   4,  4, (float)25.1, 
"BattVolts");
-    mi.SetItem ("Battery actual   volts DC",        4,  4, (float)25.1, 
"BattVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Battery TempComp",                4,  5, (float)25.1, 
"TempComp");
-    mi.SetItem ("Battery TempComp volts DC",        4,  5, (float)25.1, 
"TempComp");
-    _items[4].push_back(mi);
-    mi.SetItem ("Inverter         volts AC",        4,  6, 0, "InvertVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Grid (AC1)",                       4,  7, 0, "GridVolts");
-    mi.SetItem ("Grid (AC1)       volts AC",                             4,  
7, 0, "GridVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Generator (AC2)",                  4,  8, 0, "GenVolts");
-    mi.SetItem ("Generator (AC2)  volts AC",                             4,  
8, 0, "GenVolts");
-    _items[4].push_back(mi);
-    //mi.SetItem ("Read Frequency",                   4,  9, 0, "ReadHertz");
-    mi.SetItem ("Read Frequency   Hertz",                           4,  9, 0, 
"ReadHertz");
-    _items[4].push_back(mi);
-    mi.SetItem ("AC1 & AC2 volts  valid only when", 4, 10);
-    _items[4].push_back(mi);
-    mi.SetItem ("inverter synced  to that input.",  4, 11);
-    _items[4].push_back(mi);
-    mi.SetItem ("Batt volt actual is used for",     4, 12);
-    _items[4].push_back(mi);
-    mi.SetItem ("LBCO,HBCO,LBX,   LBCI,sell volts", 4, 13);
-    _items[4].push_back(mi);
-    mi.SetItem ("and gen starting",                 4, 14);
-    _items[4].push_back(mi);
-    mi.SetItem ("Batt volt temp   comp is used,",   4, 15);
-    _items[4].push_back(mi);
-    mi.SetItem ("for float, bulk, eq & aux relays", 4, 16);
-    _items[4].push_back(mi);
-  
-    // Error Cause - Menu Heading #5
-    mi.SetItem ("Error Causes",                 5);
-    _items[5].push_back(mi);
-    mi.SetItem ("Over Current",                 5,  1, false, "OverCurrent");
-    _items[5].push_back(mi);
-    mi.SetItem ("Transformer      overtemp",    5,  2, false, "OverTemp");
-    _items[5].push_back(mi);
-    mi.SetItem ("Heatsink         overtemp",    5,  3, false, "HeatSink");
-    _items[5].push_back(mi);
-    mi.SetItem ("High Battery     voltage",     5,  4, false, "HighBatt");
-    _items[5].push_back(mi);
-    mi.SetItem ("Low Battery      voltage",     5,  5, false, "LowBatt");
-    _items[5].push_back(mi);
-    mi.SetItem ("Inverter breaker tripped",     5,  6, false, "Tripped");
-    _items[5].push_back(mi);
-    mi.SetItem ("Manual Off",                   5,  7, false, "ManualOff");
-    _items[5].push_back(mi);
-    mi.SetItem ("AC source wired  to output",   5,  8, false, "ACWired");
-    _items[5].push_back(mi);
-    mi.SetItem ("External error   (Stacked)",   5,  9, false, "ExtError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Generator start  error",       5, 10, false, "GenError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Generator sync   error",       5, 11, false, "SyncError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Gen maximum run  time error",  5, 12, false, "MaxRunError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Gen Under/Over   speed",       5, 13, false, "SpeedError");
-    _items[5].push_back(mi);
-    mi.SetItem ("Inverter breaker tripped",     5, 14, false, "BreakerError");
-    _items[5].push_back(mi);
-  
-    // Time Of Day - Menu Heading #6
-    mi.SetItem ("Time of Day",                 6);
-    _items[6].push_back(mi);
-    mi.SetItem ("Time of Day      Set Clock hour", 6, 1, 0);
-    _items[6].push_back(mi);
-    mi.SetItem ("Set Clock minute",            6, 2, 0, "Minute");
-    _items[6].push_back(mi);
-    mi.SetItem ("Set Clock second",            6, 3, 0, "Second");
-    _items[6].push_back(mi);
-
-    // Generator timer - Menu Heading #7
-    mi.SetItem ("Generator Timer",           7);
-    _items[7].push_back(mi);
-    mi.SetItem ("Start Quiet      time h:m", 7, 1, 8 ); // FIXME: this should 
be a time
-    _items[7].push_back(mi);  
-    mi.SetItem ("End Quiet        time h:m", 7, 2, 8 ); // FIXME: this should 
be a time
-    _items[7].push_back(mi);
-
-    // End of User menus!
-    mi.SetItem ("END USER MENU", 8);
-    _items[8].push_back(mi);
-
-    // Inverter Setup - Menu heading #9
-    mi.SetItem ("Inverter Setup",               9);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Grid Usage",               9, 1); // FIXME: FLOAT
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Low battery  cut out VDC", 9, 2, (float)22.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set LBCO delay   minutes",     9, 3, 15);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set Low battery  cut in VDC",  9, 4, (float)26.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set High battery cut out VDC", 9, 5, (float)32.0);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set search       watts",       9, 6, 48);
-    _items[9].push_back(mi);
-    mi.SetItem ("Set search       spacing",     9, 7, 59);
-    _items[9].push_back(mi);
-
-    // Battery Charging - Menu heading #10
-    mi.SetItem ("Battery Charging",                10);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Bulk         volts DC",       10, 1, (float)28.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Absorption   time h:m",       10, 2, 2);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Float        volts DC",       10, 3, (float)26.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Equalize     volts DC",       10, 4, (float)28.8);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Equalize     time h:m",       10, 5, 2);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Max Charge   amps DC",        10, 6, 30);
-    _items[10].push_back(mi);
-    mi.SetItem ("Set Temp Comp    LeadAcid Nicad", 10, 7); // FIXME: LEADACID
-    _items[10].push_back(mi);
-
-    // AC Inputs - Menu heading #11
-    mi.SetItem ("AC Inputs",                       11);
-    _items[11].push_back(mi);
-    mi.SetItem ("inverter synced  to that input.", 11);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Grid (AC1)   amps AC",        11, 1, 60);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Gen (AC2)    amps AC",        11, 2, 30);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Input lower  limit VAC",      11, 3, 108);
-    _items[11].push_back(mi);
-    mi.SetItem ("Set Input upper  limit VAC",      11, 4, 132);
-    _items[11].push_back(mi);
-
-    // Generator Auto Start Setup - Menu heading #12
-    //  genauto.state = OFF;
-    mi.SetItem ("Gen Auto Start   setup",           12);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Start   amps AC",         12, 1, 33);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Start   delay min",       12, 2, 5);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Load Stop    delay min",       12, 3, 5);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 24 hr start  volts DC",        12, 4, (float)24.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 2 hr start   volts DC",        12, 5, (float)23.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set 15 min start volts DC",        12, 6, (float)22.6);
-    _items[12].push_back(mi);
-    mi.SetItem ("Read LBCO 30 sec start VDC",       12, 7, 22);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Exercise     period days",     12, 8, 30);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Maximum run  time h:m",        12, 9, 8);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Max Run time to 0 to defeat.", 12, 10, 0);
-    _items[12].push_back(mi);
-    mi.SetItem ("Set Exercise to 0 to defeat.",     12, 11, 0);
-    _items[12].push_back(mi);
-    mi.SetItem ("See menu 9 to    to set LBCO.",    12, 12, 0);
-    _items[12].push_back(mi);
-
-    //Generator Starting Details - Menu heading #13
-    mi.SetItem ("Gen starting     details",      13);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set RY7 Function GlowStop Run", 13, 1, 0);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Gen warmup   seconds",      13, 2, 60);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Pre Crank    seconds",      13, 3, 10);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Max Cranking seconds",      13, 4, 10);
-    _items[13].push_back(mi);
-    mi.SetItem ("Set Post Crank   seconds",      13, 5, 30);
-    _items[13].push_back(mi);
-
-    // Auxilary relays - Menu heading #14
-    mi.SetItem ("Auxiliary Relays R9 R10 R11", 14);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 9      volts DC",       14, 1, 29);
-    _items[14].push_back(mi);
-    mi.SetItem ("R9 Hysteresis    volts DC",       14, 2, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 10     volts DC",       14, 3, (float)29.5);
-    _items[14].push_back(mi);
-    mi.SetItem ("R10 Hysteresis   volts DC",       14, 4, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Set Relay 11     volts DC",       14, 5, 30);
-    _items[14].push_back(mi);
-    mi.SetItem ("R11 Hysteresis   volts DC",       14, 6, 2);
-    _items[14].push_back(mi);
-    mi.SetItem ("Close on batt >  setpoint.",      14, 7);
-    _items[14].push_back(mi);
-    mi.SetItem ("Open  on  batt < setpoint - Hys", 14, 8);
-    _items[14].push_back(mi);
-    mi.SetItem ("Relays have 2    second delay on",14, 9);
-    _items[14].push_back(mi);
-    mi.SetItem ("Close, 0.1 sec   delay on open",  14, 10);
-    _items[14].push_back(mi);
-
-    // Bulk Charge Trigger Time - Menu heading #15
-    mi.SetItem ("Bulk Charge      Trigger Timer",   15);
-    _items[15].push_back(mi);              
-    mi.SetItem ("Set Start Bulk   time",            15, 1, 0);
-    _items[15].push_back(mi);              
-    mi.SetItem ("To disable timer set to 00:00",    15, 2);
-    _items[15].push_back(mi);              
-    mi.SetItem ("If grid timer    active set bulk", 15, 3);
-    _items[15].push_back(mi);              
-    mi.SetItem ("time after start charge time.",    15, 4);
-    _items[15].push_back(mi);              
-    mi.SetItem ("In SLT mode don't disable this",   15, 5);
-    _items[15].push_back(mi);              
-    mi.SetItem ("timer. It is the daily chg time.", 15, 6);
-    _items[15].push_back(mi);              
-
-    // Low Battery Transfer - Menu heading #16
-    mi.SetItem ("Low Battery      Transfer (LBX)",    16);
-    _items[16].push_back(mi);
-    mi.SetItem ("Set Low Battery  TransferVDC",       16, 1, (float)26.8);
-    _items[16].push_back(mi);
-    mi.SetItem ("Set Low Battery  cut in  VDC",       16, 2, (float)26);
-    _items[16].push_back(mi);
-    mi.SetItem ("See menu 9 to    enable LBX mode.",  16, 3);
-    _items[16].push_back(mi);
-    mi.SetItem ("Make sure LBX is above LBCO volts.", 16, 4);
-    _items[16].push_back(mi);
-
-    //  Battery Power Selling - Menu heading #17
-    mi.SetItem ("Battery Selling",                    17);
-    _items[17].push_back(mi);
-    mi.SetItem ("Set Battery Sell volts",             17, 1, (float)26.8);
-    _items[17].push_back(mi);
-    mi.SetItem ("Set Max Sell     amps",              17, 2, 30);
-    _items[17].push_back(mi);
-    mi.SetItem ("See menu 9 to    enable SELL mode.", 17, 3);
-    _items[17].push_back(mi);
-    mi.SetItem ("Make sure LBX is above LBCO volts.", 17, 4);
-    _items[17].push_back(mi);
-  
-    // Grid Usage Timer - Menu heading #18
-    mi.SetItem ("Grid Usage Timer",                 18);
-    _items[18].push_back(mi);
-    mi.SetItem ("Set Charge       time",            18,  1, 21); // FIXME: TIME
-    _items[18].push_back(mi);
-    mi.SetItem ("End Charge       time",            18,  2, 21); // FIXME: TIME
-    _items[18].push_back(mi);
-    mi.SetItem ("After Start      Charge time:",    18,  3);
-    _items[18].push_back(mi);
-    mi.SetItem ("SELL mode        charges battery.",18,  4);
-    _items[18].push_back(mi);
-    mi.SetItem ("FLT mode         charges battery", 18,  5);
-    _items[18].push_back(mi);
-    mi.SetItem ("After End Charge time:",           18,  6);
-    _items[18].push_back(mi);
-    mi.SetItem ("SELL mode sells  battery to AC1.", 18,  7);
-    _items[18].push_back(mi);
-    mi.SetItem ("FLT mode drops   AC1 and inverts", 18,  8);
-    _items[18].push_back(mi);
-    mi.SetItem ("Timer on when    start < > end;",  18,  9);
-    _items[18].push_back(mi);
-    mi.SetItem ("timer off when   start = end",     18, 10);
-    _items[18].push_back(mi);
-    mi.SetItem ("Sell and float   modes use timer", 18, 11);
-    _items[18].push_back(mi);
-    mi.SetItem ("SLT and LBX mode ignore timer",    18, 12);
-    _items[18].push_back(mi);
-  
-    // Information file battery - Menu Heading #19
-    mi.SetItem ("Information file battery",          19);
-    _items[19].push_back(mi);
-    mi.SetItem ("Batt temp comp   changes battery",  19, 1);
-    _items[19].push_back(mi);
-    mi.SetItem ("voltage reading  away from actual", 19, 2);
-    _items[19].push_back(mi);
-    mi.SetItem ("HBCO resets at:  6v/48, 3v/24 and", 19, 3);
-    _items[19].push_back(mi);
-    mi.SetItem ("1.5v/12v under   HBCO.",            19, 4);
-    _items[19].push_back(mi);
-    mi.SetItem ("LowBattTransfer  used in LBX, FLT", 19, 5);
-    _items[19].push_back(mi);
-    mi.SetItem ("Modes only. Goes back to battery",  19, 6);
-    _items[19].push_back(mi);
-    mi.SetItem ("at LowBattCutIn  (aka LBCI).",      19, 7);
-    _items[19].push_back(mi);
-    mi.SetItem ("For LBX mode set below LBCI so",    19, 8);
-    _items[19].push_back(mi);
-    mi.SetItem ("charger won't    cycle batteries",  19, 9);
-    _items[19].push_back(mi);
-    mi.SetItem ("up and down and  set LBCO below.",  19, 10);
-    _items[19].push_back(mi);
-  
-    // End of Setup - Menu Heading #20
-    mi.SetItem ("END SETUP MENU", 20);
-    _items[20].push_back(mi);
-}
-
-// Dump all the MenuItem data
-void
-XantrexUI::Dump (void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-
-    dbglogfile << "There are " << (int)_items.size() << " menu _items" << endl;
-
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            //it->Dump();
-            cout << it->GetHeaderIndex()
-                 << "," << it->GetItemIndex()
-                 << ": " << it->GetLabel() << endl;
-        }
-    }
-}
-
-void
-XantrexUI::DumpAliases (void)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    string tmpstr;
-
-    cout << "Command Name\t\tMenu Item" << endl;
-    cout << "------------\t\t---------" << endl;
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            tmpstr = it->GetLabel();
-            if (it->GetAlias().size() > 0)
-                cout << it->GetAlias() << "  \t- " << CleanUpData(tmpstr) << 
endl;
-        }
-    }
-}
-
-MenuItem &
-XantrexUI::Match(string &str)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-  
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    vector< MenuItem > arg;
-
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        arg = *mh;
-        for (it = arg.begin(); it != arg.end(); ++it) {
-            dbglogfile << "Matching \"" << it->GetAlias() << "\""
-                       << " against the argument \"" << str << "\"" << endl;
-            if (it->GetAlias() == str){
-                dbglogfile << "Matched " << it->GetLabel() << " !" << endl;
-                return *it;
-            }
-        }
-    }
-    // FIXME: this is a hack to set an error condition
-    str.erase();
-    return *it;
-}
-
-MenuItem &
-XantrexUI::GetItem(int x, int y)
-{
-    DEBUGLOG_REPORT_FUNCTION;
-    vector< vector< MenuItem > >::iterator mh;
-    vector< MenuItem >::iterator it;
-    vector< MenuItem > arg;
-    string tmp;
-   
-    for (mh = _items.begin(); mh != _items.end(); ++mh) {
-        for (it = mh->begin(); it != mh->end(); ++it) {
-            tmp = it->GetLabel();
-            if ((it->GetHeaderIndex() == x) && (it->GetItemIndex() == y)) {
-                return *it;
-            }
-        }
-    }
-
-    return *it;                  // FIXME: This probably isn't what we want
-}
-
-#if 0
-retcode_t
-XantrexUI::xantrex_main(Console &con);
-{
-
-#if 0
-    if (item.size() > 0) {
-        // See if the name is actually a specified index
-        if (item.find(":",0) != string::npos)
-            {
-                menuhead = atoi(item.substr(0, item.find(":",0)).c_str());
-                menuitem = atoi(item.substr(item.find(":",0) + 1, 2).c_str());
-            } else {
-            // lookup the alias to get the indexes
-            ti = ui.Match(item);
-            if (item.size() > 0) {
-                menuhead = ti->GetHeaderIndex();
-                menuitem = ti.GetItemIndex();
-            }
-        }
-    }
-#endif
-
-    // Go into console mode where we can type direct commands
-    // via the serial port. This just saves us from firing up
-    // kermit or minicom
-    if (console) {
-        Console con;
-        con.Open();
-        //ui.SetRaw();
-        while ((ch = con.Getc())!='q') {
-            if (ch > 0){             // If we have something, process it
-                if (echo)
-                    con.Putc (ch);          // echo inputted character to 
screen
-          
-                switch (ch) {
-                  case 'Q':
-                  case 'q':
-                      con.Reset();
-                      exit(0);
-                      break;
-                  case 'L':
-                      display = ui.MenuHeadingMinus();
-                      break;
-                  case 'R':
-                      display = ui.MenuHeadingPlus();
-                      break;
-                  case 'D':
-                      display = ui.MenuItemMinus();
-                      break;
-                  case 'U':
-                      display = ui.MenuItemPlus();
-                      break;
-                  case '+':
-                      display = ui.SetPointPlus();
-                      break;
-                  case '-':
-                      display = ui.SetPointMinus();
-                      break;
-                  case '|':
-                      display = ui.Inverter();
-                      break;
-                  case 'G':
-                      display = ui.Generator();
-                      break;
-                  case 'S':
-                      display = ui.SetupMenu();
-                      break;
-                  case 's':
-                      display = ui.GotoMenuStart();
-                      break;
-                  case '/':
-                      display = ui.LedStatus();
-                      break;
-                  case 'V':
-                      display = ui.Version();
-                      break;
-                  case 'T':
-                      display = ui.SetTerminalMode();
-                      break;
-                  case '?':
-                      con.Puts("PowerGuru - Xantrex mode\r\n");
-                      con.Puts("\t? - help\r\n");
-                      con.Puts("\tL - Menu Heading Minus\r\n");
-                      con.Puts("\tR - Menu Heading Plus\r\n");
-                      con.Puts("\tR - Menu Heading Plus\r\n");
-                      con.Puts("\tD - Menu Item Minus\r\n");
-                      con.Puts("\tU - Menu Item Plus\r\n");
-                      con.Puts("\t+ - Value Plus\r\n");
-                      con.Puts("\t- - Value Item Plus\r\n");
-
-                      con.Puts("\t| - Inverter Mode\r\n");
-                      con.Puts("\tG - Generator Mode\r\n");
-                      con.Puts("\tS - Setup Menu\r\n");
-                      con.Puts("\t/ - LED Status\r\n");
-                      con.Puts("\tV - Version\r\n");
-                      con.Puts("\tT - TerminalMode\r\n");
-                      con.Puts("\tQ - Quit\r\n");
-                  default:
-                      break;
-                };
-
-                //          display += "\r";
-                con.Putc('\r');
-                con.Puts(display);
-#if 0
-                switch (ui.GetDataType()) {
-                  case MenuItem::NONE:
-                  case MenuItem::MENUHEAD:
-                  case MenuItem::MENUITEM:
-                  case MenuItem::BOOL:
-                      if (ui.GetBoolValue() == false)
-                          dbglogfile << "\tBoolean value is: " << "OFF" ;
-                      else
-                          dbglogfile << "\tBoolean value is: " << "ON" ;      
-                      dbglogfile << endl;
-                      break;
-                  case MenuItem::INT:
-                      dbglogfile << "\tInteger value is: " << value.intval << 
endl;
-                      break;
-                  case MenuItem::FLOAT:
-                      cerr << "\tFIXME: Float value is: " << value.floatval << 
endl;
-                      break;
-                  case MenuItem::TIME:
-                      dbglogfile << "\tTime value is: " << value.timeval << 
endl;
-                      break;
-                  case MenuItem::EOL:
-                  case MenuItem::CLOCK:
-                  case MenuItem::ENUM:
-                  case MenuItem::DATE:
-                      dbglogfile << "\tFIXME: unsupported type! " << 
value.intval << endl;
-                      break;
-                  default:
-                      dbglogfile << "Data Type out of range";
-                      break;
-                };
-#endif
-            }
-
-            str += ui.ReadSerial();
-            if (str.size() > 0) {
-                con.Puts(str);
-                str.erase();
-            }
-        }
-    }
-    
-    // Get the value of a menu item
-    if (getitem){
-      
-        string str = ui.GotoMenuItem(menuhead, menuitem);
-        ti = ui.GetItem(menuhead, menuitem);
-        //    ui.Read((char *)&buffy, 100);
-        cerr << "Inverter returned: " << str << endl;
-
-        //      dbglogfile << "BREAK HERE" << endl;
-      
-        switch (ti.GetType()) {
-          case MenuItem::BOOL:
-              if (ui.GetBoolValue(str) == false)
-                  cout << "The Boolean value is: NO" << endl;
-              else
-                  cout << "The Boolean value is: YES" << endl;
-              break;
-          case MenuItem::INFO:
-              value = ui.GetValue(str);
-              cout << "The value is: " << value << endl;
-              break;
-          case MenuItem::INT:
-              intval = ui.GetIntValue(str);
-              cout << "The Integer value is: " << intval << endl;
-              break;
-          case MenuItem::FLOAT:
-              fltval= ui.GetFloatValue(str);
-              cout << "The Float value is: " << fltval << endl;
-              break;
-          case MenuItem::MENUHEAD:
-              cout << "The Menu Header is: " << "\"" <<
-                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-              break;
-          case MenuItem::MENUITEM:
-              cout << "The Menu Item is: " << "\"" <<
-                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-              break;
-          case MenuItem::TIME:
-              value = ui.GetValue(str);
-              cout << "The Time is: " << "\"" << value << endl;
-              break;
-          case MenuItem::EOL:
-              value = ui.GetValue(str);
-              cout << "The Time is: " << "\"" << value << endl;
-              break;
-          case MenuItem::CLOCK:
-              value = ui.GetValue(str);
-              cout << "The Clock value is: " << "\"" << value << endl;
-              break;
-          case MenuItem::ENUM:
-              value = ui.GetValue(str);
-              cout << "The Enum value is: " << "\"" << value << endl;
-              break;
-          case MenuItem::DATE:
-              value = ui.GetValue(str);
-              cout << "The Date is: " << "\"" << value << endl;
-              break;
-          default:
-              cout << "The value is: " << value << endl;
-              value = str;
-        };
-    } // endof getitem
-
-    // Monitor an item. This means grabs successive values and
-    // display them. This is for selections that constantly update
-    // the value.
-    if (monitor) {
-        string str = ui.GotoMenuItem(menuhead, menuitem);
-        ti = ui.GetItem(menuhead, menuitem);
-
-        cout << "The Menu Header is: " << "\"" <<
-            ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-      
-        do {
-            memset(buffy, 0, 100);        
-            ret = ui.Read((char *)&buffy, 100);
-            str = buffy;
-            if (ret < 0)            // there is no input yet, try again
-                continue;
-
-            // We got something, so extract the type, and process the
-            // value.
-            switch (ti.GetType()) {
-              case MenuItem::BOOL:
-                  if (ui.GetBoolValue(str) == false)
-                      cout << "\tThe Boolean value is: NO" << endl;
-                  else
-                      cout << "\tThe Boolean value is: YES" << endl;
-                  break;
-              case MenuItem::INFO:
-                  value = ui.GetValue(str);
-                  cout << "\tThe value is: " << value << endl;
-                  break;
-              case MenuItem::INT:
-                  intval = ui.GetIntValue(str);
-                  cout << "\tThe Integer value is: " << intval << endl;
-                  break;
-              case MenuItem::FLOAT:
-                  fltval= ui.GetFloatValue(str);
-                  cout << "\tThe Float value is: " << fltval << endl;
-                  break;
-              case MenuItem::MENUHEAD:
-                  cout << "\tThe Menu Header is: " << "\"" <<
-                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-                  break;
-              case MenuItem::MENUITEM:
-                  cout << "\tThe Menu Item is: " << "\"" <<
-                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
-                  break;
-              default:
-                  cout << "\tThe value is: " << value << endl;
-                  value = str;
-            };
-        } while (ret); // endof monitor   
-    }
-}
-#endif
-
-meter_data_t *
-XantrexUI::exportMeterData(meter_data_t *data)
-{
-#if 0
-    // The unit number for the device
-    data->unit = _address;
-  
-    // The type of the device
-    switch (_type) {
-      case OUTBACK_MX:
-          data->type = MX_OUTBACK;
-          break;
-      case OUTBACK_FX:
-          data->type = FX_OUTBACK;
-          break;
-      case SW_XANTREX:
-      default:
-          break;
-    };
-  
-    // The amperage being put into the batteries
-    data->charge_amps = _charge_current;
-    // The load in amps
-    data->ac_load_amps = _inverter_current;
-    // Actual Battery Voltage
-    data->battery_volts = _battery_voltage;
-    // Battery Voltage temperature compensated. This isn't used by
-    // Outback products.
-    data->tempcomp_volts = 0;
-    // The voltage the inverter is producing
-    data->ac_volts_out = _AC_output_voltage;
-    // Grid AC input
-    data->ac1_volts_in = _AC_input_voltage;
-    // The AC current taken from the Grid and used to charge the batteries.
-    data->buy_amps = _buy_current;
-    // The AC current the batteries are putting into the grid.
-    data->sell_amps = _sell_current;
-    // The daily kilowatts put into the batteries from the PV source.
-    data->daily_kwh = _daily_kwh;
-    // The frequency in hertz. This doesn't exist on an Outback, but does on
-    // a Xantrex. It should always be 60 though, so we set it so other
-    // software can handle this  the same way.
-    data->hertz = 60;
-#endif
-
-    return data;
-}
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
diff --git a/lib/xantrex-trace.h b/lib/xantrex-trace.h
deleted file mode 100644
index 6f6975c..0000000
--- a/lib/xantrex-trace.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
-//      Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifndef  __XANTREXUI_H__
-#define __XANTREXUI_H__
-
-#ifdef __cplusplus
-
-#include <string>
-#include <vector>
-#include <map>
-#include "err.h"
-#include <console.h>
-
-#include "serial.h"
-#include "menuitem.h"
-#include "database.h"
-
-class XantrexUI : public Serial
-{
- public:
-  typedef enum {USERMENU, SETUPMENU} menu_e;
-  enum inverter_e {OFF, SRCH, ON, CHG};
-  enum invertsetup_e {FLOAT, SELL, SLT, LBX};
-  enum battery_e {NICAD, LEADACID, GEL};
-  enum genauto_e {UNINITIALIZED, RUNNING, IDLE};
-
-  XantrexUI(void);
-  ~XantrexUI(void);
-  
-  // Dump all internal data to the console
-  void Dump (void);
-  void DumpAliases(void);
-  
-  // This selects which inverter we want to control
-  std::string &SelectInverter(int x);
-
-  // Read from the serial port
-  std::string &ReadSerial(void);
-
-  // Write to the serial port
-  std::string &WriteSerial(const char *buf, int nbytes);
-
-  // These methods all go with the Xantrex display buttons
-  std::string &MenuHeadingMinus(void);
-  std::string &MenuHeadingPlus(void);
-  std::string &MenuItemMinus(void);
-  std::string &MenuItemPlus(void);
-  std::string &SetPointMinus(void);
-  std::string &SetPointPlus(void);
-  std::string &Inverter(void);
-  std::string &Generator(void);
-  std::string &SetupMenu(void);
-  std::string &LedStatus(void);
-  std::string &Version(void);
-  std::string &SetTerminalMode(void);
-  
-  std::vector<meter_data_t *> PollMeters(int loops);
-  //std::map<std::string, float> *PollMeters(int loops);
-  
-  // This method takes the data as outputted by the Xantrex inverter,
-  // and munges it to be a standard form with whitespace compressed,
-  // newlines & carriage returns stripped out, etc... This is so
-  // we can analyse the string data in a consistant fashion.
-  std::string &CleanUpData(std::string &str);
-
-  meter_data_t *exportMeterData(meter_data_t *data);
-  
-#if 0
-  std::string &UserMenu(void);
-  // These methods are for switching menu modes
-  retcode_t GotoSetupMenu(void);
-  retcode_t GotoUserMenu(void);
-#endif
-  // This method takes us to the beginning of the menu headers and items
-  // This corresponds then to being in the Inverter Mode header of the
-  // User menu.
-  retcode_t GotoMenuStart(void);
-  std::string &GotoMenuItem(int mh, int mi);
-  
-  // These methods manipulate values
-  std::string &GetValue (std::string &x);
-  std::vector<std::string> *GetValues (std::string &str);
-  retcode_t SetFloatValue(float x);
-  float GetFloatValue(std::string &x);
-  retcode_t SetIntValue(int x);
-  int GetIntValue(std::string &x);
-  retcode_t SetBoolValue(bool x);
-  bool GetBoolValue(std::string &x);
-  std::string GetLabel(std::string &x);
-  // This method populates the menu item data to default values as per
-  // the Xantrex manual.
-  void SetDefaultValues (void);
-
-  // This method tries to match the display with a menu item
-  // to verify we're where we think we are...
-  MenuItem &Match(std::string &str);
-  MenuItem &GetItem(int x, int y);
-  MenuItem &GetItem() { return GetItem(menuheading, menuitem); }
-  std::string GetLabel();
-
-  retcode_t xantrex_main(Console& con);
- private:
-  std::vector< std::vector< MenuItem > > _items;
-  int menuheading;
-  int menuitem;
-  //  Serial uart;  
-};
-
-extern "C" {
-#else
-
-  // Default object for C code. 
-  XantrexUI ui;
-  
-  /* This is the C API for this class. */
-  
-  const char *menu_heading_minus(void);
-  const char *menu_heading_plus(void);
-  const char *menu_item_minus(void);
-  const char *menu_item_mlus(void);
-  const char *set_point_minus(void);
-  const char *set_point_plus(void);
-  
-  const char *inverter(void);
-  const char *generator(void);
-  const char *setup_menu(void);
-  const char *led_status(void);
-  const char *version(void);
-  const char *set_terminal_mode(void);
-  
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-// end of __XANTREXUI_H__
-#endif
-
-// local Variables:
-// mode: C++
-// indent-tabs-mode: nil
-// End:
diff --git a/lib/xml.cc b/lib/xml.cc
index 4eb6abe..18295ee 100644
--- a/lib/xml.cc
+++ b/lib/xml.cc
@@ -25,7 +25,7 @@
 #include <sys/stat.h>
 
 #include <unistd.h>
-#include <string>
+#include <cstring>
 #include <vector>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
diff --git a/lib/xml.h b/lib/xml.h
index 68741c5..398eeb0 100644
--- a/lib/xml.h
+++ b/lib/xml.h
@@ -24,7 +24,7 @@
 # include "config.h"
 #endif
 
-#include <string>
+#include <cstring>
 #include <vector>
 #ifdef HAVE_LIBXML
 # include <libxml/xmlmemory.h>

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=72322653e11e3d03149b31ed3cac1b5f9160271d


commit 72322653e11e3d03149b31ed3cac1b5f9160271d
Author: Rob Savoye <address@hidden>
Date:   Fri Nov 16 20:55:03 2018 -0700

    Use <cstring> instead of <string>. Moved from lib

diff --git a/devices/outbackpower.cc b/devices/outbackpower.cc
new file mode 100644
index 0000000..d72477a
--- /dev/null
+++ b/devices/outbackpower.cc
@@ -0,0 +1,722 @@
+// 
+// Copyright (C) 2005, 2006 - 2018
+//      Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <vector>
+#include <map>
+
+#include "err.h"
+#include "log.h"
+#include "console.h"
+#include "outbackpower.h"
+#include "database.h"
+
+using namespace std;
+using namespace outbackpower;
+
+const int PACKET_SIZE = 49;
+
+outback::outback() : _type(OUTBACK_NONE), _address('x'),_inverter_current(0), 
_charge_current(0), _buy_current(0), _pv_current(0), _sell_current(0), 
_AC_input_voltage(0), _AC_output_voltage(0), _pv_input_voltage(0), 
_battery_voltage(0), _daily_kwh(0), _operating_mode(SUPPORT), _AC_mode(NO_AC), 
_misc_byte(RESERVE1), _aux_mode(DISABLED),_charge_mode(SILENT_MODE), 
_error_mode(NO_ERROR), _warning_mode(NO_WARNING), _checksum(0)
+{
+    DEBUGLOG_REPORT_FUNCTION;  
+}
+
+outback::outback(string filespec) :  _type(OUTBACK_NONE), 
_address('x'),_inverter_current(0),_charge_current(0), _buy_current(0), 
_pv_current(0), _sell_current(0), _AC_input_voltage(0), _AC_output_voltage(0), 
_pv_input_voltage(0), _battery_voltage(0), _daily_kwh(0), 
_operating_mode(SUPPORT), _AC_mode(NO_AC), _misc_byte(RESERVE1), 
_aux_mode(DISABLED), _charge_mode(SILENT_MODE), _error_mode(NO_ERROR), 
_warning_mode(NO_WARNING), _checksum(0)
+
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    commInit(filespec);
+}
+
+outback::outback(const char *filespec) : _type(OUTBACK_NONE), 
_address('x'),_inverter_current(0),_charge_current(0), _buy_current(0), 
_pv_current(0), _sell_current(0), _AC_input_voltage(0), _AC_output_voltage(0), 
_pv_input_voltage(0), _battery_voltage(0), _daily_kwh(0), 
_operating_mode(SUPPORT), _AC_mode(NO_AC), _misc_byte(RESERVE1), 
_aux_mode(DISABLED), _charge_mode(SILENT_MODE), _error_mode(NO_ERROR), 
_warning_mode(NO_WARNING), _checksum(0)
+
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    commInit(filespec);
+}
+
+outback::~outback()
+{
+}
+
+// Read from the serial port
+const char *
+outback::readSerial()
+{
+    // DEBUGLOG_REPORT_FUNCTION;
+
+    int ret;
+    char *buf = new char[PACKET_SIZE+1];
+  
+    memset(buf, 0, PACKET_SIZE+1);
+
+    ret = Read(buf, PACKET_SIZE);
+  
+    if (ret > 0) {
+        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buf << "\t" << 
buf << endl;
+        return buf;
+    }
+
+    //  calcChecksum(packet);
+
+    return "";
+}
+
+retcode_t
+outback::commInit(string filespec)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    if (filespec.size() == 0) {
+        dbglogfile << "ERROR: no serial device specified!" << endl;
+        exit(0);
+    }    
+
+#if 0
+    Open(filespec);
+#else
+    try {
+        Open(filespec);
+    }
+    catch (ErrCond catch_err) {
+        dbglogfile << catch_err << endl;
+        exit(1);
+    }
+#endif
+  
+    return commInit(GetFD());
+}
+
+retcode_t
+outback::commInit(int fd)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    SetRaw();
+    SetBaud(B19200);
+  
+#if 0
+    termios thistty;
+    tcgetattr(GetFD(), &thistty);
+    thistty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+    thistty.c_oflag &= ~(OPOST|~ONLCR);
+    thistty.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+    thistty.c_cflag &= ~(CSIZE|PARENB|HUPCL);
+    thistty.c_cflag |= CREAD;
+    //thistty.c_cflag |= CS8;
+    thistty.c_cc[VMIN] = 1;
+    thistty.c_cc[VTIME] = 100;
+    tcsetattr(GetFD(), TCSANOW, &thistty);
+#endif
+    SetDTR(true);
+
+    return SUCCESS;
+}
+
+// The main loop for an outback device
+retcode_t
+outback::main()
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    Console con;
+#ifdef defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
+    Database db;
+    return main(con, db);
+#endif
+}
+
+retcode_t
+outback::main(Console &con, Database &db)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    string str;
+    int ch;
+  
+    while ((ch = con.Getc()) != 'q') {
+        if (ch > 0){                // If we have something, process it
+            //con.Putc (ch);          // echo inputted character to screen
+      
+            switch (ch) {
+                // Toggle the DTR state, which is as close as we get to
+                // flow control.
+              case 'd':
+                  SetDTR(false);
+                  break;
+              case 'D':
+                  SetDTR(true);
+                  break;
+              case 'Q':
+              case 'q':
+                  return SUCCESS;
+                  break;
+              case '?':
+                  con.Puts("PowerGuru - Outback Mode\r\n");
+                  con.Puts("\t? - help\r\n");
+                  con.Puts("\tq - Quit\r\n");
+                  con.Puts("\tQ - Quit\r\n");
+                  // sleep(2); FIXME
+              default:
+                  break;
+            };
+        }
+    
+        str = readSerial();
+        if (str.size() > 0) {
+            // con.Puts(str); con.Puts("\r\n");
+            calcChecksum(str.c_str());
+            {
+                parse(str.c_str());
+                meter_data_t md;
+                exportMeterData(&md);
+#if defined(HAVE_MARIADB) && defined(HAVE_POSTGRESQL)
+                db.queryInsert(&md);
+#endif
+            }
+            str.erase();
+        }
+    }
+  
+    return SUCCESS;
+}
+
+// Send a command to the master FX inverter. Each command is a single
+// character, but is sent twice for error handling.
+retcode_t
+outback::sendFXCommand(fx_commands_t cmd) 
+{
+    char buf[3];
+    memset(buf,0, 3);
+    buf[0] = buf[1] = cmd;
+
+    if (Write(buf, 2) != 2) {
+        return ERROR;
+    }
+
+    return SUCCESS;
+}
+
+// Parse the ASCII packet into numerical data.
+//
+// A packet from an Outback Power systems device is a 49 bytes ASCII
+// string representing numerical data. It is framed by a LF character
+// (0x0a) to start, and a CR (0x0d) to end it. Each field is separated
+// by commas, but we can ignore those. The checksum is a simply the
+// addition of all the characters in the message.
+retcode_t outback::parse(const char *data)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    string packet = data;
+  
+    // The address is byte 1
+    _address = packet[1];
+    if ((_address >= '0') && (_address <= '9')) {
+        _type = OUTBACK_FX;
+    } else if ((_address >= 'A') && (_address <= 'K')) {
+        _type = OUTBACK_MX;
+    } else {
+        dbglogfile << "ERROR: bad address in packet!" << endl;
+        return ERROR;
+    }
+
+    _type = OUTBACK_MX;           // FIXME: 
+  
+    // The inverter current is bytes 4 & 4 on an FX, but unused on the MX.
+    _inverter_current = strtol(packet.substr(3,2).c_str(), NULL, 0);
+  
+    // The charger current is bytes 7 & 8.
+    _charge_current = strtol(packet.substr(6,2).c_str(), NULL, 0);
+
+    // Bytes 9 & 10 are the Buy current on an FX, and the PV current on
+    // an MX.
+    if (_type == OUTBACK_FX) {
+        _buy_current = strtol(packet.substr(9,2).c_str(), NULL, 0);
+    } else {
+        _pv_current = strtol(packet.substr(9,2).c_str(), NULL, 0);;
+    }   
+  
+    // Bytes 13, 14, & 15 are the AC Input Voltage on an FX, and the PV
+    // input voltage on an MX.
+    if (_type == OUTBACK_FX) {
+        _AC_input_voltage = strtol(packet.substr(13,3).c_str(), NULL, 0);
+    } else {
+        _pv_input_voltage = strtol(packet.substr(13,3).c_str(), NULL, 0);
+    }
+
+    // Bytes 16, 17, & 18 are the AC Output Voltage on an FX, and the
+    // Daily Kilowatts on an MX.
+    if (_type == OUTBACK_FX) {
+        _AC_output_voltage = strtol(packet.substr(16,3).c_str(), NULL, 0);
+    } else {
+        _daily_kwh = strtol(packet.substr(16,3).c_str(), NULL, 0);
+    }
+
+    // Bytes 20 & 21 are the Sell current on an FX, but unused on an MX.
+    if (_type == OUTBACK_FX) {
+        _sell_current = strtol(packet.substr(20,2).c_str(), NULL, 0);
+    }
+
+    // Bytes 23 & 24 are the Operating Mode on an FX, but is the AUX Mode
+    // on an MX.
+    if (_type == OUTBACK_FX) {
+        _operating_mode = 
static_cast<op_mode_t>(strtol(packet.substr(23,2).c_str(), NULL, 0));
+    } else {
+        _aux_mode = 
static_cast<aux_mode_t>(strtol(packet.substr(23,2).c_str(), NULL, 0));
+    }
+  
+    // Bytes 26, 27, & 28 are the Error Mode, but is unimplemented on
+    // the MX at this time. (2005/7/12)
+    if (_type == OUTBACK_FX) {
+        _error_mode = 
static_cast<error_mode_t>(strtol(packet.substr(13,3).c_str(), NULL, 0));
+    }
+
+    // Bytes 30 & 31 are the AC Mode on an FX, but is the Charger Mode
+    // on an MX.
+    if (_type == OUTBACK_FX) {
+        _AC_mode = static_cast<AC_mode_t>(strtol(packet.substr(30,2).c_str(), 
NULL, 0));
+    } else {
+        _charge_mode = 
static_cast<charge_mode_t>(strtol(packet.substr(30,2).c_str(), NULL, 0));
+    }
+  
+    // Bytes 33, 34, & 35 are the battery voltage.
+    _battery_voltage = strtol(packet.substr(33,3).c_str(), NULL, 0);
+
+    // Bytes 37, 38, & 39 are the Misc Byte on an FX, but are unused on
+    // an MX.
+    if (_type == OUTBACK_FX) {
+        _misc_byte = 
static_cast<misc_byte_t>(strtol(packet.substr(37,3).c_str(), NULL, 0));
+    }
+
+    // Bytes 41, 42, & 43 are the Warning Mode on an FX, but unused on an MX.
+    if (_type == OUTBACK_FX) {
+        _warning_mode = 
static_cast<warning_mode_t>(strtol(packet.substr(13,3).c_str(), NULL, 0));
+    }
+
+    // Bytes 45, 46, & 47 are the packet checksum.
+    _checksum = strtol(packet.substr(45,3).c_str(), NULL, 0);
+
+    dump();
+  
+    return SUCCESS;
+}
+
+//
+void
+outback::dump()
+{
+    switch (_type) {
+      case OUTBACK_MX:
+          dbglogfile << "Outback Power Systems MX Charge Controller" << endl;
+          break;
+      case OUTBACK_FX:
+          dbglogfile << "Outback Power Systems FX inverter" << endl;
+          break;
+      case OUTBACK_NONE:
+      default:
+          dbglogfile << "Outback Power Systems, no type specified!" << endl;
+          break;
+    };
+  
+    // The address of the unit.
+    string addr;
+    addr = "Unit #";
+    if ((_address >= '0') && (_address <= '9')) {
+        addr += _address;
+    } else if ((_address >= 'A') && (_address <= 'K')) {
+        addr += _address;
+    }
+    dbglogfile << "The address is: " << addr.c_str() << endl;
+
+    // Amperage readings. These range from 0-99 in 1 amp increments
+    if (_inverter_current) {
+        dbglogfile << "Inverter current is: " << _inverter_current << endl;
+    }
+
+    if (_charge_current) {
+        dbglogfile << "Charge current is: " << _charge_current << " Amps" << 
endl;
+    }
+    if (_buy_current) {
+        dbglogfile << "Buy current is: " <<  _buy_current << " Amps" << endl;
+    }
+    if (_pv_current) {
+        dbglogfile << "PV current is: " <<  _pv_current << " Amps" << endl;
+    }
+    if (_sell_current) {
+        dbglogfile << "Sell current is: " <<  _sell_current << " Amps" << endl;
+    }
+
+    // Voltage readings. These range from 0-256. If the Misc Mode bit is
+    // set, then this number is multiplied by 2.
+    if (_AC_input_voltage) {
+        dbglogfile << "AC Input voltage is: " << _AC_input_voltage << " VAC" 
<< endl;
+    }
+    if (_AC_output_voltage) {
+        dbglogfile << "AC Output voltage is: " << _AC_output_voltage << " VAC" 
<< endl;
+    }
+    // one volt increments, ignore the misc Byte. FIXME: Do we devide this by 
2 ?
+    if (_pv_input_voltage) {
+        dbglogfile << "PV Input voltage is: " << _pv_input_voltage/2 << " VDC" 
<< endl;
+    }
+  
+    // the resolution is 0.1 volts for a 12VDC system, 0.2 volts for a
+    // 24VDC system, and 0.4 for a 48 volt system.
+    if (_battery_voltage) {
+        dbglogfile << "Battery voltage is: " << _battery_voltage/10
+                   << "." << _battery_voltage%10 << " VDC" << endl;
+    }
+    // The total kilowatts used daily. This ranges from 0-999, with the
+    // last digit being the fraction. ie... 99 = 99.9.
+    if (_daily_kwh) {
+        dbglogfile << "The daily Kilowatts used is: " << _daily_kwh/10
+                   << "." << _daily_kwh%10 << " KW" << endl;
+    }
+
+    // Modes. Not all modes are currently implemented on the MX
+    // series. All the modes range from 0-99 except for the error and
+    // warning modes which range from 0-256.
+    dbglogfile << "The operating mode is: ";
+    switch (_operating_mode){
+      case INV_OFF:
+          dbglogfile << "Inverter OFF" << endl;
+          break;
+      case INV_SEARCH:
+          dbglogfile << "Inverter SEARCH" << endl;
+          break;
+      case INV_ON:
+          dbglogfile << "Inverter ON" << endl;    
+          break;
+      case CHARGE:
+          dbglogfile << "Charge" << endl;
+          break;
+      case SILENT:
+          dbglogfile << "Silent" << endl;
+          break;
+      case FLOAT:
+          dbglogfile << "Float" << endl;
+          break;
+      case EQ:
+          dbglogfile << "Equalize" << endl;
+          break;
+      case CHARGER_OFF:
+          dbglogfile << "Charger Off" << endl;
+          break;
+      case SUPPORT:
+          dbglogfile << "Support" << endl;
+          break;
+      case SELL_ON:
+          dbglogfile << "Sell On" << endl;
+          break;
+      case PASS_THRU:
+          dbglogfile << "Pass Thru" << endl;
+          break;
+      case FX_ERR:
+          dbglogfile << "FX Error" << endl;
+          break;
+      case AGS_ERR:
+          dbglogfile << "AGS Error" << endl;
+          break;
+      case COM_ERR:
+          dbglogfile << "Communications Error" << endl;
+          break;
+      default:
+          dbglogfile << "No operating mode!" << endl;
+          break;
+    };
+  
+    dbglogfile << "The AC mode is: \t";
+    switch (_AC_mode) {
+      case NO_AC:
+          dbglogfile << "No AC" << endl;
+          break;
+      case AC_DROP:
+          dbglogfile << "AC Dropped" << endl;
+          break;
+      case AC_USE:
+          dbglogfile << "AC In Use" << endl;    
+          break;
+      default:
+          dbglogfile << "No AC mode!" << endl;
+          break;
+    };
+
+    dbglogfile << "The Misc Byte is: \t";
+    switch (_misc_byte) {
+      case 0:
+          dbglogfile << "No Misc byte" << endl;
+      case AC_UNIT:
+          dbglogfile << "AC Unit" << endl;
+          break;
+      case AUX_OUT_ON:
+          dbglogfile << "Aux Mode On set" << endl;
+          break;
+      default:
+          dbglogfile << "Reserved" << endl;
+          break;
+    };
+
+    dbglogfile << "The Aux mode is: \t";
+    switch (_aux_mode) {
+      case DISABLED:
+          dbglogfile << "Aux Mode Disabled" << endl;
+          break;
+      case DIVERSION:
+          dbglogfile << "Diversion" << endl;
+          break;
+      case REMOTE:
+          dbglogfile << "Remote" << endl;
+          break;
+      case MANUAL:
+          dbglogfile << "Manual" << endl;
+          break;
+      case VENT_FAN:
+          dbglogfile << "Vent Fan" << endl;
+          break;
+      case PV_TRIGGER:
+          dbglogfile << "PV Trigger" << endl;
+          break;
+      default:
+          dbglogfile << "No AUX mode set" << endl;
+          break;
+    };
+
+    dbglogfile << "The charge mode is: \t";
+    switch (_charge_mode) {
+      case SILENT_MODE:
+          dbglogfile << "Silent Charge mode" << endl;
+          break;
+      case FLOAT_MODE:
+          dbglogfile << "Float Charge mode" << endl;
+          break;
+      case BULK_MODE:
+          dbglogfile << "Bulk Charge mode" << endl;
+          break;
+      case ABSORB_MODE:
+          dbglogfile << "Absorb Charge mode" << endl;
+          break;
+      case EQ_MODE:
+          dbglogfile << "Equalization Charge mode" << endl;
+          break;
+      default:
+          dbglogfile << "No Charge mode" << endl;
+          break;
+    };
+
+    dbglogfile << "The error mode is: \t";
+    switch (_error_mode) {
+      case NO_ERROR:
+          dbglogfile << "No error" << endl;
+          break;
+      case LOW_VAC:
+          dbglogfile << "ERROR: Low Volts AC" << endl;
+          break;
+      case STACKING:
+          dbglogfile << "ERROR: Stacking" << endl;
+          break;
+      case OVER_TEMP:
+          dbglogfile << "ERROR: Over Temperature" << endl;
+          break;
+      case LOW_BATT:
+          dbglogfile << "ERROR: Low Battery" << endl;
+          break;
+      case PHASE_LOSS:
+          dbglogfile << "ERROR: Phase Loss" << endl;
+          break;
+      case HIGH_BATT:
+          dbglogfile << "ERROR: High Battery" << endl;
+          break;
+      case SHORT:
+          dbglogfile << "ERROR: Short" << endl;
+          break;
+      case BACKFEED:
+          dbglogfile << "ERROR: Backfeed" << endl;
+          break;
+      default:
+          dbglogfile << "No error mode" << endl;
+          break;
+    };
+
+    dbglogfile << "The warning mode is: \t";
+    switch (_warning_mode) {
+      case NO_WARNING:
+          dbglogfile << "No warning" << endl;
+          break;
+      case AC_IN_FREQ_HIGH:
+          dbglogfile << "WARNING: Input Frequency High" << endl;
+          break;
+      case AC_IN_FREQ_LOW:
+          dbglogfile << "WARNING: Input Frequency Low" << endl;
+          break;
+      case IN_VAC_HIGH:
+          dbglogfile << "WARNING: Input Volts AC High" << endl;
+          break;
+      case IN_VAC_LOW:
+          dbglogfile << "WARNING: Input Volts AC low" << endl;
+          break;
+      case BUY_IN_SIZE:
+          dbglogfile << "WARNING: Buy in size" << endl;
+          break;
+      case TEMP_FAILED:
+          dbglogfile << "WARNING: Temperature Failure" << endl;
+          break;
+      case COMM_ERROR:
+          dbglogfile << "WARNING: Communications error" << endl;
+          break;
+      case FAN_FAILURE:
+          dbglogfile << "WARNING: Fan Failure" << endl;
+          break;
+      default:
+          dbglogfile << "No warning mode" << endl;
+          break;
+    };
+}
+
+// Calculate the checksum for a packet and see if it matches.
+retcode_t
+outback::calcChecksum(const char *packet)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    const char *ptr = packet;
+    int index = 45;
+    int chk_field = 0;
+    int checksum = 0;
+    int elem = 0;
+
+    // extract the checksum field from the packet. Also strip off any
+    // leading zeros, as this makes strtol() thinks it's octal by
+    // mistake.
+    char chk[4];
+    memset(chk,0, 4);
+    while (index <= 47) {
+        if (packet[index] != '0') {
+            chk[elem++] = packet[index];
+        }
+        index++;
+    }
+  
+    // Convert the checksum to a number
+    chk_field = strtol(chk, NULL, 0);
+  
+    do {
+        if (*ptr == ',') {
+            ptr++;
+            continue;
+        }
+        if (*ptr == '*') {
+            ptr++;
+            continue;
+        }
+        checksum+= (*ptr++) - '0';
+    } while ((ptr - packet) <= 44); // Don't add the checksum itself
+
+    //dbglogfile << "Transmitted checksum for packet is: " << chk << endl;
+    //dbglogfile << "Calculated checksum for packet is: " << checksum << endl;
+
+    // See if the calculated checksum matches the checksum from the
+    // packet checksum field. (the last 3 bytes before the CR terminator)
+    if (checksum != chk_field) {
+        dbglogfile << "ERROR: Checksums don't match!" << endl;
+        return ERROR;
+    }
+  
+    return SUCCESS;
+}
+
+
+//CREATE TABLE `meters` (
+//  `unit` int(11) NOT NULL default '0',
+//  `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update 
CURRENT_TIMESTAMP,
+//  `charge_amps` int(11) NOT NULL default '0',
+//  `ac_load_amps` int(11) NOT NULL default '0',
+//  `battery_volts` float NOT NULL default '0',
+//  `ac_volts_out` float NOT NULL default '0',
+//  `ac1_volts_in` float NOT NULL default '0',
+//  `ac2_volts_in` float NOT NULL default '0',
+//  `buy_amps` int(11) NOT NULL default '0',
+//  `sell_amps` int(11) NOT NULL default '0',
+//  `daily_kwh` float NOT NULL default '0',
+//  `hertz` int(11) NOT NULL default '0',
+//  `battery_tempcomp` float NOT NULL default '0'
+//) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Stores data from data 
logging output';
+meter_data_t *
+outback::exportMeterData(meter_data_t *data)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    // The unit number for the device
+    data->unit = _address;
+  
+    // The type of the device
+    switch (_type) {
+      case OUTBACK_MX:
+          data->type = MX_OUTBACK;
+          data->unit = _address - '0';
+          break;
+      case OUTBACK_FX:
+          data->type = FX_OUTBACK;
+          data->unit = _address - 'A';
+          break;
+      case SW_XANTREX:
+      default:
+          break;
+    };
+  
+    // The amperage being put into the batteries
+    data->charge_amps = _charge_current;
+    // The load in amps
+    data->ac_load_amps = _inverter_current;
+    // Actual Battery Voltage
+    data->battery_volts = _battery_voltage/10.0;
+    // Battery Voltage temperature compensated. This isn't used by
+    // Outback products.
+    data->tempcomp_volts = 0;
+    // The voltage the inverter is producing
+    data->ac_volts_out = _AC_output_voltage;
+    // Grid AC input
+    data->ac1_volts_in = _AC_input_voltage;
+    // The AC current taken from the Grid and used to charge the batteries.
+    data->buy_amps = _buy_current;
+    // The AC current the batteries are putting into the grid.
+    data->sell_amps = _sell_current;
+    // The daily kilowatts put into the batteries from the PV source.
+    data->daily_kwh = _daily_kwh/10.0;
+    // The frequency in hertz. This doesn't exist on an Outback, but does on
+    // a Xantrex. It should always be 60 though, so we set it so other
+    // software can handle this  the same way.
+    data->hertz = 60;
+    // The generator is AC2 on a Xantrex, but doesn't have a separete
+    // input on an Outback.
+    data->ac2_volts_in = 0.0;
+    // The current coming in from the PV panels before MPPT
+    data->pv_amps_in = _pv_current;
+    // The Voltage coming in from the PV panels before MPPT
+    data->pv_volts_in = _pv_input_voltage;
+
+  
+    return data;
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/devices/outbackpower.h b/devices/outbackpower.h
new file mode 100644
index 0000000..acaa663
--- /dev/null
+++ b/devices/outbackpower.h
@@ -0,0 +1,364 @@
+// 
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+//      Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef __OUTBACK_POWER_H__
+#define __OUTBACK_POWER_H__
+
+// This is generated by autoconf
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include "serial.h"
+#include "console.h"
+#include "database.h"
+
+// The outback has two variations on protocols, one for the FX
+// inverter series, and the other for the MX charge controller
+// series. Each packet is 49 bytes, and is transmitted as ASCII
+// numerals for portability, with an ASCII comma character
+// seperating each field.
+namespace outbackpower
+{
+
+// Outback FX Inverter protocol
+struct outback_fx
+{
+    char start;                   // 1. This is an ASCII(10) New Line character
+    // denoting the start of the status page.
+    char address;                 // 2. This is the Inverter address.
+    char comma1;                  // 3. ASCII(44) a comma as a data separator.
+    char inverter_current[2];     // 4. High byte of Inverter current.
+    // 5. Low byte of Inverter current.
+    char comma2;                  // 6. ASCII(44) a comma as a data separator.
+    char charger_current[2];      // 7. High byte of Charger current..
+    // 8. Low byte of Charger current.
+    char comma3;                  // 9. ASCII(44) a comma as a data separator.
+    char buy_current[2];          // 10. High byte of Buy current..
+    // 11. Low byte of Buy current.
+    char comma4;                  // 12. ASCII(44) a comma as a data separator.
+    char ac_input_voltage[3];     // 13. High byte of the AC input voltage.
+    // 14. Middle byte of AC input voltage.
+    // 15. Low byte of AC input voltage.
+    char comma5;                  // 16. ASCII(44) a comma as a data separator.
+    char ac_output_voltage[3];    // 17. High byte of the AC output voltage.
+    // 18. Middle byte of AC output voltage.
+    // 19. Low byte of AC output voltage.
+    char comma6;                  // 20. ASCII(44) a comma as a data separator.
+    char sell_current[2];         // 21. High byte of Sell current.
+    // 22. Low byte of Sell current.
+    char comma7;                  // 23. ASCII(44) a comma as a data separator.
+    char operating_mode[2];       // 24. High byte of FX operating mode.
+    // 25. Low byte of FX operating mode.
+    char comma8;                  // 26. ASCII(44) a comma as a data separator.
+    char error_mode[3];           // 27. High byte of FX Error mode.
+    // 28. Middle byte of FX Error mode.
+    // 29. Low byte of FX Error mode.
+    char comma9;                  // 30. ASCII(44) a comma as a data separator.
+    char ac_mode[2];              // 31. High byte of FX AC mode.
+    // 32. Low byte of FX AC mode
+    char comma10;                 // 33. ASCII(44) a comma as a data separator.
+    char battery_voltage[3];      // 34. High byte of FX battery voltage.
+    // 35. Middle byte of FX battery voltage.
+    // 36. Low byte of FX battery voltage.
+    char comma11;                 // 37. ASCII(44) a comma as a data separator.
+    char misc[3];                 // 38. High byte of FX Misc.
+    // 39. Middle byte of FX Misc.
+    // 40. Low byte of FX Misc.
+    char comma12;                 // 41. ASCII(44) a comma as a data separator.
+    char warning_mode[3];         // 42. High byte of FX Warning mode.
+    // 43. Middle byte of FX Warning mode.
+    // 44. Low byte of FX Warning mode.
+    char comma13;                 // 45. ASCII(44) a comma as a data separator.
+    char checksum[3];             // 46. High byte of Chksum.
+    // 47. Middle byte of Chksum.
+    // 48. Low byte of Chksum.
+    char end;                     // 49. ASCII(13) carriage return. Denotes 
end of status page.*
+
+};
+
+// Outback MX charger controller protocol
+
+struct outback_mx
+{
+    char start;                   // 1. This is an ASCII(10) New Line character
+    // denoting the start of the status page.
+    char address;                 // 2. This is the MX address.
+    char comma1;                  // 3. ASCII(44) a comma as a data separator.
+    char unused1[2];              // 4. Unused, ASCII(48).
+    // 5. Unused, ASCII(48).
+    char comma2;                  // 6. ASCII(44) a comma as a data separator.
+    char charger_current[2];      // 7. High byte of Charger current.
+    // 8. Low byte of Charger current.
+    char comma3;                  // 9. ASCII(44) a comma as a data separator.
+    char pv_current[2];           // 10. High byte of PV current.
+    // 11. Low byte of PV current.
+    char comma4;                  // 12. ASCII(44) a comma as a data separator.
+    char pv_input_voltage[3];     // 13. High byte of the PV input voltage.
+    // 14. Middle byte of PV input voltage.
+    // 15. Low byte of PV input voltage.
+    char comma5;                  // 16. ASCII(44) a comma as a data separator.
+    char daily_kwh[3];            // 17. High byte of Daily KWH.
+    // 18. Middle byte of Daily KWH.
+    // 19. Low byte of Daily KWH.
+    char comma6;                  // 20. ASCII(44) a comma as a data separator.
+    char unused2[2];              // 21. Unused, ASCII(48).
+    // 22. Unused, ASCII(48).
+    char comma7;                  // 23. ASCII(44) a comma as a data separator.
+    char aux_mode[2];             // 24. High byte of MX Aux mode.
+    // 25. Low byte of MX Aux mode.
+    char comma8;                  // 26. ASCII(44) a comma as a data separator.
+    char error_mode[3];           // 27. High byte of MX Error mode.
+    // 28. Middle byte of MX Error mode.
+    // 29. Low byte of MX Error mode.
+    char comma9;                  // 30. ASCII(44) a comma as a data separator.
+    char charger_mode[2];         // 31. High byte of MX charger mode.
+    // 32. Low byte of MX charger mode.
+    char comma10;                 // 33. ASCII(44) a comma as a data separator.
+    char battery_voltage[3];      // 34. High byte of MX battery voltage.
+    // 35. Middle byte of MX battery voltage.
+    // 36. Low byte of MX battery voltage.
+    char comma11;                 // 37. ASCII(44) a comma as a data separator.
+    char unused3[3];              // 38. Unused, ASCII(48).
+    // 39. Unused, ASCII(48).
+    // 40. Unused, ASCII(48).
+    char comma12;                 // 41. ASCII(44) a comma as a data separator.
+    char unused4[3];              // 42. Unused, ASCII(48).
+    // 43. Unused, ASCII(48)
+    // 44. Unused, ASCII(48).
+    char comma13;                 // 45. ASCII(44) a comma as a data separator.
+    char checksum[3];             // 46. High byte of Chksum.
+    // 47. Middle byte of Chksum.
+    // 48. Low byte of Chksum.
+    char end;                     // 49. ASCII(13) carriage return. Denotes 
end of status page.
+};
+
+// Voltages on an Outback need to be scaled based on the battery voltage.
+typedef enum {
+    CONVERT_12VDC = 1,
+    CONVERT_24VDC = 2,
+    CONVERT_48VDC = 4
+} voltage_conversion_t;
+
+
+// Bit masks for warning messages
+typedef enum {
+    NO_WARNING      = 0,
+    AC_IN_FREQ_HIGH = 1,
+    AC_IN_FREQ_LOW  = 1 << 1,
+    IN_VAC_HIGH     = 1 << 2,
+    IN_VAC_LOW      = 1 << 3,
+    BUY_IN_SIZE     = 1 << 4,
+    TEMP_FAILED     = 1 << 5,
+    COMM_ERROR      = 1 << 6,
+    FAN_FAILURE     = 1 << 7
+} warning_mode_t;
+
+// Bit masks for error messages
+typedef enum {
+    NO_ERROR   = 0,
+    LOW_VAC    = 1,
+    STACKING   = 1 << 1,
+    OVER_TEMP  = 1 << 2,
+    LOW_BATT   = 1 << 3,
+    PHASE_LOSS = 1 << 4,
+    HIGH_BATT  = 1 << 5,
+    SHORT      = 1 << 6,
+    BACKFEED   = 1 << 7
+} error_mode_t;
+
+// "Misc" field bit masks
+typedef enum {
+    AC_UNIT    = 1,
+    RESERVE1   = 1 << 1,
+    RESERVE2   = 1 << 2,
+    RESERVE3   = 1 << 3,
+    RESERVE4   = 1 << 4,
+    RESERVE5   = 1 << 5,
+    RESERVE6   = 1 << 6,
+    AUX_OUT_ON = 1 << 7
+} misc_byte_t;
+
+// These are the numeric equivalents for the ASCII representation
+typedef enum {
+    INV_OFF     = 0,
+    INV_SEARCH  = 1,
+    INV_ON      = 2,
+    CHARGE      = 3,
+    SILENT      = 4,
+    FLOAT       = 5,
+    EQ          = 6,
+    CHARGER_OFF = 7,
+    SUPPORT     = 8,
+    SELL_ON     = 9,
+    PASS_THRU   = 10,
+    FX_ERR      = 90,
+    AGS_ERR     = 91,
+    COM_ERR     = 92
+} op_mode_t;
+
+typedef enum {
+    DISABLED    = 0,
+    DIVERSION   = 1,
+    REMOTE      = 2,
+    MANUAL      = 3,
+    VENT_FAN    = 4,
+    PV_TRIGGER  = 5
+} aux_mode_t;
+
+typedef enum {
+    SILENT_MODE = 0,
+    FLOAT_MODE  = 1,
+    BULK_MODE   = 2,
+    ABSORB_MODE = 3,
+    EQ_MODE     = 4
+} charge_mode_t;
+
+typedef enum {
+    NO_AC = 0,
+    AC_DROP = 1,
+    AC_USE = 2  
+} AC_mode_t ;
+
+// When sending the command, each of these bytes needs to be sent twice
+typedef enum {
+    ON          = 'O',
+    SEARCH      = 'S',
+    OFF         = 'F',
+    USE         = 'U',
+    DROP        = 'D',
+    AUX_ON      = 'Z',
+    AUX_OFF     = 'X'
+} fx_commands_t;
+
+typedef enum {
+    OUTBACK_NONE,
+    OUTBACK_MX,
+    OUTBACK_FX
+} outback_type_t;
+
+class outback : public Serial
+{
+public:
+    outback();
+    outback(const char *filespec);
+    outback(std::string filespec);
+    ~outback();
+    // Set up the object with data from the packet.
+    retcode_t parse(const char *packet);
+
+    // Initialize the serial port
+    retcode_t commInit(std::string);
+    retcode_t commInit(int fd);
+
+    // The main loop for an outback device
+    retcode_t main();
+    retcode_t main(Console &con);
+    retcode_t main(Console &con, Database &db);
+  
+    // calculate the ASCII packet
+    retcode_t calcChecksum(const char *packet);  
+
+    // Get the type of device
+    outback_type_t typeGet();
+  
+    // Get the address of the unit.
+    char addressGet() { return _address; }
+  
+    // Get the current readings
+    int inverterCurrentGet()        { return _inverter_current; };
+    int chargerCurrentGet()         { return _charge_current; };
+    int buyCurrentGet()             { return _buy_current; };
+    int pvCurrentGet()              { return _pv_current; };
+    int sellCurrentGet()            { return _sell_current; };
+  
+    // Get the voltage readings
+    int pvInputVoltageGet()         { return _pv_input_voltage; };
+    int ACInputVoltageGet()         { return _AC_input_voltage; };
+    int ACOutputVoltageGet()        { return _AC_output_voltage; };
+    int batteryVoltageGet()         { return _battery_voltage; };
+
+    // Get the modes
+    op_mode_t operatingModeGet()    { return _operating_mode; };
+    error_mode_t errorModeGet()     { return _error_mode; };
+    warning_mode_t warningModeGet() { return _warning_mode; };
+    AC_mode_t ACModeGet()           { return  _AC_mode; };
+    misc_byte_t miscByteGet()       { return _misc_byte; };
+    aux_mode_t auxModeGet()         { return _aux_mode; };
+    charge_mode_t chargeModeGet()   { return _charge_mode; };
+
+    // Read from the serial port
+    const char *readSerial();
+
+    // Write an FX command to the serial port
+    retcode_t sendFXCommand(fx_commands_t cmd);
+
+    void dump();
+
+    meter_data_t *exportMeterData(meter_data_t *data);
+  
+private:
+    outback_type_t _type;
+    // The address of the unit.
+    char _address;
+
+    // Amperage readings. These range from 0-99 in 1 amp increments
+    int _inverter_current;
+    int _charge_current;
+    int _buy_current;
+    int _pv_current;
+    int _sell_current;
+
+    // Voltage readings. These range from 0-256. If the Misc Mode bit is
+    // set, then this number is multiplied by 2.
+    int _AC_input_voltage;
+    int _AC_output_voltage;
+    // one volt increments, ignore the misc Byte
+    int _pv_input_voltage;
+    // the resolution is 0.1 volts for a 12VDC system, 0.2 volts for a
+    // 24VDC system, and 0.4 for a 48 volt system.
+    int _battery_voltage;
+    // The total kilowatts used daily. This ranges from 0-999, with the
+    // last digit being the fraction. ie... 99 = 99.9.
+    int _daily_kwh;
+
+    // Modes. Not all modes are currently implemented on the MX
+    // series. All the modes range from 0-99 except for the error and
+    // warning modes which range from 0-256.
+    op_mode_t _operating_mode;
+    AC_mode_t _AC_mode;
+    misc_byte_t _misc_byte;
+    aux_mode_t _aux_mode;
+    charge_mode_t _charge_mode;
+
+    error_mode_t _error_mode;
+    warning_mode_t _warning_mode;
+    int _checksum;
+};
+
+// end of namespace outback
+}
+
+// __OUTBACK_POWER_H__
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/devices/xanbus.cc b/devices/xanbus.cc
new file mode 100644
index 0000000..efb82ef
--- /dev/null
+++ b/devices/xanbus.cc
@@ -0,0 +1,1682 @@
+// 
+// Copyright (C) 2011 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <vector>
+#include <map>
+
+#include "err.h"
+#include "log.h"
+#include "console.h"
+#include "xanbus.h"
+#include "database.h"
+
+using namespace std;
+
+static std::string menudisp;
+static char buffy[100];
+
+extern LogFile dbglogfile;
+
+const XanbusUI::cmd_data_t xanbus[] = {
+    { XanbusUI::XanbusUI::XACCESS, "ACCESS", false },
+    { XanbusUI::XanbusUI::BACKLIGHT, "BACKLIGHT", false },
+    { XanbusUI::CONT, "CONT", false },
+    { XanbusUI::CUSTOM11_QUERY, "CUSTOM11?", true },
+    { XanbusUI::CUSTOM12_QUERY, "CUSTOM12?", true },
+    { XanbusUI::CUSTOM11ERASE, "CUSTOM11ERASE", false },
+    { XanbusUI::CUSTOM12ERASE, "CUSTOM12ERASE", false },
+    { XanbusUI::CUSTOM21, "CUSTOM21", true },
+    { XanbusUI::CUSTOM22, "CUSTOM22", true },
+    { XanbusUI::CUSTOM21_QUERY, "CUSTOM21?", true },
+    { XanbusUI::CUSTOM22_QUERY, "CUSTOM22?", true },
+    { XanbusUI::CUSTOM21ERASE, "CUSTOM21ERASE", true },
+    { XanbusUI::CUSTOM22ERASE, "CUSTOM22ERASE", true },
+    { XanbusUI::DCCOMPLEV_QUERY, "DCCOMPLEV?", true },
+    { XanbusUI::DCDC_QUERY, "DCDC?", true },
+    { XanbusUI::DERATELIMIT_QUERY, "DERATELIMIT?", true },
+    { XanbusUI::ERR_QUERY, "ERR?", true },
+    { XanbusUI::FAULTACTIVE_QUERY, "FAULTACTIVE?", true },
+    { XanbusUI::FAULTGND_QUERY, "FAULTGND?", true },
+    { XanbusUI::FAULTLAST_QUERY, "FAULTLAST?", true },
+    { XanbusUI::FAULTLOG_QUERY, "FAULTLOG?", true },
+    { XanbusUI::FREQ_QUERY, "FREQ?", true },
+    { XanbusUI::FWHW_QUERY, "FWHW?", true },
+    { XanbusUI::IDN_QUERY, "IDN?", true },
+    { XanbusUI::IIN_QUERY, "IIN?", true },
+    { XanbusUI::INV_QUERY, "INV?", true },
+    { XanbusUI::IOUT_QUERY, "IOUT?", true },
+    { XanbusUI::KNOCK, "KNOCK", true },
+    { XanbusUI::KWHLIFE_QUERY, "KWHLIFE?", true },
+    { XanbusUI::KWHLIFESYS_QUERY, "KWHLIFESYS?", true },
+    { XanbusUI::KWHTODAY_QUERY, "KWHTODAY?", true },
+    { XanbusUI::KWHTODAYSYS_QUERY, "KWHTODAYSYS?", true },
+    { XanbusUI::XKWHTODAY_QUERY, "XKWHTODAY?", true },
+    { XanbusUI::MEASENGY_QUERY, "MEASENGY?", true },
+    { XanbusUI::MEASENGYSYS_QUERY, "MEASENGYSYS?", true },
+    { XanbusUI::MEASICMM_QUERY, "MEASICMM?", true },
+    { XanbusUI::MEASIN_QUERY, "MEASIN?", true },
+    { XanbusUI::MEASOUT_QUERY, "MEASOUT?", true },
+    { XanbusUI::MEASRAW_QUERY, "MEASRAW?", true },
+    { XanbusUI::MEASTEMP_QUERY, "MEASTEMP?", true },
+    { XanbusUI::MEMFREE_QUERY, "MEMFREE?", true },
+    { XanbusUI::MODELID_QUERY, "MODELID?", true },
+    { XanbusUI::MODELSTR_QUERY, "MODELSTR?", true },
+    { XanbusUI::MONPARAM_QUERY, "MONPARAM?", true },
+    { XanbusUI::MONALL_QUERY, "MONALL?", true },
+    { XanbusUI::MONAUXPARAM_QUERY, "MONAUXPARAM?", true },
+    { XanbusUI::MONENS_QUERY, "MONENS?", true },
+    { XanbusUI::MONENSPARAM_QUERY, "MONENSPARAM?", true },
+    { XanbusUI::MONEXT_QUERY, "MONEXT?", true },
+    { XanbusUI::MONEXTPARAM_QUERY, "MONEXTPARAM?", true },
+    { XanbusUI::MONFB_QUERY, "MONFB?", true },
+    { XanbusUI::MONFBPARAM_QUERY, "MONFBPARAM?", true },
+    { XanbusUI::MONGND_QUERY, "MONGND?", true },
+    { XanbusUI::MONGNDPARAM_QUERY, "MONGNDPARAM?", true },
+    { XanbusUI::MONGRID_QUERY, "MONGRID?", true },
+    { XanbusUI::MONGRIDPARAM_QUERY, "MONGRIDPARAM?", true },
+    { XanbusUI::MONTEMP_QUERY, "MONTEMP?", true },
+    { XanbusUI::MONTEMPPARAM_QUERY, "MONTEMPPARAM?", true },
+    { XanbusUI::MONOVPARAM_QUERY, "MONOVPARAM?", true },
+    { XanbusUI::MONUVPARAM_QUERY, "MONUVPARAM?", true },
+    { XanbusUI::MONVIN_QUERY, "MONVIN?", true },
+    { XanbusUI::MPPT_QUERY, "MPPT?", true },
+    { XanbusUI::MPPTDBG_QUERY, "MPPTDBG?", true },
+    { XanbusUI::MPPTLEV_QUERY, "MPPTLEV?", true },
+    { XanbusUI::MPPTLEVM_QUERY, "MPPTLEVM?", true },
+    { XanbusUI::MPPTOFFSET_QUERY, "MPPTOFFSET?", true },
+    { XanbusUI::MPPTSTAT_QUERY, "MPPTSTAT?", true },
+    { XanbusUI::NVMEMSPACE_QUERY, "NVMEMSPACE?", true },
+    { XanbusUI::OFFSET_QUERY, "OFFSET?", true },
+    { XanbusUI::OLDERLIM_QUERY, "OLDERLIM?", true },
+    { XanbusUI::PDCMPPT_QUERY, "PDCMPPT?", true },
+    { XanbusUI::PIN_QUERY, "PIN?", true },
+    { XanbusUI::POUT_QUERY, "POUT?", true },
+    { XanbusUI::POUTSYS_QUERY, "POUTSYS?", true },
+    { XanbusUI::PROD_QUERY, "PROD?", true },
+    { XanbusUI::POWLIMIT_QUERY, "POWLIMIT?", true },
+    { XanbusUI::POWSEQ_QUERY, "POWSEQ?", true },
+    { XanbusUI::POWSEQCLR, "POWSEQCLR", true },
+    { XanbusUI::QUEUED_QUERY, "QUEUED?", true },
+    { XanbusUI::RECTIME_QUERY, "RECTIME?", true },
+    { XanbusUI::RELAY_QUERY, "RELAY?", true },
+    { XanbusUI::RIPCOMP_QUERY, "RIPCOMP?", true },
+    { XanbusUI::ROM_QUERY, "ROM?", true },
+    { XanbusUI::SCALE_QUERY, "SCALE?", true },
+    { XanbusUI::SCID_QUERY, "SCID?", true },
+    { XanbusUI::SCROLL, "SCROLL", true },
+    { XanbusUI::STANDBY, "STANDBY", true },
+    { XanbusUI::STANDBY_QUERY, "STANDBY?", true },
+    { XanbusUI::TEMPLIMIT_QUERY, "TEMPLIMIT?", true },
+    { XanbusUI::TEMPLIMITSTEP_QUERY, "TEMPLIMITSTEP?", true },
+    { XanbusUI::TIME_QUERY, "TIME?", true },
+    { XanbusUI::VDCREF_QUERY, "VDCREF?", true },
+    { XanbusUI::VIN_QUERY, "VIN?", true },
+    { XanbusUI::XBADX_QUERY, "XBADX?", true }
+};
+
+XanbusUI::XanbusUI(void)
+{
+    SetDefaultValues();  
+}
+
+XanbusUI::~XanbusUI(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+string &
+XanbusUI::ReadSerial(void)
+{
+    int ret;
+    //DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+
+#if 0 
+    int retries = 1;
+  
+    while (retries--) {
+        if (ret = Read((char *)&buffy, 99) < 0) {
+            //dbglogfile << "FIXME: " << retries << "\t" << buffy << endl;
+            //ret = Read((char *)&buffy, 100);
+            continue;
+        } else {
+            break;
+        }
+    }
+#else
+    ret = Read((char *)&buffy, 100);
+#endif
+  
+    if (ret > 0) {
+        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buffy << "\t" 
<< buffy << endl;
+        menudisp = buffy;
+    } else {
+        menudisp.erase();
+    }
+  
+    return menudisp;
+}
+
+string
+XanbusUI::GetLabel() {
+    //DEBUGLOG_REPORT_FUNCTION;
+
+    dbglogfile << "menuheading: " << menuheading << " menuitem:" << menuitem 
<< endl;
+  
+    MenuItem ti = GetItem(menuheading, menuitem);
+  
+    return ti.GetLabel();
+}
+
+string &
+XanbusUI::WriteSerial(const char *buf, int nbytes)
+{
+    int ret;
+  
+    //DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    ret = Write(buf, nbytes);
+    //dbglogfile << "FIXME" << buffy << endl;
+    ret = Read(buffy, nbytes);
+  
+    menudisp = buffy;
+    return menudisp;
+}
+
+// This selects which inverter we want to control
+string &
+XanbusUI::SelectInverter(int x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+
+    Write((char *)&x, 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+// These methods all go with the Xantrex display buttons
+string &
+XanbusUI::MenuHeadingMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    //memset(buffy, 0, 100);
+  
+    Write("L", 1);
+    //Read((char *)&buffy, 100);
+    menudisp = ReadSerial();
+    //dbglogfile << "FIXME" << menudisp << endl;
+
+    //cerr << "FIXMEh-: \"" << menudisp  << "\"" << endl;
+    //cerr << "FIXMEh-: \"" << GetLabel() << "\"" << endl;
+
+    if (menuheading > 1) {
+        menuheading--;
+    }
+    menuitem = 0;
+
+    if (menudisp.find(GetLabel()) == string::npos) {
+        dbglogfile << "Heading Minus didn't Match!!" << menuheading << endl;  
+    } else {
+        dbglogfile << "Heading Minus Matched!!" << endl;
+    }
+
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::MenuHeadingPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    //memset(buffy, 0, 100);
+    MenuItem mi;
+  
+    Write("R", 1);
+  
+    //Read((char *)&buffy, 100);
+    menudisp = ReadSerial();
+    //mi = GetItem();
+
+    //dbglogfile << menudisp << endl;
+
+    menuheading++;
+    menuitem = 0;
+
+    //cerr << "FIXMEh+: \"" << menudisp  << "\"" << endl;
+    //cerr << "FIXMEh+: \"" << GetLabel() << "\"" << endl;
+  
+    if (menudisp.find(GetLabel()) == string::npos) {
+        dbglogfile << "Heading Plus didn't Match!!" << endl;  
+    } else {
+        dbglogfile << "Heading Plus Matched!!" << endl;
+    }
+
+
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+// This decends through the sub menu items of a heading
+string &
+XanbusUI::MenuItemMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int retries = 5;
+    string label;
+  
+    //memset(buffy, 0, 100);
+  
+    //Write("D", 1);
+    //Read((char *)&buffy, 100);
+    //menudisp = ReadSerial();
+    //dbglogfile << menudisp << endl;
+
+    menuitem++;
+
+    //cerr << "FIXME-I: \"" << menuheading << "," << menuitem << "\"" << endl;
+    while (retries--) {
+        Write("D", 1);
+        menudisp = ReadSerial();
+        //Flush();
+        //cerr << "FIXMEi-: \"" << menudisp  << "\"" << endl;
+        //cerr << "FIXMEi-: \"" << GetLabel() << "\"" << endl;
+
+        label = GetLabel();
+        if (label.size()) {
+            if (menudisp.find(label) == string::npos) {
+                dbglogfile << "Item Minus didn't Match!!" << endl;
+            } else {
+                dbglogfile << "Item Minus Matched!!" << endl;
+                break;
+            }
+        }
+    }
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::MenuItemPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int retries = 5;
+
+    //memset(buffy, 0, 100);
+  
+    //Write("U", 1);
+    //Read((char *)&buffy, 100);
+    //menudisp = ReadSerial();
+    //dbglogfile << menudisp << endl;
+    //menudisp = buffy;
+    if (menuitem > 1)
+        menuitem--;
+
+    //  if (strcmp(label.c_str(), buffy) == 0)
+    //    dbglogfile << "AAAAHHHHHHH" << endl;
+  
+    while (retries--) {
+        Write("U", 1);
+        menudisp = ReadSerial();
+        //Flush();
+
+        //cerr << "FIXMEi+: \"" << menudisp  << "\"" << endl;
+        //cerr << "FIXMEi+: \"" << GetLabel() << "\"" << endl;
+
+        if (menudisp.find(GetLabel()) == string::npos) {
+            dbglogfile << "Item Plus didn't Match!!" << endl;
+        } else {
+            dbglogfile << "Item Plus Matched!!" << endl;
+            break;
+        }
+    }
+
+    //  if (menudisp != label)
+    //  dbglogfile << "FIXME: Wrong Item " << menuheading << ":" << menuitem 
<< menudisp << "\t" << label << endl;
+    
+    return menudisp;
+}
+
+string &
+XanbusUI::SetPointMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("-", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::SetPointPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("+", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::Inverter(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("|", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::Generator(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("G", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::SetupMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("\003", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menuheading = 8;
+    menuitem = 0;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::LedStatus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("?", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;  
+}
+
+string &
+XanbusUI::Version(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("V", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XanbusUI::SetTerminalMode(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("T", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+#if 0
+// These methods are for switching menu modes
+retcode_t
+XanbusUI::GotoSetupMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+retcode_t
+XanbusUI::GotoUserMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+string &
+XanbusUI::UserMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+#endif
+
+// This method takes us to the beginning of the menu headers and items
+// This corresponds then to being in the Inverter Mode header of the
+// User menu.
+retcode_t
+XanbusUI::GotoMenuStart(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int i;
+    for (i=0; i<22; i++) {
+        // Don't use MenuheadingMinus, as it gets all confused
+        Write("L", 1);
+        menudisp = ReadSerial();
+        if (menudisp.find("Inverter", 0) != string::npos) {
+            break;
+        }
+    }
+  
+    menuheading = 1;
+    menuitem = 0;
+    dbglogfile << "At Start Of Menu" << endl;
+  
+    return SUCCESS;
+}
+
+// These methods manipulate values
+retcode_t
+XanbusUI::SetFloatValue(float )
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    cerr << "ERROR: unimplemented!" << endl;
+    return ERROR;
+}
+
+float
+XanbusUI::GetFloatValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    return atof(GetValue(str).c_str());
+}
+
+retcode_t
+XanbusUI::SetIntValue(int x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    cerr << "ERROR: unimplemented!" << endl;
+    return ERROR;
+}
+
+int
+XanbusUI::GetIntValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    return atoi(GetValue(str).c_str());
+}
+
+bool
+XanbusUI::GetBoolValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    string tmpstr = GetValue(str).c_str();
+  
+    if (tmpstr == "NO" || tmpstr == "OFF")
+        return false;
+    else
+        return true;
+}
+
+string &
+XanbusUI::GetValue (std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos, pos2;
+    //string value;
+    int i = 0;
+    string lookfor;
+
+    //cout << "The Raw value string is: " << str << endl;
+
+#if 0
+    pos = str.find("-00", str.length());
+    if (pos != string::npos) {
+        str.erase(pos, str.length() - pos);
+    }
+#endif
+  
+    do {
+        lookfor = " ";
+        char j = '0' + i;
+        lookfor += j;
+        pos = str.find(lookfor, 0);
+        lookfor.erase();
+    } while ((pos == string::npos) && (i++ < 10));
+  
+    pos2 = str.find(' ', pos+1);
+    if (pos2 == string::npos) {
+        pos2 = pos + 4;
+    }
+  
+    str = str.substr(pos+1, pos2 - pos);
+
+#if 0
+    if (pos != string::npos) {
+        // We want just the last data item, which is the value
+        value = str.substr(pos+1, str.length() - pos);
+        str = value;
+    } else {
+        str.erase();
+    }
+#endif
+  
+    return str;
+}
+
+vector<string> *
+XanbusUI::GetValues (std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos;
+    string value;
+    vector<string> *array;
+
+    array = new vector<string>;
+
+    //cout << "The Raw values string is: " << str << endl;
+
+    do {
+        pos = str.find("-00", str.length());
+        if (pos != string::npos) {
+            str.erase(pos, str.length() - pos);
+        }
+    
+        // Find the last space in the string
+        pos = str.rfind(' ' , str.length());
+    
+        if (pos != string::npos) {
+            // We want just the last data item, which is the value
+            value = str.substr(pos+1, str.length() - pos);
+            str = value;
+            array->push_back(value);
+        } else {
+            str.erase();
+        }
+    } while (pos != string::npos);
+  
+  
+    return array;
+}
+
+std::string
+XanbusUI::GetLabel(std::string &x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos;
+
+    // Find the last space in the string
+    pos = x.rfind(' ' , x.length());
+    //pos = x.rfind('\t' , x.length());
+
+    if (pos != string::npos) {
+        return x.substr(0, pos);
+    }
+  
+    return x;
+}
+
+
+string &
+XanbusUI::GotoMenuItem(int mh, int mi)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string tmpstr;
+    int i;
+    MenuItem item;
+  
+    GotoMenuStart();
+
+    item = GetItem(mh, mi);
+    for (i=0; i < mh-1; i++) {
+        menudisp = MenuHeadingPlus();
+    }
+  
+    for (i=0; i < mi-1; i++) {
+        menudisp = MenuItemMinus();
+    }
+
+    if (menudisp.find(item.GetLabel()) != string::npos) {
+        dbglogfile << "Didn't Match!!" << endl;  
+    }
+
+    //menudisp = CleanUpData(tmpstr);
+  
+    menuheading = mh;
+    menuitem = mi;
+
+    return menudisp;
+}
+
+//std::map<std::string, float> *
+//std::vector< std::map< std::string, float > >
+vector<meter_data_t *>
+XanbusUI::PollMeters(int loops)
+{
+    MenuItem      ti;
+    int           mh = 4;
+    int           mi = 1;
+    int           items = 7;                // the number of data items to get
+    float         fltval;
+    int           intval;
+    int           i;
+    string        str, label;
+    meter_data_t *downdata, *updata;
+    vector<meter_data_t *> meters;
+
+    //memset(buffy, 0, 100);
+
+    GotoMenuItem(mh, mi);
+    while (loops-- > 0) {
+        downdata = new meter_data_t;
+        memset(downdata, 0, sizeof(meter_data_t));
+    
+        for (i=mi; i<= mi+items; i++) {
+            str = MenuItemMinus();
+            fltval = 0.0;
+            intval = 0;
+            if (str.size() > 1) {
+                ti = GetItem();
+                if (ti.GetType() != MenuItem::INFO) {
+                    label = GetLabel(); 
+                    cout << "The Menu Item Label down is: " << label;
+                }
+                ti = GetItem();
+                if (ti.GetType() == MenuItem::FLOAT) {
+                    fltval = GetFloatValue(str);
+                    cout << ", with a float value is: " << fltval << endl;
+                }
+                if (ti.GetType() == MenuItem::INT) {
+                    intval = GetIntValue(str);
+                    cout << ", with an Integer value is: " << intval << endl;
+                }
+                if (ti.GetType() == MenuItem::INFO) {
+                    cout << ", an INFO statement  " << endl;
+                    break;
+                }
+                if (label.substr(0, 5) == "Input") {
+                    //downdata->
+                }
+                if (label.substr(0, 4) == "Load") {
+                    dbglogfile << "Matched label going down " << label;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->ac_load_amps = intval;
+                }
+                if (label.substr(8, 6) == "actual") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->battery_volts = fltval;
+                }
+                if (label.substr(8, 8) == "TempComp") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->tempcomp_volts = fltval;
+                }
+                if (label.substr(0, 8) == "Inverter") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->ac_volts_out = intval;
+                }
+                if (label.substr(0, 4) == "Grid") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->ac1_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Generator") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->ac2_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Read Freq") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->hertz = intval;
+                }
+            }
+        }
+
+        meters.push_back(downdata);
+        //MenuItemMinus();            // go one more, since the first thing
+        // we do is come back up one item.
+        updata = new meter_data_t;
+        memset(updata, 0, sizeof(meter_data_t));
+        //ptr2 = (float *)((char *)updata + 
sizeof(meter_data_t)-sizeof(float));
+        //*ptr2-- = downdata->hertz;
+    
+        // Now go up through the menu
+        for (i=mi+items; i>mi; i--) {
+            str = MenuItemPlus();
+            fltval = 0.0;
+            intval = 0;
+            if (str.size() > 0) {
+                label = GetLabel(); 
+                cout << "The Menu Item Label up is: " << label;
+                ti = GetItem();
+                if (ti.GetType() == MenuItem::FLOAT) {
+                    fltval = GetFloatValue(str);
+                    cout << ", with a float value is: " << fltval << endl;
+                }
+                if (ti.GetType() == MenuItem::INT) {
+                    intval = GetIntValue(str);
+                    cout << ", with an integer value is: " << intval << endl;
+                }
+                //Flush();
+                //_data.push(label, );
+                if (label.substr(0, 5) == "Input") {
+                    //updata->
+                }
+                if (label.substr(0, 4) == "Load ") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    updata->ac_load_amps = intval;
+                }
+                if (label.substr(8, 6) == "actual") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->battery_volts = fltval;
+                }
+                if (label.substr(8, 8) == "TempComp") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->tempcomp_volts = fltval;
+                }
+                if (label.substr(0, 8) == "Inverter") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    updata->ac_volts_out = intval;
+                }
+                if (label.substr(0, 4) == "Grid") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->ac1_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Generator") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->ac2_volts_in = fltval;
+                }
+                // Since this is the last and first reading, it doesn't really
+                // have time to change.
+                updata->hertz = downdata->hertz;
+//         if (label.substr(0, 9) == "Read Freq") {
+//           dbglogfile << "Matched label going up " << label << endl;
+//           dbglogfile << " value is: " << intval << endl;
+//           updata->hertz = intval;
+//         }
+            } // end of if str
+        } // end of for loop
+        meters.push_back(updata);
+    }
+    // Go back to the top
+//   for (i=items; i>=mi; i--) {
+//     MenuItemPlus();
+//   }
+  
+    MenuHeadingPlus();
+    MenuHeadingMinus();          
+  
+    return meters;
+}
+
+// This method takes the data as outputted by the Xantrex inverter,
+// and munges it to be a standard form with whitespace compressed,
+// newlines & carriage returns stripped out, etc... This is so
+// we can analyse the string data in a consistant fashion.
+std::string &
+XanbusUI::CleanUpData(std::string &str)
+{
+    unsigned int i;
+
+    menudisp.erase();
+    for (i=0; i< str.length(); i++) {
+        switch (str[i]) {
+            // we ignore these characters
+          case '\r':
+          case '\n':
+              break;
+              // compress multiple spaces to be just one
+          case ' ':
+              if (str[i+1] == ' ') {
+                  continue;
+              } else {
+                  menudisp += ' ';
+                  break;
+              }
+          default:
+              menudisp += str[i];
+        }
+    }
+
+    return menudisp;
+}
+
+void
+XanbusUI::SetDefaultValues(void)
+{
+
+    MenuItem mi;
+
+    // We know we always have 20 major menu headings
+    _items.resize(21);
+
+    mi.SetItem ("Top of Menu", 0);
+    _items[0].push_back(mi);
+
+    // Inverter Mode - Menu Heading #1
+    mi.SetItem ("Inverter Mode",                      1);
+    _items[1].push_back(mi);
+
+    mi.SetItem ("Set Inverter     OFF SRCH ON CHG",   1, 1, "SetVert"); // 
FIXME: enum
+    _items[1].push_back(mi);
+    mi.SetItem ("CHG avail. Only  in FLT mode",       1, 2);
+    _items[1].push_back(mi);
+    mi.SetItem ("Press red or     setpoint button",   1, 3);
+    _items[1].push_back(mi);
+    mi.SetItem ("to move.         Move cursor to",    1, 4);
+    _items[1].push_back(mi);
+    mi.SetItem ("Inverter OFF to  resetOverCurrent",  1, 5);
+    _items[1].push_back(mi);
+
+    // Generator Mode - Menu Headings #2
+    mi.SetItem ("Generator Mode",                     2);
+    _items[2].push_back(mi);
+    mi.SetItem ("Set Generator    OFF AUTO ON EQ",    2, 1, "SetGen"); // 
FIXME: enum
+    _items[2].push_back(mi);
+    mi.SetItem ("Gen under/over   speed",             2, 2, false, "GenSpeed");
+    _items[2].push_back(mi);  
+    mi.SetItem ("Generator start  error",             2, 3, false, "GenStart");
+    _items[2].push_back(mi);
+    mi.SetItem ("Generator sync   error",             2, 4, false, "GenSync");
+    _items[2].push_back(mi);
+    mi.SetItem ("Gen max run Time error",             2, 5, false, "GenMax");
+    _items[2].push_back(mi);
+    mi.SetItem ("Load Amp Start   ready",             2, 6, false, "LoadAmp");
+    _items[2].push_back(mi);
+    mi.SetItem ("Voltage Start    ready",             2, 7, false, 
"VoltStart");
+    _items[2].push_back(mi);
+    mi.SetItem ("Exercise Start   ready",             2, 8, false, 
"ExerStart");
+    _items[2].push_back(mi);
+  
+    // Xantrex Engineering - Menu Heading #3
+    // Xantrex was Trace, so this prompt varies depending on the
+    // software version on the inverter.
+    mi.SetItem ("Engineering",       3);
+    //mi.SetItem ("Trace            Engineering",       3);
+    _items[3].push_back(mi);
+    mi.SetItem ("Press reset now  for defaults",      3, 1);
+    _items[3].push_back(mi);
+    mi.SetItem ("Revision 4.01",                      3, 2, "XantrexRev");
+    _items[3].push_back(mi);
+    mi.SetItem ("5916 195th St NE Arlington, WA",     3, 3);
+    _items[3].push_back(mi);
+    mi.SetItem ("98223 USA",                          3, 4);
+    _items[3].push_back(mi);
+    mi.SetItem ("Ph  360-435-8826 Fax 360-435-2229",  3, 5);
+    _items[3].push_back(mi);
+
+    // Meters - Menu Heading #4
+    mi.SetItem ("Meters",                         4);
+    _items[4].push_back(mi);
+    mi.SetItem ("Inverter/charger amps AC",         4,  1, 0, "ChargerAmps");
+    _items[4].push_back(mi);
+    mi.SetItem ("Input            amps AC",         4,  2, 0, "InputAmps");
+    //mi.SetItem ("Input",                           4,  2, 0, "InputAmps");
+    _items[4].push_back(mi);
+    mi.SetItem ("Load             amps AC",         4,  3, 0, "LoadAmps");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Battery actual",                   4,  4, (float)25.1, 
"BattVolts");
+    mi.SetItem ("Battery actual   volts DC",        4,  4, (float)25.1, 
"BattVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Battery TempComp",                4,  5, (float)25.1, 
"TempComp");
+    mi.SetItem ("Battery TempComp volts DC",        4,  5, (float)25.1, 
"TempComp");
+    _items[4].push_back(mi);
+    mi.SetItem ("Inverter         volts AC",        4,  6, 0, "InvertVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Grid (AC1)",                       4,  7, 0, "GridVolts");
+    mi.SetItem ("Grid (AC1)       volts AC",                             4,  
7, 0, "GridVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Generator (AC2)",                  4,  8, 0, "GenVolts");
+    mi.SetItem ("Generator (AC2)  volts AC",                             4,  
8, 0, "GenVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Read Frequency",                   4,  9, 0, "ReadHertz");
+    mi.SetItem ("Read Frequency   Hertz",                           4,  9, 0, 
"ReadHertz");
+    _items[4].push_back(mi);
+    mi.SetItem ("AC1 & AC2 volts  valid only when", 4, 10);
+    _items[4].push_back(mi);
+    mi.SetItem ("inverter synced  to that input.",  4, 11);
+    _items[4].push_back(mi);
+    mi.SetItem ("Batt volt actual is used for",     4, 12);
+    _items[4].push_back(mi);
+    mi.SetItem ("LBCO,HBCO,LBX,   LBCI,sell volts", 4, 13);
+    _items[4].push_back(mi);
+    mi.SetItem ("and gen starting",                 4, 14);
+    _items[4].push_back(mi);
+    mi.SetItem ("Batt volt temp   comp is used,",   4, 15);
+    _items[4].push_back(mi);
+    mi.SetItem ("for float, bulk, eq & aux relays", 4, 16);
+    _items[4].push_back(mi);
+  
+    // Error Cause - Menu Heading #5
+    mi.SetItem ("Error Causes",                 5);
+    _items[5].push_back(mi);
+    mi.SetItem ("Over Current",                 5,  1, false, "OverCurrent");
+    _items[5].push_back(mi);
+    mi.SetItem ("Transformer      overtemp",    5,  2, false, "OverTemp");
+    _items[5].push_back(mi);
+    mi.SetItem ("Heatsink         overtemp",    5,  3, false, "HeatSink");
+    _items[5].push_back(mi);
+    mi.SetItem ("High Battery     voltage",     5,  4, false, "HighBatt");
+    _items[5].push_back(mi);
+    mi.SetItem ("Low Battery      voltage",     5,  5, false, "LowBatt");
+    _items[5].push_back(mi);
+    mi.SetItem ("Inverter breaker tripped",     5,  6, false, "Tripped");
+    _items[5].push_back(mi);
+    mi.SetItem ("Manual Off",                   5,  7, false, "ManualOff");
+    _items[5].push_back(mi);
+    mi.SetItem ("AC source wired  to output",   5,  8, false, "ACWired");
+    _items[5].push_back(mi);
+    mi.SetItem ("External error   (Stacked)",   5,  9, false, "ExtError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Generator start  error",       5, 10, false, "GenError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Generator sync   error",       5, 11, false, "SyncError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Gen maximum run  time error",  5, 12, false, "MaxRunError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Gen Under/Over   speed",       5, 13, false, "SpeedError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Inverter breaker tripped",     5, 14, false, "BreakerError");
+    _items[5].push_back(mi);
+  
+    // Time Of Day - Menu Heading #6
+    mi.SetItem ("Time of Day",                 6);
+    _items[6].push_back(mi);
+    mi.SetItem ("Time of Day      Set Clock hour", 6, 1, 0);
+    _items[6].push_back(mi);
+    mi.SetItem ("Set Clock minute",            6, 2, 0, "Minute");
+    _items[6].push_back(mi);
+    mi.SetItem ("Set Clock second",            6, 3, 0, "Second");
+    _items[6].push_back(mi);
+
+    // Generator timer - Menu Heading #7
+    mi.SetItem ("Generator Timer",           7);
+    _items[7].push_back(mi);
+    mi.SetItem ("Start Quiet      time h:m", 7, 1, 8 ); // FIXME: this should 
be a time
+    _items[7].push_back(mi);  
+    mi.SetItem ("End Quiet        time h:m", 7, 2, 8 ); // FIXME: this should 
be a time
+    _items[7].push_back(mi);
+
+    // End of User menus!
+    mi.SetItem ("END USER MENU", 8);
+    _items[8].push_back(mi);
+
+    // Inverter Setup - Menu heading #9
+    mi.SetItem ("Inverter Setup",               9);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Grid Usage",               9, 1); // FIXME: FLOAT
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Low battery  cut out VDC", 9, 2, (float)22.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set LBCO delay   minutes",     9, 3, 15);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Low battery  cut in VDC",  9, 4, (float)26.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set High battery cut out VDC", 9, 5, (float)32.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set search       watts",       9, 6, 48);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set search       spacing",     9, 7, 59);
+    _items[9].push_back(mi);
+
+    // Battery Charging - Menu heading #10
+    mi.SetItem ("Battery Charging",                10);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Bulk         volts DC",       10, 1, (float)28.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Absorption   time h:m",       10, 2, 2);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Float        volts DC",       10, 3, (float)26.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Equalize     volts DC",       10, 4, (float)28.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Equalize     time h:m",       10, 5, 2);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Max Charge   amps DC",        10, 6, 30);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Temp Comp    LeadAcid Nicad", 10, 7); // FIXME: LEADACID
+    _items[10].push_back(mi);
+
+    // AC Inputs - Menu heading #11
+    mi.SetItem ("AC Inputs",                       11);
+    _items[11].push_back(mi);
+    mi.SetItem ("inverter synced  to that input.", 11);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Grid (AC1)   amps AC",        11, 1, 60);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Gen (AC2)    amps AC",        11, 2, 30);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Input lower  limit VAC",      11, 3, 108);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Input upper  limit VAC",      11, 4, 132);
+    _items[11].push_back(mi);
+
+    // Generator Auto Start Setup - Menu heading #12
+    //  genauto.state = OFF;
+    mi.SetItem ("Gen Auto Start   setup",           12);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Start   amps AC",         12, 1, 33);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Start   delay min",       12, 2, 5);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Stop    delay min",       12, 3, 5);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 24 hr start  volts DC",        12, 4, (float)24.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 2 hr start   volts DC",        12, 5, (float)23.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 15 min start volts DC",        12, 6, (float)22.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Read LBCO 30 sec start VDC",       12, 7, 22);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Exercise     period days",     12, 8, 30);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Maximum run  time h:m",        12, 9, 8);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Max Run time to 0 to defeat.", 12, 10, 0);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Exercise to 0 to defeat.",     12, 11, 0);
+    _items[12].push_back(mi);
+    mi.SetItem ("See menu 9 to    to set LBCO.",    12, 12, 0);
+    _items[12].push_back(mi);
+
+    //Generator Starting Details - Menu heading #13
+    mi.SetItem ("Gen starting     details",      13);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set RY7 Function GlowStop Run", 13, 1, 0);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Gen warmup   seconds",      13, 2, 60);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Pre Crank    seconds",      13, 3, 10);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Max Cranking seconds",      13, 4, 10);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Post Crank   seconds",      13, 5, 30);
+    _items[13].push_back(mi);
+
+    // Auxilary relays - Menu heading #14
+    mi.SetItem ("Auxiliary Relays R9 R10 R11", 14);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 9      volts DC",       14, 1, 29);
+    _items[14].push_back(mi);
+    mi.SetItem ("R9 Hysteresis    volts DC",       14, 2, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 10     volts DC",       14, 3, (float)29.5);
+    _items[14].push_back(mi);
+    mi.SetItem ("R10 Hysteresis   volts DC",       14, 4, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 11     volts DC",       14, 5, 30);
+    _items[14].push_back(mi);
+    mi.SetItem ("R11 Hysteresis   volts DC",       14, 6, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Close on batt >  setpoint.",      14, 7);
+    _items[14].push_back(mi);
+    mi.SetItem ("Open  on  batt < setpoint - Hys", 14, 8);
+    _items[14].push_back(mi);
+    mi.SetItem ("Relays have 2    second delay on",14, 9);
+    _items[14].push_back(mi);
+    mi.SetItem ("Close, 0.1 sec   delay on open",  14, 10);
+    _items[14].push_back(mi);
+
+    // Bulk Charge Trigger Time - Menu heading #15
+    mi.SetItem ("Bulk Charge      Trigger Timer",   15);
+    _items[15].push_back(mi);              
+    mi.SetItem ("Set Start Bulk   time",            15, 1, 0);
+    _items[15].push_back(mi);              
+    mi.SetItem ("To disable timer set to 00:00",    15, 2);
+    _items[15].push_back(mi);              
+    mi.SetItem ("If grid timer    active set bulk", 15, 3);
+    _items[15].push_back(mi);              
+    mi.SetItem ("time after start charge time.",    15, 4);
+    _items[15].push_back(mi);              
+    mi.SetItem ("In SLT mode don't disable this",   15, 5);
+    _items[15].push_back(mi);              
+    mi.SetItem ("timer. It is the daily chg time.", 15, 6);
+    _items[15].push_back(mi);              
+
+    // Low Battery Transfer - Menu heading #16
+    mi.SetItem ("Low Battery      Transfer (LBX)",    16);
+    _items[16].push_back(mi);
+    mi.SetItem ("Set Low Battery  TransferVDC",       16, 1, (float)26.8);
+    _items[16].push_back(mi);
+    mi.SetItem ("Set Low Battery  cut in  VDC",       16, 2, (float)26);
+    _items[16].push_back(mi);
+    mi.SetItem ("See menu 9 to    enable LBX mode.",  16, 3);
+    _items[16].push_back(mi);
+    mi.SetItem ("Make sure LBX is above LBCO volts.", 16, 4);
+    _items[16].push_back(mi);
+
+    //  Battery Power Selling - Menu heading #17
+    mi.SetItem ("Battery Selling",                    17);
+    _items[17].push_back(mi);
+    mi.SetItem ("Set Battery Sell volts",             17, 1, (float)26.8);
+    _items[17].push_back(mi);
+    mi.SetItem ("Set Max Sell     amps",              17, 2, 30);
+    _items[17].push_back(mi);
+    mi.SetItem ("See menu 9 to    enable SELL mode.", 17, 3);
+    _items[17].push_back(mi);
+    mi.SetItem ("Make sure LBX is above LBCO volts.", 17, 4);
+    _items[17].push_back(mi);
+  
+    // Grid Usage Timer - Menu heading #18
+    mi.SetItem ("Grid Usage Timer",                 18);
+    _items[18].push_back(mi);
+    mi.SetItem ("Set Charge       time",            18,  1, 21); // FIXME: TIME
+    _items[18].push_back(mi);
+    mi.SetItem ("End Charge       time",            18,  2, 21); // FIXME: TIME
+    _items[18].push_back(mi);
+    mi.SetItem ("After Start      Charge time:",    18,  3);
+    _items[18].push_back(mi);
+    mi.SetItem ("SELL mode        charges battery.",18,  4);
+    _items[18].push_back(mi);
+    mi.SetItem ("FLT mode         charges battery", 18,  5);
+    _items[18].push_back(mi);
+    mi.SetItem ("After End Charge time:",           18,  6);
+    _items[18].push_back(mi);
+    mi.SetItem ("SELL mode sells  battery to AC1.", 18,  7);
+    _items[18].push_back(mi);
+    mi.SetItem ("FLT mode drops   AC1 and inverts", 18,  8);
+    _items[18].push_back(mi);
+    mi.SetItem ("Timer on when    start < > end;",  18,  9);
+    _items[18].push_back(mi);
+    mi.SetItem ("timer off when   start = end",     18, 10);
+    _items[18].push_back(mi);
+    mi.SetItem ("Sell and float   modes use timer", 18, 11);
+    _items[18].push_back(mi);
+    mi.SetItem ("SLT and LBX mode ignore timer",    18, 12);
+    _items[18].push_back(mi);
+  
+    // Information file battery - Menu Heading #19
+    mi.SetItem ("Information file battery",          19);
+    _items[19].push_back(mi);
+    mi.SetItem ("Batt temp comp   changes battery",  19, 1);
+    _items[19].push_back(mi);
+    mi.SetItem ("voltage reading  away from actual", 19, 2);
+    _items[19].push_back(mi);
+    mi.SetItem ("HBCO resets at:  6v/48, 3v/24 and", 19, 3);
+    _items[19].push_back(mi);
+    mi.SetItem ("1.5v/12v under   HBCO.",            19, 4);
+    _items[19].push_back(mi);
+    mi.SetItem ("LowBattTransfer  used in LBX, FLT", 19, 5);
+    _items[19].push_back(mi);
+    mi.SetItem ("Modes only. Goes back to battery",  19, 6);
+    _items[19].push_back(mi);
+    mi.SetItem ("at LowBattCutIn  (aka LBCI).",      19, 7);
+    _items[19].push_back(mi);
+    mi.SetItem ("For LBX mode set below LBCI so",    19, 8);
+    _items[19].push_back(mi);
+    mi.SetItem ("charger won't    cycle batteries",  19, 9);
+    _items[19].push_back(mi);
+    mi.SetItem ("up and down and  set LBCO below.",  19, 10);
+    _items[19].push_back(mi);
+  
+    // End of Setup - Menu Heading #20
+    mi.SetItem ("END SETUP MENU", 20);
+    _items[20].push_back(mi);
+}
+
+// Dump all the MenuItem data
+void
+XanbusUI::Dump (void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+
+    dbglogfile << "There are " << (int)_items.size() << " menu _items" << endl;
+
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            //it->Dump();
+            cout << it->GetHeaderIndex()
+                 << "," << it->GetItemIndex()
+                 << ": " << it->GetLabel() << endl;
+        }
+    }
+}
+
+void
+XanbusUI::DumpAliases (void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    string tmpstr;
+
+    cout << "Command Name\t\tMenu Item" << endl;
+    cout << "------------\t\t---------" << endl;
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            tmpstr = it->GetLabel();
+            if (it->GetAlias().size() > 0)
+                cout << it->GetAlias() << "  \t- " << CleanUpData(tmpstr) << 
endl;
+        }
+    }
+}
+
+MenuItem &
+XanbusUI::Match(string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    vector< MenuItem > arg;
+
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        arg = *mh;
+        for (it = arg.begin(); it != arg.end(); ++it) {
+            dbglogfile << "Matching \"" << it->GetAlias() << "\""
+                       << " against the argument \"" << str << "\"" << endl;
+            if (it->GetAlias() == str){
+                dbglogfile << "Matched " << it->GetLabel() << " !" << endl;
+                return *it;
+            }
+        }
+    }
+    // FIXME: this is a hack to set an error condition
+    str.erase();
+    return *it;
+}
+
+MenuItem &
+XanbusUI::GetItem(int x, int y)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    vector< MenuItem > arg;
+    string tmp;
+   
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            tmp = it->GetLabel();
+            if ((it->GetHeaderIndex() == x) && (it->GetItemIndex() == y)) {
+                return *it;
+            }
+        }
+    }
+
+    return *it;                  // FIXME: This probably isn't what we want
+}
+
+#if 0
+retcode_t
+XanbusUI::xantrex_main(Console &con);
+{
+
+#if 0
+    if (item.size() > 0) {
+        // See if the name is actually a specified index
+        if (item.find(":",0) != string::npos)
+            {
+                menuhead = atoi(item.substr(0, item.find(":",0)).c_str());
+                menuitem = atoi(item.substr(item.find(":",0) + 1, 2).c_str());
+            } else {
+            // lookup the alias to get the indexes
+            ti = ui.Match(item);
+            if (item.size() > 0) {
+                menuhead = ti->GetHeaderIndex();
+                menuitem = ti.GetItemIndex();
+            }
+        }
+    }
+#endif
+
+    // Go into console mode where we can type direct commands
+    // via the serial port. This just saves us from firing up
+    // kermit or minicom
+    if (console) {
+        Console con;
+        con.Open();
+        //ui.SetRaw();
+        while ((ch = con.Getc())!='q') {
+            if (ch > 0){             // If we have something, process it
+                if (echo)
+                    con.Putc (ch);          // echo inputted character to 
screen
+          
+                switch (ch) {
+                  case 'Q':
+                  case 'q':
+                      con.Reset();
+                      exit(0);
+                      break;
+                  case 'L':
+                      display = ui.MenuHeadingMinus();
+                      break;
+                  case 'R':
+                      display = ui.MenuHeadingPlus();
+                      break;
+                  case 'D':
+                      display = ui.MenuItemMinus();
+                      break;
+                  case 'U':
+                      display = ui.MenuItemPlus();
+                      break;
+                  case '+':
+                      display = ui.SetPointPlus();
+                      break;
+                  case '-':
+                      display = ui.SetPointMinus();
+                      break;
+                  case '|':
+                      display = ui.Inverter();
+                      break;
+                  case 'G':
+                      display = ui.Generator();
+                      break;
+                  case 'S':
+                      display = ui.SetupMenu();
+                      break;
+                  case 's':
+                      display = ui.GotoMenuStart();
+                      break;
+                  case '/':
+                      display = ui.LedStatus();
+                      break;
+                  case 'V':
+                      display = ui.Version();
+                      break;
+                  case 'T':
+                      display = ui.SetTerminalMode();
+                      break;
+                  case '?':
+                      con.Puts("PowerGuru - Xantrex mode\r\n");
+                      con.Puts("\t? - help\r\n");
+                      con.Puts("\tL - Menu Heading Minus\r\n");
+                      con.Puts("\tR - Menu Heading Plus\r\n");
+                      con.Puts("\tR - Menu Heading Plus\r\n");
+                      con.Puts("\tD - Menu Item Minus\r\n");
+                      con.Puts("\tU - Menu Item Plus\r\n");
+                      con.Puts("\t+ - Value Plus\r\n");
+                      con.Puts("\t- - Value Item Plus\r\n");
+
+                      con.Puts("\t| - Inverter Mode\r\n");
+                      con.Puts("\tG - Generator Mode\r\n");
+                      con.Puts("\tS - Setup Menu\r\n");
+                      con.Puts("\t/ - LED Status\r\n");
+                      con.Puts("\tV - Version\r\n");
+                      con.Puts("\tT - TerminalMode\r\n");
+                      con.Puts("\tQ - Quit\r\n");
+                  default:
+                      break;
+                };
+
+                //          display += "\r";
+                con.Putc('\r');
+                con.Puts(display);
+#if 0
+                switch (ui.GetDataType()) {
+                  case MenuItem::NONE:
+                  case MenuItem::MENUHEAD:
+                  case MenuItem::MENUITEM:
+                  case MenuItem::BOOL:
+                      if (ui.GetBoolValue() == false)
+                          dbglogfile << "\tBoolean value is: " << "OFF" ;
+                      else
+                          dbglogfile << "\tBoolean value is: " << "ON" ;      
+                      dbglogfile << endl;
+                      break;
+                  case MenuItem::INT:
+                      dbglogfile << "\tInteger value is: " << value.intval << 
endl;
+                      break;
+                  case MenuItem::FLOAT:
+                      cerr << "\tFIXME: Float value is: " << value.floatval << 
endl;
+                      break;
+                  case MenuItem::TIME:
+                      dbglogfile << "\tTime value is: " << value.timeval << 
endl;
+                      break;
+                  case MenuItem::EOL:
+                  case MenuItem::CLOCK:
+                  case MenuItem::ENUM:
+                  case MenuItem::DATE:
+                      dbglogfile << "\tFIXME: unsupported type! " << 
value.intval << endl;
+                      break;
+                  default:
+                      dbglogfile << "Data Type out of range";
+                      break;
+                };
+#endif
+            }
+
+            str += ui.ReadSerial();
+            if (str.size() > 0) {
+                con.Puts(str);
+                str.erase();
+            }
+        }
+    }
+    
+    // Get the value of a menu item
+    if (getitem){
+      
+        string str = ui.GotoMenuItem(menuhead, menuitem);
+        ti = ui.GetItem(menuhead, menuitem);
+        //    ui.Read((char *)&buffy, 100);
+        cerr << "Inverter returned: " << str << endl;
+
+        //      dbglogfile << "BREAK HERE" << endl;
+      
+        switch (ti.GetType()) {
+          case MenuItem::BOOL:
+              if (ui.GetBoolValue(str) == false)
+                  cout << "The Boolean value is: NO" << endl;
+              else
+                  cout << "The Boolean value is: YES" << endl;
+              break;
+          case MenuItem::INFO:
+              value = ui.GetValue(str);
+              cout << "The value is: " << value << endl;
+              break;
+          case MenuItem::INT:
+              intval = ui.GetIntValue(str);
+              cout << "The Integer value is: " << intval << endl;
+              break;
+          case MenuItem::FLOAT:
+              fltval= ui.GetFloatValue(str);
+              cout << "The Float value is: " << fltval << endl;
+              break;
+          case MenuItem::MENUHEAD:
+              cout << "The Menu Header is: " << "\"" <<
+                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+              break;
+          case MenuItem::MENUITEM:
+              cout << "The Menu Item is: " << "\"" <<
+                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+              break;
+          case MenuItem::TIME:
+              value = ui.GetValue(str);
+              cout << "The Time is: " << "\"" << value << endl;
+              break;
+          case MenuItem::EOL:
+              value = ui.GetValue(str);
+              cout << "The Time is: " << "\"" << value << endl;
+              break;
+          case MenuItem::CLOCK:
+              value = ui.GetValue(str);
+              cout << "The Clock value is: " << "\"" << value << endl;
+              break;
+          case MenuItem::ENUM:
+              value = ui.GetValue(str);
+              cout << "The Enum value is: " << "\"" << value << endl;
+              break;
+          case MenuItem::DATE:
+              value = ui.GetValue(str);
+              cout << "The Date is: " << "\"" << value << endl;
+              break;
+          default:
+              cout << "The value is: " << value << endl;
+              value = str;
+        };
+    } // endof getitem
+
+    // Monitor an item. This means grabs successive values and
+    // display them. This is for selections that constantly update
+    // the value.
+    if (monitor) {
+        string str = ui.GotoMenuItem(menuhead, menuitem);
+        ti = ui.GetItem(menuhead, menuitem);
+
+        cout << "The Menu Header is: " << "\"" <<
+            ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+      
+        do {
+            memset(buffy, 0, 100);        
+            ret = ui.Read((char *)&buffy, 100);
+            str = buffy;
+            if (ret < 0)            // there is no input yet, try again
+                continue;
+
+            // We got something, so extract the type, and process the
+            // value.
+            switch (ti.GetType()) {
+              case MenuItem::BOOL:
+                  if (ui.GetBoolValue(str) == false)
+                      cout << "\tThe Boolean value is: NO" << endl;
+                  else
+                      cout << "\tThe Boolean value is: YES" << endl;
+                  break;
+              case MenuItem::INFO:
+                  value = ui.GetValue(str);
+                  cout << "\tThe value is: " << value << endl;
+                  break;
+              case MenuItem::INT:
+                  intval = ui.GetIntValue(str);
+                  cout << "\tThe Integer value is: " << intval << endl;
+                  break;
+              case MenuItem::FLOAT:
+                  fltval= ui.GetFloatValue(str);
+                  cout << "\tThe Float value is: " << fltval << endl;
+                  break;
+              case MenuItem::MENUHEAD:
+                  cout << "\tThe Menu Header is: " << "\"" <<
+                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+                  break;
+              case MenuItem::MENUITEM:
+                  cout << "\tThe Menu Item is: " << "\"" <<
+                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+                  break;
+              default:
+                  cout << "\tThe value is: " << value << endl;
+                  value = str;
+            };
+        } while (ret); // endof monitor   
+    }
+}
+#endif
+
+meter_data_t *
+XanbusUI::exportMeterData(meter_data_t *data)
+{
+#if 0
+    // The unit number for the device
+    data->unit = _address;
+  
+    // The type of the device
+    switch (_type) {
+      case OUTBACK_MX:
+          data->type = MX_OUTBACK;
+          break;
+      case OUTBACK_FX:
+          data->type = FX_OUTBACK;
+          break;
+      case SW_XANTREX:
+      default:
+          break;
+    };
+  
+    // The amperage being put into the batteries
+    data->charge_amps = _charge_current;
+    // The load in amps
+    data->ac_load_amps = _inverter_current;
+    // Actual Battery Voltage
+    data->battery_volts = _battery_voltage;
+    // Battery Voltage temperature compensated. This isn't used by
+    // Outback products.
+    data->tempcomp_volts = 0;
+    // The voltage the inverter is producing
+    data->ac_volts_out = _AC_output_voltage;
+    // Grid AC input
+    data->ac1_volts_in = _AC_input_voltage;
+    // The AC current taken from the Grid and used to charge the batteries.
+    data->buy_amps = _buy_current;
+    // The AC current the batteries are putting into the grid.
+    data->sell_amps = _sell_current;
+    // The daily kilowatts put into the batteries from the PV source.
+    data->daily_kwh = _daily_kwh;
+    // The frequency in hertz. This doesn't exist on an Outback, but does on
+    // a Xantrex. It should always be 60 though, so we set it so other
+    // software can handle this  the same way.
+    data->hertz = 60;
+#endif
+
+    return data;
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/devices/xanbus.h b/devices/xanbus.h
new file mode 100644
index 0000000..2c87a2b
--- /dev/null
+++ b/devices/xanbus.h
@@ -0,0 +1,198 @@
+// 
+// Copyright (C) 2011 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef  __XANBUSUI_H__
+#define __XANBUSUI_H__
+
+#ifdef __cplusplus
+
+#include <cstring>
+#include <vector>
+#include <map>
+#include "err.h"
+#include <console.h>
+
+#include "serial.h"
+#include "menuitem.h"
+#include "database.h"
+
+class XanbusUI : public Serial
+{
+public:
+
+
+    
+    typedef enum {USERMENU, SETUPMENU} menu_e;
+    enum inverter_e {OFF, SRCH, ON, CHG};
+    enum invertsetup_e {FLOAT, SELL, SLT, LBX};
+    enum battery_e {NICAD, LEADACID, GEL};
+    enum genauto_e {UNINITIALIZED, RUNNING, IDLE};
+
+    typedef enum { XACCESS, ACCESS_QUERY, BACKLIGHT, CONT, CONT_QUERY,
+                   CUSTOM11_QUERY, CUSTOM12_QUERY, CUSTOM11ERASE,
+                   CUSTOM12ERASE, CUSTOM21, CUSTOM22, CUSTOM21_QUERY,
+                   CUSTOM22_QUERY, CUSTOM21ERASE, CUSTOM22ERASE,
+                   DCCOMPLEV_QUERY, DCDC_QUERY, DERATELIMIT_QUERY,
+                   ERR_QUERY, FAULTACTIVE_QUERY, FAULTGND_QUERY,
+                   FAULTLAST_QUERY, FAULTLOG_QUERY, FREQ_QUERY,
+                   FWHW_QUERY, IDN_QUERY, IIN_QUERY, INV_QUERY,
+                   IOUT_QUERY, KNOCK, KWHLIFE_QUERY, KWHLIFESYS_QUERY,
+                   KWHTODAY_QUERY, KWHTODAYSYS_QUERY, XKWHTODAY_QUERY,
+                   MEASENGY_QUERY, MEASENGYSYS_QUERY, MEASICMM_QUERY,
+                   MEASIN_QUERY, MEASOUT_QUERY, MEASRAW_QUERY, MEASTEMP_QUERY,
+                   MEMFREE_QUERY, MODELID_QUERY, MODELSTR_QUERY, 
MONPARAM_QUERY,
+                   MONALL_QUERY, MONAUXPARAM_QUERY, MONENS_QUERY,
+                   MONENSPARAM_QUERY, MONEXT_QUERY, MONEXTPARAM_QUERY,
+                   MONFB_QUERY, MONFBPARAM_QUERY, MONGND_QUERY,
+                   MONGNDPARAM_QUERY, MONGRID_QUERY, MONGRIDPARAM_QUERY,
+                   MONTEMP_QUERY, MONTEMPPARAM_QUERY, MONOVPARAM_QUERY,
+                   MONUVPARAM_QUERY, MONVIN_QUERY, MPPT_QUERY,
+                   MPPTDBG_QUERY, MPPTLEV_QUERY, MPPTLEVM_QUERY,
+                   MPPTOFFSET_QUERY, MPPTSTAT_QUERY, NVMEMSPACE_QUERY,
+                   OFFSET_QUERY, OLDERLIM_QUERY, PDCMPPT_QUERY, PIN_QUERY,
+                   POUT_QUERY, POUTSYS_QUERY, PROD_QUERY, POWLIMIT_QUERY,
+                   POWSEQ_QUERY, POWSEQCLR, QUEUED_QUERY, RECTIME_QUERY,
+                   RELAY_QUERY, RIPCOMP_QUERY, ROM_QUERY, SCALE_QUERY,
+                   SCID_QUERY, SCROLL, STANDBY, STANDBY_QUERY, TEMPLIMIT_QUERY,
+                   TEMPLIMITSTEP_QUERY, TIME_QUERY, VDCREF_QUERY, VIN_QUERY,
+                   XBADX_QUERY
+    } xanbus_command_e;
+
+
+    typedef struct {
+        xanbus_command_e type;
+        std::string      command;
+        bool             query;
+    } cmd_data_t;
+    
+    XanbusUI(void);
+    ~XanbusUI(void);
+    
+    // Dump all internal data to the console
+    void Dump (void);
+    void DumpAliases(void);
+    
+    // This selects which inverter we want to control
+    std::string &SelectInverter(int x);
+    
+    // Read from the serial port
+    std::string &ReadSerial(void);
+    
+    // Write to the serial port
+    std::string &WriteSerial(const char *buf, int nbytes);
+    
+    // These methods all go with the Xantrex display buttons
+    std::string &MenuHeadingMinus(void);
+    std::string &MenuHeadingPlus(void);
+    std::string &MenuItemMinus(void);
+    std::string &MenuItemPlus(void);
+    std::string &SetPointMinus(void);
+    std::string &SetPointPlus(void);
+    std::string &Inverter(void);
+    std::string &Generator(void);
+    std::string &SetupMenu(void);
+    std::string &LedStatus(void);
+    std::string &Version(void);
+    std::string &SetTerminalMode(void);
+    
+    std::vector<meter_data_t *> PollMeters(int loops);
+    //std::map<std::string, float> *PollMeters(int loops);
+    
+    // This method takes the data as outputted by the Xantrex inverter,
+    // and munges it to be a standard form with whitespace compressed,
+    // newlines & carriage returns stripped out, etc... This is so
+    // we can analyse the string data in a consistant fashion.
+    std::string &CleanUpData(std::string &str);
+    
+    meter_data_t *exportMeterData(meter_data_t *data);
+    
+#if 0
+    std::string &UserMenu(void);
+    // These methods are for switching menu modes
+  retcode_t GotoSetupMenu(void);
+    retcode_t GotoUserMenu(void);
+#endif
+    // This method takes us to the beginning of the menu headers and items
+    // This corresponds then to being in the Inverter Mode header of the
+    // User menu.
+    retcode_t GotoMenuStart(void);
+    std::string &GotoMenuItem(int mh, int mi);
+    
+    // These methods manipulate values
+    std::string &GetValue (std::string &x);
+    std::vector<std::string> *GetValues (std::string &str);
+    retcode_t SetFloatValue(float x);
+    float GetFloatValue(std::string &x);
+    retcode_t SetIntValue(int x);
+    int GetIntValue(std::string &x);
+    retcode_t SetBoolValue(bool x);
+    bool GetBoolValue(std::string &x);
+    std::string GetLabel(std::string &x);
+    // This method populates the menu item data to default values as per
+    // the Xantrex manual.
+    void SetDefaultValues (void);
+    
+    // This method tries to match the display with a menu item
+    // to verify we're where we think we are...
+    MenuItem &Match(std::string &str);
+    MenuItem &GetItem(int x, int y);
+    MenuItem &GetItem() { return GetItem(menuheading, menuitem); }
+    std::string GetLabel();
+    
+    retcode_t xantrex_main(Console& con);
+ private:
+    std::vector< std::vector< MenuItem > > _items;
+    int menuheading;
+    int menuitem;
+    //  Serial uart;  
+};
+
+extern "C" {
+#else
+    
+    // Default object for C code. 
+    XanbusUI ui;
+    
+    /* This is the C API for this class. */
+    
+    const char *menu_heading_minus(void);
+    const char *menu_heading_plus(void);
+    const char *menu_item_minus(void);
+    const char *menu_item_mlus(void);
+    const char *set_point_minus(void);
+    const char *set_point_plus(void);
+    
+    const char *inverter(void);
+    const char *generator(void);
+    const char *setup_menu(void);
+    const char *led_status(void);
+    const char *version(void);
+    const char *set_terminal_mode(void);
+    
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+// end of __XANBUSUI_H__
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
+
diff --git a/devices/xantrex-trace.cc b/devices/xantrex-trace.cc
new file mode 100644
index 0000000..58391fb
--- /dev/null
+++ b/devices/xantrex-trace.cc
@@ -0,0 +1,1586 @@
+// 
+// Copyright (C) 2005, 2006 - 2018
+//      Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <vector>
+#include <map>
+
+#include "err.h"
+#include "log.h"
+#include "console.h"
+#include "xantrex-trace.h"
+#include "database.h"
+
+using namespace std;
+
+static std::string menudisp;
+static char buffy[100];
+
+extern LogFile dbglogfile;
+
+XantrexUI::XantrexUI(void)
+{
+    SetDefaultValues();  
+}
+
+XantrexUI::~XantrexUI(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+string &
+XantrexUI::ReadSerial(void)
+{
+    int ret;
+    //DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+
+#if 0 
+    int retries = 1;
+  
+    while (retries--) {
+        if (ret = Read((char *)&buffy, 99) < 0) {
+            //dbglogfile << "FIXME: " << retries << "\t" << buffy << endl;
+            //ret = Read((char *)&buffy, 100);
+            continue;
+        } else {
+            break;
+        }
+    }
+#else
+    ret = Read((char *)&buffy, 100);
+#endif
+  
+    if (ret > 0) {
+        //dbglogfile << "FIXME3: Read " << ret << " bytes: " << buffy << "\t" 
<< buffy << endl;
+        menudisp = buffy;
+    } else {
+        menudisp.erase();
+    }
+  
+    return menudisp;
+}
+
+string
+XantrexUI::GetLabel() {
+    //DEBUGLOG_REPORT_FUNCTION;
+
+    dbglogfile << "menuheading: " << menuheading << " menuitem:" << menuitem 
<< endl;
+  
+    MenuItem ti = GetItem(menuheading, menuitem);
+  
+    return ti.GetLabel();
+}
+
+string &
+XantrexUI::WriteSerial(const char *buf, int nbytes)
+{
+    int ret;
+  
+    //DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    ret = Write(buf, nbytes);
+    //dbglogfile << "FIXME" << buffy << endl;
+    ret = Read(buffy, nbytes);
+  
+    menudisp = buffy;
+    return menudisp;
+}
+
+// This selects which inverter we want to control
+string &
+XantrexUI::SelectInverter(int x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+
+    Write((char *)&x, 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+// These methods all go with the Xantrex display buttons
+string &
+XantrexUI::MenuHeadingMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    //memset(buffy, 0, 100);
+  
+    Write("L", 1);
+    //Read((char *)&buffy, 100);
+    menudisp = ReadSerial();
+    //dbglogfile << "FIXME" << menudisp << endl;
+
+    //cerr << "FIXMEh-: \"" << menudisp  << "\"" << endl;
+    //cerr << "FIXMEh-: \"" << GetLabel() << "\"" << endl;
+
+    if (menuheading > 1) {
+        menuheading--;
+    }
+    menuitem = 0;
+
+    if (menudisp.find(GetLabel()) == string::npos) {
+        dbglogfile << "Heading Minus didn't Match!!" << menuheading << endl;  
+    } else {
+        dbglogfile << "Heading Minus Matched!!" << endl;
+    }
+
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::MenuHeadingPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    //memset(buffy, 0, 100);
+    MenuItem mi;
+  
+    Write("R", 1);
+  
+    //Read((char *)&buffy, 100);
+    menudisp = ReadSerial();
+    //mi = GetItem();
+
+    //dbglogfile << menudisp << endl;
+
+    menuheading++;
+    menuitem = 0;
+
+    //cerr << "FIXMEh+: \"" << menudisp  << "\"" << endl;
+    //cerr << "FIXMEh+: \"" << GetLabel() << "\"" << endl;
+  
+    if (menudisp.find(GetLabel()) == string::npos) {
+        dbglogfile << "Heading Plus didn't Match!!" << endl;  
+    } else {
+        dbglogfile << "Heading Plus Matched!!" << endl;
+    }
+
+
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+// This decends through the sub menu items of a heading
+string &
+XantrexUI::MenuItemMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int retries = 5;
+    string label;
+  
+    //memset(buffy, 0, 100);
+  
+    //Write("D", 1);
+    //Read((char *)&buffy, 100);
+    //menudisp = ReadSerial();
+    //dbglogfile << menudisp << endl;
+
+    menuitem++;
+
+    //cerr << "FIXME-I: \"" << menuheading << "," << menuitem << "\"" << endl;
+    while (retries--) {
+        Write("D", 1);
+        menudisp = ReadSerial();
+        //Flush();
+        //cerr << "FIXMEi-: \"" << menudisp  << "\"" << endl;
+        //cerr << "FIXMEi-: \"" << GetLabel() << "\"" << endl;
+
+        label = GetLabel();
+        if (label.size()) {
+            if (menudisp.find(label) == string::npos) {
+                dbglogfile << "Item Minus didn't Match!!" << endl;
+            } else {
+                dbglogfile << "Item Minus Matched!!" << endl;
+                break;
+            }
+        }
+    }
+
+    //menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::MenuItemPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int retries = 5;
+
+    //memset(buffy, 0, 100);
+  
+    //Write("U", 1);
+    //Read((char *)&buffy, 100);
+    //menudisp = ReadSerial();
+    //dbglogfile << menudisp << endl;
+    //menudisp = buffy;
+    if (menuitem > 1)
+        menuitem--;
+
+    //  if (strcmp(label.c_str(), buffy) == 0)
+    //    dbglogfile << "AAAAHHHHHHH" << endl;
+  
+    while (retries--) {
+        Write("U", 1);
+        menudisp = ReadSerial();
+        //Flush();
+
+        //cerr << "FIXMEi+: \"" << menudisp  << "\"" << endl;
+        //cerr << "FIXMEi+: \"" << GetLabel() << "\"" << endl;
+
+        if (menudisp.find(GetLabel()) == string::npos) {
+            dbglogfile << "Item Plus didn't Match!!" << endl;
+        } else {
+            dbglogfile << "Item Plus Matched!!" << endl;
+            break;
+        }
+    }
+
+    //  if (menudisp != label)
+    //  dbglogfile << "FIXME: Wrong Item " << menuheading << ":" << menuitem 
<< menudisp << "\t" << label << endl;
+    
+    return menudisp;
+}
+
+string &
+XantrexUI::SetPointMinus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("-", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::SetPointPlus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("+", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::Inverter(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("|", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::Generator(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("G", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::SetupMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("\003", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menuheading = 8;
+    menuitem = 0;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::LedStatus(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("?", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;  
+}
+
+string &
+XantrexUI::Version(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("V", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+string &
+XantrexUI::SetTerminalMode(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    memset(buffy, 0, 100);
+  
+    Write("T", 1);
+    Read((char *)&buffy, 100);
+    dbglogfile << buffy << endl;
+
+    menudisp = buffy;
+    return menudisp;
+}
+
+#if 0
+// These methods are for switching menu modes
+retcode_t
+XantrexUI::GotoSetupMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+retcode_t
+XantrexUI::GotoUserMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+string &
+XantrexUI::UserMenu(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+}
+
+#endif
+
+// This method takes us to the beginning of the menu headers and items
+// This corresponds then to being in the Inverter Mode header of the
+// User menu.
+retcode_t
+XantrexUI::GotoMenuStart(void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    int i;
+    for (i=0; i<22; i++) {
+        // Don't use MenuheadingMinus, as it gets all confused
+        Write("L", 1);
+        menudisp = ReadSerial();
+        if (menudisp.find("Inverter", 0) != string::npos) {
+            break;
+        }
+    }
+  
+    menuheading = 1;
+    menuitem = 0;
+    dbglogfile << "At Start Of Menu" << endl;
+  
+    return SUCCESS;
+}
+
+// These methods manipulate values
+retcode_t
+XantrexUI::SetFloatValue(float )
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    cerr << "ERROR: unimplemented!" << endl;
+    return ERROR;
+}
+
+float
+XantrexUI::GetFloatValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    return atof(GetValue(str).c_str());
+}
+
+retcode_t
+XantrexUI::SetIntValue(int x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    cerr << "ERROR: unimplemented!" << endl;
+    return ERROR;
+}
+
+int
+XantrexUI::GetIntValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    return atoi(GetValue(str).c_str());
+}
+
+bool
+XantrexUI::GetBoolValue(std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    string tmpstr = GetValue(str).c_str();
+  
+    if (tmpstr == "NO" || tmpstr == "OFF")
+        return false;
+    else
+        return true;
+}
+
+string &
+XantrexUI::GetValue (std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos, pos2;
+    //string value;
+    int i = 0;
+    string lookfor;
+
+    //cout << "The Raw value string is: " << str << endl;
+
+#if 0
+    pos = str.find("-00", str.length());
+    if (pos != string::npos) {
+        str.erase(pos, str.length() - pos);
+    }
+#endif
+  
+    do {
+        lookfor = " ";
+        char j = '0' + i;
+        lookfor += j;
+        pos = str.find(lookfor, 0);
+        lookfor.erase();
+    } while ((pos == string::npos) && (i++ < 10));
+  
+    pos2 = str.find(' ', pos+1);
+    if (pos2 == string::npos) {
+        pos2 = pos + 4;
+    }
+  
+    str = str.substr(pos+1, pos2 - pos);
+
+#if 0
+    if (pos != string::npos) {
+        // We want just the last data item, which is the value
+        value = str.substr(pos+1, str.length() - pos);
+        str = value;
+    } else {
+        str.erase();
+    }
+#endif
+  
+    return str;
+}
+
+vector<string> *
+XantrexUI::GetValues (std::string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos;
+    string value;
+    vector<string> *array;
+
+    array = new vector<string>;
+
+    //cout << "The Raw values string is: " << str << endl;
+
+    do {
+        pos = str.find("-00", str.length());
+        if (pos != string::npos) {
+            str.erase(pos, str.length() - pos);
+        }
+    
+        // Find the last space in the string
+        pos = str.rfind(' ' , str.length());
+    
+        if (pos != string::npos) {
+            // We want just the last data item, which is the value
+            value = str.substr(pos+1, str.length() - pos);
+            str = value;
+            array->push_back(value);
+        } else {
+            str.erase();
+        }
+    } while (pos != string::npos);
+  
+  
+    return array;
+}
+
+std::string
+XantrexUI::GetLabel(std::string &x)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string::size_type pos;
+
+    // Find the last space in the string
+    pos = x.rfind(' ' , x.length());
+    //pos = x.rfind('\t' , x.length());
+
+    if (pos != string::npos) {
+        return x.substr(0, pos);
+    }
+  
+    return x;
+}
+
+
+string &
+XantrexUI::GotoMenuItem(int mh, int mi)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    string tmpstr;
+    int i;
+    MenuItem item;
+  
+    GotoMenuStart();
+
+    item = GetItem(mh, mi);
+    for (i=0; i < mh-1; i++) {
+        menudisp = MenuHeadingPlus();
+    }
+  
+    for (i=0; i < mi-1; i++) {
+        menudisp = MenuItemMinus();
+    }
+
+    if (menudisp.find(item.GetLabel()) != string::npos) {
+        dbglogfile << "Didn't Match!!" << endl;  
+    }
+
+    //menudisp = CleanUpData(tmpstr);
+  
+    menuheading = mh;
+    menuitem = mi;
+
+    return menudisp;
+}
+
+//std::map<std::string, float> *
+//std::vector< std::map< std::string, float > >
+vector<meter_data_t *>
+XantrexUI::PollMeters(int loops)
+{
+    MenuItem      ti;
+    int           mh = 4;
+    int           mi = 1;
+    int           items = 7;                // the number of data items to get
+    float         fltval;
+    int           intval;
+    int           i;
+    string        str, label;
+    meter_data_t *downdata, *updata;
+    vector<meter_data_t *> meters;
+
+    //memset(buffy, 0, 100);
+
+    GotoMenuItem(mh, mi);
+    while (loops-- > 0) {
+        downdata = new meter_data_t;
+        memset(downdata, 0, sizeof(meter_data_t));
+    
+        for (i=mi; i<= mi+items; i++) {
+            str = MenuItemMinus();
+            fltval = 0.0;
+            intval = 0;
+            if (str.size() > 1) {
+                ti = GetItem();
+                if (ti.GetType() != MenuItem::INFO) {
+                    label = GetLabel(); 
+                    cout << "The Menu Item Label down is: " << label;
+                }
+                ti = GetItem();
+                if (ti.GetType() == MenuItem::FLOAT) {
+                    fltval = GetFloatValue(str);
+                    cout << ", with a float value is: " << fltval << endl;
+                }
+                if (ti.GetType() == MenuItem::INT) {
+                    intval = GetIntValue(str);
+                    cout << ", with an Integer value is: " << intval << endl;
+                }
+                if (ti.GetType() == MenuItem::INFO) {
+                    cout << ", an INFO statement  " << endl;
+                    break;
+                }
+                if (label.substr(0, 5) == "Input") {
+                    //downdata->
+                }
+                if (label.substr(0, 4) == "Load") {
+                    dbglogfile << "Matched label going down " << label;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->ac_load_amps = intval;
+                }
+                if (label.substr(8, 6) == "actual") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->battery_volts = fltval;
+                }
+                if (label.substr(8, 8) == "TempComp") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->tempcomp_volts = fltval;
+                }
+                if (label.substr(0, 8) == "Inverter") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->ac_volts_out = intval;
+                }
+                if (label.substr(0, 4) == "Grid") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->ac1_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Generator") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    downdata->ac2_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Read Freq") {
+                    dbglogfile << "Matched label going down " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    downdata->hertz = intval;
+                }
+            }
+        }
+
+        meters.push_back(downdata);
+        //MenuItemMinus();            // go one more, since the first thing
+        // we do is come back up one item.
+        updata = new meter_data_t;
+        memset(updata, 0, sizeof(meter_data_t));
+        //ptr2 = (float *)((char *)updata + 
sizeof(meter_data_t)-sizeof(float));
+        //*ptr2-- = downdata->hertz;
+    
+        // Now go up through the menu
+        for (i=mi+items; i>mi; i--) {
+            str = MenuItemPlus();
+            fltval = 0.0;
+            intval = 0;
+            if (str.size() > 0) {
+                label = GetLabel(); 
+                cout << "The Menu Item Label up is: " << label;
+                ti = GetItem();
+                if (ti.GetType() == MenuItem::FLOAT) {
+                    fltval = GetFloatValue(str);
+                    cout << ", with a float value is: " << fltval << endl;
+                }
+                if (ti.GetType() == MenuItem::INT) {
+                    intval = GetIntValue(str);
+                    cout << ", with an integer value is: " << intval << endl;
+                }
+                //Flush();
+                //_data.push(label, );
+                if (label.substr(0, 5) == "Input") {
+                    //updata->
+                }
+                if (label.substr(0, 4) == "Load ") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    updata->ac_load_amps = intval;
+                }
+                if (label.substr(8, 6) == "actual") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->battery_volts = fltval;
+                }
+                if (label.substr(8, 8) == "TempComp") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->tempcomp_volts = fltval;
+                }
+                if (label.substr(0, 8) == "Inverter") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << intval << endl;
+                    updata->ac_volts_out = intval;
+                }
+                if (label.substr(0, 4) == "Grid") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->ac1_volts_in = fltval;
+                }
+                if (label.substr(0, 9) == "Generator") {
+                    dbglogfile << "Matched label going up " << label << endl;
+                    dbglogfile << " value is: " << fltval << endl;
+                    updata->ac2_volts_in = fltval;
+                }
+                // Since this is the last and first reading, it doesn't really
+                // have time to change.
+                updata->hertz = downdata->hertz;
+//         if (label.substr(0, 9) == "Read Freq") {
+//           dbglogfile << "Matched label going up " << label << endl;
+//           dbglogfile << " value is: " << intval << endl;
+//           updata->hertz = intval;
+//         }
+            } // end of if str
+        } // end of for loop
+        meters.push_back(updata);
+    }
+    // Go back to the top
+//   for (i=items; i>=mi; i--) {
+//     MenuItemPlus();
+//   }
+  
+    MenuHeadingPlus();
+    MenuHeadingMinus();          
+  
+    return meters;
+}
+
+// This method takes the data as outputted by the Xantrex inverter,
+// and munges it to be a standard form with whitespace compressed,
+// newlines & carriage returns stripped out, etc... This is so
+// we can analyse the string data in a consistant fashion.
+std::string &
+XantrexUI::CleanUpData(std::string &str)
+{
+    unsigned int i;
+
+    menudisp.erase();
+    for (i=0; i< str.length(); i++) {
+        switch (str[i]) {
+            // we ignore these characters
+          case '\r':
+          case '\n':
+              break;
+              // compress multiple spaces to be just one
+          case ' ':
+              if (str[i+1] == ' ') {
+                  continue;
+              } else {
+                  menudisp += ' ';
+                  break;
+              }
+          default:
+              menudisp += str[i];
+        }
+    }
+
+    return menudisp;
+}
+
+void
+XantrexUI::SetDefaultValues(void)
+{
+
+    MenuItem mi;
+
+    // We know we always have 20 major menu headings
+    _items.resize(21);
+
+    mi.SetItem ("Top of Menu", 0);
+    _items[0].push_back(mi);
+
+    // Inverter Mode - Menu Heading #1
+    mi.SetItem ("Inverter Mode",                      1);
+    _items[1].push_back(mi);
+
+    mi.SetItem ("Set Inverter     OFF SRCH ON CHG",   1, 1, "SetVert"); // 
FIXME: enum
+    _items[1].push_back(mi);
+    mi.SetItem ("CHG avail. Only  in FLT mode",       1, 2);
+    _items[1].push_back(mi);
+    mi.SetItem ("Press red or     setpoint button",   1, 3);
+    _items[1].push_back(mi);
+    mi.SetItem ("to move.         Move cursor to",    1, 4);
+    _items[1].push_back(mi);
+    mi.SetItem ("Inverter OFF to  resetOverCurrent",  1, 5);
+    _items[1].push_back(mi);
+
+    // Generator Mode - Menu Headings #2
+    mi.SetItem ("Generator Mode",                     2);
+    _items[2].push_back(mi);
+    mi.SetItem ("Set Generator    OFF AUTO ON EQ",    2, 1, "SetGen"); // 
FIXME: enum
+    _items[2].push_back(mi);
+    mi.SetItem ("Gen under/over   speed",             2, 2, false, "GenSpeed");
+    _items[2].push_back(mi);  
+    mi.SetItem ("Generator start  error",             2, 3, false, "GenStart");
+    _items[2].push_back(mi);
+    mi.SetItem ("Generator sync   error",             2, 4, false, "GenSync");
+    _items[2].push_back(mi);
+    mi.SetItem ("Gen max run Time error",             2, 5, false, "GenMax");
+    _items[2].push_back(mi);
+    mi.SetItem ("Load Amp Start   ready",             2, 6, false, "LoadAmp");
+    _items[2].push_back(mi);
+    mi.SetItem ("Voltage Start    ready",             2, 7, false, 
"VoltStart");
+    _items[2].push_back(mi);
+    mi.SetItem ("Exercise Start   ready",             2, 8, false, 
"ExerStart");
+    _items[2].push_back(mi);
+  
+    // Xantrex Engineering - Menu Heading #3
+    // Xantrex was Trace, so this prompt varies depending on the
+    // software version on the inverter.
+    mi.SetItem ("Engineering",       3);
+    //mi.SetItem ("Trace            Engineering",       3);
+    _items[3].push_back(mi);
+    mi.SetItem ("Press reset now  for defaults",      3, 1);
+    _items[3].push_back(mi);
+    mi.SetItem ("Revision 4.01",                      3, 2, "XantrexRev");
+    _items[3].push_back(mi);
+    mi.SetItem ("5916 195th St NE Arlington, WA",     3, 3);
+    _items[3].push_back(mi);
+    mi.SetItem ("98223 USA",                          3, 4);
+    _items[3].push_back(mi);
+    mi.SetItem ("Ph  360-435-8826 Fax 360-435-2229",  3, 5);
+    _items[3].push_back(mi);
+
+    // Meters - Menu Heading #4
+    mi.SetItem ("Meters",                         4);
+    _items[4].push_back(mi);
+    mi.SetItem ("Inverter/charger amps AC",         4,  1, 0, "ChargerAmps");
+    _items[4].push_back(mi);
+    mi.SetItem ("Input            amps AC",         4,  2, 0, "InputAmps");
+    //mi.SetItem ("Input",                           4,  2, 0, "InputAmps");
+    _items[4].push_back(mi);
+    mi.SetItem ("Load             amps AC",         4,  3, 0, "LoadAmps");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Battery actual",                   4,  4, (float)25.1, 
"BattVolts");
+    mi.SetItem ("Battery actual   volts DC",        4,  4, (float)25.1, 
"BattVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Battery TempComp",                4,  5, (float)25.1, 
"TempComp");
+    mi.SetItem ("Battery TempComp volts DC",        4,  5, (float)25.1, 
"TempComp");
+    _items[4].push_back(mi);
+    mi.SetItem ("Inverter         volts AC",        4,  6, 0, "InvertVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Grid (AC1)",                       4,  7, 0, "GridVolts");
+    mi.SetItem ("Grid (AC1)       volts AC",                             4,  
7, 0, "GridVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Generator (AC2)",                  4,  8, 0, "GenVolts");
+    mi.SetItem ("Generator (AC2)  volts AC",                             4,  
8, 0, "GenVolts");
+    _items[4].push_back(mi);
+    //mi.SetItem ("Read Frequency",                   4,  9, 0, "ReadHertz");
+    mi.SetItem ("Read Frequency   Hertz",                           4,  9, 0, 
"ReadHertz");
+    _items[4].push_back(mi);
+    mi.SetItem ("AC1 & AC2 volts  valid only when", 4, 10);
+    _items[4].push_back(mi);
+    mi.SetItem ("inverter synced  to that input.",  4, 11);
+    _items[4].push_back(mi);
+    mi.SetItem ("Batt volt actual is used for",     4, 12);
+    _items[4].push_back(mi);
+    mi.SetItem ("LBCO,HBCO,LBX,   LBCI,sell volts", 4, 13);
+    _items[4].push_back(mi);
+    mi.SetItem ("and gen starting",                 4, 14);
+    _items[4].push_back(mi);
+    mi.SetItem ("Batt volt temp   comp is used,",   4, 15);
+    _items[4].push_back(mi);
+    mi.SetItem ("for float, bulk, eq & aux relays", 4, 16);
+    _items[4].push_back(mi);
+  
+    // Error Cause - Menu Heading #5
+    mi.SetItem ("Error Causes",                 5);
+    _items[5].push_back(mi);
+    mi.SetItem ("Over Current",                 5,  1, false, "OverCurrent");
+    _items[5].push_back(mi);
+    mi.SetItem ("Transformer      overtemp",    5,  2, false, "OverTemp");
+    _items[5].push_back(mi);
+    mi.SetItem ("Heatsink         overtemp",    5,  3, false, "HeatSink");
+    _items[5].push_back(mi);
+    mi.SetItem ("High Battery     voltage",     5,  4, false, "HighBatt");
+    _items[5].push_back(mi);
+    mi.SetItem ("Low Battery      voltage",     5,  5, false, "LowBatt");
+    _items[5].push_back(mi);
+    mi.SetItem ("Inverter breaker tripped",     5,  6, false, "Tripped");
+    _items[5].push_back(mi);
+    mi.SetItem ("Manual Off",                   5,  7, false, "ManualOff");
+    _items[5].push_back(mi);
+    mi.SetItem ("AC source wired  to output",   5,  8, false, "ACWired");
+    _items[5].push_back(mi);
+    mi.SetItem ("External error   (Stacked)",   5,  9, false, "ExtError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Generator start  error",       5, 10, false, "GenError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Generator sync   error",       5, 11, false, "SyncError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Gen maximum run  time error",  5, 12, false, "MaxRunError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Gen Under/Over   speed",       5, 13, false, "SpeedError");
+    _items[5].push_back(mi);
+    mi.SetItem ("Inverter breaker tripped",     5, 14, false, "BreakerError");
+    _items[5].push_back(mi);
+  
+    // Time Of Day - Menu Heading #6
+    mi.SetItem ("Time of Day",                 6);
+    _items[6].push_back(mi);
+    mi.SetItem ("Time of Day      Set Clock hour", 6, 1, 0);
+    _items[6].push_back(mi);
+    mi.SetItem ("Set Clock minute",            6, 2, 0, "Minute");
+    _items[6].push_back(mi);
+    mi.SetItem ("Set Clock second",            6, 3, 0, "Second");
+    _items[6].push_back(mi);
+
+    // Generator timer - Menu Heading #7
+    mi.SetItem ("Generator Timer",           7);
+    _items[7].push_back(mi);
+    mi.SetItem ("Start Quiet      time h:m", 7, 1, 8 ); // FIXME: this should 
be a time
+    _items[7].push_back(mi);  
+    mi.SetItem ("End Quiet        time h:m", 7, 2, 8 ); // FIXME: this should 
be a time
+    _items[7].push_back(mi);
+
+    // End of User menus!
+    mi.SetItem ("END USER MENU", 8);
+    _items[8].push_back(mi);
+
+    // Inverter Setup - Menu heading #9
+    mi.SetItem ("Inverter Setup",               9);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Grid Usage",               9, 1); // FIXME: FLOAT
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Low battery  cut out VDC", 9, 2, (float)22.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set LBCO delay   minutes",     9, 3, 15);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set Low battery  cut in VDC",  9, 4, (float)26.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set High battery cut out VDC", 9, 5, (float)32.0);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set search       watts",       9, 6, 48);
+    _items[9].push_back(mi);
+    mi.SetItem ("Set search       spacing",     9, 7, 59);
+    _items[9].push_back(mi);
+
+    // Battery Charging - Menu heading #10
+    mi.SetItem ("Battery Charging",                10);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Bulk         volts DC",       10, 1, (float)28.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Absorption   time h:m",       10, 2, 2);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Float        volts DC",       10, 3, (float)26.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Equalize     volts DC",       10, 4, (float)28.8);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Equalize     time h:m",       10, 5, 2);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Max Charge   amps DC",        10, 6, 30);
+    _items[10].push_back(mi);
+    mi.SetItem ("Set Temp Comp    LeadAcid Nicad", 10, 7); // FIXME: LEADACID
+    _items[10].push_back(mi);
+
+    // AC Inputs - Menu heading #11
+    mi.SetItem ("AC Inputs",                       11);
+    _items[11].push_back(mi);
+    mi.SetItem ("inverter synced  to that input.", 11);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Grid (AC1)   amps AC",        11, 1, 60);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Gen (AC2)    amps AC",        11, 2, 30);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Input lower  limit VAC",      11, 3, 108);
+    _items[11].push_back(mi);
+    mi.SetItem ("Set Input upper  limit VAC",      11, 4, 132);
+    _items[11].push_back(mi);
+
+    // Generator Auto Start Setup - Menu heading #12
+    //  genauto.state = OFF;
+    mi.SetItem ("Gen Auto Start   setup",           12);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Start   amps AC",         12, 1, 33);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Start   delay min",       12, 2, 5);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Load Stop    delay min",       12, 3, 5);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 24 hr start  volts DC",        12, 4, (float)24.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 2 hr start   volts DC",        12, 5, (float)23.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set 15 min start volts DC",        12, 6, (float)22.6);
+    _items[12].push_back(mi);
+    mi.SetItem ("Read LBCO 30 sec start VDC",       12, 7, 22);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Exercise     period days",     12, 8, 30);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Maximum run  time h:m",        12, 9, 8);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Max Run time to 0 to defeat.", 12, 10, 0);
+    _items[12].push_back(mi);
+    mi.SetItem ("Set Exercise to 0 to defeat.",     12, 11, 0);
+    _items[12].push_back(mi);
+    mi.SetItem ("See menu 9 to    to set LBCO.",    12, 12, 0);
+    _items[12].push_back(mi);
+
+    //Generator Starting Details - Menu heading #13
+    mi.SetItem ("Gen starting     details",      13);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set RY7 Function GlowStop Run", 13, 1, 0);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Gen warmup   seconds",      13, 2, 60);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Pre Crank    seconds",      13, 3, 10);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Max Cranking seconds",      13, 4, 10);
+    _items[13].push_back(mi);
+    mi.SetItem ("Set Post Crank   seconds",      13, 5, 30);
+    _items[13].push_back(mi);
+
+    // Auxilary relays - Menu heading #14
+    mi.SetItem ("Auxiliary Relays R9 R10 R11", 14);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 9      volts DC",       14, 1, 29);
+    _items[14].push_back(mi);
+    mi.SetItem ("R9 Hysteresis    volts DC",       14, 2, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 10     volts DC",       14, 3, (float)29.5);
+    _items[14].push_back(mi);
+    mi.SetItem ("R10 Hysteresis   volts DC",       14, 4, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Set Relay 11     volts DC",       14, 5, 30);
+    _items[14].push_back(mi);
+    mi.SetItem ("R11 Hysteresis   volts DC",       14, 6, 2);
+    _items[14].push_back(mi);
+    mi.SetItem ("Close on batt >  setpoint.",      14, 7);
+    _items[14].push_back(mi);
+    mi.SetItem ("Open  on  batt < setpoint - Hys", 14, 8);
+    _items[14].push_back(mi);
+    mi.SetItem ("Relays have 2    second delay on",14, 9);
+    _items[14].push_back(mi);
+    mi.SetItem ("Close, 0.1 sec   delay on open",  14, 10);
+    _items[14].push_back(mi);
+
+    // Bulk Charge Trigger Time - Menu heading #15
+    mi.SetItem ("Bulk Charge      Trigger Timer",   15);
+    _items[15].push_back(mi);              
+    mi.SetItem ("Set Start Bulk   time",            15, 1, 0);
+    _items[15].push_back(mi);              
+    mi.SetItem ("To disable timer set to 00:00",    15, 2);
+    _items[15].push_back(mi);              
+    mi.SetItem ("If grid timer    active set bulk", 15, 3);
+    _items[15].push_back(mi);              
+    mi.SetItem ("time after start charge time.",    15, 4);
+    _items[15].push_back(mi);              
+    mi.SetItem ("In SLT mode don't disable this",   15, 5);
+    _items[15].push_back(mi);              
+    mi.SetItem ("timer. It is the daily chg time.", 15, 6);
+    _items[15].push_back(mi);              
+
+    // Low Battery Transfer - Menu heading #16
+    mi.SetItem ("Low Battery      Transfer (LBX)",    16);
+    _items[16].push_back(mi);
+    mi.SetItem ("Set Low Battery  TransferVDC",       16, 1, (float)26.8);
+    _items[16].push_back(mi);
+    mi.SetItem ("Set Low Battery  cut in  VDC",       16, 2, (float)26);
+    _items[16].push_back(mi);
+    mi.SetItem ("See menu 9 to    enable LBX mode.",  16, 3);
+    _items[16].push_back(mi);
+    mi.SetItem ("Make sure LBX is above LBCO volts.", 16, 4);
+    _items[16].push_back(mi);
+
+    //  Battery Power Selling - Menu heading #17
+    mi.SetItem ("Battery Selling",                    17);
+    _items[17].push_back(mi);
+    mi.SetItem ("Set Battery Sell volts",             17, 1, (float)26.8);
+    _items[17].push_back(mi);
+    mi.SetItem ("Set Max Sell     amps",              17, 2, 30);
+    _items[17].push_back(mi);
+    mi.SetItem ("See menu 9 to    enable SELL mode.", 17, 3);
+    _items[17].push_back(mi);
+    mi.SetItem ("Make sure LBX is above LBCO volts.", 17, 4);
+    _items[17].push_back(mi);
+  
+    // Grid Usage Timer - Menu heading #18
+    mi.SetItem ("Grid Usage Timer",                 18);
+    _items[18].push_back(mi);
+    mi.SetItem ("Set Charge       time",            18,  1, 21); // FIXME: TIME
+    _items[18].push_back(mi);
+    mi.SetItem ("End Charge       time",            18,  2, 21); // FIXME: TIME
+    _items[18].push_back(mi);
+    mi.SetItem ("After Start      Charge time:",    18,  3);
+    _items[18].push_back(mi);
+    mi.SetItem ("SELL mode        charges battery.",18,  4);
+    _items[18].push_back(mi);
+    mi.SetItem ("FLT mode         charges battery", 18,  5);
+    _items[18].push_back(mi);
+    mi.SetItem ("After End Charge time:",           18,  6);
+    _items[18].push_back(mi);
+    mi.SetItem ("SELL mode sells  battery to AC1.", 18,  7);
+    _items[18].push_back(mi);
+    mi.SetItem ("FLT mode drops   AC1 and inverts", 18,  8);
+    _items[18].push_back(mi);
+    mi.SetItem ("Timer on when    start < > end;",  18,  9);
+    _items[18].push_back(mi);
+    mi.SetItem ("timer off when   start = end",     18, 10);
+    _items[18].push_back(mi);
+    mi.SetItem ("Sell and float   modes use timer", 18, 11);
+    _items[18].push_back(mi);
+    mi.SetItem ("SLT and LBX mode ignore timer",    18, 12);
+    _items[18].push_back(mi);
+  
+    // Information file battery - Menu Heading #19
+    mi.SetItem ("Information file battery",          19);
+    _items[19].push_back(mi);
+    mi.SetItem ("Batt temp comp   changes battery",  19, 1);
+    _items[19].push_back(mi);
+    mi.SetItem ("voltage reading  away from actual", 19, 2);
+    _items[19].push_back(mi);
+    mi.SetItem ("HBCO resets at:  6v/48, 3v/24 and", 19, 3);
+    _items[19].push_back(mi);
+    mi.SetItem ("1.5v/12v under   HBCO.",            19, 4);
+    _items[19].push_back(mi);
+    mi.SetItem ("LowBattTransfer  used in LBX, FLT", 19, 5);
+    _items[19].push_back(mi);
+    mi.SetItem ("Modes only. Goes back to battery",  19, 6);
+    _items[19].push_back(mi);
+    mi.SetItem ("at LowBattCutIn  (aka LBCI).",      19, 7);
+    _items[19].push_back(mi);
+    mi.SetItem ("For LBX mode set below LBCI so",    19, 8);
+    _items[19].push_back(mi);
+    mi.SetItem ("charger won't    cycle batteries",  19, 9);
+    _items[19].push_back(mi);
+    mi.SetItem ("up and down and  set LBCO below.",  19, 10);
+    _items[19].push_back(mi);
+  
+    // End of Setup - Menu Heading #20
+    mi.SetItem ("END SETUP MENU", 20);
+    _items[20].push_back(mi);
+}
+
+// Dump all the MenuItem data
+void
+XantrexUI::Dump (void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+
+    dbglogfile << "There are " << (int)_items.size() << " menu _items" << endl;
+
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            //it->Dump();
+            cout << it->GetHeaderIndex()
+                 << "," << it->GetItemIndex()
+                 << ": " << it->GetLabel() << endl;
+        }
+    }
+}
+
+void
+XantrexUI::DumpAliases (void)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    string tmpstr;
+
+    cout << "Command Name\t\tMenu Item" << endl;
+    cout << "------------\t\t---------" << endl;
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            tmpstr = it->GetLabel();
+            if (it->GetAlias().size() > 0)
+                cout << it->GetAlias() << "  \t- " << CleanUpData(tmpstr) << 
endl;
+        }
+    }
+}
+
+MenuItem &
+XantrexUI::Match(string &str)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+  
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    vector< MenuItem > arg;
+
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        arg = *mh;
+        for (it = arg.begin(); it != arg.end(); ++it) {
+            dbglogfile << "Matching \"" << it->GetAlias() << "\""
+                       << " against the argument \"" << str << "\"" << endl;
+            if (it->GetAlias() == str){
+                dbglogfile << "Matched " << it->GetLabel() << " !" << endl;
+                return *it;
+            }
+        }
+    }
+    // FIXME: this is a hack to set an error condition
+    str.erase();
+    return *it;
+}
+
+MenuItem &
+XantrexUI::GetItem(int x, int y)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+    vector< vector< MenuItem > >::iterator mh;
+    vector< MenuItem >::iterator it;
+    vector< MenuItem > arg;
+    string tmp;
+   
+    for (mh = _items.begin(); mh != _items.end(); ++mh) {
+        for (it = mh->begin(); it != mh->end(); ++it) {
+            tmp = it->GetLabel();
+            if ((it->GetHeaderIndex() == x) && (it->GetItemIndex() == y)) {
+                return *it;
+            }
+        }
+    }
+
+    return *it;                  // FIXME: This probably isn't what we want
+}
+
+#if 0
+retcode_t
+XantrexUI::xantrex_main(Console &con);
+{
+
+#if 0
+    if (item.size() > 0) {
+        // See if the name is actually a specified index
+        if (item.find(":",0) != string::npos)
+            {
+                menuhead = atoi(item.substr(0, item.find(":",0)).c_str());
+                menuitem = atoi(item.substr(item.find(":",0) + 1, 2).c_str());
+            } else {
+            // lookup the alias to get the indexes
+            ti = ui.Match(item);
+            if (item.size() > 0) {
+                menuhead = ti->GetHeaderIndex();
+                menuitem = ti.GetItemIndex();
+            }
+        }
+    }
+#endif
+
+    // Go into console mode where we can type direct commands
+    // via the serial port. This just saves us from firing up
+    // kermit or minicom
+    if (console) {
+        Console con;
+        con.Open();
+        //ui.SetRaw();
+        while ((ch = con.Getc())!='q') {
+            if (ch > 0){             // If we have something, process it
+                if (echo)
+                    con.Putc (ch);          // echo inputted character to 
screen
+          
+                switch (ch) {
+                  case 'Q':
+                  case 'q':
+                      con.Reset();
+                      exit(0);
+                      break;
+                  case 'L':
+                      display = ui.MenuHeadingMinus();
+                      break;
+                  case 'R':
+                      display = ui.MenuHeadingPlus();
+                      break;
+                  case 'D':
+                      display = ui.MenuItemMinus();
+                      break;
+                  case 'U':
+                      display = ui.MenuItemPlus();
+                      break;
+                  case '+':
+                      display = ui.SetPointPlus();
+                      break;
+                  case '-':
+                      display = ui.SetPointMinus();
+                      break;
+                  case '|':
+                      display = ui.Inverter();
+                      break;
+                  case 'G':
+                      display = ui.Generator();
+                      break;
+                  case 'S':
+                      display = ui.SetupMenu();
+                      break;
+                  case 's':
+                      display = ui.GotoMenuStart();
+                      break;
+                  case '/':
+                      display = ui.LedStatus();
+                      break;
+                  case 'V':
+                      display = ui.Version();
+                      break;
+                  case 'T':
+                      display = ui.SetTerminalMode();
+                      break;
+                  case '?':
+                      con.Puts("PowerGuru - Xantrex mode\r\n");
+                      con.Puts("\t? - help\r\n");
+                      con.Puts("\tL - Menu Heading Minus\r\n");
+                      con.Puts("\tR - Menu Heading Plus\r\n");
+                      con.Puts("\tR - Menu Heading Plus\r\n");
+                      con.Puts("\tD - Menu Item Minus\r\n");
+                      con.Puts("\tU - Menu Item Plus\r\n");
+                      con.Puts("\t+ - Value Plus\r\n");
+                      con.Puts("\t- - Value Item Plus\r\n");
+
+                      con.Puts("\t| - Inverter Mode\r\n");
+                      con.Puts("\tG - Generator Mode\r\n");
+                      con.Puts("\tS - Setup Menu\r\n");
+                      con.Puts("\t/ - LED Status\r\n");
+                      con.Puts("\tV - Version\r\n");
+                      con.Puts("\tT - TerminalMode\r\n");
+                      con.Puts("\tQ - Quit\r\n");
+                  default:
+                      break;
+                };
+
+                //          display += "\r";
+                con.Putc('\r');
+                con.Puts(display);
+#if 0
+                switch (ui.GetDataType()) {
+                  case MenuItem::NONE:
+                  case MenuItem::MENUHEAD:
+                  case MenuItem::MENUITEM:
+                  case MenuItem::BOOL:
+                      if (ui.GetBoolValue() == false)
+                          dbglogfile << "\tBoolean value is: " << "OFF" ;
+                      else
+                          dbglogfile << "\tBoolean value is: " << "ON" ;      
+                      dbglogfile << endl;
+                      break;
+                  case MenuItem::INT:
+                      dbglogfile << "\tInteger value is: " << value.intval << 
endl;
+                      break;
+                  case MenuItem::FLOAT:
+                      cerr << "\tFIXME: Float value is: " << value.floatval << 
endl;
+                      break;
+                  case MenuItem::TIME:
+                      dbglogfile << "\tTime value is: " << value.timeval << 
endl;
+                      break;
+                  case MenuItem::EOL:
+                  case MenuItem::CLOCK:
+                  case MenuItem::ENUM:
+                  case MenuItem::DATE:
+                      dbglogfile << "\tFIXME: unsupported type! " << 
value.intval << endl;
+                      break;
+                  default:
+                      dbglogfile << "Data Type out of range";
+                      break;
+                };
+#endif
+            }
+
+            str += ui.ReadSerial();
+            if (str.size() > 0) {
+                con.Puts(str);
+                str.erase();
+            }
+        }
+    }
+    
+    // Get the value of a menu item
+    if (getitem){
+      
+        string str = ui.GotoMenuItem(menuhead, menuitem);
+        ti = ui.GetItem(menuhead, menuitem);
+        //    ui.Read((char *)&buffy, 100);
+        cerr << "Inverter returned: " << str << endl;
+
+        //      dbglogfile << "BREAK HERE" << endl;
+      
+        switch (ti.GetType()) {
+          case MenuItem::BOOL:
+              if (ui.GetBoolValue(str) == false)
+                  cout << "The Boolean value is: NO" << endl;
+              else
+                  cout << "The Boolean value is: YES" << endl;
+              break;
+          case MenuItem::INFO:
+              value = ui.GetValue(str);
+              cout << "The value is: " << value << endl;
+              break;
+          case MenuItem::INT:
+              intval = ui.GetIntValue(str);
+              cout << "The Integer value is: " << intval << endl;
+              break;
+          case MenuItem::FLOAT:
+              fltval= ui.GetFloatValue(str);
+              cout << "The Float value is: " << fltval << endl;
+              break;
+          case MenuItem::MENUHEAD:
+              cout << "The Menu Header is: " << "\"" <<
+                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+              break;
+          case MenuItem::MENUITEM:
+              cout << "The Menu Item is: " << "\"" <<
+                  ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+              break;
+          case MenuItem::TIME:
+              value = ui.GetValue(str);
+              cout << "The Time is: " << "\"" << value << endl;
+              break;
+          case MenuItem::EOL:
+              value = ui.GetValue(str);
+              cout << "The Time is: " << "\"" << value << endl;
+              break;
+          case MenuItem::CLOCK:
+              value = ui.GetValue(str);
+              cout << "The Clock value is: " << "\"" << value << endl;
+              break;
+          case MenuItem::ENUM:
+              value = ui.GetValue(str);
+              cout << "The Enum value is: " << "\"" << value << endl;
+              break;
+          case MenuItem::DATE:
+              value = ui.GetValue(str);
+              cout << "The Date is: " << "\"" << value << endl;
+              break;
+          default:
+              cout << "The value is: " << value << endl;
+              value = str;
+        };
+    } // endof getitem
+
+    // Monitor an item. This means grabs successive values and
+    // display them. This is for selections that constantly update
+    // the value.
+    if (monitor) {
+        string str = ui.GotoMenuItem(menuhead, menuitem);
+        ti = ui.GetItem(menuhead, menuitem);
+
+        cout << "The Menu Header is: " << "\"" <<
+            ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+      
+        do {
+            memset(buffy, 0, 100);        
+            ret = ui.Read((char *)&buffy, 100);
+            str = buffy;
+            if (ret < 0)            // there is no input yet, try again
+                continue;
+
+            // We got something, so extract the type, and process the
+            // value.
+            switch (ti.GetType()) {
+              case MenuItem::BOOL:
+                  if (ui.GetBoolValue(str) == false)
+                      cout << "\tThe Boolean value is: NO" << endl;
+                  else
+                      cout << "\tThe Boolean value is: YES" << endl;
+                  break;
+              case MenuItem::INFO:
+                  value = ui.GetValue(str);
+                  cout << "\tThe value is: " << value << endl;
+                  break;
+              case MenuItem::INT:
+                  intval = ui.GetIntValue(str);
+                  cout << "\tThe Integer value is: " << intval << endl;
+                  break;
+              case MenuItem::FLOAT:
+                  fltval= ui.GetFloatValue(str);
+                  cout << "\tThe Float value is: " << fltval << endl;
+                  break;
+              case MenuItem::MENUHEAD:
+                  cout << "\tThe Menu Header is: " << "\"" <<
+                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+                  break;
+              case MenuItem::MENUITEM:
+                  cout << "\tThe Menu Item is: " << "\"" <<
+                      ui.CleanUpData(ti.GetLabel()) << "\"" << endl;
+                  break;
+              default:
+                  cout << "\tThe value is: " << value << endl;
+                  value = str;
+            };
+        } while (ret); // endof monitor   
+    }
+}
+#endif
+
+meter_data_t *
+XantrexUI::exportMeterData(meter_data_t *data)
+{
+#if 0
+    // The unit number for the device
+    data->unit = _address;
+  
+    // The type of the device
+    switch (_type) {
+      case OUTBACK_MX:
+          data->type = MX_OUTBACK;
+          break;
+      case OUTBACK_FX:
+          data->type = FX_OUTBACK;
+          break;
+      case SW_XANTREX:
+      default:
+          break;
+    };
+  
+    // The amperage being put into the batteries
+    data->charge_amps = _charge_current;
+    // The load in amps
+    data->ac_load_amps = _inverter_current;
+    // Actual Battery Voltage
+    data->battery_volts = _battery_voltage;
+    // Battery Voltage temperature compensated. This isn't used by
+    // Outback products.
+    data->tempcomp_volts = 0;
+    // The voltage the inverter is producing
+    data->ac_volts_out = _AC_output_voltage;
+    // Grid AC input
+    data->ac1_volts_in = _AC_input_voltage;
+    // The AC current taken from the Grid and used to charge the batteries.
+    data->buy_amps = _buy_current;
+    // The AC current the batteries are putting into the grid.
+    data->sell_amps = _sell_current;
+    // The daily kilowatts put into the batteries from the PV source.
+    data->daily_kwh = _daily_kwh;
+    // The frequency in hertz. This doesn't exist on an Outback, but does on
+    // a Xantrex. It should always be 60 though, so we set it so other
+    // software can handle this  the same way.
+    data->hertz = 60;
+#endif
+
+    return data;
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/devices/xantrex-trace.h b/devices/xantrex-trace.h
new file mode 100644
index 0000000..a422ecd
--- /dev/null
+++ b/devices/xantrex-trace.h
@@ -0,0 +1,158 @@
+// 
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+//      Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef  __XANTREXUI_H__
+#define __XANTREXUI_H__
+
+#ifdef __cplusplus
+
+#include <cstring>
+#include <vector>
+#include <map>
+#include "err.h"
+#include <console.h>
+
+#include "serial.h"
+#include "menuitem.h"
+#include "database.h"
+
+class XantrexUI : public Serial
+{
+ public:
+  typedef enum {USERMENU, SETUPMENU} menu_e;
+  enum inverter_e {OFF, SRCH, ON, CHG};
+  enum invertsetup_e {FLOAT, SELL, SLT, LBX};
+  enum battery_e {NICAD, LEADACID, GEL};
+  enum genauto_e {UNINITIALIZED, RUNNING, IDLE};
+
+  XantrexUI(void);
+  ~XantrexUI(void);
+  
+  // Dump all internal data to the console
+  void Dump (void);
+  void DumpAliases(void);
+  
+  // This selects which inverter we want to control
+  std::string &SelectInverter(int x);
+
+  // Read from the serial port
+  std::string &ReadSerial(void);
+
+  // Write to the serial port
+  std::string &WriteSerial(const char *buf, int nbytes);
+
+  // These methods all go with the Xantrex display buttons
+  std::string &MenuHeadingMinus(void);
+  std::string &MenuHeadingPlus(void);
+  std::string &MenuItemMinus(void);
+  std::string &MenuItemPlus(void);
+  std::string &SetPointMinus(void);
+  std::string &SetPointPlus(void);
+  std::string &Inverter(void);
+  std::string &Generator(void);
+  std::string &SetupMenu(void);
+  std::string &LedStatus(void);
+  std::string &Version(void);
+  std::string &SetTerminalMode(void);
+  
+  std::vector<meter_data_t *> PollMeters(int loops);
+  //std::map<std::string, float> *PollMeters(int loops);
+  
+  // This method takes the data as outputted by the Xantrex inverter,
+  // and munges it to be a standard form with whitespace compressed,
+  // newlines & carriage returns stripped out, etc... This is so
+  // we can analyse the string data in a consistant fashion.
+  std::string &CleanUpData(std::string &str);
+
+  meter_data_t *exportMeterData(meter_data_t *data);
+  
+#if 0
+  std::string &UserMenu(void);
+  // These methods are for switching menu modes
+  retcode_t GotoSetupMenu(void);
+  retcode_t GotoUserMenu(void);
+#endif
+  // This method takes us to the beginning of the menu headers and items
+  // This corresponds then to being in the Inverter Mode header of the
+  // User menu.
+  retcode_t GotoMenuStart(void);
+  std::string &GotoMenuItem(int mh, int mi);
+  
+  // These methods manipulate values
+  std::string &GetValue (std::string &x);
+  std::vector<std::string> *GetValues (std::string &str);
+  retcode_t SetFloatValue(float x);
+  float GetFloatValue(std::string &x);
+  retcode_t SetIntValue(int x);
+  int GetIntValue(std::string &x);
+  retcode_t SetBoolValue(bool x);
+  bool GetBoolValue(std::string &x);
+  std::string GetLabel(std::string &x);
+  // This method populates the menu item data to default values as per
+  // the Xantrex manual.
+  void SetDefaultValues (void);
+
+  // This method tries to match the display with a menu item
+  // to verify we're where we think we are...
+  MenuItem &Match(std::string &str);
+  MenuItem &GetItem(int x, int y);
+  MenuItem &GetItem() { return GetItem(menuheading, menuitem); }
+  std::string GetLabel();
+
+  retcode_t xantrex_main(Console& con);
+ private:
+  std::vector< std::vector< MenuItem > > _items;
+  int menuheading;
+  int menuitem;
+  //  Serial uart;  
+};
+
+extern "C" {
+#else
+
+  // Default object for C code. 
+  XantrexUI ui;
+  
+  /* This is the C API for this class. */
+  
+  const char *menu_heading_minus(void);
+  const char *menu_heading_plus(void);
+  const char *menu_item_minus(void);
+  const char *menu_item_mlus(void);
+  const char *set_point_minus(void);
+  const char *set_point_plus(void);
+  
+  const char *inverter(void);
+  const char *generator(void);
+  const char *setup_menu(void);
+  const char *led_status(void);
+  const char *version(void);
+  const char *set_terminal_mode(void);
+  
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+// end of __XANTREXUI_H__
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=e93fdfe977d1e7dccf9de028eb2ad4a396cfc9ec


commit e93fdfe977d1e7dccf9de028eb2ad4a396cfc9ec
Author: Rob Savoye <address@hidden>
Date:   Thu Nov 15 14:02:24 2018 -0700

    Add CPPFLAGS

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index c9bfb87..8a09dce 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -32,7 +32,7 @@ else
   SNMP_DIR = 
 endif
 
-AM_CPPFLAGS = -Wall -I$(top_srcdir)/lib $(MARIADB_CFLAGS) ${POSTGRESQL_CFLAGS} 
$(SNMP_INCLUDES) $(XML_CPPFLAGS)
+AM_CPPFLAGS = -Wall -I$(top_srcdir)/lib $(MARIADB_CFLAGS) ${POSTGRESQL_CFLAGS} 
$(SNMP_INCLUDES) $(XML_CPPFLAGS) $(CPPFLAGS)
 
 bin_PROGRAMS = pgd
 

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=a76210f7a92a795229380388bce80230efde690d


commit a76210f7a92a795229380388bce80230efde690d
Author: Rob Savoye <address@hidden>
Date:   Thu Nov 15 14:02:01 2018 -0700

    Fix copyright date

diff --git a/Makefile.am b/Makefile.am
index f77d0f4..7a00863 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 # 
-#  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+#  Copyright (C) 2003, 2004-2018.
 #      Free Software Foundation, Inc.
 # 
 # This program is free software; you can redistribute it and/or modify

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=fe72271bce330472c93b16f96403fe2c8d692af1


commit fe72271bce330472c93b16f96403fe2c8d692af1
Author: Rob Savoye <address@hidden>
Date:   Thu Nov 15 14:01:28 2018 -0700

    Cleanup building optional files

diff --git a/lib/Makefile.am b/lib/Makefile.am
index bf164de..122c761 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,8 +34,14 @@ address@hidden@
 AM_CPPFLAGS = -Wall \
        -I$(srcdir) \
        -I$(top_srcdir)/snmp \
-       -I.. $(XML_CPPFLAGS) \
-       $(MYSQL_CFLAGS)
+       -I.. $(XML_CPPFLAGS)
+#      $(MARIADB_CFLAGS) \
+#      ${POSTGRESQL_CFLAGS)
+
+if BUILD_LIBXML
+SNMP_FILES = xml.cc xml.h
+libpguru_la_LIBDADD =  $(SNMP_LIBS) -lxml2
+endif
 
 if BUILD_SNMP
 SNMP_FILES = snmp.cc snmp.h
@@ -52,8 +58,6 @@ LIBPQ_FILES = postgresql.cc
 libpguru_la_LIBDADD =  $(LIBPQ_LIBS)
 endif
 
-# Bulding sharedlib requires adding all the libtool libraries
-# sharedlib.cc
 libpguru_la_SOURCES = \
        proc.cc proc.h \
        err.cc err.h \
@@ -73,7 +77,7 @@ libpguru_la_SOURCES = \
        tcputil.cc tcputil.h \
        tcpip.cc tcpip.h \
        msgs.cc msgs.h \
-       xml.cc xml.h
+       $(XML_FILES)
 
 include_HEADERS = \
        proc.h \
diff --git a/lib/snmp.cc b/lib/snmp.cc
index c8334b4..c83464b 100644
--- a/lib/snmp.cc
+++ b/lib/snmp.cc
@@ -16,13 +16,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#include <net-snmp/net-snmp-config.h>
 #ifdef HAVE_CONFIG_H
-# undef PACKAGE_VERSION
-# undef PACKAGE_TARNAME
-# undef PACKAGE_STRING
-# undef PACKAGE_NAME
-# undef PACKAGE_BUGREPORT
 // This is generated by autoconf.
 # include "config.h"
 #endif
@@ -35,13 +29,6 @@
 #include <sys/time.h>
 #include <iostream>
 
-#if 0
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <net-snmp/agent/net-snmp-agent-includes.h>
-#include <net-snmp/agent/scalar.h>
-#endif
-
 #include "err.h"
 #include "snmp.h"
 #include "proc.h"
@@ -58,6 +45,10 @@ extern "C" {
 
 #define RETSIGTYPE void
 
+#ifndef NETSNMP_ATTRIBUTE_DEPRECATED
+#define NETSNMP_ATTRIBUTE_DEPRECATED 1
+#endif
+
 using namespace std;
 
 SnmpClient::SnmpClient()
diff --git a/lib/snmp.h b/lib/snmp.h
index ebcd8e2..4713cf6 100644
--- a/lib/snmp.h
+++ b/lib/snmp.h
@@ -37,7 +37,6 @@
 #include <sys/timeb.h>
 */
 
-#ifdef USE_SNMP
 /* if on windows: */
 #ifdef WIN32
 #include <winsock.h>
@@ -59,15 +58,21 @@
    minimal requirements */
 #define NET_SNMP_CONFIG_H
 
-#undef SNMP_TRANSPORT_UDPIPV6_DOMAIN
-#undef SNMP_TRANSPORT_TCPIPV6_DOMAIN
+//#undef SNMP_TRANSPORT_UDPIPV6_DOMAIN
+//#undef SNMP_TRANSPORT_TCPIPV6_DOMAIN
+
+// FIXME: including <net-snmp/net-snmp-includes.h> causes problems unless
+// this is defined.
+#ifndef NETSNMP_ATTRIBUTE_DEPRECATED
+#define NETSNMP_ATTRIBUTE_DEPRECATED
+#endif
 
 /* include the core Net-SNMP functionality headers */
 #include <net-snmp/net-snmp-config.h>
+#include <net-snmp/types.h>
 #include <net-snmp/net-snmp-includes.h>
 #include <net-snmp/agent/net-snmp-agent-includes.h>
 #include <net-snmp/agent/scalar.h>
-#endif
 
 #include <string>
 #include "err.h"
@@ -82,7 +87,7 @@ public:
     struct snmp_pdu *read(std::string mibnode);
 private:
     std::string           *_hostname;
-#ifdef USE_SNMP
+#ifdef HAVE_SNMP
     struct snmp_session   _session;
     struct snmp_session   *_handle;
     struct tree           *_mibtree;
diff --git a/lib/tcpip.cc b/lib/tcpip.cc
index 4c933d2..61e5d2b 100644
--- a/lib/tcpip.cc
+++ b/lib/tcpip.cc
@@ -36,11 +36,11 @@
 #include <iostream>
 #include <sys/param.h>
 #include <fcntl.h>
-#ifdef HAVE_LIBXML
-# include <libxml/encoding.h>
-# include <libxml/xmlwriter.h>
-# include <libxml/debugXML.h>
-#endif
+// #ifdef HAVE_LIBXML
+// # include <libxml/encoding.h>
+// # include <libxml/xmlwriter.h>
+// # include <libxml/debugXML.h>
+// #endif
 
 #include "tcpip.h"
 #include "tcputil.h"
diff --git a/lib/tcpip.h b/lib/tcpip.h
index 761dd74..b7032e5 100644
--- a/lib/tcpip.h
+++ b/lib/tcpip.h
@@ -31,10 +31,11 @@
 //#include <netdb.h>
 #include <string>
 #include <vector>
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-#include <libxml/debugXML.h>
-
+// #ifdef HAVE_LIBXML
+// # include <libxml/encoding.h>
+// # include <libxml/xmlwriter.h>
+// # include <libxml/debugXML.h>
+// #endif
 
 #include "log.h"
 #include "err.h"
@@ -68,8 +69,8 @@ public:
     retcode_t createNetClient(std::string &hostname, short port, std::string 
&protocol);
 
     // If there is any data, process it
-    retcode_t anydata(std::vector<const xmlChar *> &msgs);
-    retcode_t anydata(int sockfd, std::vector<const xmlChar *> &msgs);
+    retcode_t anydata(std::vector<const unsigned char *> &msgs);
+    retcode_t anydata(int sockfd, std::vector<const unsigned char *> &msgs);
 
     // Read from the socket
     int readNet(char *buffer, int nbytes);

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=92ddf5a7c2c080e73f80546d8147d6838da039f5


commit 92ddf5a7c2c080e73f80546d8147d6838da039f5
Author: Rob Savoye <address@hidden>
Date:   Thu Nov 15 14:01:04 2018 -0700

    More changes so cross configuring works better

diff --git a/configure.ac b/configure.ac
index 0437eb8..a24b679 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,7 @@ else
    AC_DOCBOOK_STYLES
 fi
 
+db="none"
 AC_ARG_WITH(db, [  --with-db          database to use, mariadb or the default 
of postgresql],
 [case "${withval}" in
   p*) db=postgresql ;;
@@ -81,7 +82,7 @@ AC_ARG_WITH(db, [  --with-db          database to use, 
mariadb or the default of
   *)   AC_MSG_ERROR([bad value ${withval} for with-db option]) ;;
 esac])
 AM_CONDITIONAL(BUILD_MARIADB, [ test x${db} = xmariadb ])
-AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${db} = xpostgressql ])
+AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${db} = xpostgresql ])
 
 AC_CANONICAL_BUILD
 AC_CANONICAL_HOST
@@ -127,12 +128,33 @@ else
 fi
 AM_CONDITIONAL(CROSS_COMPILING, [ test x$cross_compiling = xyes ])
 
+AC_ARG_WITH(sysroot,
+  AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
+  with_top_level=${withval};
+  cross_compiling=yes)
+
+with_top_level=""
+if test x"${cross_compiling}" = xyes; then
+  dnl Check if /usr isn't part of the specified path
+  if test -d ${with_top_level}/usr; then
+    with_top_level=${withval}/usr
+  else 
+    dnl Check if the specified path supplies /usr
+    if test -d ${with_top_level}/include; then
+      with_top_level=${withval}
+    else
+      AC_MSG_ERROR([Specified sysroot \"${with_top_level}/include\" doesn't 
exist!])
+    fi
+  fi
+fi
+
 save_LDFLAGS="${LDFLAGS}"
 save_CFLAGS="${CFLAGS}"
 dnl CFLAGS="${CFLAGS} -Wall -Werror `${CXX} -print-sysroot`/usr/include"
 CFLAGS="${save_CFLAGS} -Wall -Werror"
 
-dnl libxml2
+# dnl libxml2's headers are sometimes in a libxml2 directory, but not always
+CPPFLAGS="-I`${CXX} -print-sysroot`/usr/include/libxml2"
 AC_MSG_CHECKING([For libxml2 development files])
 AC_TRY_COMPILE([#include <libxml/xmlstring.h>], [
   xmlChar foo = 'x';
@@ -146,7 +168,7 @@ if test x"${has_libxml}" = x"true"; then
   AC_DEFINE([HAVE_LIBXML], [1], [Has libxml2 development files])
   LIBS="${LIBS} -lxml2"
 fi
-AM_CONDITIONAL(BUILD_LIBXML, [ test x${has_libxml} = xyes ])
+AM_CONDITIONAL(BUILD_LIBXML, [ test x${has_libxml} = xtrue ])
 dnl GNU_PKG_FIND(libxml2, [libxml/xmlstring.h], [libxml2], xmlNewReference)
 
 dnl libpq. FIXME: add libpqcxx
@@ -161,14 +183,22 @@ AC_TRY_COMPILE([#include <libpq-fe.h>], [
 AC_MSG_RESULT([${has_libpq}])
 if test x"${has_libpq}" = x"true"; then
   AC_DEFINE([HAVE_LIBPQ], [1], [Has postgresql development files])
+  LIBS="${LIBS} -lpq"
 fi
 AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${has_libpq} = xtrue ])
 
 dnl Net-SNMP
+dnl net-snmp's headers require these two config options or you get
+dnl an error. FIXME: this need to be real tests!
+AC_DEFINE([HAVE_STRCASESTR], [1], [ Has strcasestr defined ])
+AC_DEFINE([HAVE_IN_ADDR_T], [1], [ Has typedef in_addr_t])
+
+CFLAGS="${save_CFLAGS} -Wall"
 LDFLAGS="${save_LDFLAGS} -lnetsnmp"
 AC_MSG_CHECKING([For Net SNMP development files])
-AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>], [
-  config_add_mib(0);
+AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/types.h>], [
+  netsnmp_pid_t foo;
   ],
   has_snmp=true,
   has_snmp=false
@@ -176,8 +206,9 @@ AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>], [
 AC_MSG_RESULT([${has_snmp}])
 if test x"${has_snmp}" = x"true"; then
   AC_DEFINE([HAVE_SNMP], [1], [Has Net SNMP development files])
+  LIBS="${LIBS} -lnetsnmp"
 fi
-AM_CONDITIONAL(BUILD_SNMP, [ test x${has_snmp} = xyes ])
+AM_CONDITIONAL(BUILD_SNMP, [ test x${has_snmp} = xtrue ])
 
 dnl mariadb development files
 dnl FIXME
@@ -200,7 +231,7 @@ AC_SUBST(PACKAGE_LIBS)
 
 dnl AM_PATH_POSTGRESQL
 dnl AC_PATH_MYSQL
-AM_CONDITIONAL(BUILD_MARIADB, [ test x${has_mariadb} = xyes ])
+AM_CONDITIONAL(BUILD_MARIADB, [ test x${has_mariadb} = xtrue ])
 
 AC_ARG_ENABLE(sim, [  --enable-sim           enable support for Sim 
(default=no)],
 [case "${enableval}" in
@@ -226,25 +257,6 @@ AC_ARG_WITH(tty,
   AC_SUBST(TTYS)
 )
 
-AC_ARG_WITH(sysroot,
-  AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
-  with_top_level=${withval};
-  cross_compiling=yes)
-
-with_top_level=""
-if test x"${cross_compiling}" = xyes; then
-  dnl Check if /usr isn't part of the specified path
-  if test -d ${with_top_level}/usr; then
-    with_top_level=${withval}/usr
-  else 
-    dnl Check if the specified path supplies /usr
-    if test -d ${with_top_level}/include; then
-      with_top_level=${withval}
-    else
-      AC_MSG_ERROR([Specified sysroot \"${with_top_level}/include\" doesn't 
exist!])
-    fi
-  fi
-fi
 
 dnl link to the images so we can browse the HTML output before
 dnl installing it.
@@ -268,43 +280,43 @@ dnl we arent building this for now
 dnl src/Makefile
 echo ""
 echo "Configurable options are:"
-dnl SNMP
-if test x$snmp = xtrue; then
-  echo "        Using SNMP"
-else
-  echo "        Not using SNMP"
-fi
 
-if test x$sim = xtrue; then
-  echo "        Using the simulator"
-else
-  echo "        Not using the simulator"
-fi
+dnl if test x$sim = xtrue; then
+dnl   echo "        Using the simulator"
+dnl else
+dnl   echo "        Not using the simulator"
+dnl fi
+
+dnl Docbook
+dnl if test x$docbook = xyes; then
+dnl   echo "        Docbook styles in $DOCBOOK_STYLES"
+dnl fi
 
-dnl Dmalloc
-if test x$dmalloc = xyes; then
-  echo "        Using DMALLOC"
+dnl
+dnl Often warning messages get lost in the output from configure, so
+dnl redisplay the few critical ones so they don't get ignored.
+dnl
+if test x"${has_libxml}" != x"true"; then
+  echo "        To use XML, install the libxml2 development package for your 
system"
 else
-  echo "        Not using DMalloc"
+  echo "        Found libxml2, will configure XML support"
 fi
 
-dnl Docbook
-if test x$docbook = xyes; then
-  echo "        Docbook styles in $DOCBOOK_STYLES"
-fi
-if test x"$pthreads" = x"yes"; then
-  echo "        Using POSIX Threads"
+if test x"${has_snmp}" != x"true"; then
+  echo "        To use SNMP. install the net-snmp development package for your 
system"
 else
-  echo "        Not using POSIX Threads"
+  echo "        Found net-snmp. will configure SNMP support"
 fi
-if test x"$disablexml" = x"yes"; then
-  echo "        Not using XML"
+
+if test x"${db}" = x"none"; then
+  echo "        To use a database. install the mariadb or postgresql 
development package for your system"
 else
-  echo "        Using XML"
-fi
-if test x"$dom" != x"yes"; then
-  echo "        Using DOM parser"
-fi
-if test x"$reader" != x"yes"; then
-  echo "        Using XmlReader (SAX) parser"
+  echo "        Found a database. will configure database support for ${db}"
 fi
+
+dnl if test x"$dom" != x"yes"; then
+dnl   echo "        Using DOM parser"
+dnl fi
+dnl if test x"$reader" != x"yes"; then
+dnl   echo "        Using XmlReader (SAX) parser"
+dnl fi

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=64e9fb4b92da6f48656e0d42413662af96e86b30


commit 64e9fb4b92da6f48656e0d42413662af96e86b30
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 21:41:22 2018 -0700

    Make libxml optional

diff --git a/lib/tcpip.cc b/lib/tcpip.cc
index 4caeac8..4c933d2 100644
--- a/lib/tcpip.cc
+++ b/lib/tcpip.cc
@@ -36,10 +36,11 @@
 #include <iostream>
 #include <sys/param.h>
 #include <fcntl.h>
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-#include <libxml/debugXML.h>
-
+#ifdef HAVE_LIBXML
+# include <libxml/encoding.h>
+# include <libxml/xmlwriter.h>
+# include <libxml/debugXML.h>
+#endif
 
 #include "tcpip.h"
 #include "tcputil.h"

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=8eb97acdebe677c4d9cb214a98a2213f10eb15d6


commit 8eb97acdebe677c4d9cb214a98a2213f10eb15d6
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 21:22:43 2018 -0700

    support paths for gnufind.m4

diff --git a/macros/incllist b/macros/incllist
new file mode 100644
index 0000000..803e9a1
--- /dev/null
+++ b/macros/incllist
@@ -0,0 +1 @@
+${with_top_level}/include ${prefix}/${host_alias}/include ${prefix}/include 
/sw/include /usr/nekoware/include /usr/freeware/include /usr/pkg/include 
/opt/local/include /usr/local/include /home/latest/include /opt/include 
/opt/mesa/include /opt/include /usr/X11R6/include /usr/X11/include /usr/include 
/usr/pkg/include /boot/common/include /boot/develop/headers/3rdparty
diff --git a/macros/libslist b/macros/libslist
new file mode 100644
index 0000000..8148712
--- /dev/null
+++ b/macros/libslist
@@ -0,0 +1 @@
+${with_top_level}/lib ${prefix}/${host_alias}/lib ${prefix}/lib64 
${prefix}/lib32 ${prefix}/lib /usr/local/lib /lib /usr/lib64 /usr/lib32 
/usr/lib /usr/nekoware/lib /usr/freeware/lib /usr/lib /sw/lib /home/latest/lib 
/opt/lib /pkg/lib /opt/local/lib /usr/pkg/lib /usr/X11R6/lib /usr/X11/lib 
/usr/lib/opengl/xorg-x11/lib /usr/lib64/opengl/xorg-x11/lib 
/usr/lib64/opengl/xorg-x11/lib64  /opt/mesa/lib /opt/mesa/lib64 
/boot/common/lib /boot/system/lib/gcc4 /boot/system/lib .. ../..

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=33fa0a0f48b344b596d8df7fcaa7e2c1e8bbe0ab


commit 33fa0a0f48b344b596d8df7fcaa7e2c1e8bbe0ab
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:33:01 2018 -0700

    Make database a conditional

diff --git a/client/cmd.cc b/client/cmd.cc
index ca7768a..7e15a40 100644
--- a/client/cmd.cc
+++ b/client/cmd.cc
@@ -33,11 +33,11 @@
 #include <sys/types.h>
 #include <cstdio>
 #include <iostream>
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-#include <libxml/debugXML.h>
-
-#include "dejagnu.h"
+#ifdef HAVE_LIBXML
+# include <libxml/encoding.h>
+# include <libxml/xmlwriter.h>
+# include <libxml/debugXML.h>
+#endif
 #include "tcpip.h"
 #include "console.h"
 #include "msgs.h"

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=3dac25dd99e2d61185231fa4e964ddd7bc40deb9


commit 3dac25dd99e2d61185231fa4e964ddd7bc40deb9
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:32:27 2018 -0700

    Use AM_CPPFLAGS instead of INCLUDES

diff --git a/testsuite/libtests/Makefile.am b/testsuite/libtests/Makefile.am
index 39453a9..b665acb 100644
--- a/testsuite/libtests/Makefile.am
+++ b/testsuite/libtests/Makefile.am
@@ -26,7 +26,7 @@ AM_INCLUDES =  $(MYSQLH) # $(INCLTDL)
 
 noinst_PROGRAMS = tcpip tutil childtcpip
 
-INCLUDES = -I$(top_srcdir)/lib
+AM_CPPFLAGS = -I$(top_srcdir)/lib
 
 LOG = ../../lib/log.lo ../../lib/err.lo
 # Tcpip.C test case

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=02ced6806507b8ad2220af46b23032bad688ff0f


commit 02ced6806507b8ad2220af46b23032bad688ff0f
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:31:45 2018 -0700

    Make database a conditional

diff --git a/lib/database.h b/lib/database.h
index 45d9864..0aa2535 100644
--- a/lib/database.h
+++ b/lib/database.h
@@ -36,7 +36,7 @@
 #include <mysql/errmsg.h>
 #include <mysql/mysql.h>
 #else
-#error "You need to install MySQL!"
+#warning "You need to install MySQL for data base support"
 #endif
 
 // This shuts up warnings about these constants not being used.
@@ -107,8 +107,13 @@ private:
     std::string     _dbhost;
     std::string     _dbname;
     std::string     _tblname;
+#ifdef HAVE_MYSQL
     MYSQL           *_connection;
     MYSQL           _mysql;
+#endif
+#ifdef LIBPQ
+    bool           *_connection;
+#endif
 };
 
 // __DATABASE_H__
diff --git a/lib/log.cc b/lib/log.cc
index bc0dafa..9495cc3 100644
--- a/lib/log.cc
+++ b/lib/log.cc
@@ -8,18 +8,6 @@ using namespace std;
 // Target Manager internal logging sub-system
 #include "log.h"
 
-// Target Manager error sub-system
-#include "err.h"
-
-// This is so we don't get warning from strncpy()
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
 // Required for SYSTEMTIME definitions
 #ifdef _WIN32
 #include <windows.h>
@@ -264,7 +252,7 @@ LogFile::operator << (const char *c) {
 }
 
 LogFile& 
-LogFile::operator << (const xmlChar *c) {
+LogFile::operator << (const unsigned char *c) {
     logentry = timestamp();
     logentry += ": ";
 
diff --git a/lib/log.h b/lib/log.h
index 1dbbe28..d8346cc 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -19,17 +19,27 @@
 #ifndef __LOG_H__
 #define __LOG_H__
 
-#include "config.h"
+// This is generated by autoconf
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// Target Manager error sub-system
 #include "err.h"
 
+// This is so we don't get warning from strncpy()
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
 #ifdef __cplusplus
 
 #include <time.h>
 
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-
 #include <iostream>
 #include <iomanip>
 #include <string>
@@ -88,7 +98,7 @@ public:
     LogFile& operator << (bool x);
     LogFile& operator << (void *);
     LogFile& operator << (const char *);
-    LogFile& operator << (const xmlChar *);
+    LogFile& operator << (const unsigned char *);
     LogFile& operator << (std::string );
     std::ostream& operator << (std::ostream & (&)(std::ostream &));
     const char *GetEntry(void);
diff --git a/lib/xml.h b/lib/xml.h
index af81fb8..68741c5 100644
--- a/lib/xml.h
+++ b/lib/xml.h
@@ -26,9 +26,11 @@
 
 #include <string>
 #include <vector>
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
+#ifdef HAVE_LIBXML
+# include <libxml/xmlmemory.h>
+# include <libxml/parser.h>
+# include <libxml/xmlreader.h>
+#endif
 
 #include "log.h"
 #include "err.h"

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=4228f1b7835f8edad0a517fe6c0077416b28f82d


commit 4228f1b7835f8edad0a517fe6c0077416b28f82d
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:31:18 2018 -0700

    Rename file

diff --git a/lib/mysql.cc b/lib/mariadb.cc
similarity index 99%
rename from lib/mysql.cc
rename to lib/mariadb.cc
index 7311123..1ff56af 100644
--- a/lib/mysql.cc
+++ b/lib/mariadb.cc
@@ -42,6 +42,8 @@ using namespace std;
 #ifdef HAVE_MYSQL
 #include <mysql/errmsg.h>
 #include <mysql/mysql.h>
+#else
+#warning "You need to install MySQL for data base support"
 #endif
 
 const int LINELEN = 80;
@@ -115,10 +117,10 @@ Database::openDB (void)
         dbglogfile << "MySQL error when connecting: \n" << 
mysql_error(&_mysql) << endl;
         return false;
     }
-
+    
     dbglogfile << "Connected to MySQL database " << _dbname.c_str()
                <<  " on host " <<_dbhost.c_str() << endl;
-
+    
 #if 0
     if(mysql_select_db(&_mysql, "mydb")){ 
         DBG_MSG(DBG_EROR, "%s: MySQL error when selecting database: %s\n",
@@ -134,7 +136,6 @@ bool
 Database::closeDB (void)
 {
     mysql_close(&_mysql);
-
     // FIXME: do something intelligent here
     return true;
 }
@@ -183,7 +184,7 @@ Database::queryInsert(const char *query)
         }
     
         dbglogfile << "Lost connection to the database server, shutting 
down..." << endl;
-    
+        
         return false;
     }
   
@@ -243,7 +244,7 @@ Database::queryResults(const char *query)
         }
 
     mysql_free_result(result);
-
+    
     // FIXME: return something intelligent here
     return (void *)0;
 }

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=93e475a3bd17b2d2e18bc1b22ed2cc5c02f856ae


commit 93e475a3bd17b2d2e18bc1b22ed2cc5c02f856ae
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:30:45 2018 -0700

    Stubbed out driver so pguru will link.

diff --git a/lib/postgresql.cc b/lib/postgresql.cc
new file mode 100644
index 0000000..7c4cf06
--- /dev/null
+++ b/lib/postgresql.cc
@@ -0,0 +1,303 @@
+// 
+// Copyright (C) 2018
+//      Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// This is generated by autoconf
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+#include <iostream>
+#include <iomanip> 
+#include <vector>
+#include <sys/time.h>
+#include <cstdio>
+
+#ifdef __STDC_HOSTED__
+#include <sstream>
+#else
+#include <strstream>
+#endif
+
+using namespace std;
+
+#include "database.h"
+#include "log.h"
+
+#ifdef HAVE_LIBPQ
+#else
+#warning "You need to install Postgresql for data base support"
+#endif
+
+const int LINELEN = 80;
+const int QUERYLEN = 10000;
+extern LogFile dbglogfile;
+
+Database::Database()
+    : _dbtype(NODB), _dbport(0)
+{
+
+    // These values may be replaced on the command line. These are the
+    // default behaviour.
+    _tblname  = DBTABLE;
+    _dbname   = DBNAME;
+    _dbuser   = DBUSER;
+    _dbpasswd = DBPASS;
+    _dbhost   = DBHOST;
+}
+
+Database::~Database()
+{
+    //closeDB();
+}
+
+// Accessors
+void
+Database::dbUserSet(std::string user)
+{
+    _dbuser = user;
+}
+
+void
+Database::dbPasswdSet(std::string passwd)
+{
+    _dbpasswd = passwd;
+}
+
+void
+Database::dbNameSet(std::string name)
+{
+    _dbname = name;
+}
+
+void
+Database::dbHostSet(std::string host)
+{
+    _dbhost = host;
+}
+
+// methods that actually do something
+bool
+Database::openDB (void)
+{
+    // DEBUGLOG_REPORT_FUNCTION;
+
+    unsigned long flag = 0;
+
+    dbglogfile <<"Connecting to Postgresql database "  << _dbname.c_str()
+               << " on " << _dbhost.c_str()
+               << " as user " << _dbuser.c_str() << endl;
+
+    return true;
+}
+
+
+bool
+Database::closeDB (void)
+{
+    return true;
+}
+
+bool
+Database::queryInsert(const char *query)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    int retries, result;
+  
+    retries = 2;
+  
+    dbglogfile << "Query is: " << query << endl;
+  
+    dbglogfile << "Lost connection to the database server, shutting down..." 
<< endl;
+    return false;
+}
+
+  
+void *
+Database::queryResults(const char *query)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    //MYSQL_RES        *result;
+    //MYSQL_ROW        row;
+    int         nrows;
+    unsigned int i, res;
+
+    dbglogfile << "Query is: " << query << endl;
+
+    // FIXME: return something intelligent here
+    return (void *)0;
+}
+
+bool
+Database::queryInsert(vector<meter_data_t *> data)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    struct tm      *ttm;
+    struct timeval tp;
+    unsigned int   i;
+    //char           query[QUERYLEN];
+    //char           *ptr;
+#ifdef __STDC_HOSTED__
+    ostringstream  query;
+#else
+    ostrstream     query;
+#endif
+
+    if (data.size() == 0) {
+        dbglogfile << "No data to insert." << endl;
+        return false;
+    }
+  
+    gettimeofday(&tp, 0);
+    ttm = localtime (&tp.tv_sec);
+    ttm->tm_year+= 1900;          // years since 1900
+    ttm->tm_mon+=1;               // months since January
+
+    query << "INSERT INTO inverter () VALUES ";
+
+    for (i=0; i< data.size(); i++) {
+        queryInsert(data[i]);
+    }
+  
+    return true;  
+}
+  
+bool
+Database::queryInsert(meter_data_t *data)
+{
+    DEBUGLOG_REPORT_FUNCTION;
+
+    struct tm             *ttm;
+    struct timeval        tp;
+    //char                  query[QUERYLEN];
+    char                  *type = "MX";
+#ifdef __STDC_HOSTED__
+    std::ostringstream    query;
+#else
+    std::ostrstream       query;
+#endif
+
+    query.str("");
+    //  memset (query, 0, QUERYLEN);
+  
+    // EtaMsg em;
+    // em.dump(*data);
+  
+    gettimeofday(&tp, 0);
+    ttm = localtime (&tp.tv_sec);
+    ttm->tm_year+= 1900;          // years since 1900
+    ttm->tm_mon+=1;               // months since January
+
+#if 0  
+    // FIXME: For now source is the facility
+    // Build the query string to insert the data
+    sprintf(query, "INSERT INTO meters () VALUES ( \
+        '%d',                   // Unit address (int)\
+        '%s',                   // Device Type enum)\
+        '%d-%d-%d %d:%d:%d',    // timestamp\
+        '%d',                   // Charger Amps (int)\
+        '%d',                   // AC Load Amps (int)\
+        '%f',                   // Battery Volts (float)\
+        '%f',                   // AC Volts Out (float)\
+        '%f',                   // AC1 Volts In (float)\
+        '%f',                   // AC2 Volts In (float)\
+        '%d',                   // PV Amps In (int)\
+        '%f',                   // PV Volts In (float)\
+        '%f',                   // Buy Amps (int)\
+        '%f',                   // Sell Amps (int)\
+        '%f',                   // Dail Kwh (float)\
+        '%d',                   // Frequency in Hertz (int)\
+        '%f'                    // Battery Temperature Compenation (float)\
+        )",
+            //  sprintf(query, "INSERT INTO meters () VALUES 
('%d','%s','%0.4d-%0.2d-%d 
%0.2d:%0.2d:%0.2d','%d','%d','%f','%f','%f','%f','%d','%f','%f','%f','%d','%f','%f')",
+            data->unit,
+            type,
+            
ttm->tm_year,ttm->tm_mon,ttm->tm_mday,ttm->tm_hour,ttm->tm_min,ttm->tm_sec,
+            data->charge_amps,
+            data->ac_load_amps,
+            data->battery_volts,
+            data->ac_volts_out,
+            data->ac1_volts_in,
+            data->ac2_volts_in,
+            data->pv_amps_in,
+            data->pv_volts_in,
+            data->buy_amps,
+            data->sell_amps,
+            data->daily_kwh,
+            data->hertz,
+            data->tempcomp_volts
+        );
+#else
+    query << "INSERT INTO meters () VALUES (";
+    query << data->unit << ",";
+    query << "\'" << type << "\',";
+    query << "\'" << ttm->tm_year << "-" << ttm->tm_mon << "-" << ttm->tm_mday 
<< " ";
+    query << ttm->tm_hour << ":" << ttm->tm_min << ":" << ttm->tm_sec << "\',";
+    query << data->charge_amps << ",";
+    query << data->ac_load_amps << ",";
+    query << data->battery_volts << ",";
+    query << data->ac_volts_out << ",";
+    query << data->ac1_volts_in << ",";
+    query << data->ac2_volts_in << ",";
+    query << data->pv_amps_in << ",";
+    query << data->pv_volts_in << ",";
+    query << data->buy_amps << ",";
+    query << data->sell_amps << ",";
+    query << data->daily_kwh << ",";
+    query << data->hertz << ",";
+    query << data->tempcomp_volts << ")";
+    query << ends;
+#endif
+
+#ifdef __STDC_HOSTED__
+    string str = query.str().c_str();
+#else
+    string str = query.str();
+#endif
+  
+    // Execute the query
+    queryInsert(str.c_str());
+  
+    return true;
+}
+
+char *
+Database::gettime()
+{
+    struct timeval tp;
+    struct tm *tm, result;
+    static char tmpbuf[30];
+ 
+    gettimeofday(&tp, 0);
+    tm = localtime_r(&(tp.tv_sec), &result);
+    asctime(tm);
+    memset(tmpbuf, 0, 20);
+     
+    strftime(tmpbuf, 20, "%Y-%m-%d %H:%M:%S", tm);
+ 
+//    DBG_MSG(DBG_INFO, "TIMESTAMP is %s\n", tmpbuf);
+    return tmpbuf;
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=5996a6563cf9dce9d38c4cbf5f271915382c55be


commit 5996a6563cf9dce9d38c4cbf5f271915382c55be
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:30:01 2018 -0700

    Add conditional fot the data base type

diff --git a/client/Makefile.am b/client/Makefile.am
index c148bf1..dae1049 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS =
 PGURU = ../lib/libpguru.la
 bin_PROGRAMS = pguru 
 
-INCLUDES = -I$(top_srcdir)/lib $(XML_CPPFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/lib $(XML_CPPFLAGS)
 
 pguru_SOURCES = cmd.cc
 pguru_LDADD = $(PGURU) $(XML_LIBS) $(MYSQL_LIBS) -lpthread $(SNMP_LIBS)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index e45c4ae..c9bfb87 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -20,8 +20,6 @@
 
 AUTOMAKE_OPTIONS = # dejagnu
 
-AM_CPPFLAGS = -Wall
-
 if BUILD_SNMP
   SNMP_LA = ../snmp/libpgsnmp.la
   SNMP_FILES = $(SNMP_LA) $(SNMP_LIBS)
@@ -34,14 +32,14 @@ else
   SNMP_DIR = 
 endif
 
-INCLUDES = -I$(top_srcdir)/lib $(MYSQL_CFLAGS) $(SNMP_INCLUDES) $(XML_CPPFLAGS)
+AM_CPPFLAGS = -Wall -I$(top_srcdir)/lib $(MARIADB_CFLAGS) ${POSTGRESQL_CFLAGS} 
$(SNMP_INCLUDES) $(XML_CPPFLAGS)
 
 bin_PROGRAMS = pgd
 
 pgd_SOURCES = main.cc
 pgd_LDFLAGS = -export-dynamic -static -L../lib $(SNMP_DIR)
-pgd_LDADD =  -lpguru $(MYSQL_LIBS) $(XML_LIBS) $(SNMP_FILES) #-lpgsnmp
-pgd_DEPENDENCIES = ../lib/libpguru.la $(SNMP_LA) # $(LIBXML_LA)
+pgd_LDADD =  -lpguru $(MARIADB_LIBS) ${POSTGRESQL_LIBS} $(XML_LIBS) 
$(SNMP_FILES) #-lpgsnmp
+pgd_DEPENDENCIES = ../lib/libpguru.la $(SNMP_LA) ../lib/libpguru.la # 
$(LIBXML_LA)
 
 MUDFLAP_OPT = -fmudflap
 MUDFLAP_LIB =  /usr/local/lib/libmudflap.so
diff --git a/lib/Makefile.am b/lib/Makefile.am
index cf3f0e4..bf164de 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -22,7 +22,6 @@ AUTOMAKE_OPTIONS =
 #LIBLTDL = @LIBLTDL@
 # __USLC__ makes MySQL++ use the std namespace
 AM_CXXFLAGS = -g -D__USLC__
-AM_CPPFLAGS = -Wall
 
 lib_LTLIBRARIES = libpguru.la
 
@@ -32,7 +31,7 @@ address@hidden@
 # These headers get installed
 # include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
 
-INCLUDES = \
+AM_CPPFLAGS = -Wall \
        -I$(srcdir) \
        -I$(top_srcdir)/snmp \
        -I.. $(XML_CPPFLAGS) \
@@ -43,6 +42,16 @@ SNMP_FILES = snmp.cc snmp.h
 libpguru_la_LIBDADD =  $(SNMP_LIBS) ../snmp/libpgsnmp.la
 endif
 
+if BUILD_MARIADB
+MARIADB_FILES = mariadb.cc
+libpguru_la_LIBDADD =  $(MARIADB_LIBS)
+endif
+
+if BUILD_POSTGRESQL
+LIBPQ_FILES = postgresql.cc
+libpguru_la_LIBDADD =  $(LIBPQ_LIBS)
+endif
+
 # Bulding sharedlib requires adding all the libtool libraries
 # sharedlib.cc
 libpguru_la_SOURCES = \
@@ -57,8 +66,10 @@ libpguru_la_SOURCES = \
        xanbus.cc xanbus.h \
        outbackpower.cc outbackpower.h \
        menuitem.cc menuitem.h \
-       mysql.cc database.h\
+       database.h\
        $(SNMP_FILES) \
+       $(LIBPQ_FILES) \
+       $(MARIADB_FILES) \
        tcputil.cc tcputil.h \
        tcpip.cc tcpip.h \
        msgs.cc msgs.h \
diff --git a/sim/Makefile.am b/sim/Makefile.am
index 9c18fc7..e4c016c 100644
--- a/sim/Makefile.am
+++ b/sim/Makefile.am
@@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS =
 PGURU = ../lib/libpguru.la
 noinst_PROGRAMS = osim # xsim
 
-INCLUDES = -I$(top_srcdir)/lib  $(XML_CPPFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/lib  $(XML_CPPFLAGS)
 
 osim_SOURCES = fakeuart.cc fakeuart.h osim.cc
 osim_LDADD =  $(PGURU) $(MYSQL_LIBS) $(XML_LIBS)  $(SNMP_LIBS) -lpthread
diff --git a/snmp/Makefile.am b/snmp/Makefile.am
index f4e26e4..bddd402 100644
--- a/snmp/Makefile.am
+++ b/snmp/Makefile.am
@@ -31,7 +31,7 @@ libpgsnmp_la_SOURCES = \
 #              ifTable_data_access.c \
 #              ifTable_data_set.c
 
-INCLUDES = -I$(srcdir) -I.. $(SNMP_CFLAGS)
+AM_CPPFLAGS = -I$(srcdir) -I.. $(SNMP_CFLAGS)
 libpgsnmp_la_LIBDADD =  $(SNMP_LIBS)
 
 generate-templates:

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=92b1d7bcaa75b5920d529390e08c9b1795c32fd6


commit 92b1d7bcaa75b5920d529390e08c9b1795c32fd6
Author: Rob Savoye <address@hidden>
Date:   Wed Nov 14 19:28:51 2018 -0700

    Refactor so it works to cross compile

diff --git a/configure.ac b/configure.ac
index 7baf042..0437eb8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,50 +20,15 @@ dnl  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 
MA  02110-1301  USA
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59c)
-AC_INIT(snmp/POWERGURU-MIB.txt)
+AC_INIT([snmp/POWERGURU-MIB.txt], [0.4dev])
 dnl AC_CANONICAL_SYSTEM
 AC_CANONICAL_TARGET
-AM_INIT_AUTOMAKE(powerguru, 0.3dev)
+AM_INIT_AUTOMAKE
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([macros])
 
 dnl Use the DMalloc library, if specified.
-AC_ARG_ENABLE(dmalloc, [  --enable-dmalloc        enable support for DMalloc],
-[case "${enableval}" in
-  yes) dmalloc=yes ;;
-  no)  dmalloc=no ;;
-  *)   AC_MSG_ERROR([bad value ${enableval} for enable-malloc option]) ;;
-esac])
-
-if test x$dmalloc = xyes; then
-    AC_DEFINE([USE_DMALLOC], [], [Use DMalloc])
-    DMALLOC_LIB="-ldmallocxx"
-else
-    DMALLOC_LIB=""
-fi
-AC_SUBST(DMALLOC_LIB)
-dnl Use the POSIX Threads library, if specified.
-AC_ARG_ENABLE(pthreads, [  --enable-pthreads       Enable support for 
pthreads],[case "${enableval}" in
-  yes) pthreads=yes ;;
-  no)  pthreads=no ;;
-  *)   AC_MSG_ERROR([bad value ${enableval} for enable-pthreads option]) ;;
-esac])
- 
-if test x$pthreads = xyes; then
-    AC_DEFINE([HAVE_PTHREADS], [], [Use POSIX Threads])
-fi
-                                                                               
 
-dnl Add XML support, if specified.
-AC_ARG_ENABLE(libxml, [  --disable-xml           Disable support for xml 
tcpip],
-[case "${enableval}" in
-  yes) disablexml=yes ;;
-  no)  disablexml=no ;;
-  *)   AC_MSG_ERROR([bad value ${enableval} for disable-xml option]) ;;
-esac])
-if test x$disable_xml != xno; then
-    AC_DEFINE([HAVE_LIBXML], [], [Use XML])
-fi
-    AM_PATH_XML2
+AM_WITH_DMALLOC
 
 dnl Use the Dom parser from libxml2, not the xmlReader one
 dnl The default is to use the Dom parser
@@ -109,6 +74,15 @@ else
    AC_DOCBOOK_STYLES
 fi
 
+AC_ARG_WITH(db, [  --with-db          database to use, mariadb or the default 
of postgresql],
+[case "${withval}" in
+  p*) db=postgresql ;;
+  m*) db=mariadb ;;
+  *)   AC_MSG_ERROR([bad value ${withval} for with-db option]) ;;
+esac])
+AM_CONDITIONAL(BUILD_MARIADB, [ test x${db} = xmariadb ])
+AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${db} = xpostgressql ])
+
 AC_CANONICAL_BUILD
 AC_CANONICAL_HOST
 
@@ -118,6 +92,95 @@ AM_PROG_CC_STDC
 AC_HEADER_STDC
 dnl AC_PROG_AR
 AC_CHECK_TOOL(AR, ar)
+AC_PATH_PROG(DEJAGNU, runtest)
+
+dnl When cross compiling, limit the search directories cause otherwise
+dnl we may get the host headers or libraries by accident. These values
+dnl are exported, so all the other configure tests in macros/*.m4 use
+dnl these same settings rather than duplicating them like we used to.
+dnl To override thise, use the --with-*-incl= and --with-*-libs=
+dnl options to configure.
+if test x$cross_compiling = xyes; then
+  AC_MSG_NOTICE([Configuring PowerGuru for cross compilation])
+  export pkgroot="`$CXX -print-search-dirs | grep "install:" | sed -e 
's/install: //' -e 's:/lib/gcc/.*::'`"
+  dnl pkgroot only works correctly with builds of cross tools not in
+  dnl /usr, ie... installed from the distribution packages, or just
+  dnl plain installed in the system tools. This contaminates configure
+  dnl when building for variations of the same basic architecture,
+  dnl like i686-linux -> i586-mingw32.
+  if test x"${pkgroot}" = x"/usr"; then
+    export pkgroot=""
+  fi
+  export incllist="`eval echo ${with_top_level}/include 
${pkgroot}/${host_alias}/include ${pkgroot}/include`"
+  export libslist="`eval echo ${with_top_level}/lib 
${pkgroot}/${host_alias}/lib ${pkgroot}/lib64 ${pkgroot}/lib32 ${pkgroot}/lib`"
+  export pathlist="`eval echo ${pkgroot}/${host_alias}/bin:${pkgroot}/bin`"
+  npapi=no
+else
+  AC_MSG_NOTICE([Configuring PowerGuru for native compilation])
+  export incllist="`eval cat ${srcdir}/macros/incllist`"
+  libslist="`cat ${srcdir}/macros/libslist`"
+  if test -f /usr/bin/dpkg-architecture; then
+    export DEB_HOST_MULTIARCH="`eval dpkg-architecture -qDEB_HOST_MULTIARCH`"
+    export libslist="${libslist} /lib/${DEB_HOST_MULTIARCH} 
/usr/lib/${DEB_HOST_MULTIARCH}"
+  fi
+  export pathlist=$PATH
+fi
+AM_CONDITIONAL(CROSS_COMPILING, [ test x$cross_compiling = xyes ])
+
+save_LDFLAGS="${LDFLAGS}"
+save_CFLAGS="${CFLAGS}"
+dnl CFLAGS="${CFLAGS} -Wall -Werror `${CXX} -print-sysroot`/usr/include"
+CFLAGS="${save_CFLAGS} -Wall -Werror"
+
+dnl libxml2
+AC_MSG_CHECKING([For libxml2 development files])
+AC_TRY_COMPILE([#include <libxml/xmlstring.h>], [
+  xmlChar foo = 'x';
+  foo += 'y';
+  ],
+  has_libxml=true,
+  has_libxml=false
+)
+AC_MSG_RESULT([${has_libxml}])
+if test x"${has_libxml}" = x"true"; then
+  AC_DEFINE([HAVE_LIBXML], [1], [Has libxml2 development files])
+  LIBS="${LIBS} -lxml2"
+fi
+AM_CONDITIONAL(BUILD_LIBXML, [ test x${has_libxml} = xyes ])
+dnl GNU_PKG_FIND(libxml2, [libxml/xmlstring.h], [libxml2], xmlNewReference)
+
+dnl libpq. FIXME: add libpqcxx
+LDFLAGS="${save_LDFLAGS} -lpq"
+AC_MSG_CHECKING([For postgresql development files])
+AC_TRY_COMPILE([#include <libpq-fe.h>], [
+  PQpass(0);
+  ],
+  has_libpq=true,
+  has_libpq=false
+)
+AC_MSG_RESULT([${has_libpq}])
+if test x"${has_libpq}" = x"true"; then
+  AC_DEFINE([HAVE_LIBPQ], [1], [Has postgresql development files])
+fi
+AM_CONDITIONAL(BUILD_POSTGRESQL, [ test x${has_libpq} = xtrue ])
+
+dnl Net-SNMP
+LDFLAGS="${save_LDFLAGS} -lnetsnmp"
+AC_MSG_CHECKING([For Net SNMP development files])
+AC_TRY_COMPILE([#include <net-snmp/net-snmp-config.h>], [
+  config_add_mib(0);
+  ],
+  has_snmp=true,
+  has_snmp=false
+)
+AC_MSG_RESULT([${has_snmp}])
+if test x"${has_snmp}" = x"true"; then
+  AC_DEFINE([HAVE_SNMP], [1], [Has Net SNMP development files])
+fi
+AM_CONDITIONAL(BUILD_SNMP, [ test x${has_snmp} = xyes ])
+
+dnl mariadb development files
+dnl FIXME
 
 dnl These are for MinGW or Cygwin support.
 AC_EXEEXT
@@ -135,9 +198,9 @@ dnl shared libraries from our application code.
 AC_SUBST(PACKAGE_CFLAGS)
 AC_SUBST(PACKAGE_LIBS)
 
-AM_PATH_MYSQL
-AM_PATH_SNMP
-AM_CONDITIONAL(BUILD_SNMP, test x$snmp = xtrue)
+dnl AM_PATH_POSTGRESQL
+dnl AC_PATH_MYSQL
+AM_CONDITIONAL(BUILD_MARIADB, [ test x${has_mariadb} = xyes ])
 
 AC_ARG_ENABLE(sim, [  --enable-sim           enable support for Sim 
(default=no)],
 [case "${enableval}" in
@@ -163,6 +226,26 @@ AC_ARG_WITH(tty,
   AC_SUBST(TTYS)
 )
 
+AC_ARG_WITH(sysroot,
+  AC_HELP_STRING([--with-sysroot], [system root directory for cross 
compiling]),
+  with_top_level=${withval};
+  cross_compiling=yes)
+
+with_top_level=""
+if test x"${cross_compiling}" = xyes; then
+  dnl Check if /usr isn't part of the specified path
+  if test -d ${with_top_level}/usr; then
+    with_top_level=${withval}/usr
+  else 
+    dnl Check if the specified path supplies /usr
+    if test -d ${with_top_level}/include; then
+      with_top_level=${withval}
+    else
+      AC_MSG_ERROR([Specified sysroot \"${with_top_level}/include\" doesn't 
exist!])
+    fi
+  fi
+fi
+
 dnl link to the images so we can browse the HTML output before
 dnl installing it.
 AC_LINK_FILES(doc/C/images,doc/C/images)

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=9c8e9a454cf5d93964cf06535ffec2613a0fc031


commit 9c8e9a454cf5d93964cf06535ffec2613a0fc031
Author: Rob Savoye <address@hidden>
Date:   Mon Nov 12 17:43:51 2018 -0700

    Update copyright

diff --git a/lib/snmp.h b/lib/snmp.h
index b6e01cc..ebcd8e2 100644
--- a/lib/snmp.h
+++ b/lib/snmp.h
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify

http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=c1ebcf262351aace966d48e6d53d75aa73874760


commit c1ebcf262351aace966d48e6d53d75aa73874760
Author: Rob Savoye <address@hidden>
Date:   Mon Nov 12 15:53:24 2018 -0700

    Update copyright

diff --git a/client/cmd.cc b/client/cmd.cc
index c5ab7f9..ca7768a 100644
--- a/client/cmd.cc
+++ b/client/cmd.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/console.cc b/lib/console.cc
index c69ca26..de2557c 100644
--- a/lib/console.cc
+++ b/lib/console.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/err.cc b/lib/err.cc
index f6c4fb9..1558271 100644
--- a/lib/err.cc
+++ b/lib/err.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/log.cc b/lib/log.cc
index d6f4b95..bc0dafa 100644
--- a/lib/log.cc
+++ b/lib/log.cc
@@ -1,34 +1,3 @@
-// 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
-//      Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// This is generated by running configure
-#include "config.h"
-
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#endif
-
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-
-// Standard I/O headers
-#include <iostream>
 #include <iomanip>
 #include <fstream>
 #include <string>
@@ -299,7 +268,7 @@ LogFile::operator << (const xmlChar *c) {
     logentry = timestamp();
     logentry += ": ";
 
-    if (c == -0) {
+    if (c == NULL) {
         return *this;
     }
     
diff --git a/lib/menuitem.cc b/lib/menuitem.cc
index 0269706..20899f4 100644
--- a/lib/menuitem.cc
+++ b/lib/menuitem.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/msgs.cc b/lib/msgs.cc
index 034c763..26c0de7 100644
--- a/lib/msgs.cc
+++ b/lib/msgs.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/mysql.cc b/lib/mysql.cc
index cd9cf32..7311123 100644
--- a/lib/mysql.cc
+++ b/lib/mysql.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/outbackpower.cc b/lib/outbackpower.cc
index 4d13b9a..b61f2a9 100644
--- a/lib/outbackpower.cc
+++ b/lib/outbackpower.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
@@ -172,7 +172,7 @@ outback::main(Console &con, Database &db)
                   con.Puts("\t? - help\r\n");
                   con.Puts("\tq - Quit\r\n");
                   con.Puts("\tQ - Quit\r\n");
-                  sleep(2);
+                  // sleep(2); FIXME
               default:
                   break;
             };
diff --git a/lib/proc.cc b/lib/proc.cc
index 28dafc1..2976186 100644
--- a/lib/proc.cc
+++ b/lib/proc.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/rc.cc b/lib/rc.cc
index c83962e..1533bdd 100644
--- a/lib/rc.cc
+++ b/lib/rc.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/sem.cc b/lib/sem.cc
index 9721c76..c26d3f9 100644
--- a/lib/sem.cc
+++ b/lib/sem.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/serial.cc b/lib/serial.cc
index 9d0c6e2..40a759d 100644
--- a/lib/serial.cc
+++ b/lib/serial.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/sharedlib.cc b/lib/sharedlib.cc
index 5d4a985..45e198c 100644
--- a/lib/sharedlib.cc
+++ b/lib/sharedlib.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/snmp.cc b/lib/snmp.cc
index 89dba47..c8334b4 100644
--- a/lib/snmp.cc
+++ b/lib/snmp.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/tcpip.cc b/lib/tcpip.cc
index 0cdd9e8..4caeac8 100644
--- a/lib/tcpip.cc
+++ b/lib/tcpip.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/tcputil.cc b/lib/tcputil.cc
index 5139629..2daf4d7 100644
--- a/lib/tcputil.cc
+++ b/lib/tcputil.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/thread.cc b/lib/thread.cc
index b28ff35..45108d4 100644
--- a/lib/thread.cc
+++ b/lib/thread.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/xantrex-trace.cc b/lib/xantrex-trace.cc
index 80ebb0f..bb746a8 100644
--- a/lib/xantrex-trace.cc
+++ b/lib/xantrex-trace.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/lib/xml.cc b/lib/xml.cc
index 88d486d..4eb6abe 100644
--- a/lib/xml.cc
+++ b/lib/xml.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/sim/fakeuart.cc b/sim/fakeuart.cc
index ad9ab75..be4a505 100644
--- a/sim/fakeuart.cc
+++ b/sim/fakeuart.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //       Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
diff --git a/sim/osim.cc b/sim/osim.cc
index 11d52ec..ba8cbcd 100644
--- a/sim/osim.cc
+++ b/sim/osim.cc
@@ -1,5 +1,5 @@
 // 
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Copyright (C) 2005, 2006 - 2018
 //      Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify

-----------------------------------------------------------------------

Summary of changes:
 Makefile.am                       |  23 +++-
 client/Makefile.am                |  16 ++-
 client/cmd.cc                     |  14 +-
 configure.ac                      | 267 ++++++++++++++++++++++++++++----------
 daemon/Makefile.am                |  34 ++---
 daemon/main.cc                    |  27 ++--
 {lib => devices}/Makefile.am      |  45 ++-----
 {lib => devices}/outbackpower.cc  |  10 +-
 {lib => devices}/outbackpower.h   |   2 +-
 {lib => devices}/xanbus.cc        |   2 +-
 {lib => devices}/xanbus.h         |   2 +-
 {lib => devices}/xantrex-trace.cc |   4 +-
 {lib => devices}/xantrex-trace.h  |   2 +-
 lib/Makefile.am                   |  49 ++++---
 lib/console.cc                    |   4 +-
 lib/console.h                     |   2 +-
 lib/database.h                    |  11 +-
 lib/err.cc                        |   4 +-
 lib/err.h                         |   2 +-
 lib/gdb.h                         |   2 +-
 lib/log.cc                        |  49 +------
 lib/log.h                         |  24 +++-
 lib/{mysql.cc => mariadb.cc}      |  15 ++-
 lib/menuitem.cc                   |   4 +-
 lib/menuitem.h                    |   2 +-
 lib/msgs.cc                       | 250 ++++++++++++++++++-----------------
 lib/msgs.h                        |  28 ++--
 lib/{mysql.cc => postgresql.cc}   | 123 ++----------------
 lib/proc.cc                       |   4 +-
 lib/proc.h                        |   2 +-
 lib/rc.cc                         |   4 +-
 lib/rc.h                          |   2 +-
 lib/sem.cc                        |   4 +-
 lib/sem.h                         |   2 +-
 lib/serial.cc                     |   4 +-
 lib/serial.h                      |   2 +-
 lib/sharedlib.cc                  |   4 +-
 lib/sharedlib.h                   |   2 +-
 lib/snmp.cc                       |  19 +--
 lib/snmp.h                        |  19 ++-
 lib/tcpip.cc                      |  33 ++---
 lib/tcpip.h                       |  15 ++-
 lib/tcputil.cc                    |   2 +-
 lib/tcputil.h                     |   2 +-
 lib/thread.cc                     |   2 +-
 lib/xml.cc                        |  25 ++--
 lib/xml.h                         |  15 ++-
 macros/incllist                   |   1 +
 macros/libslist                   |   1 +
 sim/Makefile.am                   |   4 +-
 sim/fakeuart.cc                   |   6 +-
 sim/fakeuart.h                    |   2 +-
 sim/osim.cc                       |   6 +-
 snmp/Makefile.am                  |   4 +-
 testsuite/libtests/Makefile.am    |   2 +-
 55 files changed, 605 insertions(+), 600 deletions(-)
 copy {lib => devices}/Makefile.am (62%)
 rename {lib => devices}/outbackpower.cc (99%)
 rename {lib => devices}/outbackpower.h (99%)
 rename {lib => devices}/xanbus.cc (99%)
 rename {lib => devices}/xanbus.h (99%)
 rename {lib => devices}/xantrex-trace.cc (99%)
 rename {lib => devices}/xantrex-trace.h (99%)
 copy lib/{mysql.cc => mariadb.cc} (98%)
 rename lib/{mysql.cc => postgresql.cc} (66%)
 create mode 100644 macros/incllist
 create mode 100644 macros/libslist


hooks/post-receive
-- 
powerguru



reply via email to

[Prev in Thread] Current Thread [Next in Thread]