29#ifdef _USE_SYSTEM_JSONLIB
30#include <nlohmann/json.hpp>
46static std::unique_ptr<EsattoArco> esattoarco(
new EsattoArco());
68 setConnectionParams();
71 FirmwareTP[ESATTO_FIRMWARE_SN].
fill(
"ESATTO_FIRMWARE_SN",
"Esatto SN",
"");
72 FirmwareTP[ESATTO_FIRMWARE_VERSION].
fill(
"ESATTO_FIRMWARE_VERSION",
"Esatto Firmware",
"");
73 FirmwareTP[ARCO_FIRMWARE_SN].
fill(
"ARCO_FIRMWARE_SN",
"Arco SN",
"");
74 FirmwareTP[ARCO_FIRMWARE_VERSION].
fill(
"VERARCO_FIRMWARE_VERSIONSION",
"Arco Firmware",
"");
82 VoltageNP[VOLTAGE_12V].
fill(
"VOLTAGE_12V",
"12v",
"%.2f", 0, 100, 0., 0.);
83 VoltageNP[VOLTAGE_USB].
fill(
"VOLTAGE_USB",
"USB",
"%.2f", 0, 100, 0., 0.);
87 TemperatureNP[TEMPERATURE_MOTOR].
fill(
"TEMPERATURE",
"Motor (c)",
"%.2f", -50, 70., 0., 0.);
88 TemperatureNP[TEMPERATURE_EXTERNAL].
fill(
"TEMPERATURE_ETX",
"External (c)",
"%.2f", -50, 70., 0., 0.);
93 SpeedNP[0].
fill(
"SPEED",
"steps/s",
"%.f", 0, 7000., 1, 0);
98 BacklashMessageTP[0].
fill(
"BACKLASH",
"Backlash stage",
"Press START to measure backlash.");
103 BacklashMeasurementSP[BACKLASH_START].
fill(
"BACKLASH_START",
"Start",
ISS_OFF);
104 BacklashMeasurementSP[BACKLASH_NEXT].
fill(
"BACKLASH_NEXT",
"Next",
ISS_OFF);
110 FastMoveSP[FASTMOVE_IN].
fill(
"FASTMOVE_IN",
"Move In",
ISS_OFF);
111 FastMoveSP[FASTMOVE_OUT].
fill(
"FASTMOVE_OUT",
"Move out",
ISS_OFF);
112 FastMoveSP[FASTMOVE_STOP].
fill(
"FASTMOVE_STOP",
"Stop",
ISS_OFF);
128 RotatorAbsPosNP[0].
fill(
"ROTATOR_ABSOLUTE_POSITION",
"Ticks",
"%.f", 0., 100000., 1000., 0.);
132 RotatorCalibrationSP[ARCO_CALIBRATION_START].
fill(
"ARCO_CALIBRATION_START",
"Start",
ISS_OFF);
181 if (getStartupValues())
184 LOG_WARN(
"Failed to inquire parameters. Check logs.");
194 if (updateTemperature())
197 if (updateVoltageIn())
241 LOG_INFO(
"Error retrieving data from device, please ensure focuser is powered and the port is correct.");
250 return "Esatto Arco";
256bool EsattoArco::updateTemperature()
261 TemperatureNP[TEMPERATURE_MOTOR].setValue(
temperature);
267 TemperatureNP[TEMPERATURE_EXTERNAL].setValue(-273.15);
270 TemperatureNP[TEMPERATURE_EXTERNAL].setValue(
temperature);
279bool EsattoArco::updateMaxLimit()
281 uint32_t maxLimit = 0;
283 if (m_Esatto->getMaxPosition(maxLimit) && maxLimit > 0)
320 return m_Esatto->setBacklash(steps);
326bool EsattoArco::updatePosition()
330 if (m_Esatto->getAbsolutePosition(steps))
338 RotatorAbsPosNP[0].setValue(arcoPosition);
359bool EsattoArco::updateVoltageIn()
362 if (m_Esatto->getVoltage12v(voltage))
363 VoltageNP[VOLTAGE_12V].setValue(voltage);
366 if (m_Esatto->getVoltageUSB(voltage))
367 VoltageNP[VOLTAGE_USB].setValue(voltage);
374bool EsattoArco::isMotionComplete()
377 if (m_Esatto->getCurrentSpeed(speed))
395 BacklashMeasurementSP.
update(states, names, n);
399 BacklashMeasurementSP.
apply();
401 if (current_switch == BACKLASH_START)
403 if (bStage == BacklashIdle || bStage == BacklashComplete )
406 LOG_INFO(
"Start Backlash measurement.");
408 BacklashMeasurementSP.
apply();
410 BacklashMessageTP[0].setText(
"Drive the focuser in any direction until focus changes.");
411 BacklashMessageTP.
apply();
414 bStage = BacklashMinimum;
418 LOG_INFO(
"Already started backlash measure. Proceed to next step.");
419 BacklashMessageTP[0].setText(
"Already started. Proceed to NEXT.");
420 BacklashMessageTP.
apply();
423 else if (current_switch == BACKLASH_NEXT)
425 if (bStage == BacklashMinimum)
429 BacklashMessageTP[0].setText(
"Drive the focuser in the opposite direction, then press NEXT to finish.");
430 BacklashMessageTP.
apply();
431 bStage = BacklashMaximum;
433 else if (bStage == BacklashMaximum)
443 BacklashMessageTP[0].setText(
"Backlash Measure Completed.");
444 BacklashMessageTP.
apply();
446 bStage = BacklashComplete;
448 LOG_INFO(
"Backlash measurement completed");
450 BacklashMeasurementSP.
apply();
452 BacklashMeasurementSP.
apply();
456 BacklashMessageTP[0].setText(
"Backlash not in progress.");
457 BacklashMessageTP.
apply();
466 FastMoveSP.
update(states, names, n);
469 switch (current_switch)
472 if (!m_Esatto->fastMoveIn())
477 if (!m_Esatto->fastMoveOut())
482 if (!m_Esatto->stop())
496 if(m_Arco->calibrate())
498 LOG_INFO(
"Calibrating Arco. Please wait.");
502 RotatorCalibrationSP.
apply();
504 RotatorAbsPosNP.
apply();
508 RotatorCalibrationSP.
reset();
510 RotatorCalibrationSP.
apply();
514 else if (strstr(name,
"ROTATOR"))
538 RotatorAbsPosNP.
apply();
541 LOGF_INFO(
"Rotator moving to %.f steps...", values[0]);
544 else if (strstr(name,
"ROTATOR"))
558 if (m_Esatto->goAbsolutePosition(targetTicks))
561 RotatorAbsPosNP.
apply();
573 int relativeTicks = ((dir ==
FOCUS_INWARD) ? -ticks : ticks) * reversed;
574 double newPosition =
FocusAbsPosNP[0].getValue() + relativeTicks;
586 return m_Esatto->stop();
601 auto currentRotatorPosition = RotatorAbsPosNP[0].getValue();
602 if (updatePosition())
604 if (std::abs(currentFocusPosition -
FocusAbsPosNP[0].getValue()) > 0)
621 if (std::abs(currentRotatorPosition - RotatorAbsPosNP[0].getValue()) > 0)
630 RotatorCalibrationSP.
apply();
631 LOG_INFO(
"Arco calibration complete.");
633 LOG_INFO(
"Arco position synced to zero.");
638 RotatorAbsPosNP.
apply();
643 RotatorAbsPosNP.
apply();
648 if (m_TemperatureCounter++ == TEMPERATURE_FREQUENCY)
650 auto currentTemperature = TemperatureNP[0].getValue();
651 if (updateTemperature())
653 if (std::abs(currentTemperature - TemperatureNP[0].getValue()) >= 0.1)
654 TemperatureNP.
apply();
657 auto current12V = VoltageNP[VOLTAGE_12V].getValue();
658 auto currentUSB = VoltageNP[VOLTAGE_USB].getValue();
659 if (updateVoltageIn())
661 if (std::abs(current12V - VoltageNP[VOLTAGE_12V].getValue()) >= 0.1 ||
662 std::abs(currentUSB - VoltageNP[VOLTAGE_USB].getValue()) >= 0.1)
665 if (VoltageNP[VOLTAGE_12V].getValue() < 11.0)
666 LOG_WARN(
"Please check 12v DC power supply is connected.");
670 m_TemperatureCounter = 0;
679bool EsattoArco::getStartupValues()
683 if (m_Arco->getMotorInfo(info))
688 info[
"get"][
"MOT2"][
"CAL_MAXPOS"].
get_to(calMax);
689 info[
"get"][
"MOT2"][
"CAL_MINPOS"].
get_to(calMin);
694 LOGF_ERROR(
"Failed to parse info: %s Exception: %s id: %d", info.
dump().c_str(),
698 RotatorAbsPosNP[0].setMin(calMin);
699 RotatorAbsPosNP[0].setMax(calMax);
700 RotatorAbsPosNP[0].setStep(std::abs(calMax - calMin) / 50.0);
708bool EsattoArco::Ack()
710 std::string serial, firmware;
712 if(initCommandSet() ==
false)
714 LOG_ERROR(
"Failed setting attributes on serial port and init command sets");
718 if (m_Arco->setEnabled(
true) && !m_Arco->isEnabled())
720 LOG_ERROR(
"Failed to enable ARCO rotator. Please check it is powered and connected.");
724 bool rc1 = m_Esatto->getSerialNumber(serial);
725 bool rc2 = m_Esatto->getFirmwareVersion(firmware);
729 FirmwareTP[ESATTO_FIRMWARE_SN].setText(serial);
730 FirmwareTP[ESATTO_FIRMWARE_VERSION].setText(firmware);
731 LOGF_INFO(
"Esatto SN: %s Firmware version: %s", FirmwareTP[ESATTO_FIRMWARE_SN].
getText(),
732 FirmwareTP[ESATTO_FIRMWARE_VERSION].
getText());
737 rc1 = m_Arco->getSerialNumber(serial);
738 rc2 = m_Arco->getFirmwareVersion(firmware);
742 FirmwareTP[ARCO_FIRMWARE_SN].setText(serial);
743 FirmwareTP[ARCO_FIRMWARE_VERSION].setText(firmware);
744 LOGF_INFO(
"Arco SN: %s Firmware version: %s", FirmwareTP[ARCO_FIRMWARE_SN].
getText(),
745 FirmwareTP[ARCO_FIRMWARE_VERSION].
getText());
756void EsattoArco::setConnectionParams()
765bool EsattoArco::initCommandSet()
770 LOG_ERROR(
"setTTYFlags: failed getting tty attributes.");
776 LOG_ERROR(
"setTTYFlags: failed setting attributes on serial port.");
790 Focuser::saveConfigItems(fp);
806 newAngle = ( angle > 180 ? 360 - angle : angle * -1);
808 newAngle = ( angle > 180 ? angle - 360 : angle);
820 auto rc = m_Arco->stop();
825 RotatorAbsPosNP.
apply();
852 newAngle = ( angle > 180 ? 360 - angle : angle * -1);
854 newAngle = ( angle > 180 ? angle - 360 : angle);
void setWordSize(const uint8_t &value)
setWordSize Set word size to be used in the serial connection. Default 8
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
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 TimerHit() override
Callback function to be called once SetTimer duration elapses.
const char * getDefaultName() override
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual IPState MoveRotator(double angle) override
MoveRotator Go to specific angle.
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...
virtual bool saveConfigItems(FILE *fp) override
virtual bool ReverseRotator(bool enabled) override
ReverseRotator Reverse the direction of the rotator. CW is usually the normal direction,...
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual bool SyncRotator(double angle) override
SyncRotator Set current angle as the supplied angle without moving the rotator.
virtual bool AbortRotator() override
AbortRotator Abort all motion.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
INDI::PropertyText getText(const char *name) const
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
uint32_t getDriverInterface() const
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
virtual bool SetFocuserBacklashEnabled(bool enabled)
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusBacklashNP
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 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
INDI::PropertyNumber PresetNP
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool load()
load Attempt to load property values from configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
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)
int findOnSwitchIndex() const
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)
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process Rotator switch properties.
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
void initProperties(const char *groupName)
Initialize Rotator 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...
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process Rotator number properties.
INDI::PropertySwitch ReverseRotatorSP
INDI::PropertyNumber GotoRotatorNP
Provides interface to implement Rotator functionality.
a class to store JSON values
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
general exception of the basic_json class
const int id
the id of the exception
const char * what() const noexcept override
returns the explanatory string
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
Implementations for common driver routines.
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
struct termios tty_setting