Instrument Neutral Distributed Interface INDI 2.2.5
indi_shelyak_usis.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2022 Etienne Cochard. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18
19 The full GNU General Public License is included in this distribution in the
20 file called LICENSE.
21*******************************************************************************/
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include <map>
29#include <math.h>
30#include <memory>
31
32#include <indicom.h>
33
34#include "version.h"
35#include "indi_shelyak_usis.h"
36
37double _atof( const char* in )
38{
39 char* e;
40 return strtof( in, &e );
41}
42
43static std::unique_ptr<ShelyakDriver> usis(new ShelyakDriver());
44
45// :: Driver ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
46
54
56{
57 if ( _serialPort != -1 )
58 {
59 clearProperties( );
60 tty_disconnect( _serialPort );
61 }
62}
63
68bool ShelyakDriver::readConfig( )
69{
70 auto fname = getSharedFilePath("shelyak_boards.json");
71
72 try
73 {
74 std::ifstream file( fname );
75 file >> _config;
76 return true;
77 }
78 catch( const std::ifstream::failure &e )
79 {
80 LOGF_ERROR( "File not found: %s", fname.c_str() );
81 return false;
82 }
83 catch( json::exception & )
84 {
85 LOGF_ERROR( "Bad json file format: %s", fname.c_str() );
86 return false;
87 }
88}
89
94bool ShelyakDriver::findBoard( const char* boardName, json* result )
95{
96 if( !_config.is_object() )
97 {
98 return false;
99 }
100
101 json boards = _config["boards"];
102 if( !boards.is_array() )
103 {
104 return false;
105 }
106
107 for( json::iterator it = boards.begin(); it != boards.end(); ++it)
108 {
109
110 if( !it->is_object() )
111 {
112 continue;
113 }
114
115 json sig = (*it)["signature"];
116 if( !sig.is_string() )
117 {
118 continue;
119 }
120
121 std::string s = sig;
122 if( s == boardName )
123 {
124 *result = *it;
125 return true;
126 }
127 }
128
129 return false;
130}
131
132/* Returns the name of the device. */
134{
135 return "Shelyak Usis";
136}
137
138/* */
139bool ShelyakDriver::Connect( )
140{
141 int rc = TTY_OK;
142 if ( ( rc = tty_connect( serialConnection->port(), 2400, 8, 0, 1, &_serialPort ) ) != TTY_OK )
143 {
144 char errMsg[MAXRBUF];
145 tty_error_msg( rc, errMsg, MAXRBUF );
146 LOGF_ERROR( "Failed to connect to port %s. Error: %s", serialConnection->port(), errMsg );
147 return false;
148 }
149
150 LOGF_INFO( "%s is online.", getDeviceName( ) );
151 return true;
152}
153
154bool ShelyakDriver::Disconnect( )
155{
156 if ( _serialPort != -1 )
157 {
158 tty_disconnect( _serialPort );
159 LOGF_INFO( "%s is offline.", getDeviceName( ) );
160 }
161
162 clearProperties( );
163
164 return true;
165}
166
167/* Initialize and setup all properties on startup. */
168bool ShelyakDriver::initProperties( )
169{
171
172 //--------------------------------------------------------------------------------
173 // Options
174 //--------------------------------------------------------------------------------
175 serialConnection = new Connection::Serial(this);
176 serialConnection->setDefaultPort("/dev/ttyACM0");
177 serialConnection->registerHandshake([&]()
178 {
179 return true;
180 });
181 registerConnection(serialConnection);
182
183 // read the usis.json file
184 readConfig();
185
187 return true;
188}
189
190Action* ShelyakDriver::createAction( PropType type, const std::string &command )
191{
192 Action* act = new Action( _guid++, command, type );
193 _actions.push_back( act );
194 return act;
195}
196
201void ShelyakDriver::scanProperties( )
202{
203 if( !_config.is_object() )
204 {
205 return;
206 }
207
208 UsisResponse rsp;
209
210 // ask the board name
211 if ( sendCmd( &rsp, "GET;DEVICE_NAME;VALUE" ) )
212 {
213
214 // try to find the device definition in the .json
215 json device;
216 if( !findBoard( rsp.parts[4], &device ) )
217 {
218 LOGF_ERROR( "unknown device: %s", rsp.parts[4] );
219 fprintf( stderr, "device not found %s\n", rsp.parts[4] );
220 return;
221 }
222 else
223 {
224 LOGF_DEBUG( "found device: %s", rsp.parts[4] );
225 fprintf( stderr, "found device %s\n", rsp.parts[4] );
226
227 // ok, found:
228 // enumerate categories and build properties
229
230 json categs = device["categories"];
231 if( categs.is_object() )
232 {
233 for (json::iterator it = categs.begin(); it != categs.end(); ++it)
234 {
235 fprintf( stderr, "category %s\n", it.key().c_str() );
236 genCatProps( it.key().c_str(), it.value() );
237 }
238 }
239 }
240 }
241
242}
243
248void ShelyakDriver::genCatProps( const char* catName, json &category )
249{
250
251 //we scan different properties
252 if( !category.is_array() )
253 {
254 return;
255 }
256
257 for ( auto it = category.begin(); it != category.end(); ++it)
258 {
259
260 json item = *it;
261 if( !item.is_object( ) )
262 {
263 continue;
264 }
265
266 json jname = item["name"];
267 if( !jname.is_string( ) )
268 {
269 LOGF_ERROR( "expected property name", "" );
270 continue;
271 }
272
273 json jtype = item["type"];
274 if( !jtype.is_string() )
275 {
276 LOGF_ERROR( "expected property type", "" );
277 continue;
278 }
279
280 json jcmd = item["command"];
281 if( !jcmd.is_string() )
282 {
283 LOGF_ERROR( "expected property command", "" );
284 continue;
285 }
286
287 // we create a internal action
288
289 Action* act;
290
291 std::string name = jname;
292 std::string type = jtype;
293 std::string cmd = jcmd;
294
295 fprintf( stderr, " name: %s\n", name.c_str() );
296
297 // ------------------------------------------------------
298 if ( type == "string" )
299 {
300
301 fprintf( stderr, " type: string\n" );
302
303 act = createAction( _text, type.c_str() );
304
305 TextValue &text = act->text;
306 IUFillText( &text._val, act->uid, cmd.c_str(), "" );
307 IUFillTextVector( &text._vec, &text._val, 1, getDeviceName( ), act->uid, name.c_str(), catName, IP_RW, 60, IPS_OK );
308
309 defineProperty( &act->text._vec );
310 }
311 // ------------------------------------------------------
312 else if ( type == "enum" )
313 {
314
315 fprintf( stderr, " type: enum\n" );
316
317 json values = item["values"];
318 if( !values.is_array() )
319 {
320 LOGF_ERROR( "expected enum values", "" );
321 continue;
322 }
323
324 act = createAction( _enum, cmd.c_str() );
325 EnumValue &enm = act->enm;
326
327 ISwitch* sws = enm._vals;
328 unsigned nsw = 0;
329
330 // allowed values
331 for (json::iterator it = values.begin(); it != values.end() && nsw < MAX_ENUMS; ++it, ++nsw)
332 {
333 json jvalue = (*it);
334
335 if( jvalue.is_string() )
336 {
337 std::string value = jvalue;
338
339 Action* sub_act = createAction( _eitm, cmd.c_str() );
340 sub_act->itm.parent = act;
341 sub_act->itm.index = nsw;
342 sub_act->itm.val = value;
343 IUFillSwitch( &sws[nsw], sub_act->uid, value.c_str(), ISS_OFF );
344 }
345 }
346
347 IUFillSwitchVector( &enm._vec, sws, nsw, getDeviceName( ), act->uid, name.c_str(), catName, IP_RW, ISR_1OFMANY, 60,
348 IPS_OK );
349 defineProperty( &enm._vec );
350 }
351 // ------------------------------------------------------
352 else if ( type == "number" )
353 {
354
355 fprintf( stderr, " type: number\n" );
356
357 double minVal = -9999.0;
358 double maxVal = +9999.0;
359 double precVal = 0.01;
360
361 // fix min / max
362 json min = item["min"];
363 if( min.is_number() )
364 {
365 minVal = min;
366 fprintf( stderr, " min: %lf\n", minVal );
367 }
368
369 json max = item["max"];
370 if( max.is_number() )
371 {
372 maxVal = max;
373 fprintf( stderr, " max: %lf\n", maxVal );
374 }
375
376 json prec = item["prec"];
377 if( prec.is_number() )
378 {
379 precVal = prec;
380 fprintf( stderr, " prec: %lf\n", precVal );
381 }
382
383 act = createAction( _number, cmd );
384
385 NumValue &num = act->num;
386 IUFillNumber( &num._val, act->uid, name.c_str(), "%.2f", minVal, maxVal, precVal, 0 );
387 IUFillNumberVector( &num._vec, &num._val, 1, getDeviceName( ), act->uid, name.c_str(), catName, IP_RW, 5, IPS_OK );
388
389 defineProperty( &num._vec );
390
391
392 json actions = item["actions"];
393 if( actions.is_array() )
394 {
395 fprintf( stderr, " actions:\n" );
396
397 uint32_t flags = 0;
398 for (json::iterator it = actions.begin(); it != actions.end(); ++it)
399 {
400
401 json value = (*it);
402 if( value.is_string() )
403 {
404 std::string n = value;
405 if( n == "STOP" )
406 {
407 flags |= ACTION_STOP;
408 fprintf( stderr, " stop\n" );
409 }
410 else if( n == "CALIB" )
411 {
412 flags |= ACTION_CALIB;
413 fprintf( stderr, " calib\n" );
414 }
415 }
416 }
417
418 if( flags )
419 {
420
421 act = createAction( _enum, cmd );
422 EnumValue &enm = act->enm;
423
424 ISwitch* sws = enm._vals;
425 unsigned nsw = 0;
426
427 if( flags & ACTION_STOP )
428 {
429 Action* sub_act = createAction( _ecmd, "" );
430 sub_act->cmd.cmd = "STOP";
431 sub_act->cmd.name = cmd;
432 sub_act->cmd.parent = act;
433 IUFillSwitch( &sws[nsw++], sub_act->uid, "STOP", ISS_OFF );
434 }
435
436 if( flags & ACTION_CALIB )
437 {
438 Action* sub_act = createAction( _ecmd, "" );
439 sub_act->cmd.cmd = "CALIB";
440 sub_act->cmd.name = cmd;
441 sub_act->cmd.parent = act;
442 IUFillSwitch( &sws[nsw++], sub_act->uid, "CALIB", ISS_OFF );
443 }
444
445 IUFillSwitchVector( &enm._vec, sws, nsw, getDeviceName( ), act->uid, " ", catName, IP_RW, ISR_ATMOST1, 60, IPS_IDLE );
446 defineProperty( &enm._vec );
447 }
448 }
449 }
450 else
451 {
452 LOGF_ERROR( "bad property type %s", type.c_str() );
453 }
454 }
455}
456
461void ShelyakDriver::__update( void* ptr )
462{
463 ((ShelyakDriver*)ptr)->update( );
464}
465
467{
468
469 if ( isConnected( ) )
470 {
471 //fprintf( stderr, "updating --------------------------------------\n" );
472
473 for( auto it = _actions.cbegin(); it != _actions.cend(); ++it )
474 {
475
476 Action* p = (*it);
477 if( !(p->type & 0x10) )
478 {
479 continue;
480 }
481
482 //fprintf( stderr, "test: %s\n", p->name );
483
484 UsisResponse rsp;
485 if( sendCmd( &rsp, "GET;%s;VALUE", p->name.c_str() ) )
486 {
487
488 if ( p->type == _text )
489 {
490 p->text._vec.s = strcmp( rsp.parts[3], "BUSY") == 0 ? IPS_BUSY : IPS_OK;
491
492 p->text._vec.tp->text = rsp.parts[4];
493 IDSetText( &p->text._vec, NULL );
494 }
495 else if( p->type == _enum )
496 {
497 p->enm._vec.s = strcmp( rsp.parts[3], "BUSY") == 0 ? IPS_BUSY : IPS_OK;
498
499 ISwitch* values = p->enm._vals;
500 for( int i = 0; i < p->enm._vec.nsp; i++ )
501 {
502 values[i].s = ISS_OFF;
503 }
504
505 for( auto it2 = _actions.cbegin(); it2 != _actions.cend(); ++it2 )
506 {
507 Action* c = (*it2);
508 if( c->type == _eitm && c->itm.parent == p && c->itm.val == rsp.parts[4] )
509 {
510 values[c->itm.index].s = ISS_ON;
511 IDSetSwitch( &p->enm._vec, NULL );
512 break;
513 }
514 }
515 }
516 else if ( p->type == _number )
517 {
518 p->num._vec.s = strcmp( rsp.parts[3], "BUSY") == 0 ? IPS_BUSY : IPS_OK;
519
520 double value = _atof( rsp.parts[4] );
521 p->num._vec.np->value = value;
522 IDSetNumber( &p->num._vec, NULL );
523 }
524 }
525 }
526
527 IEAddTimer( 1000, __update, this );
528 }
529}
530
531
532
533
534// :: SERIAL ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
535
536
537bool ShelyakDriver::sendCmd( UsisResponse* rsp, const char* text, ... )
538{
539 va_list lst;
540 va_start( lst, text );
541
542 bool rc = _send( text, lst ) && _receive( rsp );
543
544 va_end( lst );
545 return rc;
546}
547
548bool ShelyakDriver::_send( const char* text, va_list lst )
549{
550 char buf[MAX_FRAME_LENGTH + 1];
551 vsnprintf( buf, MAX_FRAME_LENGTH, text, lst );
552
553 //fprintf( stderr, "> sending %s\n", buf );
554 //LOGF_INFO("> sending %s", buf );
555
556 strcat( buf, "\n" );
557
558 int rc, nbytes_written;
559 if ( ( rc = tty_write( _serialPort, buf, strlen( buf ),
560 &nbytes_written ) ) != TTY_OK ) // send the bytes to the spectrograph
561 {
562 char errmsg[MAXRBUF];
563 tty_error_msg( rc, errmsg, MAXRBUF );
564 LOGF_ERROR("> sending %s", buf );
565 LOGF_ERROR( "error: %s.", errmsg );
566 return false;
567 }
568
569 return true;
570}
571
572bool ShelyakDriver::_receive( UsisResponse* rsp )
573{
574 int rc, nread;
575 if ( ( rc = tty_nread_section( _serialPort, rsp->buffer, sizeof( rsp->buffer ), '\n', 100,
576 &nread ) ) != TTY_OK ) // send the bytes to the spectrograph
577 {
578 char errmsg[MAXRBUF];
579 tty_error_msg( rc, errmsg, MAXRBUF );
580 LOGF_ERROR( "error: %s.", errmsg );
581 return false;
582 }
583
584 rsp->buffer[nread] = 0;
585
586 fprintf( stderr, "< received %s\n", rsp->buffer );
587 //LOGF_INFO("< received %s", rsp->buffer );
588
589 char* p = rsp->buffer;
590 char* e = p + nread;
591
592 // trim '\n' & ' '
593 while ( e >= p && ( e[-1] == '\n' || e[-1] == ' ' ) )
594 {
595 e--;
596 *e = 0;
597 }
598
599 rsp->pcount = 0;
600 rsp->parts[rsp->pcount++] = p;
601
602 while ( p < e && rsp->pcount < 5 )
603 {
604 if ( *p == ';' )
605 {
606 *p = 0;
607 rsp->parts[rsp->pcount++] = p + 1;
608 }
609
610 p++;
611 }
612
613 if ( strcmp( rsp->parts[0], "M00" ) != 0 )
614 {
615 LOGF_ERROR( "response error: %s", rsp->parts[1] );
616 return false;
617 }
618
619 return true;
620}
621
622
623// :: PROPERTIES ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
624
625
626bool ShelyakDriver::updateProperties( )
627{
629 if ( isConnected( ) )
630 {
631 //fprintf( stderr, "update request --------------------------------------\n" );
632 scanProperties( );
633 update( );
634 }
635 else
636 {
637 clearProperties( );
638 }
639
640 return true;
641}
642
643void ShelyakDriver::clearProperties( )
644{
645 //fprintf( stderr, "clear properties --------------------------------------\n" );
646 for( auto it = _actions.cbegin(); it != _actions.cend(); ++it )
647 {
648 Action* p = *it;
649 deleteProperty( p->uid );
650 }
651
652 _actions.clear();
653}
654
659bool ShelyakDriver::ISNewSwitch( const char* dev, const char* name, ISState* states, char* names[], int n )
660{
661 if ( dev && strcmp( dev, getDeviceName( ) ) == 0 )
662 {
663
664 for( auto it = _actions.cbegin(); it != _actions.cend(); ++it )
665 {
666 Action* p = *it;
667
668 if( p->type == _eitm && strcmp( p->uid, names[0] ) == 0 )
669 {
670 UsisResponse rsp;
671 sendCmd( &rsp, "SET;%s;VALUE;%s", p->name.c_str(), p->itm.val.c_str() );
672 return true;
673 }
674 else if( p->type == _ecmd && strcmp( p->uid, names[0] ) == 0 )
675 {
676 UsisResponse rsp;
677 sendCmd( &rsp, "%s;%s;", p->cmd.cmd.c_str(), p->cmd.name.c_str() );
678
679 EnumValue &enm = p->cmd.parent->enm;
680 IUResetSwitch( &enm._vec );
681 enm._vec.s = IPS_IDLE;
682 IDSetSwitch(&enm._vec, nullptr);
683 return true;
684 }
685 }
686 }
687
688 return INDI::DefaultDevice::ISNewSwitch( dev, name, states, names, n ); // send it to the parent classes
689}
690
695bool ShelyakDriver::ISNewText( const char* dev, const char* name, char* texts[], char* names[], int n )
696{
697 if ( dev && strcmp( dev, getDeviceName( ) ) == 0 )
698 {
699 for( auto it = _actions.cbegin(); it != _actions.cend(); ++it )
700 {
701 Action* p = *it;
702 if ( p->type == _text && strcmp( p->uid, names[0] ) == 0 )
703 {
704 UsisResponse rsp;
705 sendCmd( &rsp, "SET;%s;VALUE;%s", p->name.c_str(), texts[0] );
706 return true;
707 }
708 }
709 }
710
711 return INDI::DefaultDevice::ISNewText( dev, name, texts, names, n );
712}
713
718bool ShelyakDriver::ISNewNumber( const char* dev, const char* name, double values[], char* names[], int n )
719{
720 if ( dev && strcmp( dev, getDeviceName( ) ) == 0 && n == 1 )
721 {
722
723 for( auto it = _actions.cbegin(); it != _actions.cend(); ++it )
724 {
725 Action* p = *it;
726 if ( p->type == _number && strcmp( p->uid, names[0] ) == 0 )
727 {
728 UsisResponse rsp;
729 sendCmd( &rsp, "SET;%s;VALUE;%lf", p->name.c_str(), values[0] );
730 return true;
731 }
732 }
733 }
734
735 return INDI::DefaultDevice::ISNewNumber( dev, name, values, names, n );
736}
737
738
739
hid_device * device
TextValue text
EnumItem itm
char uid[8]
std::string name
NumValue num
EnumValue enm
PropType type
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
virtual const char * port()
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
bool isConnected() const
static std::string getSharedFilePath(std::string fileName)
const char * getDeviceName() const
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
const char * getDefaultName() override
static void __update(void *ptr)
bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
a class to store JSON values
iterator begin() noexcept
returns an iterator to the first element
constexpr bool is_object() const noexcept
return whether value is an object
iterator end() noexcept
returns an iterator to one past the last element
constexpr bool is_string() const noexcept
return whether value is a string
constexpr bool is_array() const noexcept
return whether value is an array
constexpr bool is_number() const noexcept
return whether value is a number
general exception of the basic_json class
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition eventloop.c:586
double max(void)
#define min(a, b)
double _atof(const char *in)
#define SHELYAK_USIS_VERSION_MINOR
#define ACTION_CALIB
@ _number
@ _eitm
@ _ecmd
@ _text
@ _enum
#define ACTION_STOP
#define MAX_FRAME_LENGTH
#define MAX_ENUMS
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_ATMOST1
Definition indiapi.h:172
int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
Establishes a tty connection to a terminal device.
Definition indicom.c:1022
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
int tty_disconnect(int fd)
Closes a tty connection and flushes the bus.
Definition indicom.c:1224
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:759
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:490
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:509
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition indidevapi.c:376
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition indidevapi.c:416
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition indidevapi.c:398
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:453
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#define MAXRBUF
Definition indidriver.c:52
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
uint16_t type
Definition pwc-ioctl.h:0
uint8_t cmd[4]
Definition pwc-ioctl.h:2
#define SHELYAK_USIS_VERSION_MAJOR
Action * parent
std::string cmd
std::string name
Action * parent
std::string val
ISwitchVectorProperty _vec
ISwitch _vals[MAX_ENUMS]
One switch descriptor.
INumberVectorProperty _vec
ITextVectorProperty _vec
char buffer[MAX_FRAME_LENGTH]
double value
Definition indiapi.h:288
char * text
Definition indiapi.h:230