33 static std::unique_ptr<DomePro2> domepro2(
new DomePro2());
51 IUFillText(&VersionT[VERSION_FIRMWARE],
"VERSION_FIRMWARE",
"Firmware",
"NA");
52 IUFillText(&VersionT[VERSION_HARDWARE],
"VERSION_HARDWARE",
"Hardware",
"NA");
56 IUFillText(&StatusT[STATUS_DOME],
"STATUS_DOME",
"Dome",
"NA");
57 IUFillText(&StatusT[STATUS_SHUTTER],
"STATUS_SHUTTER",
"Shutter",
"NA");
61 IUFillNumber(&SettingsN[SETTINGS_AZ_CPR],
"SETTINGS_AZ_CPR",
"Az CPR (steps)",
"%.f", 0x20, 0x40000000, 0, 0);
62 IUFillNumber(&SettingsN[SETTINGS_AZ_COAST],
"SETTINGS_AZ_COAST",
"Az Coast (deg)",
"%.2f", 0, 15, 0, 0);
63 IUFillNumber(&SettingsN[SETTINGS_AZ_HOME],
"SETTINGS_AZ_HOME",
"Az Home (deg)",
"%.2f", 0, 360, 0, 0);
64 IUFillNumber(&SettingsN[SETTINGS_AZ_PARK],
"SETTINGS_AZ_PARK",
"Az Park (deg)",
"%.2f", 0, 360, 0, 0);
65 IUFillNumber(&SettingsN[SETTINGS_AZ_STALL_COUNT],
"SETTINGS_AZ_STALL_COUNT",
"Az Stall Count (steps)",
"%.f", 0, 0x40000000,
72 IUFillSwitchVector(&HomeSP, HomeS, 2,
getDeviceName(),
"HOME",
"Home",
MAIN_CONTROL_TAB,
IP_RW,
ISR_ATMOST1, 60,
IPS_OK);
85 bool DomePro2::setupInitialParameters()
99 if (getFirmwareVersion() && getHardwareConfig())
102 if (getDomeStatus() && getShutterStatus())
105 if (getDomeAzCPR() && getDomeAzCoast() && getDomeHomeAz() && getDomeParkAz() && getDomeAzStallCount())
119 return getFirmwareVersion();
139 setupInitialParameters();
165 if (!strcmp(name, HomeSP.
name))
168 for (
int i = 0; i < HomeSP.
nsp; i++)
173 if (!strcmp(HomeS[HOME_GOTO].name, names[i]))
175 if (!gotoHomeDomeAz())
178 LOG_ERROR(
"Failed to go to Home Dome Az.");
182 HomeS[HOME_GOTO].s =
ISS_ON;
186 else if (!strcmp(HomeS[HOME_DISCOVER].name, names[i]))
188 if (!discoverHomeDomeAz())
191 LOG_ERROR(
"Failed to discover Home Dome Az.");
195 HomeS[HOME_DISCOVER].s =
ISS_ON;
221 if (!strcmp(name, SettingsNP.
name))
224 for (
int i = 0; i < SettingsNP.
nnp; i++)
226 if (!strcmp(SettingsN[SETTINGS_AZ_CPR].name, names[i]))
228 if (setDomeAzCPR(
static_cast<uint32_t
>(values[i])))
229 SettingsN[SETTINGS_AZ_CPR].value = values[i];
236 else if (!strcmp(SettingsN[SETTINGS_AZ_COAST].name, names[i]))
238 if (setDomeAzCoast(
static_cast<uint32_t
>(values[i])))
239 SettingsN[SETTINGS_AZ_COAST].value = values[i];
243 LOG_ERROR(
"Failed to set Dome AZ Coast.");
246 else if (!strcmp(SettingsN[SETTINGS_AZ_HOME].name, names[i]))
248 if (setDomeHomeAz(
static_cast<uint32_t
>(values[i])))
249 SettingsN[SETTINGS_AZ_HOME].value = values[i];
253 LOG_ERROR(
"Failed to set Dome AZ Home.");
256 else if (!strcmp(SettingsN[SETTINGS_AZ_PARK].name, names[i]))
258 if (setDomeParkAz(
static_cast<uint32_t
>(values[i])))
259 SettingsN[SETTINGS_AZ_PARK].value = values[i];
263 LOG_ERROR(
"Failed to set Dome AZ Park.");
266 else if (!strcmp(SettingsN[SETTINGS_AZ_STALL_COUNT].name, names[i]))
268 if (setDomeAzStallCount(
static_cast<uint32_t
>(values[i])))
269 SettingsN[SETTINGS_AZ_STALL_COUNT].value = values[i];
273 LOG_ERROR(
"Failed to set Dome AZ Stall Count.");
297 if(getDomeAzPos() && std::abs(currentAz -
DomeAbsPosN[0].value) > DOME_AZ_THRESHOLD)
300 std::string domeStatus = StatusT[STATUS_DOME].text;
301 std::string shutterStatus = StatusT[STATUS_SHUTTER].text;
302 if(getDomeStatus() && getShutterStatus() && (strcmp(domeStatus.c_str(), StatusT[STATUS_DOME].text) != 0 ||
303 strcmp(shutterStatus.c_str(), StatusT[STATUS_DOME].text) != 0))
308 if (!strcmp(StatusT[STATUS_DOME].text,
"Idle"))
326 int statusVal = processShutterStatus();
327 if (statusVal == 0x00)
329 else if (statusVal == 0x01)
331 else if ((statusVal >= 0x04 && statusVal <= 12) || statusVal >= 15)
333 else if (statusVal == 0x13)
349 uint32_t steps =
static_cast<uint32_t
>(az * (SettingsN[SETTINGS_AZ_CPR].value / 360));
350 if (gotoDomeAz(steps))
377 if(calibrateDomeAz(az))
391 if(killDomeAzMovement())
433 if (openDomeShutters())
438 if (closeDomeShutters())
449 if (!killDomeAzMovement())
504 uint8_t DomePro2::processShutterStatus()
506 if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Opened"))
508 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Closed"))
510 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Opening"))
512 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Closing"))
514 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"ShutterError"))
516 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter module is not communicating to the azimuth module"))
518 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 opposite direction timeout error on open occurred"))
520 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 opposite direction timeout error on close occurred"))
522 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 opposite direction timeout error on open occurred"))
524 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 opposite direction timeout error on close occurred"))
526 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 completion timeout error on open occurred"))
528 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 completion timeout error on close occurred"))
530 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 completion timeout error on open occurred"))
532 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 completion timeout error on close occurred"))
534 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 limit fault on open occurred"))
536 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 limit fault on close occurred"))
538 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 limit fault on open occurred"))
540 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 limit fault on close occurred"))
542 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Shutter disabled (Shutter Enable input is not asserted)"))
544 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"Intermediate"))
546 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"GoTo"))
548 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 OCP trip on open occurred"))
550 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 1 OCP trip on close occurred"))
552 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 OCP trip on open occurred"))
554 else if (!strcmp(StatusT[STATUS_SHUTTER].text,
"shutter 2 OCP trip on close occurred"))
562 bool DomePro2::getFirmwareVersion()
564 char res[DRIVER_LEN] = {0};
565 if (sendCommand(
"DGfv", res) ==
false)
569 if (sscanf(res,
"%X", &version) == 1)
571 char versionString[DRIVER_LEN] = {0};
572 snprintf(versionString, DRIVER_LEN,
"%d", version);
573 IUSaveText(&VersionT[VERSION_FIRMWARE], versionString);
583 bool DomePro2::getHardwareConfig()
585 char res[DRIVER_LEN] = {0};
586 if (sendCommand(
"DGhc", res) ==
false)
590 if (sscanf(res,
"%X", &config) == 1)
592 char configString[DRIVER_LEN] = {0};
593 uint8_t index =
static_cast<uint8_t
>(config);
594 if (DomeHardware.count(index))
596 snprintf(configString, DRIVER_LEN,
"%s", DomeHardware.at(index).c_str());
597 IUSaveText(&VersionT[VERSION_HARDWARE], configString);
602 LOGF_WARN(
"Unknown model detected %d", config);
614 bool DomePro2::getDomeStatus()
616 char res[DRIVER_LEN] = {0};
617 if (sendCommand(
"DGam", res) ==
false)
620 if (DomeStatus.count(res))
622 IUSaveText(&StatusT[STATUS_DOME], DomeStatus.at(res).c_str());
627 LOGF_WARN(
"Unknown dome status detected %d", res);
635 bool DomePro2::getShutterStatus()
637 char res[DRIVER_LEN] = {0};
638 if (sendCommand(
"DGsx", res) ==
false)
642 if (sscanf(res,
"%X", &status) == 1)
644 char statusString[DRIVER_LEN] = {0};
645 uint8_t index =
static_cast<uint8_t
>(status);
646 if (ShutterStatus.count(index))
648 snprintf(statusString, DRIVER_LEN,
"%s", ShutterStatus.at(index).c_str());
649 IUSaveText(&StatusT[STATUS_SHUTTER], statusString);
654 LOGF_WARN(
"Unknown shutter status detected %d", status);
666 bool DomePro2::getDomeAzCPR()
668 char res[DRIVER_LEN] = {0};
669 if (sendCommand(
"DGcp", res) ==
false)
673 if (sscanf(res,
"%X", &cpr) == 1)
675 SettingsN[SETTINGS_AZ_CPR].value = cpr;
685 bool DomePro2::setDomeAzCPR(uint32_t cpr)
687 char cmd[DRIVER_LEN] = {0};
688 if (cpr < 0x20 || cpr > 0x40000000)
690 LOG_ERROR(
"CPR value out of bounds (32 to 1,073,741,824)");
693 else if (cpr % 2 != 0)
695 LOG_ERROR(
"CPR value must be an even number");
698 snprintf(
cmd, DRIVER_LEN,
"DScp0x%08X", cpr);
699 if (sendCommand(
cmd) ==
false)
707 bool DomePro2::getDomeAzCoast()
709 char res[DRIVER_LEN] = {0};
710 if (sendCommand(
"DGco", res) ==
false)
714 if (sscanf(res,
"%X", &coast) == 1)
716 SettingsN[SETTINGS_AZ_COAST].value = coast * (360 / SettingsN[SETTINGS_AZ_CPR].value);
726 bool DomePro2::setDomeAzCoast(uint32_t az)
728 char cmd[DRIVER_LEN] = {0};
729 uint32_t steps =
static_cast<uint32_t
>(az * (SettingsN[SETTINGS_AZ_CPR].value / 360));
735 snprintf(
cmd, DRIVER_LEN,
"DSco0x%08X", steps);
736 if (sendCommand(
cmd) ==
false)
744 bool DomePro2::getDomeHomeAz()
746 char res[DRIVER_LEN] = {0};
747 if (sendCommand(
"DGha", res) ==
false)
751 if (sscanf(res,
"%X", &home) == 1)
753 SettingsN[SETTINGS_AZ_HOME].value = home * (360 / SettingsN[SETTINGS_AZ_CPR].value);
763 bool DomePro2::setDomeHomeAz(uint32_t az)
765 char cmd[DRIVER_LEN] = {0};
766 uint32_t steps =
static_cast<uint32_t
>(az * (SettingsN[SETTINGS_AZ_CPR].value / 360));
775 snprintf(
cmd, DRIVER_LEN,
"DSha0x%08X", steps);
776 if (sendCommand(
cmd) ==
false)
784 bool DomePro2::getDomeParkAz()
786 char res[DRIVER_LEN] = {0};
787 if (sendCommand(
"DGpa", res) ==
false)
791 if (sscanf(res,
"%X", &
park) == 1)
793 SettingsN[SETTINGS_AZ_PARK].value =
park * (360 / SettingsN[SETTINGS_AZ_CPR].value);
803 bool DomePro2::setDomeParkAz(uint32_t az)
805 char cmd[DRIVER_LEN] = {0};
806 uint32_t steps =
static_cast<uint32_t
>(az * (SettingsN[SETTINGS_AZ_CPR].value / 360));
815 snprintf(
cmd, DRIVER_LEN,
"DSpa0x%08X", steps);
816 if (sendCommand(
cmd) ==
false)
824 bool DomePro2::calibrateDomeAz(
double az)
826 char cmd[DRIVER_LEN] = {0};
827 uint32_t steps =
static_cast<uint32_t
>(az * (SettingsN[SETTINGS_AZ_CPR].value / 360));
835 snprintf(
cmd, DRIVER_LEN,
"DSca0x%08X", steps);
836 if (sendCommand(
cmd) ==
false)
844 bool DomePro2::getDomeAzStallCount()
846 char res[DRIVER_LEN] = {0};
847 if (sendCommand(
"DGas", res) ==
false)
851 if (sscanf(res,
"%X", &count) == 1)
853 SettingsN[SETTINGS_AZ_STALL_COUNT].value = count;
863 bool DomePro2::setDomeAzStallCount(uint32_t count)
865 char cmd[DRIVER_LEN] = {0};
866 snprintf(
cmd, DRIVER_LEN,
"DSha0x%08X", count);
867 if (sendCommand(
cmd) ==
false)
875 bool DomePro2::getDomeAzPos()
877 char res[DRIVER_LEN] = {0};
878 if (sendCommand(
"DGap", res) ==
false)
882 if (sscanf(res,
"%X", &pos) == 1)
884 DomeAbsPosN[0].value = pos * (360 / SettingsN[SETTINGS_AZ_CPR].value);
894 bool DomePro2::gotoDomeAz(uint32_t az)
896 char cmd[DRIVER_LEN] = {0};
897 if (az >= SettingsN[SETTINGS_AZ_CPR].value)
899 snprintf(
cmd, DRIVER_LEN,
"DSgo0x%08X", az);
900 if (sendCommand(
cmd) ==
false)
908 bool DomePro2::gotoDomePark()
910 if (sendCommand(
"DSgp") ==
false)
918 bool DomePro2::killDomeAzMovement()
920 if (sendCommand(
"DXxa") ==
false)
928 bool DomePro2::killDomeShutterMovement()
930 if (sendCommand(
"DXxs") ==
false)
938 bool DomePro2::openDomeShutters()
940 if (sendCommand(
"DSso") ==
false)
948 bool DomePro2::closeDomeShutters()
950 if (sendCommand(
"DSsc") ==
false)
958 bool DomePro2::gotoHomeDomeAz()
960 if (sendCommand(
"DSah") ==
false)
968 bool DomePro2::discoverHomeDomeAz()
970 if (sendCommand(
"DSdh") ==
false)
978 bool DomePro2::setDomeLeftOn()
980 if (sendCommand(
"DSol") ==
false)
988 bool DomePro2::setDomeRightOn()
990 if (sendCommand(
"DSor") ==
false)
998 bool DomePro2::sendCommand(
const char *
cmd,
char * res,
int cmd_len,
int res_len)
1000 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1002 tcflush(
PortFD, TCIOFLUSH);
1006 char hex_cmd[DRIVER_LEN * 3] = {0};
1007 hexDump(hex_cmd,
cmd, cmd_len);
1015 char formatted_command[DRIVER_LEN] = {0};
1016 snprintf(formatted_command, DRIVER_LEN,
"!%s;",
cmd);
1024 LOGF_ERROR(
"Serial write error: %s.", errstr);
1032 rc =
tty_read(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
1040 LOGF_ERROR(
"Serial read error: %s.", errstr);
1046 char hex_res[DRIVER_LEN * 3] = {0};
1047 hexDump(hex_res, res, res_len);
1053 res[nbytes_read - 1] = 0;
1057 tcflush(
PortFD, TCIOFLUSH);
1065 void DomePro2::hexDump(
char * buf,
const char * data,
int size)
1067 for (
int i = 0; i < size; i++)
1068 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
1071 buf[3 * size - 1] =
'\0';
1077 std::vector<std::string> DomePro2::split(
const std::string &input,
const std::string ®ex)
1080 std::regex re(regex);
1081 std::sregex_token_iterator
1082 first{input.begin(), input.end(), re, -1},
1084 return {first, last};
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual IPState UnPark() override
UnPark dome. The action of the Unpark command is dome specific, but it may include opening the shutte...
virtual IPState ControlShutter(ShutterOperation operation) override
Open or Close shutter.
virtual bool Sync(double az) override
Sync sets the dome current azimuth as the supplied azimuth position.
virtual const char * getDefaultName() override
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
virtual IPState MoveRel(double azDiff) override
Move the Dome to an relative position.
virtual IPState MoveAbs(double az) override
Move the Dome to an absolute azimuth.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual IPState Move(DomeDirection dir, DomeMotionCommand operation) override
Move the Dome in a particular direction.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool Abort() override
Abort all dome motion.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Dome Presets in the configuration file
virtual IPState Park() override
Goto Park Position. The park position is an absolute azimuth value.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * getDeviceName() const
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
void SetDomeCapability(uint32_t cap)
SetDomeCapability set the dome capabilities. All capabilities must be initialized.
ShutterState m_ShutterState
void SetAxis1Park(double value)
SetRAPark Set current AZ parking position. The data park file (stored in ~/.indi/ParkData....
void SetAxis1ParkDefault(double steps)
SetAxis1Park Set default AZ parking position.
ShutterOperation
Shutter operation command.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
INumberVectorProperty DomeAbsPosNP
ISwitchVectorProperty ParkSP
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Dome Presets in the configuration file
void setShutterState(const ShutterState &value)
void setDomeState(const DomeState &value)
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
Connection::Serial * serialConnection
void SetParkDataType(DomeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
ShutterState getShutterState() const
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
DomeState getDomeState() const
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
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.
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.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
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.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)