Instrument Neutral Distributed Interface INDI  2.0.2
activefocuser.cpp
Go to the documentation of this file.
1 /*
2  ActiveFocuser driver for Takahashi CCA-250 and Mewlon-250/300CRS
3 
4  Driver written by Alvin FREY <https://afrey.fr> for Optique Unterlinden and Takahashi Europe
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 
20 */
21 
22 
23 #include "activefocuser.h"
24 #include "activefocuser_utils.h"
25 
26 static std::unique_ptr<ActiveFocuser> activeFocuser(new ActiveFocuser());
27 
28 #define DRIVER_NAME "ActiveFocuser"
29 #define DRIVER_VERSION_MAJOR 1
30 #define DRIVER_VERSION_MINOR 0
31 
32 #define VENDOR_ID 0x20E1
33 #define PRODUCT_ID 0x0002
34 
35 int MAX_TICKS = 192307;
36 
38 {
39 
40  hid_handle = nullptr;
43 
44 }
45 
47 {
48 
49  if (hid_handle)
50  {
51 
53  if(poller->IsRunning)
54  {
55  poller->Stop() ;
56  }
57 
58  hid_close(hid_handle);
59 
60  }
61 
62  hid_exit();
63 
64 }
65 
67 {
68 
69  if (!hid_handle)
70  {
71 
72  hid_handle = hid_open(VENDOR_ID, PRODUCT_ID, nullptr);
73 
74  if (hid_handle)
75  {
76 
77  hid_set_nonblocking(hid_handle, 1);
78 
80  if (!poller->IsRunning)
81  {
82  poller->Start();
83  }
84 
85  return true;
86 
87  }
88  else
89  {
90 
91  return false;
92 
93  }
94 
95  }
96 
97  return hid_handle != nullptr;
98 
99 }
100 
102 {
103 
104  if (hid_handle)
105  {
106 
108  if (poller->IsRunning)
109  {
110  poller->Stop();
111  }
112 
113  hid_close(hid_handle);
114 
115  }
116 
117  hid_handle = nullptr;
118 
119  return true;
120 
121 
122 }
123 
125 {
126 
127  return DRIVER_NAME;
128 
129 }
130 
131 void ActiveFocuser::ISGetProperties(const char *dev)
132 {
133 
134  if (dev != nullptr && strcmp(dev, getDeviceName()) != 0)
135  return;
136 
138 
139 }
140 
142 {
143 
145 
147 
148  // Adding version display
149 
150  IUFillText(&HardwareVersionN[0], "Version infos", "", "1.04");
151  IUFillTextVector(&HardwareVersionNP, HardwareVersionN, 1, getDeviceName(), "HARDWARE_VERSION", "Hardware Version",
153 
154  std::stringstream softwareVersionStream;
155  softwareVersionStream << DRIVER_VERSION_MAJOR << "." << DRIVER_VERSION_MINOR;
156 
157  IUFillText(&SoftwareVersionN[0], "Version infos", "", softwareVersionStream.str().c_str());
158  IUFillTextVector(&SoftwareVersionNP, SoftwareVersionN, 1, getDeviceName(), "SOFTWARE_VERSION", "Software Version",
160 
161  // Adding temperature sensor display
162 
163  IUFillNumber(&AirTemperatureN[0], "AIR TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
164  IUFillNumberVector(&AirTemperatureNP, AirTemperatureN, 1, getDeviceName(), "AIR_TEMPERATURE", "Air Temperature",
166 
167  IUFillNumber(&TubeTemperatureN[0], "TUBE TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
168  IUFillNumberVector(&TubeTemperatureNP, TubeTemperatureN, 1, getDeviceName(), "TUBE_TEMPERATURE", "Tube Temperature",
170 
171  IUFillNumber(&MirrorTemperatureN[0], "MIRROR TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
172  IUFillNumberVector(&MirrorTemperatureNP, MirrorTemperatureN, 1, getDeviceName(), "MIRROR_TEMPERATURE",
173  "Mirror Temperature",
175 
176  // Adding FAN control button
177 
178  IUFillSwitch(&FanS[0], "FAN_ON", "On", ISS_ON);
179  IUFillSwitch(&FanS[1], "FAN_OFF", "Off", ISS_OFF);
180  IUFillSwitchVector(&FanSP, FanS, 2, getDeviceName(), "FAN_STATE", "Fan", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 60,
181  IPS_IDLE);
182 
183  // Setting focus max position constant
184 
185  FocusMaxPosN[0].value = MAX_TICKS;
187  strncpy(FocusMaxPosN[0].label, "Steps", MAXINDILABEL);
188 
189  // Disabling focuser speed
190 
191  FocusSpeedN[0].min = 0;
192  FocusSpeedN[0].max = 0;
193  FocusSpeedN[0].value = 1;
195 
196  // Setting default absolute position values
197 
198  FocusAbsPosN[0].min = 0.;
199  FocusAbsPosN[0].max = MAX_TICKS;
200  FocusAbsPosN[0].value = 0;
201  FocusAbsPosN[0].step = 1000.;
202  strncpy(FocusAbsPosN[0].label, "Steps", MAXINDILABEL);
203 
204 
205  // Setting default relative position values
206 
207  FocusRelPosN[0].min = 0.;
208  FocusRelPosN[0].max = 5000;
209  FocusRelPosN[0].value = 100;
210  FocusRelPosN[0].step = 1;
211  strncpy(FocusRelPosN[0].label, "Steps", MAXINDILABEL);
212 
213  PresetN[0].max = MAX_TICKS;
214  PresetN[1].max = MAX_TICKS;
215  PresetN[2].max = MAX_TICKS;
216 
217  internalTicks = FocusAbsPosN[0].value;
218 
220 
222 
223  return true;
224 
225 }
226 
228 {
229 
231 
232  if (hid_handle)
233  {
234 
235  defineProperty(&HardwareVersionNP);
236  defineProperty(&SoftwareVersionNP);
237  defineProperty(&AirTemperatureNP);
238  defineProperty(&TubeTemperatureNP);
239  defineProperty(&MirrorTemperatureNP);
240  defineProperty(&FanSP);
241 
242  }
243  else
244  {
245 
246  deleteProperty(HardwareVersionNP.name);
247  deleteProperty(SoftwareVersionNP.name);
248  deleteProperty(AirTemperatureNP.name);
249  deleteProperty(TubeTemperatureNP.name);
250  deleteProperty(MirrorTemperatureNP.name);
251  deleteProperty(FanSP.name);
252 
253  }
254 
255  return true;
256 
257 }
258 
259 bool ActiveFocuser::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
260 {
261 
262  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
263  {
264 
265  if (strcmp(FanSP.name, name) == 0)
266  {
267 
268  IUUpdateSwitch(&FanSP, states, names, n);
269 
271  {
272 
273  if (hid_handle)
274  {
275 
276  const unsigned char data[3] = {0x01,
278  };
279  hid_write(hid_handle, data, sizeof(data));
280 
281  }
282  else
283  {
284 
285  IDLog("Connection failed");
286 
287  }
288 
289  }
290  else if (FanS[0].s == ISS_OFF && ActiveFocuserUtils::SystemState::GetIsFanOn())
291  {
292 
293  if (hid_handle)
294  {
295 
296  const unsigned char data[3] = {0x01,
298  };
299  hid_write(hid_handle, data, sizeof(data));
300 
301  }
302  else
303  {
304 
305  IDLog("Connection failed");
306 
307  }
308 
309  }
310 
311  FanSP.s = IPS_OK;
312  IDSetSwitch(&FanSP, nullptr);
313 
314  return true;
315 
316  }
317 
318 
319  }
320 
321  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
322 
323 }
324 
325 bool ActiveFocuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
326 {
327 
328  if(dev != nullptr && strcmp(dev, getDeviceName()) == 0)
329  {
330  }
331 
332  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
333 
334 }
335 
337 {
338 
339  if (hid_handle)
340  {
341 
343  {
344 
345  const unsigned char data[3] = {0x01, ActiveFocuserUtils::CommandsMap.at(ActiveFocuserUtils::STOP)}; // STOP
346  hid_write(hid_handle, data, sizeof(data));
347 
348  return true;
349 
350  }
351  else
352  {
353 
354  return false;
355 
356  }
357 
358  }
359  else
360  {
361 
362  IDLog("Connection failed");
363 
364  return false;
365 
366  }
367 
368 }
369 
371 {
372 
373  internalTicks = targetTicks;
374 
375  if (targetTicks > (uint32_t)MAX_TICKS)
376  {
377 
378  return IPS_ALERT;
379 
380  }
381  else
382  {
383 
385  {
386 
387  if(hid_handle)
388  {
389 
390  unsigned char data[8] = {0x00, 0x05, ActiveFocuserUtils::CommandsMap.at(ActiveFocuserUtils::MOVE), 0x00, 0x00, 0x00, 0x00, 0x00};
391 
392  for (int i = 0; i < 4; ++i)
393  {
394  auto num = (targetTicks >> 8 * (3 - i) & 255);
395  data[3 + i] = num;
396  }
397 
398  hid_write(hid_handle, data, sizeof(data));
399 
400  return IPS_OK;
401 
402  }
403  else
404  {
405 
406  return IPS_ALERT;
407 
408  }
409 
410  }
411  else
412  {
413 
414  return IPS_BUSY;
415 
416  }
417 
418  }
419 
420 }
421 
423 {
424 
425  FocusRelPosN[0].value = ticks;
426  IDSetNumber(&FocusRelPosNP, nullptr);
427 
428  int relativeTicks = ((dir == FOCUS_INWARD ? ticks : -ticks));
429 
430  double newTicks = internalTicks + relativeTicks;
431 
432  return MoveAbsFocuser(newTicks);
433 
434 }
435 
437 {
438 
439  if(!hid_handle)
440  {
441 
443 
444  }
445  else
446  {
447 
449  FocusMaxPosN[0].value = MAX_TICKS;
450  IDSetNumber(&FocusMaxPosNP, nullptr);
451 
452  PresetN[0].max = MAX_TICKS;
453  PresetN[1].max = MAX_TICKS;
454  PresetN[2].max = MAX_TICKS;
455 
456  HardwareVersionN[0].text = ActiveFocuserUtils::SystemState::GetHardwareRevision();
457  IDSetText(&HardwareVersionNP, nullptr);
458 
460  IDSetNumber(&FocusAbsPosNP, nullptr);
461 
462  internalTicks = FocusAbsPosN[0].value;
463 
464  AirTemperatureN[0].value = ActiveFocuserUtils::SystemState::GetAirTemperature();
465  IDSetNumber(&AirTemperatureNP, nullptr);
466  TubeTemperatureN[0].value = ActiveFocuserUtils::SystemState::GetTubeTemperature();
467  IDSetNumber(&TubeTemperatureNP, nullptr);
468  MirrorTemperatureN[0].value = ActiveFocuserUtils::SystemState::GetMirrorTemperature();
469  IDSetNumber(&MirrorTemperatureNP, nullptr);
470 
472  {
473  FanS[0].s = ISS_ON;
474  IDSetSwitch(&FanSP, nullptr);
475  }
476  else
477  {
478  FanS[0].s = ISS_OFF;
479  IDSetSwitch(&FanSP, nullptr);
480  }
481 
483  {
486  }
487  else
488  {
491  }
492 
494 
495  }
496 
497 }
int MAX_TICKS
#define DRIVER_NAME
#define DRIVER_VERSION_MINOR
#define VENDOR_ID
#define PRODUCT_ID
#define DRIVER_VERSION_MAJOR
static Poller * GetInstance(hid_device &hid_handle)
static const std::map< Commands, unsigned char > CommandsMap
IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
bool Disconnect() override
Disconnect from device.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
bool AbortFocuser() override
AbortFocuser all focus motion.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
const char * getDefaultName() override
const char * getDeviceName() const
Definition: basedevice.cpp:821
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INumberVectorProperty FocusSpeedNP
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INumberVectorProperty FocusMaxPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: indifocuser.cpp:95
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
INumber PresetN[3]
Definition: indifocuser.h:107
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:42
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
void setSupportedConnections(const uint8_t &value)
setConnection Set Focuser connection mode. Child class should call this in the constructor before Foc...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number.
Definition: hid_libusb.c:612
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
Write an Output report to a HID device.
Definition: hid_libusb.c:929
void HID_API_EXPORT hid_close(hid_device *dev)
Close a HID device.
Definition: hid_libusb.c:1163
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
Set the device handle to be non-blocking.
Definition: hid_libusb.c:1100
int HID_API_EXPORT hid_exit(void)
Finalize the HIDAPI library.
Definition: hid_libusb.c:407
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
#define MAXINDILABEL
Definition: indiapi.h:192
@ ISR_1OFMANY
Definition: indiapi.h:173
void IDLog(const char *fmt,...)
Definition: indicom.c:316
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:272
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:291
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:158
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:198
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:180
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:235
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
Definition: indidriver.c:1296
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250