Instrument Neutral Distributed Interface INDI  1.9.2
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 }
INDI::FilterInterface::FilterSlotNP
INumberVectorProperty FilterSlotNP
Definition: indifilterinterface.h:121
newLilXML
LilXML * newLilXML()
Create a new lilxml parser.
Definition: lilxml.c:148
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
min
double min(void)
INDI::FilterInterface::FilterInterface
FilterInterface(DefaultDevice *defaultDevice)
FilterInterface Initiailize Filter Interface.
Definition: indifilterinterface.cpp:28
pcdataXMLEle
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition: lilxml.c:575
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
nextXMLEle
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition: lilxml.c:524
INumber
One number descriptor.
MAXINDINAME
#define MAXINDINAME
Definition: indiapi.h:190
IUFillNumber
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: indidriver.c:348
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
INDI::Logger::DBG_ERROR
@ DBG_ERROR
Definition: indilogger.h:192
IUFillTextVector
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: indidriver.c:477
nXMLEle
int nXMLEle(XMLEle *ep)
Return the number of nested XML elements in a parent XML element.
Definition: lilxml.c:599
INDI_UNUSED
#define INDI_UNUSED(x)
Definition: indidevapi.h:799
INDI::FilterInterface::processNumber
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process number properties.
Definition: indifilterinterface.cpp:71
_ITextVectorProperty::ntp
int ntp
Definition: indiapi.h:263
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
INDI::Logger::DBG_SESSION
@ DBG_SESSION
Definition: indilogger.h:194
INDI::DefaultDevice::getDefaultName
virtual const char * getDefaultName()=0
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1434
IUFillText
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: indidriver.c:369
INDI::FilterInterface::FilterSlotN
INumber FilterSlotN[1]
Definition: indifilterinterface.h:122
IUUpdateText
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:259
INDI::FilterInterface::GetFilterNames
virtual bool GetFilterNames()
Obtains a list of filter names from the hardware and initializes the FilterNameTP property....
Definition: indifilterinterface.cpp:215
INDI::FilterInterface::generateSampleFilters
void generateSampleFilters()
generateSampleFilters Generate sample 8-filter wheel and fill it sample filters
Definition: indifilterinterface.cpp:187
DEBUGDEVICE
#define DEBUGDEVICE(device, priority, msg)
Definition: indilogger.h:60
INDI::FilterInterface::updateProperties
bool updateProperties()
updateProperties Defines or Delete proprties based on default device connection status
Definition: indifilterinterface.cpp:48
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
max
double max(void)
indilogger.h
INDI::FilterInterface::SelectFilter
virtual bool SelectFilter(int position)=0
Select a new filter position.
delLilXML
void delLilXML(LilXML *lp)
Delete a lilxml parser.
Definition: lilxml.c:157
IUSaveConfigText
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indicom.c:1439
IText
One text descriptor.
IUFillNumberVector
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: indidriver.c:455
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
readXMLFile
XMLEle * readXMLFile(FILE *fp, LilXML *lp, char ynot[])
Handy wrapper to read one xml file.
Definition: lilxml.c:622
xml_ele_
Definition: lilxml.c:105
INDI::FilterInterface::SetFilterNames
virtual bool SetFilterNames()
Set filter names as defined by the client for each filter position. The desired filter names are stor...
Definition: indifilterinterface.cpp:235
INDI::FilterInterface::FilterNameTP
ITextVectorProperty * FilterNameTP
Definition: indifilterinterface.h:125
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
indifilterinterface.h
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
IUFindNumber
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition: indicom.c:1351
INDI::FilterInterface::loadingFromConfig
bool loadingFromConfig
Definition: indifilterinterface.h:130
ITextVectorProperty
struct _ITextVectorProperty ITextVectorProperty
INDI::FilterInterface::TargetFilter
int TargetFilter
Definition: indifilterinterface.h:129
INDI::FilterInterface::FilterNameT
IText * FilterNameT
Definition: indifilterinterface.h:126
DEBUGFDEVICE
#define DEBUGFDEVICE(device, priority, msg,...)
Definition: indilogger.h:61
INDI::FilterInterface::saveConfigItems
bool saveConfigItems(FILE *fp)
saveConfigItems save Filter Names in config file
Definition: indifilterinterface.cpp:167
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
INDI::FilterInterface::processText
bool processText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process text properties.
Definition: indifilterinterface.cpp:112
INDI::DefaultDevice::saveConfig
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
Definition: defaultdevice.cpp:221
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
IP_RW
@ IP_RW
Definition: indiapi.h:185
MAXINDILABEL
#define MAXINDILABEL
Definition: indiapi.h:191
INDI::FilterInterface::SelectFilterDone
void SelectFilterDone(int newpos)
The child class calls this function when the hardware successfully finished selecting a new filter wh...
Definition: indifilterinterface.cpp:176
LilXML_
Definition: lilxml.c:91
INDI::FilterInterface::~FilterInterface
~FilterInterface()
Definition: indifilterinterface.cpp:34
IUGetConfigFP
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:1555
_INumberVectorProperty::group
char group[MAXINDIGROUP]
Definition: indiapi.h:326
INDI::FilterInterface::initProperties
void initProperties(const char *groupName)
Initilize filter wheel properties. It is recommended to call this function within initProperties() of...
Definition: indifilterinterface.cpp:39
INDI::DefaultDevice
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
Definition: defaultdevice.h:118
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
delXMLEle
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
Definition: lilxml.c:165
INDI::FilterInterface::m_defaultDevice
DefaultDevice * m_defaultDevice
Definition: indifilterinterface.h:132
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
crackDN
int crackDN(XMLEle *root, char **dev, char **name, char msg[])
Extract dev and name attributes from an XML element.
Definition: indicom.c:1317