22#define VERSION_MAJOR 0
23#define VERSION_MINOR 2
25#define ASTROLINK4_LEN 200
26#define ASTROLINK4_TIMEOUT 3
45 return "AstroLink 4 mini II";
51bool IndiAstroLink4mini2::Handshake()
58 if (strncmp(res,
"#:AstroLink4mini", 16) != 0)
91 char focuserSelectLabel[15];
92 memset(focuserSelectLabel, 0, 15);
119 FocuserSelectSP[FOC_SEL_1].
fill(
"FOC_SEL_1",
"Focuser 1", (getFindex() == 0 ?
ISS_ON :
ISS_OFF));
120 FocuserSelectSP[FOC_SEL_2].
fill(
"FOC_SEL_2",
"Focuser 2", (getFindex() > 0 ?
ISS_ON :
ISS_OFF));
124 PowerDataNP[POW_VIN].
fill(
"VIN",
"Input voltage [V]",
"%.1f", 0, 15, 10, 0);
125 PowerDataNP[POW_REG].
fill(
"REG",
"Regulated voltage [V]",
"%.1f", 0, 15, 10, 0);
126 PowerDataNP[POW_ITOT].
fill(
"ITOT",
"Total current [A]",
"%.1f", 0, 15, 10, 0);
127 PowerDataNP[POW_AH].
fill(
"AH",
"Energy consumed [Ah]",
"%.1f", 0, 1000, 10, 0);
128 PowerDataNP[POW_WH].
fill(
"WH",
"Energy consumed [Wh]",
"%.1f", 0, 10000, 10, 0);
132 Power1SP[PWR1BTN_ON].
fill(
"PWR1BTN_ON",
"ON",
ISS_OFF);
133 Power1SP[PWR1BTN_OFF].
fill(
"PWR1BTN_OFF",
"OFF",
ISS_ON);
136 Power2SP[PWR2BTN_ON].
fill(
"PWR2BTN_ON",
"ON",
ISS_OFF);
137 Power2SP[PWR2BTN_OFF].
fill(
"PWR2BTN_OFF",
"OFF",
ISS_ON);
140 Power3SP[PWR3BTN_ON].
fill(
"PWR3BTN_ON",
"ON",
ISS_OFF);
141 Power3SP[PWR3BTN_OFF].
fill(
"PWR3BTN_OFF",
"OFF",
ISS_ON);
144 PWMNP[PWM1_VAL].
fill(
"PWM1_VAL",
"A",
"%3.0f", 0, 100, 10, 0);
145 PWMNP[PWM2_VAL].
fill(
"PWM2_VAL",
"B",
"%3.0f", 0, 100, 10, 0);
148 PowerDefaultOnSP[POW_DEF_ON1].
fill(
"POW_DEF_ON1",
"DC1",
ISS_OFF);
149 PowerDefaultOnSP[POW_DEF_ON2].
fill(
"POW_DEF_ON2",
"DC2",
ISS_OFF);
150 PowerDefaultOnSP[POW_DEF_ON3].
fill(
"POW_DEF_ON3",
"DC3",
ISS_OFF);
154 Focuser1SettingsNP[FS1_SPEED].
fill(
"FS1_SPEED",
"Speed [pps]",
"%.0f", 10, 200, 1, 100);
155 Focuser1SettingsNP[FS1_CURRENT].
fill(
"FS1_CURRENT",
"Current [mA]",
"%.0f", 100, 2000, 100, 400);
156 Focuser1SettingsNP[FS1_HOLD].
fill(
"FS1_HOLD",
"Hold torque [%]",
"%.0f", 0, 100, 10, 0);
157 Focuser1SettingsNP[FS1_STEP_SIZE].
fill(
"FS1_STEP_SIZE",
"Step size [um]",
"%.2f", 0, 100, 0.1, 5.0);
158 Focuser1SettingsNP[FS1_COMPENSATION].
fill(
"FS1_COMPENSATION",
"Compensation [steps/C]",
"%.2f", -1000, 1000, 1, 0);
159 Focuser1SettingsNP[FS1_COMP_THRESHOLD].
fill(
"FS1_COMP_THRESHOLD",
"Compensation threshold [steps]",
"%.0f", 1, 1000, 10,
163 Focuser2SettingsNP[FS2_SPEED].
fill(
"FS2_SPEED",
"Speed [pps]",
"%.0f", 10, 200, 1, 100);
164 Focuser2SettingsNP[FS2_CURRENT].
fill(
"FS2_CURRENT",
"Current [mA]",
"%.0f", 100, 2000, 100, 400);
165 Focuser2SettingsNP[FS2_HOLD].
fill(
"FS2_HOLD",
"Hold torque [%]",
"%.0f", 0, 100, 10, 0);
166 Focuser2SettingsNP[FS2_STEP_SIZE].
fill(
"FS2_STEP_SIZE",
"Step size [um]",
"%.2f", 0, 100, 0.1, 5.0);
167 Focuser2SettingsNP[FS2_COMPENSATION].
fill(
"FS2_COMPENSATION",
"Compensation [steps/C]",
"%.2f", -1000, 1000, 1, 0);
168 Focuser2SettingsNP[FS2_COMP_THRESHOLD].
fill(
"FS2_COMP_THRESHOLD",
"Compensation threshold [steps]",
"%.0f", 1, 1000, 10,
172 Focuser1ModeSP[FS1_MODE_UNI].
fill(
"FS1_MODE_UNI",
"Unipolar",
ISS_ON);
173 Focuser1ModeSP[FS1_MODE_MICRO_L].
fill(
"FS1_MODE_MICRO_L",
"Microstep 1/8",
ISS_OFF);
174 Focuser1ModeSP[FS1_MODE_MICRO_H].
fill(
"FS1_MODE_MICRO_H",
"Microstep 1/32",
ISS_OFF);
177 Focuser2ModeSP[FS2_MODE_UNI].
fill(
"FS2_MODE_UNI",
"Unipolar",
ISS_ON);
178 Focuser2ModeSP[FS2_MODE_MICRO_L].
fill(
"FS2_MODE_MICRO_L",
"Microstep 1/8",
ISS_OFF);
179 Focuser2ModeSP[FS2_MODE_MICRO_H].
fill(
"FS2_MODE_MICRO_H",
"Microstep 1/32",
ISS_OFF);
183 addParameter(
"WEATHER_TEMPERATURE",
"Temperature (C)", -15, 35, 15);
184 addParameter(
"WEATHER_HUMIDITY",
"Humidity %", 0, 100, 15);
185 addParameter(
"WEATHER_DEWPOINT",
"Dew Point (C)", 0, 100, 15);
242 if (PWMNP[PWM1_VAL].getValue() != values[0])
244 sprintf(
cmd,
"B:0:%d",
static_cast<uint8_t
>(values[0]));
247 if (PWMNP[PWM2_VAL].getValue() != values[1])
249 sprintf(
cmd,
"B:1:%d",
static_cast<uint8_t
>(values[1]));
254 PWMNP.
update(values, names, n);
263 std::map<int, std::string> updates;
264 updates[
U_FOC1_STEP] = doubleToStr(values[FS1_STEP_SIZE] * 100.0);
268 updates[
U_FOC1_ACC] = intToStr(values[FS1_SPEED] * 5.0);
269 updates[
U_FOC1_CUR] = intToStr(values[FS1_CURRENT] / 10.0);
271 allOk = allOk && updateSettings(
"u",
"U", updates);
276 Focuser1SettingsNP.
update(values, names, n);
277 Focuser1SettingsNP.
apply();
279 (values[FS1_COMPENSATION] > 0) ?
"enabled" :
"disabled");
289 std::map<int, std::string> updates;
290 updates[
U_FOC2_STEP] = doubleToStr(values[FS2_STEP_SIZE] * 100.0);
294 updates[
U_FOC2_ACC] = intToStr(values[FS2_SPEED] * 5.0);
295 updates[
U_FOC2_CUR] = intToStr(values[FS2_CURRENT] / 10.0);
297 allOk = allOk && updateSettings(
"u",
"U", updates);
302 Focuser2SettingsNP.
update(values, names, n);
303 Focuser2SettingsNP.
apply();
305 (values[FS2_COMPENSATION] > 0) ?
"enabled" :
"disabled");
312 if (strstr(name,
"FOCUS"))
328 sprintf(
cmd,
"C:0:%s", (strcmp(Power1SP[PWR1BTN_ON].getName(), names[0])) ?
"0" :
"1");
332 Power1SP.
update(states, names, n);
341 sprintf(
cmd,
"C:1:%s", (strcmp(Power2SP[PWR2BTN_ON].getName(), names[0])) ?
"0" :
"1");
345 Power2SP.
update(states, names, n);
354 sprintf(
cmd,
"C:2:%s", (strcmp(Power3SP[PWR3BTN_ON].getName(), names[0])) ?
"0" :
"1");
358 Power3SP.
update(states, names, n);
367 std::map<int, std::string> updates;
371 if (updateSettings(
"u",
"U", updates))
374 PowerDefaultOnSP.
update(states, names, n);
375 PowerDefaultOnSP.
apply();
385 std::string value =
"0";
386 if (!strcmp(Focuser1ModeSP[FS1_MODE_UNI].getName(), names[0]))
388 if (!strcmp(Focuser1ModeSP[FS1_MODE_MICRO_L].getName(), names[0]))
390 if (!strcmp(Focuser1ModeSP[FS1_MODE_MICRO_H].getName(), names[0]))
392 if (updateSettings(
"u",
"U",
U_FOC1_MODE, value.c_str()))
395 Focuser1ModeSP.
update(states, names, n);
396 Focuser1ModeSP.
apply();
404 std::string value =
"0";
405 if (!strcmp(Focuser2ModeSP[FS2_MODE_UNI].getName(), names[0]))
407 if (!strcmp(Focuser2ModeSP[FS2_MODE_MICRO_L].getName(), names[0]))
409 if (!strcmp(Focuser2ModeSP[FS2_MODE_MICRO_H].getName(), names[0]))
411 if (updateSettings(
"u",
"U",
U_FOC2_MODE, value.c_str()))
414 Focuser2ModeSP.
update(states, names, n);
415 Focuser2ModeSP.
apply();
425 setFindex((strcmp(FocuserSelectSP[0].getName(), names[0])) ? 1 : 0);
432 FocuserSelectSP.
update(states, names, n);
433 FocuserSelectSP.
apply();
441 if (strstr(name,
"FOCUS"))
454 FocuserSelectSP.
save(fp);
485 if (updateSettings(
"u",
"U", index, (enabled) ?
"1" :
"0"))
514 if (updateSettings(
"u",
"U", index, std::to_string(ticks).c_str()))
542 int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
547 if (strncmp(
cmd,
"#", 1) == 0)
548 sprintf(res,
"%s\n",
"#:AstroLink4mini");
549 if (strncmp(
cmd,
"q", 1) == 0)
551 "q:AL4MII:1234:0:5678:0:3.14:1:23.12:45:9.11:1:19.19:35:80:1:0:1:12.11:7.62:20.01:132.11:33:0:0:0:1:-10.1:7.7:1:19.19:35:8.22:1:1:18.11");
552 if (strncmp(
cmd,
"p", 1) == 0)
553 sprintf(res,
"%s\n",
"p:1234");
554 if (strncmp(
cmd,
"i", 1) == 0)
555 sprintf(res,
"%s\n",
"i:0");
556 if (strncmp(
cmd,
"u", 1) == 0)
558 "u:1:1:80:120:30:50:200:800:200:800:0:2:10000:80000:0:0:50:18:30:15:5:10:10:0:1:0:0:0:0:0:0:0:40:90:10:1100:14000:10000:100:0");
559 if (strncmp(
cmd,
"A", 1) == 0)
560 sprintf(res,
"%s\n",
"A:4.5.0 mini II");
561 if (strncmp(
cmd,
"R", 1) == 0)
562 sprintf(res,
"%s\n",
"R:");
563 if (strncmp(
cmd,
"C", 1) == 0)
564 sprintf(res,
"%s\n",
"C:");
565 if (strncmp(
cmd,
"B", 1) == 0)
566 sprintf(res,
"%s\n",
"B:");
567 if (strncmp(
cmd,
"H", 1) == 0)
568 sprintf(res,
"%s\n",
"H:");
569 if (strncmp(
cmd,
"P", 1) == 0)
570 sprintf(res,
"%s\n",
"P:");
571 if (strncmp(
cmd,
"U", 1) == 0)
572 sprintf(res,
"%s\n",
"U:");
573 if (strncmp(
cmd,
"S", 1) == 0)
574 sprintf(res,
"%s\n",
"S:");
578 tcflush(PortFD, TCIOFLUSH);
579 sprintf(command,
"%s\n",
cmd);
586 tcflush(PortFD, TCIOFLUSH);
594 tcflush(PortFD, TCIOFLUSH);
595 res[nbytes_read - 1] =
'\0';
605 return (
cmd[0] == res[0]);
608bool IndiAstroLink4mini2::readDevice()
613 std::vector<std::string> result = split(res,
":");
614 result.erase(result.begin());
632 if (result.size() > 5)
664 PWMNP[PWM1_VAL].setValue(std::stod(result[
Q_PWM1]));
665 PWMNP[PWM2_VAL].setValue(std::stod(result[
Q_PWM2]));
669 PowerDataNP[POW_ITOT].setValue(std::stod(result[
Q_ITOT]));
670 PowerDataNP[POW_REG].setValue(std::stod(result[
Q_VREG]));
671 PowerDataNP[POW_VIN].setValue(std::stod(result[
Q_VIN]));
672 PowerDataNP[POW_AH].setValue(std::stod(result[
Q_AH]));
673 PowerDataNP[POW_WH].setValue(std::stod(result[
Q_WH]));
686 std::vector<std::string> result = split(res,
":");
694 PowerDefaultOnSP.
apply();
701 Focuser1SettingsNP[FS1_STEP_SIZE].setValue(std::stod(result[
U_FOC1_STEP]) / 100.0);
702 Focuser1SettingsNP[FS1_COMPENSATION].setValue(std::stod(result[
U_FOC1_COMPSTEPS]) / 100.0);
703 Focuser1SettingsNP[FS1_COMP_THRESHOLD].setValue(std::stod(result[
U_FOC1_COMPTRIGGER]));
704 Focuser1SettingsNP[FS1_SPEED].setValue(std::stod(result[
U_FOC1_SPEED]));
705 Focuser1SettingsNP[FS1_CURRENT].setValue(std::stod(result[
U_FOC1_CUR]) * 10.0);
706 Focuser1SettingsNP[FS1_HOLD].setValue(std::stod(result[
U_FOC1_HOLD]));
708 Focuser1SettingsNP.
apply();
714 Focuser2SettingsNP[FS2_STEP_SIZE].setValue(std::stod(result[
U_FOC2_STEP]) / 100.0);
715 Focuser2SettingsNP[FS2_COMPENSATION].setValue(std::stod(result[
U_FOC2_COMPSTEPS]) / 100.0);
716 Focuser2SettingsNP[FS2_COMP_THRESHOLD].setValue(std::stod(result[
U_FOC2_COMPTRIGGER]));
717 Focuser2SettingsNP[FS2_SPEED].setValue(std::stod(result[
U_FOC2_SPEED]));
718 Focuser2SettingsNP[FS2_CURRENT].setValue(std::stod(result[
U_FOC2_CUR]) * 10.0);
719 Focuser2SettingsNP[FS2_HOLD].setValue(std::stod(result[
U_FOC2_HOLD]));
721 Focuser2SettingsNP.
apply();
726 Focuser1ModeSP[FS1_MODE_UNI].
setState(Focuser1ModeSP[FS1_MODE_MICRO_L].s = Focuser1ModeSP[FS1_MODE_MICRO_H].s =
ISS_OFF);
734 Focuser1ModeSP.
apply();
739 Focuser2ModeSP[FS2_MODE_UNI].
setState(Focuser2ModeSP[FS2_MODE_MICRO_L].s = Focuser2ModeSP[FS2_MODE_MICRO_H].s =
ISS_OFF);
747 Focuser2ModeSP.
apply();
768 FocuserSelectSP.
apply();
778std::vector<std::string> IndiAstroLink4mini2::split(
const std::string &input,
const std::string ®ex)
781 std::regex re(regex);
782 std::sregex_token_iterator
783 first{input.begin(), input.end(), re, -1},
785 return {first, last};
788std::string IndiAstroLink4mini2::doubleToStr(
double val)
791 sprintf(buf,
"%.0f", val);
792 return std::string(buf);
795std::string IndiAstroLink4mini2::intToStr(
double val)
798 sprintf(buf,
"%i", (
int)val);
799 return std::string(buf);
802bool IndiAstroLink4mini2::updateSettings(
const char *getCom,
const char *setCom,
int index,
const char *value)
804 std::map<int, std::string> values;
805 values[index] = value;
806 return updateSettings(getCom, setCom, values);
809bool IndiAstroLink4mini2::updateSettings(
const char *getCom,
const char *setCom, std::map<int, std::string> values)
815 std::string concatSettings =
"";
816 std::vector<std::string> result = split(res,
":");
817 if (result.size() >= values.size())
820 for (std::map<int, std::string>::iterator it = values.begin(); it != values.end(); ++it)
821 result[it->first] = it->second;
823 for (
const auto &piece : result)
824 concatSettings += piece +
":";
834int IndiAstroLink4mini2::getFindex()
839void IndiAstroLink4mini2::setFindex(
int index)
842 focuserIndex = index;
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
const char * getDeviceName() const
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
void addConfigurationControl()
Add Configuration control to the driver.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void addSimulationControl()
Add Simulation control to the driver.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
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)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
bool isSimulation() const
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
Provides interface to implement focuser functionality.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
void initProperties(const char *groupName)
Initialize focuser properties. It is recommended to call this function within initProperties() of you...
INDI::PropertyNumber FocusMaxPosNP
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
INDI::PropertyNumber FocusAbsPosNP
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
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)
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)
Provides interface to implement weather reporting and safety monitoring functionality.
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning, bool flipWarning=false)
Add a physical weather measurable parameter to the weather driver.
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
INDI::PropertyNumber ParametersNP
void initProperties(const char *statusGroup, const char *paramsGroup)
Initialize focuser properties. It is recommended to call this function within initProperties() of you...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
IndiAstroLink4mini2()
Constructor.
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool sendCommand(const char *cmd, char *res)
Serial commands.
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Set Focuser Maximum position limit in the hardware.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
virtual bool initProperties() override
Overrides.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
Focuser interface.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual const char * getDefaultName() override
const char * FOCUS_TAB
FOCUS_TAB Where all the properties for focuser are located.
#define ASTROLINK4_TIMEOUT
std::unique_ptr< IndiAstroLink4mini2 > indiFocuserLink(new IndiAstroLink4mini2())
Delegates.
#define U_FOC1_COMPTRIGGER
#define U_FOC2_COMPTRIGGER
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
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
Implementations for common driver routines.
int IUGetConfigOnSwitchName(const char *dev, const char *property, char *name, size_t size)
IUGetConfigOnSwitchLabel Opens configuration file and returns the name of the ON switch property,...
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
#define LOGF_ERROR(fmt,...)
#define DEBUGF(priority, msg,...)