Instrument Neutral Distributed Interface INDI 2.2.5
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
26static std::unique_ptr<ActiveFocuser> activeFocuser(new ActiveFocuser());
27
28#define DRIVER_NAME "ActiveFocuser"
29#define DRIVER_VERSION_MAJOR 1
30#define DRIVER_VERSION_MINOR 1
31
32#define VENDOR_ID 0x20E1
33#define PRODUCT_ID 0x0002
34
35int MAX_TICKS = 192307;
36
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
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 HardwareVersionNP[0].fill("Version infos", "", "1.04");
151 HardwareVersionNP.fill(getDeviceName(), "HARDWARE_VERSION", "Hardware Version",
153
154 std::stringstream softwareVersionStream;
155 softwareVersionStream << DRIVER_VERSION_MAJOR << "." << DRIVER_VERSION_MINOR;
156
157 SoftwareVersionNP[0].fill("Version infos", "", softwareVersionStream.str().c_str());
158 SoftwareVersionNP.fill(getDeviceName(), "SOFTWARE_VERSION", "Software Version",
160
161 // Adding temperature sensor display
162
163 AirTemperatureNP[0].fill("AIR TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
164 AirTemperatureNP.fill(getDeviceName(), "AIR_TEMPERATURE", "Air Temperature",
166
167 TubeTemperatureNP[0].fill("TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
168 TubeTemperatureNP.fill(getDeviceName(), "FOCUS_TEMPERATURE", "Tube Temperature",
170
171 MirrorTemperatureNP[0].fill("MIRROR TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
172 MirrorTemperatureNP.fill(getDeviceName(), "MIRROR_TEMPERATURE",
173 "Mirror Temperature",
175
176 // Adding FAN control button
177
178 FanSP[FAN_ON].fill("FAN_ON", "On", ISS_ON);
179 FanSP[FAN_OFF].fill("FAN_OFF", "Off", ISS_OFF);
180 FanSP.fill(getDeviceName(), "FAN_STATE", "Fan", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 60,
181 IPS_IDLE);
182
183 // Setting focus max position constant
184
185 FocusMaxPosNP[0].setValue(MAX_TICKS);
187 strncpy(FocusMaxPosNP[0].label, "Steps", MAXINDILABEL);
188
189 // Disabling focuser speed
190
191 FocusSpeedNP[0].setMin(0);
192 FocusSpeedNP[0].setMax(0);
193 FocusSpeedNP[0].setValue(1);
195
196 // Setting default absolute position values
197
198 FocusAbsPosNP[0].setMin(0.);
199 FocusAbsPosNP[0].setMax(MAX_TICKS);
200 FocusAbsPosNP[0].setValue(0);
201 FocusAbsPosNP[0].setStep(1000.);
202 strncpy(FocusAbsPosNP[0].label, "Steps", MAXINDILABEL);
203
204
205 // Setting default relative position values
206
207 FocusRelPosNP[0].setMin(0.);
208 FocusRelPosNP[0].setMax(5000);
209 FocusRelPosNP[0].setValue(100);
210 FocusRelPosNP[0].setStep(1);
211 strncpy(FocusRelPosNP[0].label, "Steps", MAXINDILABEL);
212
213 PresetNP[0].setMax(MAX_TICKS);
214 PresetNP[1].setMax(MAX_TICKS);
215 PresetNP[2].setMax(MAX_TICKS);
216
217 internalTicks = FocusAbsPosNP[0].getValue();
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);
247 deleteProperty(SoftwareVersionNP);
248 deleteProperty(AirTemperatureNP);
249 deleteProperty(TubeTemperatureNP);
250 deleteProperty(MirrorTemperatureNP);
251 deleteProperty(FanSP);
252
253 }
254
255 return true;
256
257}
258
259bool 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 (FanSP.isNameMatch(name))
266 {
267
268 FanSP.update(states, names, n);
269
270 if (FanSP[FAN_ON].getState() == ISS_ON && !ActiveFocuserUtils::SystemState::GetIsFanOn())
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 (FanSP[FAN_ON].getState() == 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.setState(IPS_OK);
312 FanSP.apply();
313
314 return true;
315
316 }
317
318
319 }
320
321 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
322
323}
324
325bool 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 FocusRelPosNP[0].setValue(ticks);
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 FocusMaxPosNP[0].setValue(MAX_TICKS);
451
452 PresetNP[0].setMax(MAX_TICKS);
453 PresetNP[1].setMax(MAX_TICKS);
454 PresetNP[2].setMax(MAX_TICKS);
455
456 HardwareVersionNP[0].setText(ActiveFocuserUtils::SystemState::GetHardwareRevision());
457 HardwareVersionNP.apply();
458
461
462 internalTicks = FocusAbsPosNP[0].getValue();
463
464 AirTemperatureNP[0].setValue(ActiveFocuserUtils::SystemState::GetAirTemperature());
465 AirTemperatureNP.apply();
466 TubeTemperatureNP[0].setValue(ActiveFocuserUtils::SystemState::GetTubeTemperature());
467 TubeTemperatureNP.apply();
468 MirrorTemperatureNP[0].setValue(ActiveFocuserUtils::SystemState::GetMirrorTemperature());
469 MirrorTemperatureNP.apply();
470
472 {
473 FanSP[FAN_ON].setState(ISS_ON);
474 FanSP.apply(nullptr);
475 }
476 else
477 {
478 FanSP[FAN_ON].setState(ISS_OFF);
479 FanSP.apply(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
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
bool Disconnect() override
Disconnect from device.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
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
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
const char * getDefaultName() override
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.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSpeedNP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
INDI::PropertyNumber PresetNP
void setSupportedConnections(const uint8_t &value)
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool isNameMatch(const char *otherName) const
void setPermission(IPerm permission)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
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.
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
Set the device handle to be non-blocking.
int HID_API_EXPORT hid_exit(void)
Finalize the HIDAPI library.
Definition hid_libusb.c:407
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
@ IP_RO
Definition indiapi.h:182
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
#define MAXINDILABEL
Definition indiapi.h:190
@ ISR_1OFMANY
Definition indiapi.h:171
void IDLog(const char *fmt,...)
Definition indicom.c:305
#define getDeviceName