Instrument Neutral Distributed Interface INDI  1.9.2
hitecastrodcfocuser.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2016 Andy Kirkham. All rights reserved.
3 
4  HitecAstroDCFocuser Focuser
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
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  Library General Public License for more details.
14  .
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 *******************************************************************************/
20 
21 #include "hitecastrodcfocuser.h"
22 
23 #include <cstring>
24 #include <memory>
25 
26 #define HID_TIMEOUT 10000 /* 10s */
27 #define FUDGE_FACTOR_H 1000
28 #define FUDGE_FACTOR_L 885
29 
30 #define FOCUS_SETTINGS_TAB "Settings"
31 
32 static std::unique_ptr<HitecAstroDCFocuser> hitecastroDcFocuser(new HitecAstroDCFocuser());
33 
35 {
38  setVersion(0, 2);
39 }
40 
42 {
43  if (m_HIDHandle != nullptr)
44  {
45  hid_close(m_HIDHandle);
46  m_HIDHandle = nullptr;
47  }
48 }
49 
51 {
52  if (hid_init() != 0)
53  {
54  LOG_ERROR("hid_init() failed.");
55  }
56 
57  m_HIDHandle = hid_open(0x04D8, 0xFAC2, nullptr);
58 
59  if (m_HIDHandle == nullptr)
60  m_HIDHandle = hid_open(0x04D8, 0xF53A, nullptr);
61 
62  LOG_DEBUG(m_HIDHandle ? "HitecAstroDCFocuser opened." : "HitecAstroDCFocuser failed.");
63 
64  if (m_HIDHandle != nullptr)
65  {
66  LOG_INFO("Experimental driver. Report issues to https://github.com/A-j-K/hitecastrodcfocuser/issues");
68  return true;
69  }
70 
71  LOGF_ERROR("Failed to connect to focuser: %s", hid_error(m_HIDHandle));
72  return false;
73 }
74 
76 {
77  if (m_HIDHandle != nullptr)
78  {
79  hid_close(m_HIDHandle);
80  m_HIDHandle = nullptr;
81  }
82 
83  LOG_DEBUG("focuser is offline.");
84  return true;
85 }
86 
88 {
89  return "HitecAstro DC";
90 }
91 
93 {
95 
96  //IDMessage(getDeviceName(), "HitecAstroDCFocuser::initProperties()");
97 
99  //addSimulationControl();
100 
101  // IUFillNumber(&MaxPositionN[0], "Steps", "", "%.f", 0, 500000, 0., 10000);
102  // IUFillNumberVector(&MaxPositionNP, MaxPositionN, 1, getDeviceName(), "MAX_POSITION", "Max position",
103  // FOCUS_SETTINGS_TAB, IP_RW, 0, IPS_IDLE);
104 
105  IUFillNumber(&SlewSpeedN[0], "Steps/sec", "", "%.f", 1, 100, 0., 50);
106  IUFillNumberVector(&SlewSpeedNP, SlewSpeedN, 1, getDeviceName(), "SLEW_SPEED", "Slew speed", MAIN_CONTROL_TAB,
107  IP_RW, 0, IPS_IDLE);
108 
109  // IUFillSwitch(&ReverseDirectionS[0], "ENABLED", "Reverse direction", ISS_OFF);
110  // IUFillSwitchVector(&ReverseDirectionSP, ReverseDirectionS, 1, getDeviceName(), "REVERSE_DIRECTION",
111  // "Reverse direction", OPTIONS_TAB, IP_RW, ISR_NOFMANY, 0, IPS_IDLE);
112 
113  FocusSpeedN[0].value = 100.;
114  FocusSpeedN[0].min = 1.;
115  FocusSpeedN[0].max = 100.;
116  FocusSpeedN[0].value = 100.;
117 
118  FocusRelPosN[0].min = 1;
119  FocusRelPosN[0].max = 50000;
120  FocusRelPosN[0].step = 1000;
121  FocusRelPosN[0].value = 1000;
122 
124 
125  return true;
126 }
127 
129 {
131 
132  if (isConnected())
133  {
134  //defineProperty(&MaxPositionNP);
135  defineProperty(&SlewSpeedNP);
136  //defineProperty(&ReverseDirectionSP);
137  }
138  else
139  {
140  //deleteProperty(MaxPositionNP.name);
141  deleteProperty(SlewSpeedNP.name);
142  //deleteProperty(ReverseDirectionSP.name);
143  }
144 
145  return true;
146 }
147 
149 {
150  if (m_State == SLEWING && m_Duration > 0)
151  {
152  --m_Duration;
153  if (m_Duration == 0)
154  {
155  int rc;
156  unsigned char command[8] = {0};
157  m_State = IDLE;
158  memset(command, 0, 8);
159  command[0] = m_StopChar;
160  rc = hid_write(m_HIDHandle, command, 8);
161  if (rc < 0)
162  {
163  LOGF_DEBUG("::MoveFocuser() fail (%s)", hid_error(m_HIDHandle));
164  }
165  hid_read_timeout(m_HIDHandle, command, 8, 1000);
166  }
167  }
168  SetTimer(1);
169 }
170 
171 bool HitecAstroDCFocuser::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
172 {
173  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
174  {
175  // if (strcmp(name, MaxPositionNP.name) == 0)
176  // {
177  // IUUpdateNumber(&MaxPositionNP, values, names, n);
178  // MaxPositionNP.s = IPS_OK;
179  // IDSetNumber(&MaxPositionNP, nullptr);
180  // return true;
181  // }
182  if (strcmp(name, SlewSpeedNP.name) == 0)
183  {
184  if (values[0] > 100)
185  {
186  SlewSpeedNP.s = IPS_ALERT;
187  return false;
188  }
189  IUUpdateNumber(&SlewSpeedNP, values, names, n);
190  SlewSpeedNP.s = IPS_OK;
191  IDSetNumber(&SlewSpeedNP, nullptr);
192  return true;
193  }
194  }
195  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
196 }
197 
199 {
200  int rc, speed = (int)SlewSpeedN[0].value;
201  // int32_t iticks = ticks;
202  unsigned char command[8] = {0};
203  IPState rval;
204 
205  LOGF_DEBUG("::move() begin %d ticks at speed %d", ticks, speed);
206 
207  if (m_HIDHandle == nullptr)
208  {
209  LOG_DEBUG("::move() bad handle");
210  return IPS_ALERT;
211  }
212 
213  // FocusRelPosNP.s = IPS_BUSY;
214  // IDSetNumber(&FocusRelPosNP, nullptr);
215 
216  // JM 2017-03-16: iticks is not used, FIXME.
217  // if (dir == FOCUS_INWARD)
218  // {
219  // iticks = ticks * -1;
220  // }
221 
222  //if (ReverseDirectionS[0].s == ISS_ON)
224  {
225  dir = dir == FOCUS_INWARD ? FOCUS_OUTWARD : FOCUS_INWARD;
226  }
227 
228  if (speed > 100)
229  {
230  LOGF_DEBUG("::move() over speed %d, limiting to 100", ticks, speed);
231  speed = 100;
232  }
233 
234  ticks *= FUDGE_FACTOR_H;
235  ticks /= FUDGE_FACTOR_L;
236 
237  memset(command, 0, 8);
238  command[0] = dir == FOCUS_INWARD ? 0x50 : 0x52;
239  command[1] = (unsigned char)((ticks >> 8) & 0xFF);
240  command[2] = (unsigned char)(ticks & 0xFF);
241  command[3] = 0x03;
242  command[4] = (unsigned char)(speed & 0xFF);
243  command[5] = 0;
244  command[6] = 0;
245  command[7] = 0;
246 
247  LOGF_DEBUG("==> TX %2.2x %2.2x%2.2x %2.2x %2.2x %2.2x%2.2x%2.2x", command[0], command[1],
248  command[2], command[3], command[4], command[5], command[6], command[7]);
249 
250  rc = hid_write(m_HIDHandle, command, 8);
251  if (rc < 0)
252  {
253  LOGF_DEBUG("::MoveRelFocuser() fail (%s)", hid_error(m_HIDHandle));
254  return IPS_ALERT;
255  }
256 
257  //FocusRelPosNP.s = IPS_BUSY;
258 
259  memset(command, 0, 8);
260  hid_read_timeout(m_HIDHandle, command, 8, HID_TIMEOUT);
261  LOGF_DEBUG("==> RX %2.2x %2.2x%2.2x %2.2x %2.2x %2.2x%2.2x%2.2x", command[0], command[1],
262  command[2], command[3], command[4], command[5], command[6], command[7]);
263 
264  rval = command[1] == 0x21 ? IPS_OK : IPS_ALERT;
265 
266  //FocusRelPosNP.s = rval;
267  //IDSetNumber(&FocusRelPosNP, nullptr);
268 
269  return rval;
270 }
271 
272 IPState HitecAstroDCFocuser::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
273 {
274  int rc;
275  unsigned char command[8] = {0};
276  IPState rval;
277 
278  LOGF_DEBUG("::MoveFocuser(%d %d %d)", dir, speed, duration);
279 
280  if (m_HIDHandle == nullptr)
281  {
282  return IPS_ALERT;
283  }
284 
286  IDSetNumber(&FocusSpeedNP, nullptr);
287 
289  {
290  dir = (dir == FOCUS_INWARD) ? FOCUS_OUTWARD : FOCUS_INWARD;
291  }
292 
293  if (speed > 100)
294  {
295  LOGF_DEBUG("::MoveFocuser() over speed %d, limiting to 100", speed);
296  speed = 100;
297  }
298 
299  m_StopChar = dir == FOCUS_INWARD ? 0xB0 : 0xBA;
300 
301  memset(command, 0, 8);
302  command[0] = dir == FOCUS_INWARD ? 0x54 : 0x56;
303  command[1] = (unsigned char)((speed >> 8) & 0xFF);
304  command[2] = (unsigned char)(speed & 0xFF);
305  command[3] = 0x03;
306  command[4] = 0;
307  command[5] = 0;
308  command[6] = 0;
309  command[7] = 0;
310 
311  LOGF_DEBUG("==> TX %2.2x %2.2x%2.2x %2.2x %2.2x %2.2x%2.2x%2.2x", command[0], command[1],
312  command[2], command[3], command[4], command[5], command[6], command[7]);
313 
314  rc = hid_write(m_HIDHandle, command, 8);
315  if (rc < 0)
316  {
317  LOGF_DEBUG("::MoveFocuser() fail (%s)", hid_error(m_HIDHandle));
318  return IPS_ALERT;
319  }
320 
321  memset(command, 0, 8);
322  hid_read_timeout(m_HIDHandle, command, 8, HID_TIMEOUT);
323  LOGF_DEBUG("==> RX %2.2x %2.2x%2.2x %2.2x %2.2x %2.2x%2.2x%2.2x", command[0], command[1],
324  command[2], command[3], command[4], command[5], command[6], command[7]);
325 
326  rval = command[1] == 0x24 ? IPS_OK : IPS_ALERT;
327 
328  FocusSpeedNP.s = rval;
329  IDSetNumber(&FocusSpeedNP, nullptr);
330 
331  m_Duration = duration;
332  m_State = SLEWING;
333 
334  return IPS_BUSY;
335 }
336 
338 {
340 
341  //IUSaveConfigNumber(fp, &MaxPositionNP);
342  IUSaveConfigNumber(fp, &SlewSpeedNP);
343  //IUSaveConfigSwitch(fp, &ReverseDirectionSP);
344 
345  return true;
346 }
HitecAstroDCFocuser::~HitecAstroDCFocuser
virtual ~HitecAstroDCFocuser() override
Definition: hitecastrodcfocuser.cpp:41
HitecAstroDCFocuser::SLEWING
@ SLEWING
Definition: hitecastrodcfocuser.h:66
HitecAstroDCFocuser::IDLE
@ IDLE
Definition: hitecastrodcfocuser.h:66
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
IPState
IPState
Property state.
Definition: indiapi.h:158
hid_write
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
HitecAstroDCFocuser::HitecAstroDCFocuser
HitecAstroDCFocuser()
Definition: hitecastrodcfocuser.cpp:34
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
HitecAstroDCFocuser
Definition: hitecastrodcfocuser.h:27
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
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
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
HitecAstroDCFocuser::TimerHit
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: hitecastrodcfocuser.cpp:148
HitecAstroDCFocuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: hitecastrodcfocuser.cpp:92
INDI::DefaultDevice::setDefaultPollingPeriod
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
Definition: defaultdevice.cpp:1157
INDI::Focuser::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: indifocuser.cpp:241
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1434
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
HID_TIMEOUT
#define HID_TIMEOUT
Definition: hitecastrodcfocuser.cpp:26
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
HitecAstroDCFocuser::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: hitecastrodcfocuser.cpp:198
INDI::DefaultDevice::SetTimer
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
Definition: defaultdevice.cpp:865
HitecAstroDCFocuser::MoveFocuser
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser the focuser in a particular direction with a specific speed for a finite duration.
Definition: hitecastrodcfocuser.cpp:272
hid_read_timeout
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
Definition: hid_libusb.c:997
HitecAstroDCFocuser::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: hitecastrodcfocuser.cpp:337
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
INDI::USBDevice::dev
libusb_device * dev
Definition: indiusbdevice.h:40
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
hitecastrodcfocuser.h
INDI::FocuserInterface::FocusRelPosN
INumber FocusRelPosN[1]
Definition: indifocuserinterface.h:287
hid_error
const HID_API_EXPORT wchar_t *HID_API_CALL hid_error(hid_device *dev)
Get a string describing the last error which occurred.
Definition: hid_libusb.c:1227
INDI::FocuserInterface::FOCUSER_CAN_REVERSE
@ FOCUSER_CAN_REVERSE
Definition: indifocuserinterface.h:77
INDI::Focuser::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indifocuser.cpp:120
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
INDI::Focuser::CONNECTION_NONE
@ CONNECTION_NONE
Definition: indifocuser.h:54
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
HitecAstroDCFocuser::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: hitecastrodcfocuser.cpp:128
INDI::FocuserInterface::FocusReverseS
ISwitch FocusReverseS[2]
Definition: indifocuserinterface.h:303
HitecAstroDCFocuser::Disconnect
bool Disconnect() override
Disconnect from device.
Definition: hitecastrodcfocuser.cpp:75
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
FUDGE_FACTOR_H
#define FUDGE_FACTOR_H
Definition: hitecastrodcfocuser.cpp:27
IP_RW
@ IP_RW
Definition: indiapi.h:185
FUDGE_FACTOR_L
#define FUDGE_FACTOR_L
Definition: hitecastrodcfocuser.cpp:28
HitecAstroDCFocuser::Connect
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
Definition: hitecastrodcfocuser.cpp:50
INDI::FocuserInterface::FocusSpeedNP
INumberVectorProperty FocusSpeedNP
Definition: indifocuserinterface.h:268
INDI::Focuser::setSupportedConnections
void setSupportedConnections(const uint8_t &value)
setConnection Set Focuser connection mode. Child class should call this in the constructor before Foc...
Definition: indifocuser.cpp:373
HitecAstroDCFocuser::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: hitecastrodcfocuser.cpp:171
hid_open
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
INDI::DefaultDevice::addDebugControl
void addDebugControl()
Add Debug control to the driver.
Definition: defaultdevice.cpp:639
INDI::Focuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:58
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
hid_close
void HID_API_EXPORT hid_close(hid_device *dev)
Close a HID device.
Definition: hid_libusb.c:1163
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
HitecAstroDCFocuser::getDefaultName
const char * getDefaultName() override
Definition: hitecastrodcfocuser.cpp:87
INDI::Focuser::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: indifocuser.cpp:145
hid_init
int HID_API_EXPORT hid_init(void)
Initialize the HIDAPI library.
Definition: hid_libusb.c:388
INDI::FocuserInterface::FocusSpeedN
INumber FocusSpeedN[1]
Definition: indifocuserinterface.h:269
ISS_ON
@ ISS_ON
Definition: indiapi.h:151
INDI::FocuserInterface::FOCUS_OUTWARD
@ FOCUS_OUTWARD
Definition: indifocuserinterface.h:69