source: BAORadio/libindi/libindi/libs/indibase/basedevice.cpp

Last change on this file was 698, checked in by frichard, 12 years ago
File size: 31.0 KB
Line 
1/*******************************************************************************
2  Copyright(c) 2011 Jasem Mutlaq. All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB.  If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*******************************************************************************/
18
19#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <zlib.h>
23
24#include "basedevice.h"
25#include "baseclient.h"
26#include "indicom.h"
27#include "base64.h"
28#include "indiproperty.h"
29
30INDI::BaseDevice::BaseDevice()
31{
32    mediator = NULL;
33    lp = newLilXML();
34    deviceID = new char[MAXINDIDEVICE];
35    char indidev[MAXINDIDEVICE];
36    strncpy(indidev, "INDIDEV=", MAXINDIDEVICE);
37
38    if (getenv("INDIDEV") != NULL)
39    {
40        strncpy(deviceID, getenv("INDIDEV"), MAXINDIDEVICE);
41        putenv(indidev);
42    }
43}
44
45INDI::BaseDevice::~BaseDevice()
46{
47    delLilXML (lp);
48    while(!pAll.empty())
49    {
50      delete pAll.back();
51      pAll.pop_back();
52    }
53
54    delete[] deviceID;
55}
56
57INumberVectorProperty * INDI::BaseDevice::getNumber(const char *name)
58{
59    INumberVectorProperty * nvp = NULL;
60
61    nvp = static_cast<INumberVectorProperty *> (getRawProperty(name, INDI_NUMBER));
62
63    return nvp;
64}
65
66ITextVectorProperty * INDI::BaseDevice::getText(const char *name)
67{
68    ITextVectorProperty * tvp = NULL;
69
70    tvp = static_cast<ITextVectorProperty *> (getRawProperty(name, INDI_TEXT));
71
72    return tvp;
73}
74
75ISwitchVectorProperty * INDI::BaseDevice::getSwitch(const char *name)
76{
77    ISwitchVectorProperty * svp = NULL;
78
79    svp = static_cast<ISwitchVectorProperty *> (getRawProperty(name, INDI_SWITCH));
80
81    return svp;
82}
83
84ILightVectorProperty * INDI::BaseDevice::getLight(const char *name)
85{
86    ILightVectorProperty * lvp = NULL;
87
88    lvp = static_cast<ILightVectorProperty *> (getRawProperty(name, INDI_LIGHT));
89
90    return lvp;
91}
92
93IBLOBVectorProperty * INDI::BaseDevice::getBLOB(const char *name)
94{       
95  IBLOBVectorProperty * bvp = NULL;
96
97  bvp = static_cast<IBLOBVectorProperty *> (getRawProperty(name, INDI_BLOB));
98
99  return bvp;
100}
101
102
103void * INDI::BaseDevice::getRawProperty(const char *name, INDI_TYPE type)
104{
105    INDI_TYPE pType;
106    void *pPtr;
107    bool pRegistered = false;
108
109    std::vector<INDI::Property *>::iterator orderi;
110
111    INumberVectorProperty *nvp;
112    ITextVectorProperty *tvp;
113    ISwitchVectorProperty *svp;
114    ILightVectorProperty *lvp;
115    IBLOBVectorProperty *bvp;
116
117    for (orderi = pAll.begin(); orderi != pAll.end(); orderi++)
118    {
119        pType       = (*orderi)->getType();
120        pPtr        = (*orderi)->getProperty();
121        pRegistered = (*orderi)->getRegistered();
122
123        if (type != INDI_UNKNOWN && pType != type)
124            continue;
125
126        switch (pType)
127        {
128        case INDI_NUMBER:
129            nvp = static_cast<INumberVectorProperty *>(pPtr);
130            if (nvp == NULL)
131                continue;
132
133            if (!strcmp(name, nvp->name) && pRegistered)
134                return pPtr;
135             break;
136        case INDI_TEXT:
137             tvp = static_cast<ITextVectorProperty *>(pPtr);
138             if (tvp == NULL)
139                 continue;
140
141             if (!strcmp(name, tvp->name)  && pRegistered)
142                return pPtr;
143             break;
144        case INDI_SWITCH:
145             svp = static_cast<ISwitchVectorProperty *>(pPtr);
146             if (svp == NULL)
147                 continue;
148
149             //IDLog("Switch %s and aux value is now %d\n", svp->name, regStatus );
150             if (!strcmp(name, svp->name) && pRegistered)
151                 return pPtr;
152             break;
153        case INDI_LIGHT:
154             lvp = static_cast<ILightVectorProperty *>(pPtr);
155             if (lvp == NULL)
156                 continue;
157
158             if (!strcmp(name, lvp->name)  && pRegistered)
159                 return pPtr;
160             break;
161        case INDI_BLOB:
162             bvp = static_cast<IBLOBVectorProperty *>(pPtr);
163             if (bvp == NULL)
164                 continue;
165
166             if (!strcmp(name, bvp->name) && pRegistered)
167                 return pPtr;
168             break;
169        }
170
171    }
172
173    return NULL;
174}
175
176INDI::Property * INDI::BaseDevice::getProperty(const char *name, INDI_TYPE type)
177{
178    INDI_TYPE pType;
179    void *pPtr;
180    bool pRegistered = false;
181
182    std::vector<INDI::Property *>::iterator orderi;
183
184    INumberVectorProperty *nvp;
185    ITextVectorProperty *tvp;
186    ISwitchVectorProperty *svp;
187    ILightVectorProperty *lvp;
188    IBLOBVectorProperty *bvp;
189
190    for (orderi = pAll.begin(); orderi != pAll.end(); orderi++)
191    {
192        pType       = (*orderi)->getType();
193        pPtr        = (*orderi)->getProperty();
194        pRegistered = (*orderi)->getRegistered();
195
196        if (type != INDI_UNKNOWN && pType != type)
197            continue;
198
199        switch (pType)
200        {
201        case INDI_NUMBER:
202            nvp = static_cast<INumberVectorProperty *>(pPtr);
203            if (nvp == NULL)
204                continue;
205
206            if (!strcmp(name, nvp->name) && pRegistered)
207                return *orderi;
208             break;
209        case INDI_TEXT:
210             tvp = static_cast<ITextVectorProperty *>(pPtr);
211             if (tvp == NULL)
212                 continue;
213
214             if (!strcmp(name, tvp->name)  && pRegistered)
215                return *orderi;
216             break;
217        case INDI_SWITCH:
218             svp = static_cast<ISwitchVectorProperty *>(pPtr);
219             if (svp == NULL)
220                 continue;
221
222             //IDLog("Switch %s and aux value is now %d\n", svp->name, regStatus );
223             if (!strcmp(name, svp->name) && pRegistered)
224                 return *orderi;
225             break;
226        case INDI_LIGHT:
227             lvp = static_cast<ILightVectorProperty *>(pPtr);
228             if (lvp == NULL)
229                 continue;
230
231             if (!strcmp(name, lvp->name)  && pRegistered)
232                 return *orderi;
233             break;
234        case INDI_BLOB:
235             bvp = static_cast<IBLOBVectorProperty *>(pPtr);
236             if (bvp == NULL)
237                 continue;
238
239             if (!strcmp(name, bvp->name) && pRegistered)
240                 return *orderi;
241             break;
242        }
243
244    }
245
246    return NULL;
247}
248
249int INDI::BaseDevice::removeProperty(const char *name, char *errmsg)
250{   
251    std::vector<INDI::Property *>::iterator orderi;
252
253    INDI_TYPE pType;
254    void *pPtr;
255
256    INumberVectorProperty *nvp;
257    ITextVectorProperty *tvp;
258    ISwitchVectorProperty *svp;
259    ILightVectorProperty *lvp;
260    IBLOBVectorProperty *bvp;
261
262    for (orderi = pAll.begin(); orderi != pAll.end(); orderi++)
263    {
264        pType       = (*orderi)->getType();
265        pPtr        = (*orderi)->getProperty();
266
267        switch (pType)
268        {
269        case INDI_NUMBER:
270            nvp = static_cast<INumberVectorProperty *>(pPtr);
271            if (!strcmp(name, nvp->name))
272            {
273                (*orderi)->setRegistered(false);
274                delete *orderi;
275                orderi = pAll.erase(orderi);
276
277                 return 0;
278             }
279             break;
280        case INDI_TEXT:
281             tvp = static_cast<ITextVectorProperty *>(pPtr);
282             if (!strcmp(name, tvp->name))
283             {
284                  (*orderi)->setRegistered(false);
285                 delete *orderi;
286                 orderi = pAll.erase(orderi);
287
288                  return 0;
289              }
290             break;
291        case INDI_SWITCH:
292             svp = static_cast<ISwitchVectorProperty *>(pPtr);
293             if (!strcmp(name, svp->name))
294             {
295                 (*orderi)->setRegistered(false);
296                 delete *orderi;
297                 orderi = pAll.erase(orderi);
298                  return 0;
299              }
300             break;
301        case INDI_LIGHT:
302             lvp = static_cast<ILightVectorProperty *>(pPtr);
303             if (!strcmp(name, lvp->name))
304             {
305                 (*orderi)->setRegistered(false);
306                 delete *orderi;
307                 orderi = pAll.erase(orderi);
308                 return 0;
309              }
310             break;
311        case INDI_BLOB:
312             bvp = static_cast<IBLOBVectorProperty *>(pPtr);
313             if (!strcmp(name, bvp->name))
314             {
315                 (*orderi)->setRegistered(false);
316                 delete *orderi;
317                 orderi = pAll.erase(orderi);
318                 return 0;
319              }
320             break;
321        }
322    }
323
324    snprintf(errmsg, MAXRBUF, "Error: Property %s not found in device %s.", name, deviceID);
325    return INDI_PROPERTY_INVALID;
326}
327
328void INDI::BaseDevice::buildSkeleton(const char *filename)
329{
330    char errmsg[MAXRBUF];
331    FILE *fp = NULL;
332    XMLEle *root = NULL, *fproot = NULL;
333
334    fp = fopen(filename, "r");
335
336    if (fp == NULL)
337    {
338        IDLog("Unable to build skeleton. Error loading file %s: %s\n", filename, strerror(errno));
339        return;
340    }
341
342    fproot = readXMLFile(fp, lp, errmsg);
343
344    if (fproot == NULL)
345    {
346        IDLog("Unable to parse skeleton XML: %s", errmsg);
347        return;
348    }
349
350    //prXMLEle(stderr, fproot, 0);
351
352    for (root = nextXMLEle (fproot, 1); root != NULL; root = nextXMLEle (fproot, 0))
353            buildProp(root, errmsg);
354
355    /**************************************************************************/
356}
357
358int INDI::BaseDevice::buildProp(XMLEle *root, char *errmsg)
359{
360    IPerm perm;
361    IPState state;
362    XMLEle *ep = NULL;
363    char *rtag, *rname, *rdev;
364    double timeout=0;
365
366    rtag = tagXMLEle(root);
367
368    /* pull out device and name */
369    if (crackDN (root, &rdev, &rname, errmsg) < 0)
370        return -1;
371
372   /* if (!deviceID[0])
373    {
374        if (getenv("INDIDEV"))
375            strncpy(deviceID, getenv("INDIDEV"), MAXINDINAME);
376        else
377            strncpy(deviceID, rdev, MAXINDINAME);
378    }*/
379
380    if (!deviceID[0])
381        strncpy(deviceID, rdev, MAXINDINAME);
382
383    //if (getProperty(rname, type) != NULL)
384    if (getProperty(rname) != NULL)
385        return INDI::BaseClient::INDI_PROPERTY_DUPLICATED;
386
387    if (strcmp (rtag, "defLightVector") && crackIPerm(findXMLAttValu(root, "perm"), &perm) < 0)
388    {
389        IDLog("Error extracting %s permission (%s)\n", rname, findXMLAttValu(root, "perm"));
390        return -1;
391    }
392
393    timeout = atoi(findXMLAttValu(root, "timeout"));
394
395    if (crackIPState (findXMLAttValu(root, "state"), &state) < 0)
396    {
397        IDLog("Error extracting %s state (%s)\n", rname, findXMLAttValu(root, "state"));
398        return -1;
399    }
400
401
402    if (!strcmp (rtag, "defNumberVector"))
403    {
404        INDI::Property *indiProp = new INDI::Property();
405        INumberVectorProperty *nvp = new INumberVectorProperty;
406
407        INumber *np = NULL;
408        int n=0;
409
410        strncpy(nvp->device, deviceID, MAXINDIDEVICE);
411        strncpy(nvp->name, rname, MAXINDINAME);
412        strncpy(nvp->label, findXMLAttValu(root, "label"), MAXINDILABEL);
413        strncpy(nvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP);
414
415        nvp->p       = perm;
416        nvp->s       = state;
417        nvp->timeout = timeout;
418
419    /* pull out each name/value pair */
420    for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++)
421    {
422        if (!strcmp (tagXMLEle(ep), "defNumber"))
423        {
424            np = (INumber *) realloc(np, (n+1) * sizeof(INumber));
425
426            np[n].nvp = nvp;
427
428            XMLAtt *na = findXMLAtt (ep, "name");
429
430            if (na)
431            {
432                if (f_scansexa (pcdataXMLEle(ep), &(np[n].value)) < 0)
433                    IDLog("%s: Bad format %s\n", rname, pcdataXMLEle(ep));
434                else
435                {
436
437                    strncpy(np[n].name, valuXMLAtt(na), MAXINDINAME);
438
439                    na = findXMLAtt (ep, "label");
440                    if (na)
441                      strncpy(np[n].label, valuXMLAtt(na),MAXINDILABEL);
442                    na = findXMLAtt (ep, "format");
443                    if (na)
444                        strncpy(np[n].format, valuXMLAtt(na), MAXINDIFORMAT);
445
446                   na = findXMLAtt (ep, "min");
447                   if (na)
448                       np[n].min = atof(valuXMLAtt(na));
449                   na = findXMLAtt (ep, "max");
450                   if (na)
451                       np[n].max = atof(valuXMLAtt(na));
452                   na = findXMLAtt (ep, "step");
453                   if (na)
454                       np[n].step = atof(valuXMLAtt(na));
455
456                }
457            }
458        }
459    }
460
461    if (n > 0)
462    {
463        nvp->nnp = n;
464        nvp->np  = np;
465
466        indiProp->setProperty(nvp);
467        indiProp->setDynamic(true);
468        indiProp->setType(INDI_NUMBER);
469
470        pAll.push_back(indiProp);
471
472        //IDLog("Adding number property %s to list.\n", nvp->name);
473        if (mediator)
474            mediator->newProperty(indiProp);
475    }
476    else
477        IDLog("%s: newNumberVector with no valid members\n",rname);
478  }
479  else if (!strcmp (rtag, "defSwitchVector"))
480  {
481            INDI::Property *indiProp = new INDI::Property();
482            ISwitchVectorProperty *svp = new ISwitchVectorProperty;
483
484            ISwitch *sp = NULL;
485            int n=0;
486
487            strncpy(svp->device, deviceID, MAXINDIDEVICE);
488            strncpy(svp->name, rname, MAXINDINAME);
489            strncpy(svp->label, findXMLAttValu(root, "label"), MAXINDILABEL);
490            strncpy(svp->group, findXMLAttValu(root, "group"), MAXINDIGROUP);
491
492            if (crackISRule(findXMLAttValu(root, "rule"), (&svp->r)) < 0)
493                svp->r = ISR_1OFMANY;
494
495            svp->p       = perm;
496            svp->s       = state;
497            svp->timeout = timeout;
498
499
500        /* pull out each name/value pair */
501        for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++)
502        {
503            if (!strcmp (tagXMLEle(ep), "defSwitch"))
504            {
505                sp = (ISwitch *) realloc(sp, (n+1) * sizeof(ISwitch));
506
507                sp[n].svp = svp;
508
509                XMLAtt *na = findXMLAtt (ep, "name");
510
511                if (na)
512                {
513                    crackISState(pcdataXMLEle(ep), &(sp[n].s));
514                    strncpy(sp[n].name, valuXMLAtt(na), MAXINDINAME);
515
516                    na = findXMLAtt (ep, "label");
517                    if (na)
518                        strncpy(sp[n].label, valuXMLAtt(na),MAXINDILABEL);
519                 }
520            }
521        }
522
523        if (n > 0)
524        {
525            svp->nsp = n;
526            svp->sp  = sp;
527
528            indiProp->setProperty(svp);
529            indiProp->setDynamic(true);
530            indiProp->setType(INDI_SWITCH);
531
532            pAll.push_back(indiProp);
533            //IDLog("Adding Switch property %s to list.\n", svp->name);
534            if (mediator)
535                mediator->newProperty(indiProp);
536        }
537        else
538            IDLog("%s: newSwitchVector with no valid members\n",rname);
539    }
540
541else if (!strcmp (rtag, "defTextVector"))
542    {
543
544        INDI::Property *indiProp = new INDI::Property();
545        ITextVectorProperty *tvp = new ITextVectorProperty;
546        IText *tp = NULL;
547        int n=0;
548
549        strncpy(tvp->device, deviceID, MAXINDIDEVICE);
550        strncpy(tvp->name, rname, MAXINDINAME);
551        strncpy(tvp->label, findXMLAttValu(root, "label"), MAXINDILABEL);
552        strncpy(tvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP);
553
554        tvp->p       = perm;
555        tvp->s       = state;
556        tvp->timeout = timeout;
557
558    // pull out each name/value pair
559    for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++)
560    {
561        if (!strcmp (tagXMLEle(ep), "defText"))
562        {
563            tp = (IText *) realloc(tp, (n+1) * sizeof(IText));
564
565            tp[n].tvp = tvp;
566
567            XMLAtt *na = findXMLAtt (ep, "name");
568
569            if (na)
570            {
571                tp[n].text = (char *) malloc( (pcdatalenXMLEle(ep)*sizeof(char)) + 1);
572                strncpy(tp[n].text, pcdataXMLEle(ep), pcdatalenXMLEle(ep));
573                tp[n].text[pcdatalenXMLEle(ep)] = '\0';
574                strncpy(tp[n].name, valuXMLAtt(na), MAXINDINAME);
575
576                na = findXMLAtt (ep, "label");
577                if (na)
578                    strncpy(tp[n].label, valuXMLAtt(na),MAXINDILABEL);
579             }
580        }
581    }
582
583    if (n > 0)
584    {
585        tvp->ntp = n;
586        tvp->tp  = tp;
587
588        indiProp->setProperty(tvp);
589        indiProp->setDynamic(true);
590        indiProp->setType(INDI_TEXT);
591
592        pAll.push_back(indiProp);
593
594        //IDLog("Adding Text property %s to list with initial value of %s.\n", tvp->name, tvp->tp[0].text);
595        if (mediator)
596            mediator->newProperty(indiProp);
597    }
598    else
599        IDLog("%s: newTextVector with no valid members\n",rname);
600}
601else if (!strcmp (rtag, "defLightVector"))
602    {
603
604        INDI::Property *indiProp = new INDI::Property();
605        ILightVectorProperty *lvp = new ILightVectorProperty;
606        ILight *lp = NULL;
607        int n=0;
608
609        strncpy(lvp->device, deviceID, MAXINDIDEVICE);
610        strncpy(lvp->name, rname, MAXINDINAME);
611        strncpy(lvp->label, findXMLAttValu(root, "label"), MAXINDILABEL);
612        strncpy(lvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP);
613
614        lvp->s       = state;
615
616    /* pull out each name/value pair */
617    for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++)
618    {
619        if (!strcmp (tagXMLEle(ep), "defLight"))
620        {
621            lp = (ILight *) realloc(lp, (n+1) * sizeof(ILight));
622
623            lp[n].lvp = lvp;
624
625            XMLAtt *na = findXMLAtt (ep, "name");
626
627            if (na)
628            {
629                crackIPState(pcdataXMLEle(ep), &(lp[n].s));
630                strncpy(lp[n].name, valuXMLAtt(na), MAXINDINAME);
631
632                na = findXMLAtt (ep, "label");
633                if (na)
634                    strncpy(lp[n].label, valuXMLAtt(na),MAXINDILABEL);
635
636             }
637        }
638    }
639
640    if (n > 0)
641    {
642        lvp->nlp = n;
643        lvp->lp  = lp;
644
645        indiProp->setProperty(lvp);
646        indiProp->setDynamic(true);
647        indiProp->setType(INDI_LIGHT);
648
649        pAll.push_back(indiProp);
650
651        //IDLog("Adding Light property %s to list.\n", lvp->name);
652        if (mediator)
653            mediator->newProperty(indiProp);
654    }
655    else
656        IDLog("%s: newLightVector with no valid members\n",rname);
657}
658else if (!strcmp (rtag, "defBLOBVector"))
659    {
660        INDI::Property *indiProp = new INDI::Property();
661        IBLOBVectorProperty *bvp = new IBLOBVectorProperty;
662        IBLOB *bp = NULL;
663        int n=0;
664
665        strncpy(bvp->device, deviceID, MAXINDIDEVICE);
666        strncpy(bvp->name, rname, MAXINDINAME);
667        strncpy(bvp->label, findXMLAttValu(root, "label"), MAXINDILABEL);
668        strncpy(bvp->group, findXMLAttValu(root, "group"), MAXINDIGROUP);
669
670        bvp->s       = state;
671        bvp->p       = perm;
672
673    /* pull out each name/value pair */
674    for (n = 0, ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0), n++)
675    {
676        if (!strcmp (tagXMLEle(ep), "defBLOB"))
677        {
678            bp = (IBLOB *) realloc(bp, (n+1) * sizeof(IBLOB));
679
680            bp[n].bvp = bvp;
681
682            XMLAtt *na = findXMLAtt (ep, "name");
683
684            if (na)
685            {
686                strncpy(bp[n].name, valuXMLAtt(na), MAXINDINAME);
687
688                na = findXMLAtt (ep, "label");
689                if (na)
690                    strncpy(bp[n].label, valuXMLAtt(na),MAXINDILABEL);
691
692                na = findXMLAtt (ep, "format");
693                if (na)
694                    strncpy(bp[n].label, valuXMLAtt(na),MAXINDIBLOBFMT);
695
696                // Initialize everything to zero
697
698                bp[n].blob    = NULL;
699                bp[n].size    = 0;
700                bp[n].bloblen = 0;
701             }
702
703        }
704    }
705
706    if (n > 0)
707    {
708        bvp->nbp = n;
709        bvp->bp  = bp;
710
711        indiProp->setProperty(bvp);
712        indiProp->setDynamic(true);
713        indiProp->setType(INDI_BLOB);
714
715        pAll.push_back(indiProp);
716        //IDLog("Adding BLOB property %s to list.\n", bvp->name);
717        if (mediator)
718            mediator->newProperty(indiProp);
719    }
720    else
721        IDLog("%s: newBLOBVector with no valid members\n",rname);
722 }
723
724return (0);
725
726}
727
728bool INDI::BaseDevice::isConnected()
729{
730    ISwitchVectorProperty *svp = getSwitch("CONNECTION");
731    if (!svp)
732        return false;
733
734    ISwitch * sp = IUFindSwitch(svp, "CONNECT");
735
736    if (!sp)
737        return false;
738
739    if (sp->s == ISS_ON)
740        return true;
741    else
742        return false;
743
744}
745
746/*
747 * return 0 if ok else -1 with reason in errmsg
748 */
749int INDI::BaseDevice::setValue (XMLEle *root, char * errmsg)
750{
751    XMLAtt *ap;
752    XMLEle *ep;
753    char *rtag, *name;
754    double timeout;
755    IPState state;
756    bool stateSet=false, timeoutSet=false;
757
758    rtag = tagXMLEle(root);
759
760    ap = findXMLAtt (root, "name");
761    if (!ap)
762    {
763        snprintf(errmsg, MAXRBUF, "INDI: <%s> unable to find name attribute", tagXMLEle(root));
764        return (-1);
765    }
766
767    name = valuXMLAtt(ap);
768
769    /* set overall property state, if any */
770    ap = findXMLAtt (root, "state");
771    if (ap)
772    {
773        if (crackIPState(valuXMLAtt(ap), &state) != 0)
774        {
775            snprintf(errmsg, MAXRBUF, "INDI: <%s> bogus state %s for %s", tagXMLEle(root),
776                     valuXMLAtt(ap), name);
777            return (-1);
778        }
779
780        stateSet = true;
781    }
782
783    /* allow changing the timeout */
784    ap = findXMLAtt (root, "timeout");
785    if (ap)
786    {
787        timeout = atof(valuXMLAtt(ap));
788        timeoutSet = true;
789    }
790
791    checkMessage (root);
792
793    if (!strcmp(rtag, "setNumberVector"))
794    {
795        INumberVectorProperty *nvp = getNumber(name);
796        if (nvp == NULL)
797        {
798            snprintf(errmsg, MAXRBUF, "INDI: Could not find property %s in %s", name, deviceID);
799            return -1;
800        }
801
802        if (stateSet)
803            nvp->s = state;
804
805        if (timeoutSet)
806            nvp->timeout = timeout;
807
808       for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
809        {
810           INumber *np =  IUFindNumber(nvp, findXMLAttValu(ep, "name"));
811           if (!np)
812               continue;
813
814          np->value = atof(pcdataXMLEle(ep));
815
816          // Permit changing of min/max
817          if (findXMLAtt(ep, "min"))
818              np->min = atof(findXMLAttValu(ep, "min"));
819          if (findXMLAtt(ep, "max"))
820              np->max = atof(findXMLAttValu(ep, "max"));
821       }
822
823       if (mediator)
824           mediator->newNumber(nvp);
825
826       return 0;
827    }
828    else if (!strcmp(rtag, "setTextVector"))
829    {
830        ITextVectorProperty *tvp = getText(name);
831        if (tvp == NULL)
832            return -1;
833
834        if (stateSet)
835            tvp->s = state;
836
837        if (timeoutSet)
838            tvp->timeout = timeout;
839
840       for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
841        {
842           IText *tp =  IUFindText(tvp, findXMLAttValu(ep, "name"));
843           if (!tp)
844               continue;
845
846          IUSaveText(tp, pcdataXMLEle(ep));
847       }
848
849       if (mediator)
850           mediator->newText(tvp);
851
852       return 0;
853    }
854    else if (!strcmp(rtag, "setSwitchVector"))
855    {
856        ISState swState;
857        ISwitchVectorProperty *svp = getSwitch(name);
858        if (svp == NULL)
859            return -1;
860
861        if (stateSet)
862            svp->s = state;
863
864        if (timeoutSet)
865            svp->timeout = timeout;
866
867       for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
868        {
869           ISwitch *sp =  IUFindSwitch(svp, findXMLAttValu(ep, "name"));
870           if (!sp)
871               continue;
872
873           if (crackISState(pcdataXMLEle(ep), &swState) == 0)
874               sp->s = swState;
875        }
876
877       if (mediator)
878           mediator->newSwitch(svp);
879
880       return 0;
881    }
882    else if (!strcmp(rtag, "setLightVector"))
883    {
884        IPState lState;
885        ILightVectorProperty *lvp = getLight(name);
886        if (lvp == NULL)
887            return -1;
888
889        if (stateSet)
890            lvp->s = state;
891
892       for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
893        {
894           ILight *lp =  IUFindLight(lvp, findXMLAttValu(ep, "name"));
895           if (!lp)
896               continue;
897
898           if (crackIPState(pcdataXMLEle(ep), &lState) == 0)
899               lp->s = lState;
900        }
901
902       if (mediator)
903           mediator->newLight(lvp);
904
905       return 0;
906
907    }
908    else if (!strcmp(rtag, "setBLOBVector"))
909    {
910        IBLOBVectorProperty *bvp = getBLOB(name);
911        if (bvp == NULL)
912            return -1;
913
914        if (stateSet)
915            bvp->s = state;
916
917        if (timeoutSet)
918            bvp->timeout = timeout;
919
920        return setBLOB(bvp, root, errmsg);
921    }
922
923    snprintf(errmsg, MAXRBUF, "INDI: <%s> Unable to process tag", tagXMLEle(root));
924    return -1;
925}
926
927/* Set BLOB vector. Process incoming data stream
928 * Return 0 if okay, -1 if error
929*/
930int INDI::BaseDevice::setBLOB(IBLOBVectorProperty *bvp, XMLEle * root, char * errmsg)
931{   
932    IBLOB *blobEL;
933    unsigned char * dataBuffer=NULL;
934    XMLEle *ep;
935    int n=0, r=0;
936    uLongf dataSize=0;
937
938    /* pull out each name/BLOB pair, decode */
939    for (n = 0, ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0))
940    {
941        if (strcmp (tagXMLEle(ep), "oneBLOB") == 0)
942        {
943            XMLAtt *na = findXMLAtt (ep, "name");
944
945            blobEL = IUFindBLOB(bvp, findXMLAttValu (ep, "name"));
946
947            XMLAtt *fa = findXMLAtt (ep, "format");
948            XMLAtt *sa = findXMLAtt (ep, "size");
949            if (na && fa && sa)
950            {
951
952                blobEL->size = atoi(valuXMLAtt(sa));
953
954                /* Blob size = 0 when only state changes */
955                if (blobEL->size == 0)
956                    continue;
957
958                 blobEL->blob = (unsigned char *) realloc (blobEL->blob, 3*pcdatalenXMLEle(ep)/4);
959
960                 blobEL->bloblen = from64tobits( static_cast<char *> (blobEL->blob), pcdataXMLEle(ep));
961
962                 strncpy(blobEL->format, valuXMLAtt(fa), MAXINDIFORMAT);
963
964                    if (strstr(blobEL->format, ".z"))
965                    {
966                        blobEL->format[strlen(blobEL->format)-2] = '\0';
967                        dataSize = blobEL->size * sizeof(unsigned char);
968                        dataBuffer = (unsigned char *) malloc(dataSize);
969
970                        if (dataBuffer == NULL)
971                        {
972                                strncpy(errmsg, "Unable to allocate memory for data buffer", MAXRBUF);
973                                return (-1);
974                        }
975
976                        r = uncompress(dataBuffer, &dataSize, static_cast<unsigned char *> (blobEL->blob), (uLong) blobEL->bloblen);
977                        if (r != Z_OK)
978                        {
979                            snprintf(errmsg, MAXRBUF, "INDI: %s.%s.%s compression error: %d", blobEL->bvp->device, blobEL->bvp->name, blobEL->name, r);
980                            free (dataBuffer);
981                            return -1;
982                        }
983                        blobEL->size = dataSize;
984                        free(blobEL->blob);
985                        blobEL->blob = dataBuffer;
986                    }
987
988                    if (mediator)
989                        mediator->newBLOB(blobEL);
990                }
991            else
992            {
993                snprintf(errmsg, MAXRBUF, "INDI: %s.%s.%s No valid members.", blobEL->bvp->device, blobEL->bvp->name, blobEL->name);
994                return -1;
995            }
996
997           }
998    }
999
1000}
1001
1002void INDI::BaseDevice::setDeviceName(const char *dev)
1003{
1004    strncpy(deviceID, dev, MAXINDINAME);
1005}
1006
1007const char * INDI::BaseDevice::getDeviceName()
1008{
1009    return deviceID;
1010}
1011
1012/* add message to queue
1013 * N.B. don't put carriage control in msg, we take care of that.
1014 */
1015void INDI::BaseDevice::checkMessage (XMLEle *root)
1016{
1017    XMLAtt *ap;
1018    ap = findXMLAtt(root, "message");
1019
1020    if (ap)
1021        doMessage(root);
1022}
1023
1024/* Store msg in queue */
1025void INDI::BaseDevice::doMessage (XMLEle *msg)
1026{
1027    XMLAtt *message;
1028    XMLAtt *time_stamp;
1029
1030    // FIXME: delete the buffer in the destructor!
1031    char * msgBuffer = new char[MAXRBUF];
1032
1033    /* prefix our timestamp if not with msg */
1034    time_stamp = findXMLAtt (msg, "timestamp");
1035
1036    /* finally! the msg */
1037    message = findXMLAtt(msg, "message");
1038        if (!message) return;
1039
1040    if (time_stamp)
1041        snprintf(msgBuffer, MAXRBUF, "%s: %s ", valuXMLAtt(time_stamp), valuXMLAtt(message));
1042    else
1043        snprintf(msgBuffer, MAXRBUF, "%s: %s ", timestamp(), valuXMLAtt(message));
1044
1045    // Prepend to the log
1046   addMessage(msgBuffer);
1047
1048}
1049
1050
1051void INDI::BaseDevice::addMessage(const char *msg)
1052{
1053    messageLog.push_back(msg);
1054
1055    if (mediator)
1056        mediator->newMessage(this);
1057}
1058
1059const char * INDI::BaseDevice::messageQueue(int index)
1060{
1061    if (index >= messageLog.size())
1062        return NULL;
1063
1064    return messageLog.at(index);
1065
1066}
1067
1068const char * INDI::BaseDevice::lastMessage()
1069{
1070    return messageLog.back();
1071}
1072
1073void INDI::BaseDevice::registerProperty(void *p, INDI_TYPE type)
1074{
1075    INDI::Property *pContainer;
1076
1077    if (type == INDI_NUMBER)
1078    {
1079        INumberVectorProperty *nvp = static_cast<INumberVectorProperty *> (p);
1080        if ( (pContainer = getProperty(nvp->name, INDI_NUMBER)) != NULL)
1081        {
1082            pContainer->setRegistered(true);
1083            return;
1084        }
1085
1086        pContainer = new INDI::Property();
1087        pContainer->setProperty(p);
1088        pContainer->setType(type);
1089
1090        pAll.push_back(pContainer);
1091
1092    }
1093    else if (type == INDI_TEXT)
1094    {
1095       ITextVectorProperty *tvp = static_cast<ITextVectorProperty *> (p);
1096
1097       if ( (pContainer = getProperty(tvp->name, INDI_TEXT)) != NULL)
1098       {
1099           pContainer->setRegistered(true);
1100           return;
1101       }
1102
1103       pContainer = new INDI::Property();
1104       pContainer->setProperty(p);
1105       pContainer->setType(type);
1106
1107       pAll.push_back(pContainer);
1108
1109
1110   }
1111    else if (type == INDI_SWITCH)
1112    {
1113       ISwitchVectorProperty *svp = static_cast<ISwitchVectorProperty *> (p);
1114
1115       if ( (pContainer = getProperty(svp->name, INDI_SWITCH)) != NULL)
1116       {
1117           pContainer->setRegistered(true);
1118           return;
1119       }
1120
1121       pContainer = new INDI::Property();
1122       pContainer->setProperty(p);
1123       pContainer->setType(type);
1124
1125       pAll.push_back(pContainer);
1126
1127    }
1128    else if (type == INDI_LIGHT)
1129    {
1130       ILightVectorProperty *lvp = static_cast<ILightVectorProperty *> (p);
1131
1132       if ( (pContainer = getProperty(lvp->name, INDI_LIGHT)) != NULL)
1133       {
1134           pContainer->setRegistered(true);
1135           return;
1136       }
1137
1138       pContainer = new INDI::Property();
1139       pContainer->setProperty(p);
1140       pContainer->setType(type);
1141
1142       pAll.push_back(pContainer);
1143   }
1144    else if (type == INDI_BLOB)
1145    {
1146       IBLOBVectorProperty *bvp = static_cast<IBLOBVectorProperty *> (p);
1147
1148       if ( (pContainer = getProperty(bvp->name, INDI_BLOB)) != NULL)
1149       {
1150           pContainer->setRegistered(true);
1151           return;
1152       }
1153
1154       pContainer = new INDI::Property();
1155       pContainer->setProperty(p);
1156       pContainer->setType(type);
1157
1158       pAll.push_back(pContainer);
1159
1160    }
1161
1162}
1163
Note: See TracBrowser for help on using the repository browser.