00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00042
00043
00044
00045
00046
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
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
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
00134 return true;
00135 }
00136
00137
00138 void DeviceManager::dataReceived()
00139 {
00140 char ibuf[32];
00141 char errmsg[ERRMSG_SIZE];
00142 int i, nr;
00143
00144
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
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
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
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
00224
00225
00226
00227
00228 int DeviceManager::delPropertyCmd (XMLEle *root, char errmsg[])
00229 {
00230
00231 XMLAtt *ap;
00232 INDI_D *dp;
00233 INDI_P *pp;
00234
00235
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
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
00255 else
00256 return removeDevice(dp->name, errmsg);
00257
00258 }
00259
00260 int DeviceManager::removeDevice(QString devName, char errmsg[])
00261 {
00262
00263
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
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
00300
00301
00302 INDI_D * DeviceManager::addDevice (XMLEle *dep, char errmsg[])
00303 {
00304 INDI_D *dp;
00305 XMLAtt *ap;
00306
00307
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
00322 parent->currentLabel = "";
00323
00324
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
00334 ap = findAtt (root, "device", errmsg);
00335 if (!ap)
00336 return (NULL);
00337 dn = valuXMLAtt(ap);
00338
00339
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
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
00356
00357
00358 int DeviceManager::messageCmd (XMLEle *root, char errmsg[])
00359 {
00360 checkMsg (root, findDev (root, 0, errmsg));
00361 return (0);
00362 }
00363
00364
00365
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
00377
00378
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
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
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"