| 1 | #include <stdlib.h>
 | 
|---|
| 2 | #include <string.h>
 | 
|---|
| 3 | 
 | 
|---|
| 4 | #include <unistd.h>
 | 
|---|
| 5 | #include <sys/types.h>
 | 
|---|
| 6 | #include <sys/socket.h>
 | 
|---|
| 7 | #include <netinet/in.h>
 | 
|---|
| 8 | #include <netdb.h>
 | 
|---|
| 9 | 
 | 
|---|
| 10 | #include "baseclient.h"
 | 
|---|
| 11 | #include "basedriver.h"
 | 
|---|
| 12 | #include "indicom.h"
 | 
|---|
| 13 | 
 | 
|---|
| 14 | #include <errno.h>
 | 
|---|
| 15 | 
 | 
|---|
| 16 | #define MAXINDIBUF 64
 | 
|---|
| 17 | 
 | 
|---|
| 18 | INDI::BaseClient::BaseClient()
 | 
|---|
| 19 | {
 | 
|---|
| 20 |     cServer = "localhost";
 | 
|---|
| 21 |     cPort   = 7624;
 | 
|---|
| 22 | 
 | 
|---|
| 23 | }
 | 
|---|
| 24 | 
 | 
|---|
| 25 | 
 | 
|---|
| 26 | INDI::BaseClient::~BaseClient()
 | 
|---|
| 27 | {
 | 
|---|
| 28 | 
 | 
|---|
| 29 |     disconnect();
 | 
|---|
| 30 | 
 | 
|---|
| 31 | }
 | 
|---|
| 32 | 
 | 
|---|
| 33 | void INDI::BaseClient::setServer(const char * hostname, unsigned int port)
 | 
|---|
| 34 | {
 | 
|---|
| 35 |     cServer = hostname;
 | 
|---|
| 36 |     cPort   = port;
 | 
|---|
| 37 | 
 | 
|---|
| 38 | }
 | 
|---|
| 39 | 
 | 
|---|
| 40 | void INDI::BaseClient::watchDevice(const char * deviceName)
 | 
|---|
| 41 | {
 | 
|---|
| 42 |     cDeviceNames.push_back(deviceName);
 | 
|---|
| 43 | }
 | 
|---|
| 44 | 
 | 
|---|
| 45 | bool INDI::BaseClient::connect()
 | 
|---|
| 46 | {
 | 
|---|
| 47 |     struct sockaddr_in serv_addr;
 | 
|---|
| 48 |     struct hostent *hp;
 | 
|---|
| 49 | 
 | 
|---|
| 50 |     /* lookup host address */
 | 
|---|
| 51 |     hp = gethostbyname(cServer.c_str());
 | 
|---|
| 52 |     if (!hp)
 | 
|---|
| 53 |     {
 | 
|---|
| 54 |         herror ("gethostbyname");
 | 
|---|
| 55 |         return false;
 | 
|---|
| 56 |     }
 | 
|---|
| 57 | 
 | 
|---|
| 58 |     /* create a socket to the INDI server */
 | 
|---|
| 59 |     (void) memset ((char *)&serv_addr, 0, sizeof(serv_addr));
 | 
|---|
| 60 |     serv_addr.sin_family = AF_INET;
 | 
|---|
| 61 |     serv_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr_list[0]))->s_addr;
 | 
|---|
| 62 |     serv_addr.sin_port = htons(cPort);
 | 
|---|
| 63 |     if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
 | 
|---|
| 64 |     {
 | 
|---|
| 65 |         perror ("socket");
 | 
|---|
| 66 |         return false;
 | 
|---|
| 67 |     }
 | 
|---|
| 68 | 
 | 
|---|
| 69 |     /* connect */
 | 
|---|
| 70 |     if (::connect (sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
 | 
|---|
| 71 |     {
 | 
|---|
| 72 |         perror ("connect");
 | 
|---|
| 73 |         return false;
 | 
|---|
| 74 |     }
 | 
|---|
| 75 | 
 | 
|---|
| 76 |     /* prepare for line-oriented i/o with client */
 | 
|---|
| 77 |     svrwfp = fdopen (sockfd, "w");
 | 
|---|
| 78 |     svrrfp = fdopen (sockfd, "r");
 | 
|---|
| 79 | 
 | 
|---|
| 80 |     int result = pthread_create( &listen_thread, NULL, &INDI::BaseClient::listenHelper, this);
 | 
|---|
| 81 | 
 | 
|---|
| 82 |     if (result != 0)
 | 
|---|
| 83 |     {
 | 
|---|
| 84 |         perror("thread");
 | 
|---|
| 85 |         return false;
 | 
|---|
| 86 |     }
 | 
|---|
| 87 | 
 | 
|---|
| 88 |     return true;
 | 
|---|
| 89 | }
 | 
|---|
| 90 | 
 | 
|---|
| 91 | void INDI::BaseClient::disconnect()
 | 
|---|
| 92 | {
 | 
|---|
| 93 |     char errmsg[MAXRBUF];
 | 
|---|
| 94 |     removeDevice(NULL, errmsg);
 | 
|---|
| 95 |     if (lillp)
 | 
|---|
| 96 |         delLilXML(lillp);
 | 
|---|
| 97 |     lillp = NULL;
 | 
|---|
| 98 |     pthread_cancel(listen_thread);
 | 
|---|
| 99 |     close(sockfd);
 | 
|---|
| 100 |     if (svrwfp)
 | 
|---|
| 101 |         fclose(svrwfp);
 | 
|---|
| 102 |     svrwfp = NULL;
 | 
|---|
| 103 |     if (svrrfp)
 | 
|---|
| 104 |         fclose(svrrfp);
 | 
|---|
| 105 |     svrrfp = NULL;
 | 
|---|
| 106 | }
 | 
|---|
| 107 | 
 | 
|---|
| 108 | INDI::BaseDriver * INDI::BaseClient::getDevice(const char * deviceName)
 | 
|---|
| 109 | {
 | 
|---|
| 110 |     vector<INDI::BaseDriver *>::const_iterator devi;
 | 
|---|
| 111 |     for ( devi = cDevices.begin(); devi != cDevices.end(); devi++)
 | 
|---|
| 112 |         if (!strcmp(deviceName, (*devi)->deviceName()))
 | 
|---|
| 113 |             return (*devi);
 | 
|---|
| 114 | 
 | 
|---|
| 115 |     return NULL;
 | 
|---|
| 116 | }
 | 
|---|
| 117 | 
 | 
|---|
| 118 | void * INDI::BaseClient::listenHelper(void *context)
 | 
|---|
| 119 | {
 | 
|---|
| 120 |   (static_cast<INDI::BaseClient *> (context))->listenINDI();
 | 
|---|
| 121 | }
 | 
|---|
| 122 | 
 | 
|---|
| 123 | void INDI::BaseClient::listenINDI()
 | 
|---|
| 124 | {
 | 
|---|
| 125 |     char msg[MAXRBUF];
 | 
|---|
| 126 |     char buffer[MAXINDIBUF];
 | 
|---|
| 127 |     int n=0, err_code=0;
 | 
|---|
| 128 | 
 | 
|---|
| 129 |     if (cDeviceNames.empty())
 | 
|---|
| 130 |        fprintf(svrwfp, "<getProperties version='%g'/>\n", INDIV);
 | 
|---|
| 131 |     else
 | 
|---|
| 132 |     {
 | 
|---|
| 133 |         vector<string>::const_iterator stri;
 | 
|---|
| 134 |         for ( stri = cDeviceNames.begin(); stri != cDeviceNames.end(); stri++)
 | 
|---|
| 135 |             fprintf(svrwfp, "<getProperties version='%g' device='%s'/>\n", INDIV, (*stri).c_str());
 | 
|---|
| 136 |     }
 | 
|---|
| 137 | 
 | 
|---|
| 138 |     fflush (svrwfp);
 | 
|---|
| 139 | 
 | 
|---|
| 140 |     lillp = newLilXML();
 | 
|---|
| 141 | 
 | 
|---|
| 142 |     /* read from server, exit if find all requested properties */
 | 
|---|
| 143 |     while (1)
 | 
|---|
| 144 |     {
 | 
|---|
| 145 |         n = fread(buffer, 1, MAXINDIBUF, svrrfp);
 | 
|---|
| 146 | 
 | 
|---|
| 147 |         if (n ==0)
 | 
|---|
| 148 |         {
 | 
|---|
| 149 |             if (ferror(svrrfp))
 | 
|---|
| 150 |                 perror ("read");
 | 
|---|
| 151 |             else
 | 
|---|
| 152 |                 fprintf (stderr,"INDI server %s/%d disconnected\n", cServer.c_str(), cPort);
 | 
|---|
| 153 | 
 | 
|---|
| 154 |             serverDisconnected();
 | 
|---|
| 155 |             return;
 | 
|---|
| 156 |         }
 | 
|---|
| 157 | 
 | 
|---|
| 158 |         for (int i=0; i < n; i++)
 | 
|---|
| 159 |         {
 | 
|---|
| 160 |             XMLEle *root = readXMLEle (lillp, buffer[i], msg);
 | 
|---|
| 161 |             if (root)
 | 
|---|
| 162 |             {
 | 
|---|
| 163 |                 if ( (err_code = dispatchCommand(root, msg)) < 0)
 | 
|---|
| 164 |                 {
 | 
|---|
| 165 |                      // Silenty ignore property duplication errors
 | 
|---|
| 166 |                      if (err_code != INDI_PROPERTY_DUPLICATED)
 | 
|---|
| 167 |                      {
 | 
|---|
| 168 |                          IDLog("Dispatch command error: %s\n", msg);
 | 
|---|
| 169 |                          prXMLEle (stderr, root, 0);
 | 
|---|
| 170 |                      }
 | 
|---|
| 171 |                 }
 | 
|---|
| 172 | 
 | 
|---|
| 173 |                delXMLEle (root);        /* not yet, delete and continue */
 | 
|---|
| 174 |             }
 | 
|---|
| 175 |             else if (msg[0])
 | 
|---|
| 176 |             {
 | 
|---|
| 177 |                fprintf (stderr, "Bad XML from %s/%d: %s\n%s\n", cServer.c_str(), cPort, msg, buffer);
 | 
|---|
| 178 |                return;
 | 
|---|
| 179 |             }
 | 
|---|
| 180 |         }
 | 
|---|
| 181 |     }
 | 
|---|
| 182 | }
 | 
|---|
| 183 | 
 | 
|---|
| 184 | int INDI::BaseClient::dispatchCommand(XMLEle *root, char * errmsg)
 | 
|---|
| 185 | {
 | 
|---|
| 186 |     if  (!strcmp (tagXMLEle(root), "message"))
 | 
|---|
| 187 |         return messageCmd(root, errmsg);
 | 
|---|
| 188 |     else if  (!strcmp (tagXMLEle(root), "delProperty"))
 | 
|---|
| 189 |         return delPropertyCmd(root, errmsg);
 | 
|---|
| 190 | 
 | 
|---|
| 191 |     /* Get the device, if not available, create it */
 | 
|---|
| 192 |     INDI::BaseDriver *dp = findDev (root, 1, errmsg);
 | 
|---|
| 193 |     if (dp == NULL)
 | 
|---|
| 194 |     {
 | 
|---|
| 195 |         strcpy(errmsg,"No device available and none was created");
 | 
|---|
| 196 |         return INDI_DEVICE_NOT_FOUND;
 | 
|---|
| 197 |     }
 | 
|---|
| 198 | 
 | 
|---|
| 199 |     if ((!strcmp (tagXMLEle(root), "defTextVector"))  ||
 | 
|---|
| 200 |        (!strcmp (tagXMLEle(root), "defNumberVector")) ||
 | 
|---|
| 201 |        (!strcmp (tagXMLEle(root), "defSwitchVector")) ||
 | 
|---|
| 202 |        (!strcmp (tagXMLEle(root), "defLightVector"))  ||
 | 
|---|
| 203 |        (!strcmp (tagXMLEle(root), "defBLOBVector")))
 | 
|---|
| 204 |         return dp->buildProp(root, errmsg);
 | 
|---|
| 205 |     else if (!strcmp (tagXMLEle(root), "setTextVector") ||
 | 
|---|
| 206 |              !strcmp (tagXMLEle(root), "setNumberVector") ||
 | 
|---|
| 207 |              !strcmp (tagXMLEle(root), "setSwitchVector") ||
 | 
|---|
| 208 |              !strcmp (tagXMLEle(root), "setLightVector") ||
 | 
|---|
| 209 |              !strcmp (tagXMLEle(root), "setBLOBVector"))
 | 
|---|
| 210 |             return dp->setValue(root, errmsg);
 | 
|---|
| 211 | 
 | 
|---|
| 212 |     return INDI_DISPATCH_ERROR;
 | 
|---|
| 213 | }
 | 
|---|
| 214 | 
 | 
|---|
| 215 | /* delete the property in the given device, including widgets and data structs.
 | 
|---|
| 216 |  * when last property is deleted, delete the device too.
 | 
|---|
| 217 |  * if no property name attribute at all, delete the whole device regardless.
 | 
|---|
| 218 |  * return 0 if ok, else -1 with reason in errmsg[].
 | 
|---|
| 219 |  */
 | 
|---|
| 220 | int INDI::BaseClient::delPropertyCmd (XMLEle *root, char * errmsg)
 | 
|---|
| 221 | {
 | 
|---|
| 222 |     XMLAtt *ap;
 | 
|---|
| 223 |     INDI::BaseDriver *dp;
 | 
|---|
| 224 | 
 | 
|---|
| 225 |     /* dig out device and optional property name */
 | 
|---|
| 226 |     dp = findDev (root, 0, errmsg);
 | 
|---|
| 227 |     if (!dp)
 | 
|---|
| 228 |         return INDI_DEVICE_NOT_FOUND;
 | 
|---|
| 229 | 
 | 
|---|
| 230 |     checkMsg(root, dp);
 | 
|---|
| 231 | 
 | 
|---|
| 232 |     ap = findXMLAtt (root, "name");
 | 
|---|
| 233 | 
 | 
|---|
| 234 |     /* Delete property if it exists, otherwise, delete the whole device */
 | 
|---|
| 235 |     if (ap)
 | 
|---|
| 236 |         return dp->removeProperty(valuXMLAtt(ap));
 | 
|---|
| 237 |     // delete the whole device
 | 
|---|
| 238 |     else
 | 
|---|
| 239 |         return removeDevice(dp->deviceName(), errmsg);
 | 
|---|
| 240 | }
 | 
|---|
| 241 | 
 | 
|---|
| 242 | int INDI::BaseClient::removeDevice( const char * devName, char * errmsg )
 | 
|---|
| 243 | {
 | 
|---|
| 244 |     std::vector<INDI::BaseDriver *>::iterator devicei = cDevices.begin();
 | 
|---|
| 245 | 
 | 
|---|
| 246 |     while (devicei != cDevices.end())
 | 
|---|
| 247 |     {
 | 
|---|
| 248 |       if (devName == NULL || !strcmp(devName, (*devicei)->deviceName()))
 | 
|---|
| 249 |       {
 | 
|---|
| 250 |           cDevices.erase(devicei);
 | 
|---|
| 251 |           delete (*devicei);
 | 
|---|
| 252 |           return 0;
 | 
|---|
| 253 |       }
 | 
|---|
| 254 | 
 | 
|---|
| 255 |       devicei++;
 | 
|---|
| 256 |     }
 | 
|---|
| 257 | 
 | 
|---|
| 258 |     snprintf(errmsg, MAXRBUF, "Device %s not found", devName);
 | 
|---|
| 259 |     return INDI_DEVICE_NOT_FOUND;
 | 
|---|
| 260 | }
 | 
|---|
| 261 | 
 | 
|---|
| 262 | INDI::BaseDriver * INDI::BaseClient::findDev( const char * devName, char * errmsg )
 | 
|---|
| 263 | {
 | 
|---|
| 264 | 
 | 
|---|
| 265 |     std::vector<INDI::BaseDriver *>::const_iterator devicei;
 | 
|---|
| 266 | 
 | 
|---|
| 267 |     for (devicei = cDevices.begin(); devicei != cDevices.end(); devicei++)
 | 
|---|
| 268 |     {
 | 
|---|
| 269 |         if (!strcmp(devName, (*devicei)->deviceName()))
 | 
|---|
| 270 |          return (*devicei);
 | 
|---|
| 271 | 
 | 
|---|
| 272 |     }
 | 
|---|
| 273 | 
 | 
|---|
| 274 |     snprintf(errmsg, MAXRBUF, "Device %s not found", devName);
 | 
|---|
| 275 |     return NULL;
 | 
|---|
| 276 | }
 | 
|---|
| 277 | 
 | 
|---|
| 278 | /* add new device */
 | 
|---|
| 279 | INDI::BaseDriver * INDI::BaseClient::addDevice (XMLEle *dep, char * errmsg)
 | 
|---|
| 280 | {
 | 
|---|
| 281 |     INDI::BaseDriver *dp;
 | 
|---|
| 282 |     XMLAtt *ap;
 | 
|---|
| 283 |     char * device_name;
 | 
|---|
| 284 | 
 | 
|---|
| 285 |     /* allocate new INDI::BaseDriver */
 | 
|---|
| 286 |     ap = findXMLAtt (dep, "device");
 | 
|---|
| 287 |     if (!ap)
 | 
|---|
| 288 |     {
 | 
|---|
| 289 |         strncpy(errmsg, "Unable to find device attribute in XML element. Cannot add device.", MAXRBUF);
 | 
|---|
| 290 |         return NULL;
 | 
|---|
| 291 |     }
 | 
|---|
| 292 | 
 | 
|---|
| 293 |     device_name = valuXMLAtt(ap);
 | 
|---|
| 294 | 
 | 
|---|
| 295 |     dp = new INDI::BaseDriver();
 | 
|---|
| 296 |     dp->setMediator(this);
 | 
|---|
| 297 |     dp->setDeviceName(device_name);
 | 
|---|
| 298 | 
 | 
|---|
| 299 |     cDevices.push_back(dp);
 | 
|---|
| 300 | 
 | 
|---|
| 301 |     newDevice();
 | 
|---|
| 302 | 
 | 
|---|
| 303 |     /* ok */
 | 
|---|
| 304 |     return dp;
 | 
|---|
| 305 | }
 | 
|---|
| 306 | 
 | 
|---|
| 307 | INDI::BaseDriver * INDI::BaseClient::findDev (XMLEle *root, int create, char * errmsg)
 | 
|---|
| 308 | {
 | 
|---|
| 309 |     XMLAtt *ap;
 | 
|---|
| 310 |     INDI::BaseDriver *dp;
 | 
|---|
| 311 |     char *dn;
 | 
|---|
| 312 | 
 | 
|---|
| 313 |     /* get device name */
 | 
|---|
| 314 |     ap = findXMLAtt (root, "device");
 | 
|---|
| 315 |     if (!ap)
 | 
|---|
| 316 |     {
 | 
|---|
| 317 |         snprintf(errmsg, MAXRBUF, "No device attribute found in element %s", tagXMLEle(root));
 | 
|---|
| 318 |         return (NULL);
 | 
|---|
| 319 |     }
 | 
|---|
| 320 | 
 | 
|---|
| 321 |     dn = valuXMLAtt(ap);
 | 
|---|
| 322 | 
 | 
|---|
| 323 |     dp = findDev(dn, errmsg);
 | 
|---|
| 324 | 
 | 
|---|
| 325 |     if (dp)
 | 
|---|
| 326 |         return dp;
 | 
|---|
| 327 | 
 | 
|---|
| 328 |     /* not found, create if ok */
 | 
|---|
| 329 |     if (create)
 | 
|---|
| 330 |         return (addDevice (root, errmsg));
 | 
|---|
| 331 | 
 | 
|---|
| 332 |     snprintf(errmsg, MAXRBUF, "INDI: <%s> no such device %s", tagXMLEle(root), dn);
 | 
|---|
| 333 |     return NULL;
 | 
|---|
| 334 | }
 | 
|---|
| 335 | 
 | 
|---|
| 336 | /* a general message command received from the device.
 | 
|---|
| 337 |  * return 0 if ok, else -1 with reason in errmsg[].
 | 
|---|
| 338 |  */
 | 
|---|
| 339 | int INDI::BaseClient::messageCmd (XMLEle *root, char * errmsg)
 | 
|---|
| 340 | {
 | 
|---|
| 341 |     checkMsg (root, findDev (root, 0, errmsg));
 | 
|---|
| 342 |     return (0);
 | 
|---|
| 343 | }
 | 
|---|
| 344 | 
 | 
|---|
| 345 | /* add message to queue
 | 
|---|
| 346 |  * N.B. don't put carriage control in msg, we take care of that.
 | 
|---|
| 347 |  */
 | 
|---|
| 348 | void INDI::BaseClient::checkMsg (XMLEle *root, INDI::BaseDriver *dp)
 | 
|---|
| 349 | {
 | 
|---|
| 350 |     XMLAtt *ap;
 | 
|---|
| 351 |     ap = findXMLAtt(root, "message");
 | 
|---|
| 352 | 
 | 
|---|
| 353 |     if (ap)
 | 
|---|
| 354 |         doMsg(root, dp);
 | 
|---|
| 355 | }
 | 
|---|
| 356 | 
 | 
|---|
| 357 | /* Store msg in queue */
 | 
|---|
| 358 | void INDI::BaseClient::doMsg (XMLEle *msg, INDI::BaseDriver *dp)
 | 
|---|
| 359 | {
 | 
|---|
| 360 |     XMLAtt *message;
 | 
|---|
| 361 |     XMLAtt *time_stamp;
 | 
|---|
| 362 |     char msgBuffer[MAXRBUF];
 | 
|---|
| 363 | 
 | 
|---|
| 364 |     if (dp == NULL)
 | 
|---|
| 365 |         return;
 | 
|---|
| 366 | 
 | 
|---|
| 367 |     /* prefix our timestamp if not with msg */
 | 
|---|
| 368 |     time_stamp = findXMLAtt (msg, "timestamp");
 | 
|---|
| 369 | 
 | 
|---|
| 370 |     if (time_stamp)
 | 
|---|
| 371 |         snprintf(msgBuffer, MAXRBUF, "%s ", valuXMLAtt(time_stamp));
 | 
|---|
| 372 |     else
 | 
|---|
| 373 |         snprintf(msgBuffer, MAXRBUF, "%s ", timestamp());
 | 
|---|
| 374 | 
 | 
|---|
| 375 |     /* finally! the msg */
 | 
|---|
| 376 |     message = findXMLAtt(msg, "message");
 | 
|---|
| 377 | 
 | 
|---|
| 378 |     if (!message) return;
 | 
|---|
| 379 | 
 | 
|---|
| 380 |     // Prepend to the log
 | 
|---|
| 381 |    dp->addMessage(msgBuffer);
 | 
|---|
| 382 |    dp->addMessage(valuXMLAtt(message));
 | 
|---|
| 383 |    dp->addMessage("\n");
 | 
|---|
| 384 | \
 | 
|---|
| 385 | }
 | 
|---|
| 386 | 
 | 
|---|
| 387 | void INDI::BaseClient::sendNewText (ITextVectorProperty *tvp)
 | 
|---|
| 388 | {
 | 
|---|
| 389 |     fprintf(svrwfp, "<newTextVector\n");
 | 
|---|
| 390 |     fprintf(svrwfp, "  device='%s'\n", tvp->device);
 | 
|---|
| 391 |     fprintf(svrwfp, "  name='%s'\n>", tvp->name);
 | 
|---|
| 392 | 
 | 
|---|
| 393 |     for (int i=0; i < tvp->ntp; i++)
 | 
|---|
| 394 |     {
 | 
|---|
| 395 |         fprintf(svrwfp, "  <oneText\n");
 | 
|---|
| 396 |         fprintf(svrwfp, "    name='%s'>\n", tvp->tp[i].name);
 | 
|---|
| 397 |         fprintf(svrwfp, "      %s\n", tvp->tp[i].text);
 | 
|---|
| 398 |         fprintf(svrwfp, "  </oneText>\n");
 | 
|---|
| 399 |     }
 | 
|---|
| 400 |     fprintf(svrwfp, "</newTextVector>\n");
 | 
|---|
| 401 | 
 | 
|---|
| 402 |     fflush(svrwfp);
 | 
|---|
| 403 | }
 | 
|---|
| 404 | 
 | 
|---|
| 405 | void INDI::BaseClient::sendNewNumber (INumberVectorProperty *nvp)
 | 
|---|
| 406 | {
 | 
|---|
| 407 |     fprintf(svrwfp, "<newNumberVector\n");
 | 
|---|
| 408 |     fprintf(svrwfp, "  device='%s'\n", nvp->device);
 | 
|---|
| 409 |     fprintf(svrwfp, "  name='%s'\n>", nvp->name);
 | 
|---|
| 410 | 
 | 
|---|
| 411 |     for (int i=0; i < nvp->nnp; i++)
 | 
|---|
| 412 |     {
 | 
|---|
| 413 |         fprintf(svrwfp, "  <oneNumber\n");
 | 
|---|
| 414 |         fprintf(svrwfp, "    name='%s'>\n", nvp->np[i].name);
 | 
|---|
| 415 |         fprintf(svrwfp, "      %g\n", nvp->np[i].value);
 | 
|---|
| 416 |         fprintf(svrwfp, "  </oneNumber>\n");
 | 
|---|
| 417 |     }
 | 
|---|
| 418 |     fprintf(svrwfp, "</newNumberVector>\n");
 | 
|---|
| 419 | 
 | 
|---|
| 420 |    fflush(svrwfp);
 | 
|---|
| 421 | }
 | 
|---|
| 422 | 
 | 
|---|
| 423 | void INDI::BaseClient::sendNewSwitch (ISwitchVectorProperty *svp, ISwitch *sp)
 | 
|---|
| 424 | {
 | 
|---|
| 425 |     fprintf(svrwfp, "<newSwitchVector\n");
 | 
|---|
| 426 | 
 | 
|---|
| 427 |     fprintf(svrwfp, "  device='%s'\n", svp->device);
 | 
|---|
| 428 |     fprintf(svrwfp, "  name='%s'>\n", svp->name);
 | 
|---|
| 429 |     fprintf(svrwfp, "  <oneSwitch\n");
 | 
|---|
| 430 |     fprintf(svrwfp, "    name='%s'>\n", sp->name);
 | 
|---|
| 431 |     fprintf(svrwfp, "      %s\n", (sp->s == ISS_ON) ? "On" : "Off");
 | 
|---|
| 432 |     fprintf(svrwfp, "  </oneSwitch>\n");
 | 
|---|
| 433 | 
 | 
|---|
| 434 |     fprintf(svrwfp, "</newSwitchVector>\n");
 | 
|---|
| 435 | 
 | 
|---|
| 436 |     fflush(svrwfp);
 | 
|---|
| 437 | }
 | 
|---|
| 438 | 
 | 
|---|
| 439 | void INDI::BaseClient::startBlob( const char *devName, const char *propName, const char *timestamp)
 | 
|---|
| 440 | {
 | 
|---|
| 441 |     fprintf(svrwfp, "<newBLOBVector\n");
 | 
|---|
| 442 |     fprintf(svrwfp, "  device='%s'\n", devName);
 | 
|---|
| 443 |     fprintf(svrwfp, "  name='%s'\n", propName);
 | 
|---|
| 444 |     fprintf(svrwfp, "  timestamp='%s'>\n",  timestamp);
 | 
|---|
| 445 | }
 | 
|---|
| 446 | 
 | 
|---|
| 447 | void INDI::BaseClient::sendOneBlob( const char *blobName, unsigned int blobSize, const char *blobFormat, unsigned char * blobBuffer)
 | 
|---|
| 448 | {
 | 
|---|
| 449 |     fprintf(svrwfp, "  <oneBLOB\n");
 | 
|---|
| 450 |     fprintf(svrwfp, "    name='%s'\n", blobName);
 | 
|---|
| 451 |     fprintf(svrwfp, "    size='%d'\n", blobSize);
 | 
|---|
| 452 |     fprintf(svrwfp, "    format='%s'>\n", blobFormat);
 | 
|---|
| 453 | 
 | 
|---|
| 454 |     for (unsigned i = 0; i < blobSize; i += 72)
 | 
|---|
| 455 |         fprintf(svrwfp, "    %.72s\n", blobBuffer+i);
 | 
|---|
| 456 | 
 | 
|---|
| 457 |     fprintf(svrwfp, "   </oneBLOB>\n");
 | 
|---|
| 458 | }
 | 
|---|
| 459 | 
 | 
|---|
| 460 | void INDI::BaseClient::finishBlob()
 | 
|---|
| 461 | {
 | 
|---|
| 462 |     fprintf(svrwfp, "</newBLOBVector>\n");
 | 
|---|
| 463 |     fflush(svrwfp);
 | 
|---|
| 464 | 
 | 
|---|
| 465 | }
 | 
|---|
| 466 | 
 | 
|---|
| 467 | void INDI::BaseClient::setBLOBMode(BLOBHandling blobH, const char *dev, const char *prop)
 | 
|---|
| 468 | {
 | 
|---|
| 469 |     char blobOpenTag[64];
 | 
|---|
| 470 | 
 | 
|---|
| 471 |     if (dev)
 | 
|---|
| 472 |     {
 | 
|---|
| 473 |         if (prop)
 | 
|---|
| 474 |             snprintf(blobOpenTag, 64, "<enableBLOB device='%s' name='%s'>", dev, prop);
 | 
|---|
| 475 |         else
 | 
|---|
| 476 |             snprintf(blobOpenTag, 64, "<enableBLOB device='%s'>", dev);
 | 
|---|
| 477 |     }
 | 
|---|
| 478 |     else
 | 
|---|
| 479 |         snprintf(blobOpenTag, 64, "<enableBLOB>", dev, prop);
 | 
|---|
| 480 | 
 | 
|---|
| 481 | 
 | 
|---|
| 482 |     switch (blobH)
 | 
|---|
| 483 |     {
 | 
|---|
| 484 |     case B_NEVER:
 | 
|---|
| 485 |         fprintf(svrwfp, "%sNever</enableBLOB>\n", blobOpenTag);
 | 
|---|
| 486 |         break;
 | 
|---|
| 487 |     case B_ALSO:
 | 
|---|
| 488 |         fprintf(svrwfp, "%sAlso</enableBLOB>\n", blobOpenTag);
 | 
|---|
| 489 |         break;
 | 
|---|
| 490 |     case B_ONLY:
 | 
|---|
| 491 |         fprintf(svrwfp, "%sOnly</enableBLOB>\n", blobOpenTag);
 | 
|---|
| 492 |         break;
 | 
|---|
| 493 |     }
 | 
|---|
| 494 | 
 | 
|---|
| 495 |     fflush(svrwfp);
 | 
|---|
| 496 | }
 | 
|---|
| 497 | 
 | 
|---|
| 498 | 
 | 
|---|
| 499 | 
 | 
|---|