Instrument Neutral Distributed Interface INDI 2.2.5
astromech_focuser.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2019 Christian Liska. All rights reserved.
3
4 Implementation based on Lacerta MFOC driver
5 (written 2018 by Franck Le Rhun and Christian Liska).
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
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 Library General Public License for more details.
15 .
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*******************************************************************************/
21
22#include "astromech_focuser.h"
23#include "config.h"
24
25#include <indicom.h>
27
28#include <cmath>
29#include <memory>
30#include <cstring>
31#include <unistd.h>
32#include <termios.h>
33#include <chrono>
34#include <regex>
35#include <thread>
36
37static std::unique_ptr<astromechanics_foc> Astromechanics_foc(new astromechanics_foc());
38
39// Delay for receiving messages
40#define FOC_POSMAX_HARDWARE 32767
41#define FOC_POSMIN_HARDWARE 0
42
44{
45 SetApperture(0);
46 return true;
47}
48
50{
51 Astromechanics_foc->ISSnoopDevice(root);
52}
53
54/************************************************************************************
55 *
56************************************************************************************/
62
63/************************************************************************************
64 *
65************************************************************************************/
67{
68 return "Astromechanics FOC";
69}
70
71/************************************************************************************
72 *
73************************************************************************************/
75{
77
80 FocusMaxPosNP[0].setStep(500);
82
85 FocusAbsPosNP[0].setStep(500);
86 FocusAbsPosNP[0].setValue(0);
87
88 FocusRelPosNP[0].setMin(FocusAbsPosNP[0].getMin());
89 FocusRelPosNP[0].setMax(FocusAbsPosNP[0].getMax() / 2);
90 FocusRelPosNP[0].setStep(250);
91 FocusRelPosNP[0].setValue(0);
92
93 // Aperture
94 AppertureNP[0].fill("LENS_APP", "Index", "%.f", 0, 22, 1, 0);
95 AppertureNP.fill(getDeviceName(), "LENS_APP_SETTING", "Apperture", MAIN_CONTROL_TAB, IP_RW,
96 60, IPS_IDLE);
97
99 return true;
100}
101
102/************************************************************************************
103 *
104************************************************************************************/
106{
107 // Get Initial Position before we define it in the INDI::Focuser class
108 FocusAbsPosNP[0].setValue(GetAbsFocuserPosition());
109
111
112 if (isConnected())
113 {
114 defineProperty(AppertureNP);
115 }
116 else
117 {
118 deleteProperty(AppertureNP);
119 }
120
121 return true;
122}
123
124/************************************************************************************
125 *
126************************************************************************************/
128{
129 char res[DRIVER_LEN] = {0};
130 int position = 0;
131 for (int i = 0; i < 3; i++)
132 {
133 if (!sendCommand("P#", res))
134 std::this_thread::sleep_for(std::chrono::milliseconds(100));
135 else
136 {
137 sscanf(res, "%d", &position);
138 FocusAbsPosNP[0].setValue(position);
140 SetApperture(0);
141 return true;
142 }
143 }
144
145 return false;
146}
147
148/************************************************************************************
149 *
150************************************************************************************/
151bool astromechanics_foc::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
152{
153 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
154 {
155 if (strcmp(name, "LENS_APP_SETTING") == 0)
156 {
157 AppertureNP.update(values, names, n);
158 AppertureNP.setState(IPS_OK);
159 AppertureNP.apply();
160 SetApperture(AppertureNP[0].getValue());
161 return true;
162 }
163 }
164
165 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
166}
167
168/************************************************************************************
169 *
170************************************************************************************/
172{
173 char cmd[DRIVER_LEN] = {0};
174 snprintf(cmd, DRIVER_LEN, "M%u#", targetTicks);
175 if (sendCommand(cmd))
176 {
177 FocusAbsPosNP[0].setValue(GetAbsFocuserPosition());
178 return IPS_OK;
179 }
180
181 return IPS_ALERT;
182}
183
184/************************************************************************************
185 *
186************************************************************************************/
188{
189 // Clamp
190 int32_t offset = ((dir == FOCUS_INWARD) ? -1 : 1) * static_cast<int32_t>(ticks);
191 int32_t newPosition = FocusAbsPosNP[0].getValue() + offset;
192 newPosition = std::max(static_cast<int32_t>(FocusAbsPosNP[0].getMin()),
193 std::min(static_cast<int32_t>(FocusAbsPosNP[0].getMax()),
194 newPosition));
195
198
199 return MoveAbsFocuser(newPosition);
200}
201
202/************************************************************************************
203 *
204************************************************************************************/
205bool astromechanics_foc::SetApperture(uint32_t index)
206{
207 char cmd[DRIVER_LEN] = {0};
208 snprintf(cmd, DRIVER_LEN, "A%u#", index);
209 return sendCommand(cmd);
210}
211
212/************************************************************************************
213 *
214************************************************************************************/
215uint32_t astromechanics_foc::GetAbsFocuserPosition()
216{
217 char res[DRIVER_LEN] = {0};
218 int position = 0;
219
220 if (!sendCommand("P#", res))
221 std::this_thread::sleep_for(std::chrono::milliseconds(100));
222 else
223 {
224 sscanf(res, "%d", &position);
225 return position;
226 }
227
228 return 0;
229}
230
234bool astromechanics_foc::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
235{
236 int nbytes_written = 0, nbytes_read = 0, rc = -1;
237 tcflush(PortFD, TCIOFLUSH);
238
239 if (cmd_len > 0)
240 {
241 char hex_cmd[DRIVER_LEN * 3] = {0};
242 hexDump(hex_cmd, cmd, cmd_len);
243 LOGF_DEBUG("CMD <%s>", hex_cmd);
244 rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
245 }
246 else
247 {
248 LOGF_DEBUG("CMD <%s>", cmd);
249 rc = tty_write_string(PortFD, cmd, &nbytes_written);
250 }
251
252 if (rc != TTY_OK)
253 {
254 char errstr[MAXRBUF] = {0};
255 tty_error_msg(rc, errstr, MAXRBUF);
256 LOGF_ERROR("Serial write error: %s.", errstr);
257 return false;
258 }
259
260 if (res == nullptr)
261 return true;
262
263 if (res_len > 0)
264 rc = tty_read(PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
265 else
266 {
267 // Read respose
268 rc = tty_nread_section(PortFD, res, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
269 }
270
271 if (rc != TTY_OK)
272 {
273 char errstr[MAXRBUF] = {0};
274 tty_error_msg(rc, errstr, MAXRBUF);
275 LOGF_ERROR("Serial read error: %s.", errstr);
276 return false;
277 }
278
279 if (res_len > 0)
280 {
281 char hex_res[DRIVER_LEN * 3] = {0};
282 hexDump(hex_res, res, res_len);
283 LOGF_DEBUG("RES <%s>", hex_res);
284 }
285 else
286 {
287 // Remove extra #
288 res[nbytes_read - 1] = 0;
289 LOGF_DEBUG("RES <%s>", res);
290 }
291
292 tcflush(PortFD, TCIOFLUSH);
293
294 return true;
295}
296
300void astromechanics_foc::hexDump(char * buf, const char * data, int size)
301{
302 for (int i = 0; i < size; i++)
303 sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
304
305 if (size > 0)
306 buf[3 * size - 1] = '\0';
307}
308
312std::vector<std::string> astromechanics_foc::split(const std::string &input, const std::string &regex)
313{
314 // passing -1 as the submatch index parameter performs splitting
315 std::regex re(regex);
316 std::sregex_token_iterator
317 first{input.begin(), input.end(), re, -1},
318 last;
319 return {first, last};
320}
#define FOC_POSMAX_HARDWARE
#define FOC_POSMIN_HARDWARE
void ISSnoopDevice(XMLEle *root)
Function defined by Drivers that is called when another Driver it is snooping (by having previously c...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
bool isConnected() const
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)
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusAbsPosNP
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...
Connection::Serial * serialConnection
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
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...
const char * getDefaultName() override
bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool Disconnect() override
Disconnect from device.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
@ IP_RW
Definition indiapi.h:184
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
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition indicom.c:548
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:759
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
#define MAXRBUF
Definition indidriver.c:52
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2