File: tutorial_one.c

package info (click to toggle)
libindi 0.9.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,232 kB
  • sloc: ansic: 17,921; cpp: 17,821; xml: 260; makefile: 12
file content (194 lines) | stat: -rw-r--r-- 7,577 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
   INDI Developers Manual
   Tutorial #1
   
   "Hello INDI"
   
   We construct a most basic (and useless) device driver to illustate INDI.
   
   Refer to README, which contains instruction on how to build this driver, and use it 
   with an INDI-compatible client.

*/

/** \file tutorial_one.c
    \brief Construct a basic INDI driver with only one property.
    \author Jasem Mutlaq
*/

/* Standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>

/* INDI Core headers */

/* indidevapi.h contains API declerations */
#include "indidevapi.h"

/* INDI Eventloop mechanism */
#include "eventloop.h"

/* INDI Common Routines */
#include "indicom.h"

/* Definitions */

#define mydev		"Simple Device"				/* Device name */
#define MAIN_GROUP	"Main Control"				/* Group name */

/* Function protptypes */
void connectDevice(void);

/*INDI controls */

/* We will define only one vector switch property. The CONNECTION property is an INDI Standard Property and should be implemented in all INDI drivers.
 * A vector property may have one or more members. */

/* First, we define and initilize the members of the vector property */
static ISwitch PowerS[]          	= {
							  {"CONNECT"			/* 1st Swtich name */
							  , "Connect" 			/* Switch Label, i.e. what the GUI displays */
							  , ISS_OFF 			/* State of the switch, initially off */
						          , 0					/* auxiluary, set to 0 for now.*/
						          , 0}					/* auxiluary, set to 0 for now */
							 
						         ,{"DISCONNECT"		/* 2nd Swtich name */
						         , "Disconnect"			/* Switch Label, i.e. what the GUI displays */
						         , ISS_ON				/* State of the switch, initially on */
						         , 0					/* auxiluary, set to 0 for now.*/
						         , 0}					/* auxiluary, set to 0 for now */
						     };
						     
/* Next, we define and initlize the vector switch property that contains the two switches we defined above */
static ISwitchVectorProperty PowerSP    = { 
								mydev			/* Device name */
								, "CONNECTION"  	/* Property name */
								, "Connection"		/* Property label */
								, MAIN_GROUP	/* Property group */
								, IP_RW			/* Property premission, it's both read and write */
								, ISR_1OFMANY	/* Switch behavior. Only 1 of many switches are allowed to be on at the same time */
								, 0				/* Timeout, 0 seconds */
								, IPS_IDLE		/* Initial state is idle */
								, PowerS			/* Switches comprimising this vector that we defined above */
								, NARRAY(PowerS)	/* Number of Switches. NARRAY is defined in indiapi.h */
								, ""				/* Timestamp, set to 0 */
								, 0};				/* auxiluary, set to 0 for now */


/* void ISGetProperties (const char *dev)
*  INDI will call this function when the client inquires about the device properties.
*  Here we will use IDxxx functions to define new properties to the client */
void ISGetProperties (const char *dev)
{ 
  /* Tell the client to create a new Switch property PowerSP */
  IDDefSwitch(&PowerSP, NULL); 
}
  
/* void ISNewSwitch(...)
 * INDI will call this function when the client wants to set a new state of existing switches 
 ** Parameters **
 
 * dev: the device name
 * name: the property name the client wants to update
 * states: an array of states of members switches (ISS_ON and ISS_OFF)
 * names: names of the switches. The names are parallel to the states. That is, member names[0] has a state states[0], and so on...
 * n: number of switches to update, which is also the dimension of *states and names[]
*/
void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
{
      /* Let's check if the property the client wants to change is the PowerSP (name: CONNECTION) property*/
     if (!strcmp (name, PowerSP.name))
     {
          /* If the clients wants to update this property, let's perform the following */
	  
	  /* A. We update the switches by sending their names and updated states IUUpdateSwitches function. If there is an error, we return */
	  if (IUUpdateSwitch(&PowerSP, states, names, n) < 0) return;
	  
	  /* B. We try to establish a connection to our device */
   	  connectDevice();
	  return;
     }
}

/* void ISNewText(...)
 * INDI will call this function when the client wants to update an existing text.
 ** Parameters **
 
 * dev: the device name
 * name: the property name the client wants to update
 * texts: an array of texts.
 * names: names of the members. The names are parallel to the texts.
 * n: number of texts to update, which is also the dimension of *texts and names[]
*/
void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
{
        /* Even though we didn't define any text members, we need to define this function. Otherwise, the driver will not compile */
	/* Since there is nothing to do, we simply return */
	return;	
}

/* void ISNewNumber(...)
 * INDI will call this function when the client wants to update an existing number.
 ** Parameters **
 
 * dev: the device name
 * name: the property name the client wants to update
 * values: an array of values.
 * names: names of the members. The names are parallel to the values.
 * n: number of numbers to update, which is the dimension of *numbers and names[]
*/
void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
{
         /* Even though we didn't define any number members, we need to define this function. Otherwise, the driver will not compile */
	/* Since there is nothing to do, we simply return */
        return;
}

/* Note that we must define ISNewBLOB and ISSnoopDevice even if we don't use them, otherwise, the driver will NOT compile */
void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) {}
void ISSnoopDevice (XMLEle *root) {}


/* void connectDevice(void)
 * This function is called when the state of PowerSP is changed in the ISNewSwitch() function.
 * We check the state of CONNECT and DISCONNECT switches, and connect or disconnect our fake device accordingly */
void connectDevice(void)
{

  /* Now we check the state of CONNECT, the 1st member of the PowerSP property we defined earliar */
  switch (PowerS[0].s)
  {
     /* If CONNECT is on, then try to establish a connection to the device */
     case ISS_ON:
      
      /* The IDLog function is a very useful function that will log time-stamped messages to stderr. This function is invaluable to debug your drivers.
       * It operates like printf */
     IDLog ("Establishing a connection to %s...\n", mydev);

      /* Change the state of the PowerSP (CONNECTION) property to OK */
      PowerSP.s = IPS_OK;
      
      /* Tell the client to update the states of the PowerSP property, and send a message to inform successful connection */
      IDSetSwitch(&PowerSP, "Connection to %s is successful.", mydev);
      break;
      
    /* If CONNECT is off (which is the same thing as DISCONNECT being on), then try to disconnect the device */
    case ISS_OFF:
    
       IDLog ("Terminating connection to %s...\n", mydev);
       
      /* The device is disconnected, change the state to IDLE */
      PowerSP.s = IPS_IDLE;
      
      /* Tell the client to update the states of the PowerSP property, and send a message to inform successful disconnection */
      IDSetSwitch(&PowerSP, "%s has been disconneced.", mydev);
      
      break;
     }
     
}

/* That's it! check out tutorial_two where we simulate a simple telescope! */