diff --git a/README.md b/README.md index a6862d8..46a232b 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,63 @@ # FBSmartHome -**fbsh-cli** - FritzBox SmartHome Console Client +A small collection of usefull FritzBox SmartHome tools and scripts. Still in development and highly experimental. + +## fb-login-test.sh + +A simple script to test the user name and passwort set in file `~/.fbsh.config`. If the login was successfull an XML file with connected SmartHome devices will be printed out. + +The config file for both script and client use the same syntax. + + # + # PARAMETERNAME=VALUE no space allowed except for the value. + # but not between parametername, = and value. + # + # + FBSH_USER=testuser + FBSH_PASS=anypassword + FBSH_SIDFILE=/home/username/.fbsh.sid + FBSH_HOSTNAME=http://192.168.0.1 + + +## fbsh-cli FritzBox SmartHome Console Client + +### Compilation + +On debian you need the libxml2 and openssl devel pakages for compilation. If you have a debian based distribution you can install them with: + + apt install libxml2-dev libssl-dev + +Compile the source with make and run the binary. If needed manually copy the binary to a place of your choise. The Makefile does not support installation. + + make + ./fbsh-cli + + +### Configuration File -## Configuration File To set some default settings and create the configuration file, just run the command. `./fbsh-cli -host http://192.168.0.1 -user SOMEUSER -pass SOMEPASSWORD saveconfig` The default configuration will be saved under `$HOME/.fbsh.config`. In addition the client will save a SID file `.fbsh.sid` which contains the last known SID (session ID). This file will also be located inside the home directory. -## Check the Login +Both script and the client will use the same config file. + +### Test the Login Test the connection with `./fbsh-cli connect`. The successfull conntion will look like: user@desktop ~/FBSmartHome $ ./fbsh-cli connect SID:989346018a2dca53 user@desktop ~/FBSmartHome $ -## Supported Commands +### Supported Commands + saveconfig + connect + list + help -## Currently Not Working +### Currently Not Working + HTTPS is yet not supported ++ sending commands to switches and lights ++ readin additional data from devices diff --git a/fbsh-cli.cc b/fbsh-cli.cc index 4f262d1..cbe8ab5 100644 --- a/fbsh-cli.cc +++ b/fbsh-cli.cc @@ -61,8 +61,7 @@ void getlist(int argpos, int argc, char **argv) { } for (iter = devlist->begin(); iter != devlist->end(); iter++) { - printf ("%s,%s,%s,%s,%d,%s\n", iter->id.c_str(), iter->name.c_str(), iter->product.c_str(), - iter->vendor.c_str(), iter->present, iter->attributes.c_str()); + printf ("%s\t%s\t%s\t%s\n", iter->id.c_str(), iter->type.c_str(), iter->name.c_str(), iter->others.c_str()); } delete devlist; } diff --git a/fbsh.cc b/fbsh.cc index 04dda13..085817e 100644 --- a/fbsh.cc +++ b/fbsh.cc @@ -264,6 +264,116 @@ int FBSmartHome::CloseSIDFile() { } +int FBSmartHome::XMLReadAttr(FBSmartHomeDevice *dev, std::string objPrefix, xmlDocPtr xmldoc, xmlAttrPtr xmlattr) { + char *txt = NULL; + + while (xmlattr) { + if (dev->others.length() > 0) dev->others += "\t"; + txt = (char*) xmlNodeListGetString(xmldoc, xmlattr->children, 1); + if (txt != NULL) + dev->others += objPrefix + "." + (std::string)(char*) xmlattr->name + "=" + txt; + else + dev->others += (std::string)(char*) xmlattr->name + "="; + + xmlattr = xmlattr->next; + } + + return 0; +} + + +int FBSmartHome::XMLReadOBJ(FBSmartHomeDevice *dev, std::string objPrefix, xmlDocPtr xmldoc, xmlNodePtr xmlobj) { + std::string tmp = ""; + char *txt = NULL; + + while (xmlobj) { + if (dev->others.length() > 0) dev->others += "\t"; + txt = (char*) xmlNodeListGetString(xmldoc, xmlobj->children, 1); + if (txt != NULL) + dev->others += objPrefix + "." + (std::string)(char*) xmlobj->name + "=" + txt; + else if (xmlobj->children) { + XMLReadAttr(dev, objPrefix+"."+(std::string)(char*)xmlobj->name, xmldoc, xmlobj->properties); + XMLReadOBJ(dev, objPrefix+"."+(std::string)(char*)xmlobj->name, xmldoc, xmlobj->children); + } + else + dev->others += (std::string)(char*) xmlobj->name + "="; + + xmlobj = xmlobj->next; + } + + return 0; +} + + +int FBSmartHome::XMLReadAndAddDevice(std::list *devlist, std::string defType, + xmlDocPtr xmldoc, xmlNodePtr xmlnode) { + xmlAttrPtr xmlattr; + xmlNodePtr child; + std::string tmp = ""; + char *txt = NULL; + FBSmartHomeDevice fbdev; + + // + // reset all fields + fbdev.others = ""; + fbdev.id = ""; + fbdev.name = ""; + fbdev.type = defType; + + // + // read attributes + xmlattr = xmlnode->properties; + while (xmlattr) { + if (!xmlStrcmp(xmlattr->name, (const xmlChar *)"identifier")) + fbdev.id = (char *) xmlNodeListGetString(xmldoc, xmlattr->children, 1); + else { + txt = (char*) xmlNodeListGetString(xmldoc, xmlattr->children, 1); + + if (txt != NULL) fbdev.others += (std::string)(char*) xmlattr->name + "=" + txt + "\t"; + else fbdev.others += (std::string)(char*) xmlattr->name + "=\t"; + } + xmlattr = xmlattr->next; + } + + // + // read subelements + child = xmlnode->children; + while (child) { + if (!xmlStrcmp(child->name, (const xmlChar *)"name")) + fbdev.name = (char *) xmlNodeListGetString(xmldoc, child->children, 1); + + else if (!xmlStrcmp(child->name, (const xmlChar *)"button")) { + fbdev.type = "button"; + XMLReadAndAddDevice(devlist, "button", xmldoc, child); + } + + else if (!xmlStrcmp(child->name, (const xmlChar *)"hkr")) { + fbdev.type = (char*)child->name; + XMLReadOBJ(&fbdev, "hkr" , xmldoc, child->children); + } + + else { + txt = (char*) xmlNodeListGetString(xmldoc, child->children, 1); + if (txt != NULL) { + fbdev.others += (std::string)(char*) child->name + "=" + txt + "\t"; + } else { + if (child->children) { + XMLReadAttr(&fbdev, (std::string)(char*)child->name, xmldoc, child->properties); + XMLReadOBJ(&fbdev, (std::string)(char*)child->name, xmldoc, child->children); + } + else { + fbdev.others += (std::string)(char*) child->name + "=\t"; + } + } + } + + child = child->next; + } + devlist->push_back(fbdev); + + return 0; +} + /* * retrieve the device list from the fritzbox @@ -273,9 +383,9 @@ std::list *FBSmartHome::GetDevices() { FBSmartHomeDevice smd; xmlDocPtr xmldoc; xmlNodePtr xmlnode; - xmlAttr *xmlattr; int len; + devlist = new std::list; // retrieve data len = tcp.WebGetFile(hostname+"/webservices/homeautoswitch.lua?sid="+SID+"&switchcmd=getdevicelistinfos", inbuffer, FB_BUFFER, NULL); @@ -287,7 +397,6 @@ std::list *FBSmartHome::GetDevices() { } inbuffer[len] = '\0'; XMLPrepare(inbuffer, len, &xmldoc, &xmlnode); - printf ("*********************************************\n%s\n*********************************\n", inbuffer); // // parse for SID and Challange @@ -299,44 +408,8 @@ std::list *FBSmartHome::GetDevices() { // read each device details // while (xmlchild) { - printf ("Name:%s\n", xmlchild->name); - // - // read attributes - xmlattr = xmlchild->properties; - while (xmlattr) { - printf (" %s:%s ", xmlattr->name, xmlNodeListGetString(xmldoc, xmlattr->children, 1)); - xmlattr = xmlattr->next; - } - printf ("\n"); - - // go thought all the subchildreen - xmlNodePtr xmlsubchild = xmlchild->children; - while (xmlsubchild) { - printf (" %s,%s ", xmlsubchild->name, - (char *)xmlNodeListGetString(xmldoc, xmlsubchild->children, 1)); - xmlattr = xmlsubchild->properties; - while (xmlattr) { - printf (" %s:%s ", xmlattr->name, xmlNodeListGetString(xmldoc, xmlattr->children, 1)); - xmlattr = xmlattr->next; - } - printf ("\n"); - - xmlNodePtr xmlsubchild2 = xmlsubchild->children; - while (xmlsubchild2) { - printf (" %s,%s ", xmlsubchild2->name, - (char *)xmlNodeListGetString(xmldoc, xmlsubchild2->children, 1)); - xmlattr = xmlsubchild2->properties; - while (xmlattr) { - printf (" %s:%s ", xmlattr->name, xmlNodeListGetString(xmldoc, xmlattr->children, 1)); - xmlattr = xmlattr->next; - } - printf ("\n"); - xmlsubchild2 = xmlsubchild2->next; - } - - xmlsubchild = xmlsubchild->next; - } - printf ("\n"); + if (!xmlStrcmp(xmlchild->name, (const xmlChar *)"device")) + XMLReadAndAddDevice(devlist, "", xmldoc, xmlchild); xmlchild = xmlchild->next; } } diff --git a/fbsh.h b/fbsh.h index 602561c..e4c1006 100644 --- a/fbsh.h +++ b/fbsh.h @@ -19,10 +19,8 @@ std::string generateMD5 (char* input, int size); struct { std::string id; std::string name; - std::string product; - std::string vendor; - int present; - std::string attributes; + std::string others; + std::string type; } typedef FBSmartHomeDevice; @@ -37,6 +35,11 @@ private: TCP tcp; int XMLPrepare(char *buffer, int len, xmlDocPtr *xmldoc, xmlNodePtr *xmlnode); + + int XMLReadAttr(FBSmartHomeDevice *dev, std::string objPrefix, xmlDocPtr xmldoc, xmlAttrPtr xmlattr); + int XMLReadOBJ(FBSmartHomeDevice *dev, std::string objPrefix, xmlDocPtr xmldoc, xmlNodePtr xmlobj); + int XMLReadAndAddDevice(std::list *devlist, std::string defType, xmlDocPtr xmldoc, + xmlNodePtr xmlnode); public: FBSmartHome (); ~FBSmartHome ();