Instrument Neutral Distributed Interface INDI  1.7.6
indifilterinterface.cpp
Go to the documentation of this file.
1 /*
2  Filter Interface
3  Copyright (C) 2011 Jasem Mutlaq (mutlaqja@ikarustech.com)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
21 #include "indifilterinterface.h"
22 #include <cstring>
23 #include "indilogger.h"
24 
25 namespace INDI
26 {
27 
28 FilterInterface::FilterInterface(DefaultDevice *defaultDevice) : m_defaultDevice(defaultDevice)
29 {
31  FilterNameT = nullptr;
32 }
33 
35 {
36  delete FilterNameTP;
37 }
38 
39 void FilterInterface::initProperties(const char *groupName)
40 {
41  IUFillNumber(&FilterSlotN[0], "FILTER_SLOT_VALUE", "Filter", "%3.0f", 1.0, 12.0, 1.0, 1.0);
42  IUFillNumberVector(&FilterSlotNP, FilterSlotN, 1, m_defaultDevice->getDeviceName(), "FILTER_SLOT", "Filter Slot", groupName, IP_RW, 60,
43  IPS_IDLE);
44 
45  loadFilterNames();
46 }
47 
49 {
51  {
52  // Define the Filter Slot and name properties
54  if (FilterNameT == nullptr)
55  {
56  if (GetFilterNames() == true)
58  }
59  else
61  }
62  else
63  {
66  }
67 
68  return true;
69 }
70 
71 bool FilterInterface::processNumber(const char *dev, const char *name, double values[], char *names[], int n)
72 {
73  INDI_UNUSED(n);
74 
75  if (dev && !strcmp(dev, m_defaultDevice->getDeviceName()) && !strcmp(name, FilterSlotNP.name))
76  {
77  TargetFilter = values[0];
78 
79  INumber *np = IUFindNumber(&FilterSlotNP, names[0]);
80 
81  if (!np)
82  {
84  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_ERROR, "Unknown error. %s is not a member of %s property.", names[0], FilterSlotNP.name);
85  IDSetNumber(&FilterSlotNP, nullptr);
86  return false;
87  }
88 
90  {
92  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_ERROR, "Error: valid range of filter is from %g to %g", FilterSlotN[0].min, FilterSlotN[0].max);
93  IDSetNumber(&FilterSlotNP, nullptr);
94  return false;
95  }
96 
98  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_SESSION, "Setting current filter to slot %d", TargetFilter);
99 
100  if (SelectFilter(TargetFilter) == false)
101  {
103  }
104 
105  IDSetNumber(&FilterSlotNP, nullptr);
106  return true;
107  }
108 
109  return false;
110 }
111 
112 bool FilterInterface::processText(const char *dev, const char *name, char *texts[], char *names[], int n)
113 {
114  if (dev && !strcmp(dev, m_defaultDevice->getDeviceName()) && !strcmp(name, "FILTER_NAME"))
115  {
116  // If this call due to config loading, let's delete existing dummy property and define the full one
117  if (loadingFromConfig)
118  {
119  loadingFromConfig = false;
120  m_defaultDevice->deleteProperty("FILTER_NAME");
121 
122  char filterName[MAXINDINAME];
123  char filterLabel[MAXINDILABEL];
124 
125  if (FilterNameT != nullptr)
126  {
127  for (int i=0; i < FilterNameTP->ntp; i++)
128  free(FilterNameT[i].text);
129  delete [] FilterNameT;
130  }
131 
132  FilterNameT = new IText[n];
133  memset(FilterNameT, 0, sizeof(IText) * n);
134 
135  for (int i = 0; i < n; i++)
136  {
137  snprintf(filterName, MAXINDINAME, "FILTER_SLOT_NAME_%d", i + 1);
138  snprintf(filterLabel, MAXINDILABEL, "Filter#%d", i + 1);
139  IUFillText(&FilterNameT[i], filterName, filterLabel, texts[i]);
140  }
141 
144  return true;
145  }
146 
147  IUUpdateText(FilterNameTP, texts, names, n);
148  FilterNameTP->s = IPS_OK;
149 
150  if (SetFilterNames() == true)
151  {
152  IDSetText(FilterNameTP, nullptr);
153  return true;
154  }
155  else
156  {
158  DEBUGDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_ERROR, "Error updating names of filters.");
159  IDSetText(FilterNameTP, nullptr);
160  return false;
161  }
162  }
163 
164  return false;
165 }
166 
168 {
170  if (FilterNameTP)
172 
173  return true;
174 }
175 
177 {
178  // The hardware has finished changing
179  // filters
180  FilterSlotN[0].value = f;
182  // Tell the clients we are done, and
183  // filter is now useable
184  IDSetNumber(&FilterSlotNP, nullptr);
185 }
186 
188 {
189  char filterName[MAXINDINAME];
190  char filterLabel[MAXINDILABEL];
191  int MaxFilter = FilterSlotN[0].max;
192 
193  const char *filterDesignation[8] = { "Red", "Green", "Blue", "H_Alpha", "SII", "OIII", "LPR", "Luminance" };
194 
195  if (FilterNameT != nullptr)
196  {
197  for (int i=0; i < FilterNameTP->ntp; i++)
198  free(FilterNameT[i].text);
199  delete [] FilterNameT;
200  }
201 
202  FilterNameT = new IText[MaxFilter];
203  memset(FilterNameT, 0, sizeof(IText) * MaxFilter);
204 
205  for (int i = 0; i < MaxFilter; i++)
206  {
207  snprintf(filterName, MAXINDINAME, "FILTER_SLOT_NAME_%d", i + 1);
208  snprintf(filterLabel, MAXINDILABEL, "Filter#%d", i + 1);
209  IUFillText(&FilterNameT[i], filterName, filterLabel, i < 8 ? filterDesignation[i] : filterLabel);
210  }
211 
213 }
214 
216 {
217  // Load from config
218  if (FilterNameT == nullptr)
219  {
221 
222 // // JM 2018-07-09: Set loadingFromConfig to true here before calling loadConfig
223 // // since if loadConfig is successful, ISNewText could be executed _before_ we have a chance
224 // // to set loadFromConfig below
225 // loadingFromConfig = true;
226 
227 // // If property is found, let's define it once loaded to the client and delete
228 // // the generate sample filters above
229 // loadingFromConfig = m_defaultDevice->loadConfig(true, "FILTER_NAME");
230  }
231 
232  return true;
233 }
234 
236 {
237  return m_defaultDevice->saveConfig(true, "FILTER_NAME");
238 }
239 
240 bool FilterInterface::loadFilterNames()
241 {
242  if (FilterNameT != nullptr)
243  return true;
244 
245  char *rname, *rdev;
246  XMLEle *root = nullptr, *fproot = nullptr;
247  char filterName[MAXINDINAME] = {0};
248  char errmsg[MAXRBUF];
249  LilXML *lp = newLilXML();
250  int nelem=0;
251 
252  FILE *fp = IUGetConfigFP(nullptr, m_defaultDevice->getDefaultName(), "r", errmsg);
253 
254  if (fp == nullptr)
255  {
256  delLilXML(lp);
257  return false;
258  }
259 
260  fproot = readXMLFile(fp, lp, errmsg);
261 
262  if (fproot == nullptr)
263  {
264  delLilXML(lp);
265  fclose(fp);
266  return false;
267  }
268 
269  for (root = nextXMLEle(fproot, 1); root != nullptr; root = nextXMLEle(fproot, 0))
270  {
271  /* pull out device and name */
272  if (crackDN(root, &rdev, &rname, errmsg) < 0)
273  {
274  fclose(fp);
275  delXMLEle(fproot);
276  delLilXML(lp);
277  return false;
278  }
279 
280  // It doesn't belong to our device??
281  if (strcmp(m_defaultDevice->getDeviceName(), rdev))
282  continue;
283 
284  if (!strcmp("FILTER_NAME", rname))
285  {
286  nelem = nXMLEle(root);
287  FilterNameT = new IText[nelem];
288  memset(FilterNameT, 0, sizeof(IText) * nelem);
289 
290  XMLEle *oneText = nullptr;
291  uint8_t counter=0;
292 
293  for (oneText = nextXMLEle(root, 1); oneText != nullptr; oneText = nextXMLEle(root, 0))
294  {
295  const char *filter = pcdataXMLEle(oneText);
296  snprintf(filterName, MAXINDINAME, "FILTER_SLOT_NAME_%d", counter + 1);
297  IUFillText(&FilterNameT[counter], filterName, filter, filter);
298  counter++;
299  }
300 
301  break;
302  }
303  }
304 
306 
307  fclose(fp);
308  delXMLEle(fproot);
309  delLilXML(lp);
310 
311  return true;
312 }
313 }
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indidriver.c:1548
XMLEle * readXMLFile(FILE *fp, LilXML *lp, char ynot[])
Handy wrapper to read one xml file.
Definition: lilxml.c:622
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
void generateSampleFilters()
generateSampleFilters Generate sample 8-filter wheel and fill it sample filters
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process number properties.
#define MAXINDINAME
Definition: indiapi.h:183
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
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&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:549
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition: lilxml.c:575
void IDSetText(const ITextVectorProperty *t, const char *msg,...)
Tell client to update an existing text vector property.
Definition: indidriver.c:1934
void initProperties(const char *groupName)
Initilize filter wheel properties. It is recommended to call this function within initProperties() of...
#define DEBUGDEVICE(device, priority, msg)
Definition: indilogger.h:60
virtual bool GetFilterNames()
Obtains a list of filter names from the hardware and initializes the FilterNameTP property...
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:319
FILE * IUGetConfigFP(const char *filename, const char *dev, const char *mode, char errmsg[])
Open a configuration file for writing and return a configuration file FILE pointer.
Definition: indidriver.c:1461
One number descriptor.
Definition: indiapi.h:267
char group[MAXINDIGROUP]
Definition: indiapi.h:319
virtual bool SelectFilter(int position)=0
Select a new filter position.
INumberVectorProperty FilterSlotNP
double max(void)
#define MAXRBUF
Definition: indidriver.c:43
Definition: indiapi.h:178
const char * name
Definition: indiserver.c:115
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
Definition: lilxml.c:164
void IDSetNumber(const INumberVectorProperty *n, const char *msg,...)
Tell client to update an existing number vector property.
Definition: indidriver.c:1976
virtual bool SetFilterNames()
Set filter names as defined by the client for each filter position. The desired filter names are stor...
Namespace to encapsulate INDI client, drivers, and mediator classes. Developers can subclass the base...
ITextVectorProperty * FilterNameTP
char name[MAXINDINAME]
Definition: indiapi.h:315
virtual const char * getDefaultName()=0
bool saveConfigItems(FILE *fp)
saveConfigItems save Filter Names in config file
int nXMLEle(XMLEle *ep)
Return the number of nested XML elements in a parent XML element.
Definition: lilxml.c:599
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:445
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidriver.c:1529
int crackDN(XMLEle *root, char **dev, char **name, char msg[])
Extract dev and name attributes from an XML element.
Definition: indicom.c:1363
bool updateProperties()
updateProperties Defines or Delete proprties based on default device connection status ...
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&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:420
bool processText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process text properties.
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition: indicom.c:1399
One text descriptor.
Definition: indiapi.h:217
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
const char * getDeviceName()
void SelectFilterDone(int newpos)
The child class calls this function when the hardware successfully finished selecting a new filter wh...
double min
Definition: indiapi.h:276
char name[MAXINDINAME]
Definition: indiapi.h:242
void delLilXML(LilXML *lp)
Delete a lilxml parser.
Definition: lilxml.c:156
#define INDI_UNUSED(x)
Definition: indidevapi.h:801
Definition: lilxml.c:90
double max
Definition: indiapi.h:278
void defineText(ITextVectorProperty *tvp)
Define text vector to client & register it. Alternatively, IDDefText can be used but the property wil...
DefaultDevice * m_defaultDevice
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&#39;s auxiliary elements will be set to NULL...
Definition: indidriver.c:575
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition: lilxml.c:524
struct _ITextVectorProperty ITextVectorProperty
#define MAXINDILABEL
Definition: indiapi.h:184
double min(void)
LilXML * newLilXML()
Create a new lilxml parser.
Definition: lilxml.c:147
#define DEBUGFDEVICE(device, priority, msg,...)
Definition: indilogger.h:61
FilterInterface(DefaultDevice *defaultDevice)
FilterInterface Initiailize Filter Interface.
void defineNumber(INumberVectorProperty *nvp)
Define number vector to client & register it. Alternatively, IDDefNumber can be used but the property...
double value
Definition: indiapi.h:282