• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

devicemanager.cpp

Go to the documentation of this file.
00001 /*  Device Manager
00002     Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
00003 
00004     This application is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008     
00009     JM Changelog
00010     2004-16-1:  Start
00011    
00012  */
00013  
00014 #include "Options.h"
00015 #include "devicemanager.h"
00016 #include "indimenu.h"
00017 #include "indiproperty.h"
00018 #include "indigroup.h"
00019 #include "indidevice.h"
00020 #include "indi/indicom.h"
00021 #include "kstars.h"
00022 #include "kstarsdatetime.h"
00023 
00024 #include <qsocketnotifier.h>
00025 #include <qtextedit.h>
00026 
00027 #include <klocale.h>
00028 #include <kdebug.h>
00029 #include <kmessagebox.h>
00030 #include <kstatusbar.h>
00031  
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035 #include <netdb.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <termios.h>
00039  
00040  /*******************************************************************
00041 ** The device manager contain devices running from one indiserver
00042 ** This allow KStars to control multiple devices distributed acorss
00043 ** multiple servers seemingly in a way that is completely transparent
00044 ** to devices and drivers alike.
00045 ** The device Manager can be thought of as the 'networking' parent
00046 ** of devices, while indimenu is 'GUI' parent of devices
00047 *******************************************************************/
00048 
00049 DeviceManager::DeviceManager(INDIMenu *INDIparent, int inID) 
00050 {
00051 
00052  parent = INDIparent;
00053  mgrID  = inID;
00054 
00055  indi_dev.setAutoDelete(true);
00056  
00057  serverFD  = -1;
00058  serverFP  = NULL;
00059  XMLParser = NULL;
00060  sNotifier = NULL;
00061 
00062 }
00063 
00064 DeviceManager::~DeviceManager()
00065 {
00066   
00067    if (serverFP)
00068         fclose(serverFP);
00069     
00070   if (serverFD >= 0)
00071     close(serverFD);
00072   
00073   if (XMLParser)
00074   {
00075    delLilXML(XMLParser);
00076    XMLParser = NULL;
00077   }
00078   
00079   indi_dev.clear();
00080 
00081 }
00082 
00083 bool DeviceManager::indiConnect(QString inHost, QString inPort)
00084 {
00085         host = inHost;
00086     port = inPort;
00087     QString errMsg;
00088     struct sockaddr_in pin;
00089     struct hostent *serverHostName = gethostbyname(host.ascii());
00090     errMsg = QString("Connection to INDI host at %1 on port %2 failed.").arg(host).arg(port);
00091 
00092     memset(&pin, 0, sizeof(pin));
00093     pin.sin_family      = AF_INET;
00094     pin.sin_addr.s_addr     = ((struct in_addr *) (serverHostName->h_addr))->s_addr;
00095     pin.sin_port        = htons(port.toInt());
00096 
00097     if ( (serverFD = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00098     {
00099      KMessageBox::error(0, i18n("Cannot create socket"));
00100      return false;
00101     }
00102 
00103     if ( ::connect(serverFD, (struct sockaddr*) &pin, sizeof(pin)) == -1)
00104     {
00105       KMessageBox::error(0, errMsg);
00106       serverFD = -1;
00107       return false;
00108     }
00109 
00110     // callback notified
00111     sNotifier = new QSocketNotifier( serverFD, QSocketNotifier::Read, this);
00112         QObject::connect( sNotifier, SIGNAL(activated(int)), this, SLOT(dataReceived()));
00113 
00114     if (XMLParser)
00115        delLilXML(XMLParser);
00116     XMLParser = newLilXML();
00117 
00118     // ready for fprintf
00119     serverFP = fdopen(serverFD, "w");
00120 
00121     if (serverFP == NULL)
00122     {
00123      KMessageBox::error(0, i18n("Cannot read server file descriptor"));
00124      serverFD = -1;
00125      return false;
00126     }
00127 
00128     setbuf (serverFP, NULL);
00129 
00130     fprintf(serverFP, "<enableBLOB>Also</enableBLOB>\n");
00131     fprintf(serverFP, "<getProperties version='%g'/>\n", INDIVERSION);
00132 
00133     // We made it!
00134     return true;
00135 }
00136 
00137 
00138 void DeviceManager::dataReceived()
00139 {
00140     char ibuf[32];  /* not so much user input lags */
00141     char errmsg[ERRMSG_SIZE];
00142     int i, nr;
00143 
00144     /* read INDI command */
00145     nr = read (serverFD, ibuf, sizeof(ibuf)-1);
00146     if (nr <= 0)
00147     {
00148         if (nr < 0)
00149         strcpy (errmsg, "INDI: input error.");
00150         else
00151         strcpy (errmsg, "INDI: agent closed connection.");
00152 
00153 
00154             tcflush(serverFD, TCIFLUSH);
00155         sNotifier->disconnect();
00156         close(serverFD);
00157         parent->removeDeviceMgr(mgrID);
00158         KMessageBox::error(0, QString::fromLatin1(errmsg));
00159 
00160             return;
00161     }
00162 
00163         ibuf[ sizeof( ibuf )-1 ] = '\0';
00164 
00165     /* process each char */
00166     for (i = 0; i < nr; i++)
00167     {
00168       if (!XMLParser)
00169             return;
00170 
00171         XMLEle *root = readXMLEle (XMLParser, (int)ibuf[i], errmsg);
00172         if (root)
00173         {
00174                 //prXMLEle (stdout, root, 0);
00175         if (dispatchCommand(root, errmsg) < 0)
00176         {
00177             fprintf(stderr, "%s", errmsg);
00178             prXMLEle (stdout, root, 0);
00179         }
00180 
00181         delXMLEle (root);
00182         }
00183         else if (*errmsg)
00184         {
00185         kdDebug() << errmsg << endl;
00186         }
00187     }
00188 }
00189 
00190 int DeviceManager::dispatchCommand(XMLEle *root, char errmsg[])
00191 {
00192 
00193   if  (!strcmp (tagXMLEle(root), "message"))
00194          return messageCmd(root, errmsg);
00195   else if  (!strcmp (tagXMLEle(root), "delProperty"))
00196         return delPropertyCmd(root, errmsg);
00197 
00198   /* Get the device, if not available, create it */
00199   INDI_D *dp = findDev (root, 1, errmsg);
00200       if (dp == NULL)
00201         return -1;
00202 
00203    if (!strcmp (tagXMLEle(root), "defTextVector"))
00204       return dp->buildTextGUI(root, errmsg);
00205    else if (!strcmp (tagXMLEle(root), "defNumberVector"))
00206       return dp->buildNumberGUI(root, errmsg);
00207    else if (!strcmp (tagXMLEle(root), "defSwitchVector"))
00208        return dp->buildSwitchesGUI(root, errmsg);
00209    else if (!strcmp (tagXMLEle(root), "defLightVector"))
00210         return dp->buildLightsGUI(root, errmsg);
00211    else if (!strcmp (tagXMLEle(root), "defBLOBVector"))
00212      return dp->buildBLOBGUI(root, errmsg);
00213    else if (!strcmp (tagXMLEle(root), "setTextVector") ||
00214         !strcmp (tagXMLEle(root), "setNumberVector") ||
00215         !strcmp (tagXMLEle(root), "setSwitchVector") ||
00216         !strcmp (tagXMLEle(root), "setLightVector") ||
00217         !strcmp (tagXMLEle(root), "setBLOBVector")) 
00218     return dp->setAnyCmd(root, errmsg);
00219 
00220    return (-1);
00221 }
00222 
00223 /* delete the property in the given device, including widgets and data structs.
00224  * when last property is deleted, delete the device too.
00225  * if no property name attribute at all, delete the whole device regardless.
00226  * return 0 if ok, else -1 with reason in errmsg[].
00227  */
00228 int DeviceManager::delPropertyCmd (XMLEle *root, char errmsg[])
00229 {
00230 
00231     XMLAtt *ap;
00232     INDI_D *dp;
00233     INDI_P *pp;
00234 
00235     /* dig out device and optional property name */
00236     dp = findDev (root, 0, errmsg);
00237     if (!dp)
00238         return (-1);
00239         
00240     checkMsg(root, dp);
00241     
00242     ap = findXMLAtt (root, "name");
00243 
00244     /* Delete property if it exists, otherwise, delete the whole device */
00245     if (ap)
00246     {
00247       pp = dp->findProp(QString(valuXMLAtt(ap)));
00248 
00249      if(pp)
00250      return dp->removeProperty(pp);
00251         else
00252           return (-1);
00253     }
00254     // delete the whole device
00255     else
00256             return removeDevice(dp->name, errmsg);
00257 
00258 }
00259 
00260 int DeviceManager::removeDevice(QString devName, char errmsg[])
00261 {
00262 
00263     // remove all devices if devName == NULL
00264     if (devName == NULL)
00265     {
00266         indi_dev.clear();
00267     return (0);
00268     }
00269 
00270     for (unsigned int i=0; i < indi_dev.count(); i++)
00271     {
00272          if (indi_dev.at(i)->name ==  devName)
00273      {
00274         kdDebug() << "Device Manager: Device found, deleting " << devName << endl;
00275         indi_dev.remove(i);
00276             return (0);
00277      }
00278     }
00279 
00280    snprintf(errmsg, ERRMSG_SIZE, "Device %.32s not found" , devName.ascii());
00281    return -1;
00282 }
00283 
00284 INDI_D * DeviceManager::findDev (QString devName, char errmsg[])
00285 {
00286     /* search for existing */
00287     for (unsigned int i = 0; i < indi_dev.count(); i++)
00288     {
00289         if (indi_dev.at(i)->name == devName)
00290         return (indi_dev.at(i));
00291     }
00292 
00293     snprintf (errmsg, ERRMSG_SIZE, "INDI: no such device %.32s", devName.ascii());
00294     kdDebug() << errmsg;
00295 
00296     return NULL;
00297 }
00298 
00299 /* add new device to mainrc_w using info in dep.
00300 - * if trouble return NULL with reason in errmsg[]
00301 - */
00302 INDI_D * DeviceManager::addDevice (XMLEle *dep, char errmsg[])
00303 {
00304     INDI_D *dp;
00305     XMLAtt *ap;
00306 
00307     /* allocate new INDI_D on indi_dev */
00308     ap = findAtt (dep, "device", errmsg);
00309     if (!ap)
00310         return NULL;
00311 
00312     if (parent->currentLabel.isEmpty())
00313      parent->setCustomLabel(valuXMLAtt(ap));
00314 
00315     dp = new INDI_D(parent, this, QString(valuXMLAtt(ap)), parent->currentLabel);
00316 
00317     indi_dev.append(dp);
00318     
00319     emit newDevice();
00320     
00321     // Reset label
00322     parent->currentLabel = "";
00323     
00324        /* ok */
00325     return dp;
00326 }
00327 
00328 INDI_D * DeviceManager::findDev (XMLEle *root, int create, char errmsg[])
00329 {
00330     XMLAtt *ap;
00331     char *dn;
00332 
00333     /* get device name */
00334     ap = findAtt (root, "device", errmsg);
00335     if (!ap)
00336         return (NULL);
00337     dn = valuXMLAtt(ap);
00338 
00339     /* search for existing */
00340     for (uint i = 0; i < indi_dev.count(); i++)
00341     {
00342         if (indi_dev.at(i)->name == QString(dn))
00343         return (indi_dev.at(i));
00344     }
00345 
00346     /* not found, create if ok */
00347     if (create)
00348         return (addDevice (root, errmsg));
00349 
00350 
00351     snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.32s> no such device %.32s", tagXMLEle(root), dn);
00352     return NULL;
00353 }
00354 
00355 /* a general message command received from the device.
00356  * return 0 if ok, else -1 with reason in errmsg[].
00357  */
00358 int DeviceManager::messageCmd (XMLEle *root, char errmsg[])
00359 {
00360     checkMsg (root, findDev (root, 0, errmsg));
00361     return (0);
00362 }
00363 
00364 /* display message attribute.
00365  * N.B. don't put carriage control in msg, we take care of that.
00366  */
00367 void DeviceManager::checkMsg (XMLEle *root, INDI_D *dp)
00368 {
00369     XMLAtt *ap;
00370     ap = findXMLAtt(root, "message");
00371       
00372     if (ap)
00373       doMsg(root, dp);
00374 }
00375 
00376 /* display valu of message and timestamp in dp's scrolled area, if any, else general.
00377  * prefix our time stamp if not included.
00378  * N.B. don't put carriage control in msg, we take care of that.
00379  */
00380 void DeviceManager::doMsg (XMLEle *msg, INDI_D *dp)
00381 {
00382     QTextEdit *txt_w;
00383     XMLAtt *message;
00384     XMLAtt *timestamp;
00385 
00386         if (dp == NULL)
00387     {
00388       kdDebug() << "Warning: dp is null." << endl;
00389       return;
00390     }
00391     
00392     txt_w = dp->msgST_w;
00393 
00394     /* prefix our timestamp if not with msg */
00395     timestamp = findXMLAtt (msg, "timestamp");
00396     
00397     if (timestamp)
00398        txt_w->insert(QString(valuXMLAtt(timestamp)) + QString(" "));
00399     else
00400        txt_w->insert( KStarsDateTime::currentDateTime().toString("yyyy/mm/dd - h:m:s ap "));
00401     
00402     /* finally! the msg */
00403         message = findXMLAtt(msg, "message");
00404     
00405        txt_w->insert( QString(valuXMLAtt(message)) + QString("\n"));
00406        
00407        if ( Options::indiMessages() )
00408             parent->ksw->statusBar()->changeItem( QString(valuXMLAtt(message)), 0);
00409 
00410 }
00411 
00412 void DeviceManager::sendNewText (INDI_P *pp)
00413 {
00414         INDI_E *lp;
00415     
00416     fprintf(serverFP, "<newTextVector\n");
00417     fprintf(serverFP, "  device='%s'\n", pp->pg->dp->name.ascii());
00418     fprintf(serverFP, "  name='%s'\n>", pp->name.ascii());
00419     
00420     for (lp = pp->el.first(); lp != NULL; lp = pp->el.next())
00421     {
00422         fprintf(serverFP, "  <oneText\n");
00423         fprintf(serverFP, "    name='%s'>\n", lp->name.ascii());
00424         fprintf(serverFP, "      %s\n", lp->text.ascii());
00425         fprintf(serverFP, "  </oneText>\n");
00426     }
00427     fprintf(serverFP, "</newTextVector>\n");
00428 }
00429 
00430 void DeviceManager::sendNewNumber (INDI_P *pp)
00431 {
00432         INDI_E *lp;
00433     
00434         fprintf(serverFP, "<newNumberVector\n");
00435     fprintf(serverFP, "  device='%s'\n", pp->pg->dp->name.ascii());
00436     fprintf(serverFP, "  name='%s'\n>", pp->name.ascii());
00437     
00438     for (lp = pp->el.first(); lp != NULL; lp = pp->el.next())
00439     {
00440         fprintf(serverFP, "  <oneNumber\n");
00441         fprintf(serverFP, "    name='%s'>\n", lp->name.ascii());
00442         fprintf(serverFP, "      %g\n", lp->targetValue);
00443         fprintf(serverFP, "  </oneNumber>\n");
00444     }
00445     fprintf(serverFP, "</newNumberVector>\n");
00446 
00447 }
00448 
00449 void DeviceManager::sendNewSwitch (INDI_P *pp, int index)
00450 {  
00451         INDI_E *lp;
00452     int i=0;
00453 
00454     fprintf (serverFP,"<newSwitchVector\n");
00455     fprintf (serverFP,"  device='%s'\n", pp->pg->dp->name.ascii());
00456     fprintf (serverFP,"  name='%s'>\n", pp->name.ascii());
00457     
00458     for (lp = pp->el.first(); lp != NULL; lp = pp->el.next(), i++)
00459       if (i == index)
00460           {
00461         fprintf (serverFP,"  <oneSwitch\n");
00462         fprintf (serverFP,"    name='%s'>\n", lp->name.ascii());
00463         fprintf (serverFP,"      %s\n", lp->state == PS_ON ? "On" : "Off");
00464         fprintf (serverFP,"  </oneSwitch>\n");
00465         break;
00466       }
00467     fprintf (serverFP, "</newSwitchVector>\n");
00468     
00469 }
00470 
00471 void DeviceManager::startBlob (QString devName, QString propName, QString timestamp)
00472 {
00473 
00474    fprintf (serverFP, "<newBLOBVector\n");
00475    fprintf (serverFP, "  device='%s'\n", devName.ascii());
00476    fprintf (serverFP, "  name='%s'\n", propName.ascii());
00477    fprintf (serverFP, "  timestamp='%s'>\n", timestamp.ascii());
00478 
00479 }
00480 
00481 void DeviceManager::sendOneBlob(QString blobName, unsigned int blobSize, QString blobFormat, unsigned char * blobBuffer)
00482 {
00483 
00484  fprintf (serverFP, "  <oneBLOB\n");
00485  fprintf (serverFP, "    name='%s'\n", blobName.ascii());
00486  fprintf (serverFP, "    size='%d'\n", blobSize);
00487  fprintf (serverFP, "    format='%s'>\n", blobFormat.ascii());
00488 
00489   for (unsigned i = 0; i < blobSize; i += 72)
00490     fprintf (serverFP, "    %.72s\n", blobBuffer+i);
00491 
00492   fprintf (serverFP, "  </oneBLOB>\n");
00493 
00494 }
00495 
00496 void DeviceManager::finishBlob()
00497 {
00498        fprintf (serverFP, "</newBLOBVector>\n");
00499 }
00500 
00501 
00502 #include "devicemanager.moc"

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal