36static std::unique_ptr<EFA> steelDrive(
new EFA());
59 InfoTP[INFO_VERSION].
fill(
"INFO_VERSION",
"Version",
"NA");
63 TemperatureNP[TEMPERATURE_PRIMARY].
fill(
"TEMPERATURE_PRIMARY",
"Primary (c)",
"%.2f", -50, 70., 0., 0.);
64 TemperatureNP[TEMPERATURE_AMBIENT].
fill(
"TEMPERATURE_AMBIENT",
"Ambient (c)",
"%.2f", -50, 70., 0., 0.);
70 FanStateSP[FAN_OFF].
fill(
"FAN_OFF",
"Off",
ISS_ON);
75 FanControlSP[FAN_MANUAL].
fill(
"FAN_MANUAL",
"Manual",
ISS_ON);
76 FanControlSP[FAN_AUTOMATIC_ABSOLUTE].
fill(
"FAN_AUTOMATIC_ABSOLUTE",
"Auto. Absolute",
ISS_OFF);
77 FanControlSP[FAN_AUTOMATIC_RELATIVE].
fill(
"FAN_AUTOMATIC_RELATIVE",
"Auto. Relative",
ISS_OFF);
82 FanControlNP[FAN_MAX_ABSOLUTE].
fill(
"FAN_MAX_ABSOLUTE",
"Max Primary (c)",
"%.2f", 0, 50., 5., 25.);
83 FanControlNP[FAN_MAX_RELATIVE].
fill(
"FAN_MAX_RELATIVE",
"Max Relative (c)",
"%.2f", 0., 30., 1., 2.5);
84 FanControlNP[FAN_DEADZONE].
fill(
"FAN_DEADZONE",
"Deadzone (c)",
"%.2f", 0.1, 10, 0.5, 0.5);
89 FanDisconnectSP[FAN_OFF_ON_DISCONNECT].
fill(
"FAN_OFF_ON_DISCONNECT",
"Switch Off",
ISS_ON);
90 FanDisconnectSP.
fill(
getDeviceName(),
"FOCUS_FAN_DISCONNECT",
"On Disconnect", FAN_TAB,
94 CalibrationStateSP[CALIBRATION_ON].
fill(
"CALIBRATION_ON",
"Calibrated",
ISS_OFF);
95 CalibrationStateSP[CALIBRATION_OFF].
fill(
"CALIBRATION_OFF",
"Not Calibrated",
ISS_ON);
101 ApproachDirectionSP[APPROACH_POSITIVE].
fill(
"APPROACH_POSITIVE",
"Positive (Outward)",
ISS_ON);
102 ApproachDirectionSP[APPROACH_NEGATIVE].
fill(
"APPROACH_NEGATIVE",
"Negative (Inward)",
ISS_OFF);
103 ApproachDirectionSP.
fill(
getDeviceName(),
"FOCUS_APPROACH",
"Approach Direction",
107 StopDetectSP[STOP_DETECT_ON].
fill(
"STOP_DETECT_ON",
"Enabled",
ISS_ON);
108 StopDetectSP[STOP_DETECT_OFF].
fill(
"STOP_DETECT_OFF",
"Disabled",
ISS_OFF);
189 if (FanDisconnectSP[FAN_OFF_ON_DISCONNECT].getState() ==
ISS_ON)
190 setFanEnabled(
false);
204 int bits = TIOCM_RTS;
205 (void) ioctl(
PortFD, TIOCMBIC, &bits);
207 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
214 cmd[5] = calculateCheckSum(
cmd, len);
216 if (!validateLengths(
cmd, len))
219 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
222 version = std::to_string(res[5]) +
"." + std::to_string(res[6]);
223 InfoTP[INFO_VERSION].setText(version.c_str());
225 LOGF_INFO(
"Detected version %s", version.c_str());
235 return "PlaneWave EFA";
248 bool enabled = strcmp(CalibrationStateSP[CALIBRATION_ON].getName(),
IUFindOnSwitchName(states, names, n)) == 0;
249 if (setCalibrationEnabled(enabled))
251 CalibrationStateSP.
update(states, names, n);
259 CalibrationStateSP.
apply();
265 if (FanControlSP[FAN_MANUAL].getState() ==
ISS_OFF)
268 LOG_WARN(
"Cannot control fan while manual control is turned off.");
269 FanControlSP.
apply();
273 bool enabled = strcmp(FanStateSP[FAN_ON].getName(),
IUFindOnSwitchName(states, names, n)) == 0;
274 if (setFanEnabled(enabled))
276 FanStateSP.
update(states, names, n);
290 FanControlSP.
update(states, names, n);
291 if (FanControlSP[FAN_MANUAL].getState() ==
ISS_ON)
294 LOG_INFO(
"Fan is now controlled manually.");
298 LOG_INFO(
"Fan is now controlled automatically per the control parameters.");
303 FanControlSP.
apply();
309 FanDisconnectSP.
update(states, names, n);
311 if (FanDisconnectSP[FAN_OFF_ON_DISCONNECT].getState() ==
ISS_ON)
312 LOG_INFO(
"Fan shall be turned off upon device disconnection.");
314 LOG_INFO(
"Fan shall left as-is upon device disconnection.");
317 FanDisconnectSP.
apply();
323 const bool positiveApproach =
324 strcmp(ApproachDirectionSP[APPROACH_POSITIVE].getName(),
IUFindOnSwitchName(states, names, n)) == 0;
328 const bool currentPositive = (ApproachDirectionSP[APPROACH_POSITIVE].
getState() ==
ISS_ON);
329 if (positiveApproach == currentPositive)
331 LOGF_DEBUG(
"Approach direction already %s; skipping hardware command.",
332 positiveApproach ?
"Positive (Outward)" :
"Negative (Inward)");
334 ApproachDirectionSP.
apply();
338 if (setApproachDirection(positiveApproach ? 0 : 1))
340 ApproachDirectionSP.
update(states, names, n);
342 LOGF_INFO(
"Approach direction set to %s.", positiveApproach ?
"Positive (Outward)" :
"Negative (Inward)");
348 ApproachDirectionSP.
apply();
355 strcmp(StopDetectSP[STOP_DETECT_ON].getName(),
IUFindOnSwitchName(states, names, n)) == 0;
359 const bool currentEnabled = (StopDetectSP[STOP_DETECT_ON].
getState() ==
ISS_ON);
360 if (enabled == currentEnabled)
362 LOGF_DEBUG(
"Stop detection already %s; skipping hardware command.",
363 enabled ?
"enabled" :
"disabled");
365 StopDetectSP.
apply();
369 if (setStopDetect(enabled))
371 StopDetectSP.
update(states, names, n);
373 LOGF_INFO(
"Stop detection %s.", enabled ?
"enabled" :
"disabled");
379 StopDetectSP.
apply();
390bool EFA::ISNewNumber(
const char *dev,
const char *name,
double values[],
char *names[],
int n)
397 FanControlNP.
update(values, names, n);
399 FanControlNP.
apply();
412 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 9;
419 cmd[5] = (ticks >> 16) & 0xFF;
420 cmd[6] = (ticks >> 8) & 0xFF;
421 cmd[7] = (ticks >> 0) & 0xFF;
422 cmd[8] = calculateCheckSum(
cmd, len);
424 if (!validateLengths(
cmd, len))
427 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
430 return (res[5] == 1);
438 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 9;
445 cmd[5] = (targetTicks >> 16) & 0xFF;
446 cmd[6] = (targetTicks >> 8) & 0xFF;
447 cmd[7] = (targetTicks >> 0) & 0xFF;
448 cmd[8] = calculateCheckSum(
cmd, len);
450 if (!validateLengths(
cmd, len))
453 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
466 int relative =
static_cast<int>(ticks);
467 int targetAbsPosition =
FocusAbsPosNP[0].getValue() + (relative * direction * reversed);
469 targetAbsPosition = std::min(
static_cast<uint32_t
>(
FocusAbsPosNP[0].getMax()),
470 static_cast<uint32_t
>(std::max(
static_cast<int>(
FocusAbsPosNP[0].getMin()), targetAbsPosition)));
483 uint32_t currentPos =
static_cast<uint32_t
>(
FocusAbsPosNP[0].getValue());
493 return setMotorSlewRate(
static_cast<uint8_t
>(speed));
508 if (readTemperature())
511 bool aboveThreshold =
false;
512 for (
size_t i = 0; i < TemperatureNP.
count(); i++)
515 if (std::fabs(TemperatureNP[i].getValue() - TEMPERATURE_INVALID) < 0.1)
518 if (std::fabs(TemperatureNP[i].getValue() - m_LastTemperature[i]) > TEMPERATURE_THRESHOLD)
520 aboveThreshold =
true;
521 m_LastTemperature[i] = TemperatureNP[i].getValue();
526 TemperatureNP.
apply();
529 if (FanControlSP[FAN_MANUAL].getState() ==
ISS_OFF)
531 bool turnOn =
false, turnOff =
false;
535 if (FanControlSP[FAN_AUTOMATIC_ABSOLUTE].getState() ==
ISS_ON)
538 if (std::fabs(TemperatureNP[TEMPERATURE_PRIMARY].getValue() - TEMPERATURE_INVALID) > 0.1)
541 double min_delta = FanControlNP[FAN_MAX_ABSOLUTE].getValue() - FanControlNP[FAN_DEADZONE].getValue();
542 double max_delta = FanControlNP[FAN_MAX_ABSOLUTE].getValue() + FanControlNP[FAN_DEADZONE].getValue();
544 turnOn = TemperatureNP[TEMPERATURE_PRIMARY].getValue() > max_delta;
545 turnOff = TemperatureNP[TEMPERATURE_PRIMARY].getValue() < min_delta;
548 else if (FanControlSP[FAN_AUTOMATIC_RELATIVE].getState() ==
ISS_ON)
551 if (std::fabs(TemperatureNP[TEMPERATURE_PRIMARY].getValue() - TEMPERATURE_INVALID) > 0.1 &&
552 std::fabs(TemperatureNP[TEMPERATURE_AMBIENT].getValue() - TEMPERATURE_INVALID) > 0.1)
555 double tDiff = TemperatureNP[TEMPERATURE_PRIMARY].getValue() - TemperatureNP[TEMPERATURE_AMBIENT].getValue();
557 double min_delta = FanControlNP[FAN_MAX_RELATIVE].getValue() - FanControlNP[FAN_DEADZONE].getValue();
558 double max_delta = FanControlNP[FAN_MAX_RELATIVE].getValue() + FanControlNP[FAN_DEADZONE].getValue();
561 turnOn = tDiff > max_delta;
562 turnOff = tDiff < min_delta;
566 if (isFanOn && turnOff)
568 setFanEnabled(
false);
574 else if (!isFanOn && turnOn)
587 if (isGOTOComplete())
593 LOG_INFO(
"Focuser reached requested position.");
598 else if (std::fabs(
FocusAbsPosNP[0].getValue() - m_LastPosition) > 0)
614 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 9;
621 cmd[5] = (ticks >> 16) & 0xFF;
622 cmd[6] = (ticks >> 8) & 0xFF;
623 cmd[7] = (ticks >> 0) & 0xFF;
624 cmd[8] = calculateCheckSum(
cmd, len);
626 if (!validateLengths(
cmd, len))
629 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
632 return (res[5] == 1);
651 FanControlSP.
save(fp);
653 FanControlNP.
save(fp);
654 FanDisconnectSP.
save(fp);
665void EFA::getStartupValues()
668 readCalibrationState();
672 readApproachDirection();
675 if (readMaxSlewLimit())
696inline int EFA::readByte(
int fd, uint8_t *buf,
int timeout,
int *nbytes_read)
698 return tty_read(
fd, (
char *)buf, 1, timeout, nbytes_read);
704inline int EFA::readBytes(
int fd, uint8_t *buf,
int nbytes,
int timeout,
int *nbytes_read)
706 return tty_read(
fd, (
char *)buf, nbytes, timeout, nbytes_read);
712inline int EFA::writeBytes(
int fd,
const uint8_t *buf,
int nbytes,
int *nbytes_written)
714 return tty_write(
fd, (
const char *)buf, nbytes, nbytes_written);
720int EFA::readPacket(
int fd, uint8_t *buf,
int nbytes,
int timeout,
int *nbytes_read)
722 int len = 0, rc = 0, read_bytes = *nbytes_read = 0;
726 LOGF_ERROR(
"Read needs at least 6 bytes; exceeds supplied buffer size (%d)", nbytes);
730 for (
int i = 0; i < 10; i++)
733 rc = readByte(
fd, &buf[0], timeout, &read_bytes);
734 if (rc ==
TTY_OK && read_bytes == 1)
736 if (buf[0] == DRIVER_SOM)
742 LOGF_DEBUG(
"Looking for SOM (%02X); found %d byte (%02X)", DRIVER_SOM, read_bytes, buf[0]);
749 LOGF_DEBUG(
"Looking for SOM (%02X); found %s", DRIVER_SOM, errstr);
755 if (rc !=
TTY_OK || read_bytes != 1 || buf[0] != DRIVER_SOM)
763 if ((rc = readByte(
fd, &buf[1], timeout, &read_bytes)) !=
TTY_OK)
771 if ((rc = readByte(
fd, &buf[2], timeout, &read_bytes)) !=
TTY_OK)
777 if ((rc = readByte(
fd, &buf[3], timeout, &read_bytes)) !=
TTY_OK)
783 if ((rc = readByte(
fd, &buf[4], timeout, &read_bytes)) !=
TTY_OK)
789 if ((len + 3) > nbytes)
791 LOGF_ERROR(
"Read (%d) will exceed supplied buffer size (%d) for command %02X", (len + 3), nbytes, buf[4]);
797 for (n = 0; n < (len - 3); ++n)
799 if ((rc = readByte(
fd, &buf[5 + n], timeout, &read_bytes)) !=
TTY_OK)
801 LOGF_DEBUG(
"%s byte not encountered",
"DATA");
806 if ((rc = readByte(
fd, &buf[5 + n], timeout, &read_bytes)) !=
TTY_OK)
808 LOGF_DEBUG(
"%s byte not encountered",
"DATA");
812 uint8_t chk = calculateCheckSum(buf, (len + 3));
814 if (chk != buf[len + 2])
820 *nbytes_read = len + 3;
828bool EFA::sendCommand(
const uint8_t *
cmd, uint8_t *res, uint32_t cmd_len, uint32_t res_len)
830 int nbytes_written = 0, nbytes_read = 0, bits = 0, rc = 0, hexbuflen = (DRIVER_LEN * 3 + 4);
831 char hexbuf[DRIVER_LEN * 3 + 4];
833 for (
int j = 0; j < 3; usleep(100000), j++)
837 (void) ioctl(
PortFD, TIOCMBIC, &bits);
841 for (
int i = 0; i < 10; i++)
843 if ((rc = ioctl(
PortFD, TIOCMGET, &bits)) == 0 && (bits & TIOCM_CTS) == 0)
853 else if ((bits & TIOCM_CTS) != 0)
855 LOG_ERROR(
"CTS timed out: serial bus is still busy.");
861 ioctl(
PortFD, TIOCMBIS, &bits);
863 if (!IN_TIMER && efaDump(hexbuf, hexbuflen,
cmd, cmd_len) != NULL)
868 tcflush(
PortFD, TCIFLUSH);
869 rc = writeBytes(
PortFD,
cmd, cmd_len, &nbytes_written);
876 rc = readPacket(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
878 if (rc !=
TTY_OK || nbytes_read == 0)
883 if ((
int)cmd_len == nbytes_read && memcmp(
cmd, res, cmd_len) == 0)
888 ioctl(
PortFD, TIOCMBIC, &bits);
891 rc = readPacket(
PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
893 if (rc !=
TTY_OK || nbytes_read == 0)
898 else if (efaDump(hexbuf, hexbuflen,
cmd, cmd_len) != NULL)
901 LOGF_DEBUG(
"no echo for command packet: %s", hexbuf);
904 if (!IN_TIMER && efaDump(hexbuf, hexbuflen, res, nbytes_read) != NULL)
909 if (
cmd[2] != res[3] ||
cmd[3] != res[2] ||
cmd[4] != res[4])
911 LOGF_DEBUG(
"Send/Receive mismatch - %s!",
"packet not for us");
919 ioctl(
PortFD, TIOCMBIC, &bits);
929 if (
cmd[2] != res[3] ||
cmd[3] != res[2] ||
cmd[4] != res[4])
931 LOGF_ERROR(
"Send/Receive mismatch and %s",
"timeout");
941bool EFA::readPosition()
943 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
950 cmd[5] = calculateCheckSum(
cmd, len);
952 if (!validateLengths(
cmd, len))
955 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
958 FocusAbsPosNP[0].setValue(res[5] << 16 | res[6] << 8 | res[7]);
965bool EFA::readMaxSlewLimit()
967 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
974 cmd[5] = calculateCheckSum(
cmd, len);
976 if (!validateLengths(
cmd, len))
979 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
982 uint32_t limit = res[5] << 16 | res[6] << 8 | res[7];
995bool EFA::readSlewRate()
998 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
1000 cmd[0] = DRIVER_SOM;
1005 cmd[5] = calculateCheckSum(
cmd, len);
1007 if (!validateLengths(
cmd, len))
1010 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1013 uint8_t rate = res[5];
1014 if (rate >= 1 && rate <= 9)
1027bool EFA::setMotorSlewRate(uint8_t rate)
1029 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1032 cmd[0] = DRIVER_SOM;
1038 cmd[6] = calculateCheckSum(
cmd, len);
1040 if (!validateLengths(
cmd, len))
1043 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1050 memset(
cmd, 0,
sizeof(
cmd));
1051 memset(res, 0,
sizeof(res));
1052 cmd[0] = DRIVER_SOM;
1058 cmd[6] = calculateCheckSum(
cmd, len);
1060 if (!validateLengths(
cmd, len))
1063 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1066 return (res[5] == 1);
1072bool EFA::readApproachDirection()
1074 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
1076 cmd[0] = DRIVER_SOM;
1081 cmd[5] = calculateCheckSum(
cmd, len);
1083 if (!validateLengths(
cmd, len))
1086 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1090 bool positiveApproach = (res[5] == 0);
1102bool EFA::setApproachDirection(uint8_t direction)
1104 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1106 cmd[0] = DRIVER_SOM;
1112 cmd[6] = calculateCheckSum(
cmd, len);
1114 if (!validateLengths(
cmd, len))
1117 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1120 return (res[5] == 1);
1126bool EFA::readStopDetect()
1128 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
1130 cmd[0] = DRIVER_SOM;
1135 cmd[5] = calculateCheckSum(
cmd, len);
1137 if (!validateLengths(
cmd, len))
1140 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1143 bool enabled = (res[5] == 1);
1153bool EFA::setStopDetect(
bool enabled)
1155 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1157 cmd[0] = DRIVER_SOM;
1162 cmd[5] = enabled ? 1 : 0;
1163 cmd[6] = calculateCheckSum(
cmd, len);
1165 if (!validateLengths(
cmd, len))
1168 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1171 return (res[5] == 1);
1177bool EFA::isGOTOComplete()
1179 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
1181 cmd[0] = DRIVER_SOM;
1186 cmd[5] = calculateCheckSum(
cmd, len);
1188 if (!validateLengths(
cmd, len))
1191 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1194 return (res[5] != 0);
1200bool EFA::setFanEnabled(
bool enabled)
1202 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1204 cmd[0] = DRIVER_SOM;
1209 cmd[5] = enabled ? 1 : 0;
1210 cmd[6] = calculateCheckSum(
cmd, len);
1212 if (!validateLengths(
cmd, len))
1215 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1218 return (res[5] == 1);
1225bool EFA::readFanState()
1227 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 6;
1229 cmd[0] = DRIVER_SOM;
1234 cmd[5] = calculateCheckSum(
cmd, len);
1236 if (!validateLengths(
cmd, len))
1239 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1243 bool enabled = (res[5] == 1);
1254bool EFA::setCalibrationEnabled(
bool enabled)
1256 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 8;
1258 cmd[0] = DRIVER_SOM;
1264 cmd[6] = enabled ? 1 : 0;
1265 cmd[7] = calculateCheckSum(
cmd, len);
1267 if (!validateLengths(
cmd, len))
1270 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1273 return (res[5] == 1);
1279bool EFA::readCalibrationState()
1281 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1283 cmd[0] = DRIVER_SOM;
1289 cmd[6] = calculateCheckSum(
cmd, len);
1291 if (!validateLengths(
cmd, len))
1294 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1297 bool enabled = (res[5] == 1);
1310bool EFA::readTemperature()
1312 uint8_t
cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0}, len = 7;
1314 for (uint8_t i = 0; i < 2; i++)
1316 cmd[0] = DRIVER_SOM;
1322 cmd[6] = calculateCheckSum(
cmd, len);
1324 if (!validateLengths(
cmd, len))
1327 if (!sendCommand(
cmd, res, len, DRIVER_LEN))
1330 double temperature = calculateTemperature(res[5], res[6]);
1332 if (std::fabs(
temperature - TEMPERATURE_INVALID) < 0.1)
1335 LOGF_DEBUG(
"Temperature sensor %d returned invalid data.", i);
1350double EFA::calculateTemperature(uint8_t byte2, uint8_t byte3)
1352 if (byte2 == 0x7F && byte3 == 0x7F)
1353 return TEMPERATURE_INVALID;
1355 int raw_temperature = byte3 << 8 | byte2;
1356 if (raw_temperature & 0x8000)
1357 raw_temperature = raw_temperature - 0x10000;
1359 return raw_temperature / 16.0;
1365char * EFA::efaDump(
char * buf,
int buflen,
const uint8_t * data, uint32_t size)
1367 int needed = 0, idx = 0;
1369 needed = size * 3 + 4;
1371 if (needed > buflen)
1376 for (uint32_t i = 0; i < size; i++)
1380 (void) sprintf(buf + idx,
"<%02X> ", data[i]);
1383 else if (i == 5 && i < (size - 1))
1386 for (uint32_t j = i, k = 3; j < (size - 1) && k < data[1]; j++, k++)
1388 (void) sprintf(buf + idx,
"%02X ", data[j]);
1397 (void) sprintf(buf + idx,
"%02X ", data[i]);
1402 buf[idx - 1] =
'\0';
1410std::vector<std::string> EFA::split(
const std::string &input,
const std::string ®ex)
1413 std::regex re(regex);
1414 std::sregex_token_iterator
1415 first{input.begin(), input.end(), re, -1},
1417 return {first, last};
1423template <
typename T>
1424std::string EFA::to_string(
const T a_value,
const int n)
1426 std::ostringstream out;
1428 out << std::fixed << a_value;
1435bool EFA::validateLengths(
const uint8_t *
cmd, uint32_t len)
1439 LOGF_ERROR(
"packet length (%d) is too short for command %02X", len,
cmd[4]);
1442 if (
cmd[1] + 3 != (
int)len)
1444 LOGF_ERROR(
"packet length (%d) and data length (%d) discrepancy for command %02X", len,
cmd[1],
cmd[4]);
1454uint8_t EFA::calculateCheckSum(
const uint8_t *
cmd, uint32_t len)
1458 for (uint32_t i = 1; i < len - 1; i++)
1461 return ((-sum) & 0xFF);
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
virtual bool SyncFocuser(uint32_t ticks) override
Sync focuser.
virtual IPState MoveRelFocuser(FocusDirection dir, unsigned int ticks) override
Move Focuser relatively.
virtual bool ReverseFocuser(bool enabled) override
Reverse Focuser Motion.
virtual bool saveConfigItems(FILE *fp) override
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
Set Maximum Position.
@ MTR_GET_APPROACH_DIRECTION
@ MTR_SET_CALIBRATION_STATE
@ MTR_GET_CALIBRATION_STATE
const char * getDefaultName() override
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.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
Move Absolute Focuser.
virtual bool AbortFocuser() override
virtual bool SetFocuserSpeed(int speed) override
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...
virtual bool Disconnect() override
Disconnect from device.
virtual bool Disconnect()
Disconnect from device.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSyncNP
@ FOCUSER_HAS_VARIABLE_SPEED
INDI::PropertyNumber FocusSpeedNP
INDI::PropertyNumber FocusMaxPosNP
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 saveConfigItems(FILE *fp) override
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 load()
load Attempt to load property values from configuration file.
void save(FILE *f) const
save Save property to configuration file.
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)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
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
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Implementations for common driver routines.
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
#define LOGF_INFO(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,...)