31 #define NIGHTCRAWLER_TIMEOUT 3
32 #define NIGHTCRAWLER_THRESHOLD 0.1
34 #define NC_25_STEPS 374920
35 #define NC_30_STEPS 444080
36 #define NC_35_STEPS 505960
38 #define ROTATOR_TAB "Rotator"
40 #define SETTINGS_TAB "Settings"
45 static std::unique_ptr<NightCrawler> tommyGoodBoy(
new NightCrawler());
65 IUFillNumber(&SyncFocusN[0],
"FOCUS_SYNC_OFFSET",
"Ticks",
"%.f", 0, 100000., 0., 0.);
70 IUFillNumber(&VoltageN[0],
"VALUE",
"Value (v)",
"%.2f", 0, 30., 1., 0.);
74 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Value (C)",
"%.2f", -100, 100., 1., 0.);
79 IUFillNumber(&TemperatureOffsetN[0],
"OFFSET",
"Offset",
"%.2f", -15, 15., 1., 0.);
84 IUFillNumber(&FocusStepDelayN[0],
"FOCUS_STEP",
"Value",
"%.f", 7, 100., 1., 7.);
89 IUFillLight(&LimitSwitchL[ROTATION_SWITCH],
"ROTATION_SWITCH",
"Rotation Home",
IPS_OK);
110 IUFillSwitchVector(&EncoderSP, EncoderS, 2,
getDeviceName(),
"ENCODERS",
"Encoders",
SETTINGS_TAB,
IP_RW,
ISR_1OFMANY, 0,
114 IUFillNumber(&BrightnessN[BRIGHTNESS_DISPLAY],
"BRIGHTNESS_DISPLAY",
"Display",
"%.f", 0, 255., 10., 150.);
115 IUFillNumber(&BrightnessN[BRIGHTNESS_SLEEP],
"BRIGHTNESS_SLEEP",
"Sleep",
"%.f", 1, 255., 10., 16.);
126 IUFillNumber(&RotatorAbsPosN[0],
"ROTATOR_ABSOLUTE_POSITION",
"Ticks",
"%.f", 0., 100000., 1000., 0.);
131 IUFillNumber(&RotatorStepDelayN[0],
"ROTATOR_STEP",
"Value",
"%.f", 7, 100., 1., 7.);
136 CustomRotatorStepNP[0].
fill(
"STEPS",
"Steps",
"%.f", 0, 5000000, 0, 0);
144 IUFillNumber(&GotoAuxN[0],
"AUX_ABSOLUTE_POSITION",
"Ticks",
"%.f", 0, 100000., 0., 0.);
153 IUFillNumber(&SyncAuxN[0],
"AUX_SYNC_TICK",
"Ticks",
"%.f", 0, 100000., 0., 0.);
157 IUFillNumber(&AuxStepDelayN[0],
"AUX_STEP",
"Value",
"%.f", 7, 100., 1., 7.);
248 LOG_INFO(
"Error retrieving data from NightCrawler, please ensure NightCrawler controller is powered and the port is correct.");
254 return "NightCrawler";
257 bool NightCrawler::Ack()
259 bool rcFirmware = getFirmware();
260 bool rcType = getFocuserType();
262 return (rcFirmware && rcType);
265 bool NightCrawler::getFirmware()
267 int nbytes_written = 0, nbytes_read = 0, rc = -1;
271 tcflush(
PortFD, TCIOFLUSH);
287 tcflush(
PortFD, TCIOFLUSH);
289 resp[nbytes_read - 1] =
'\0';
296 bool NightCrawler::getFocuserType()
298 int nbytes_written = 0, nbytes_read = 0, rc = -1;
302 tcflush(
PortFD, TCIOFLUSH);
318 tcflush(
PortFD, TCIOFLUSH);
320 resp[nbytes_read - 1] =
'\0';
324 if (strcmp(resp,
"2.5 NC") == 0)
330 else if (strcmp(resp,
"3.0 NC") == 0)
343 m_RotatorTicksPerDegree = m_RotatorStepsPerRevolution / 360.0;
348 bool NightCrawler::gotoMotor(MotorType
type, int32_t position)
353 int nbytes_written = 0, nbytes_read = 0, rc = -1;
356 snprintf(
cmd, 16,
"%dSN %d#",
type + 1, position);
360 tcflush(
PortFD, TCIOFLUSH);
372 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
378 return startMotor(
type);
381 bool NightCrawler::getPosition(MotorType
type)
387 int nbytes_written = 0, nbytes_read = 0, rc = -1;
390 snprintf(
cmd, 16,
"%dGP#",
type + 1);
394 tcflush(
PortFD, TCIOFLUSH);
401 abnormalDisconnect();
408 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
412 res[nbytes_read] =
'\0';
416 position = atoi(res);
418 if (position != -1e6)
423 RotatorAbsPosN[0].value = position;
425 GotoAuxN[0].value = position;
444 void NightCrawler::abnormalDisconnect()
462 if (strcmp(name, HomeSelectionSP.
name) == 0)
464 bool atLeastOne =
false;
466 for (
int i = 0; i < n; i++)
478 LOG_ERROR(
"At least one selection must be on.");
488 else if (strcmp(name, FindHomeSP.
name) == 0)
490 uint8_t selection = 0;
499 if (findHome(selection))
503 LOG_WARN(
"Homing process can take up to 10 minutes. You cannot control the unit until the process is fully complete.");
509 LOG_ERROR(
"Failed to start homing process.");
515 else if (strcmp(name, EncoderSP.
name) == 0)
520 LOGF_INFO(
"Encoders are %s", (EncoderS[0].s ==
ISS_ON) ?
"ON" :
"OFF");
524 else if (strcmp(name, AbortAuxSP.
name) == 0)
538 else if (strstr(name,
"ROTATOR"))
552 if (strcmp(name, SyncFocusNP.
name) == 0)
554 bool rc = syncMotor(
MOTOR_FOCUS,
static_cast<uint32_t
>(values[0]));
557 SyncFocusN[0].value = values[0];
562 else if (strcmp(name, SyncAuxNP.
name) == 0)
564 bool rc = syncMotor(
MOTOR_AUX,
static_cast<uint32_t
>(values[0]));
567 SyncAuxN[0].value = values[0];
572 else if (strcmp(name, TemperatureOffsetNP.
name) == 0)
574 bool rc = setTemperatureOffset(values[0]);
579 else if (strcmp(name, FocusStepDelayNP.
name) == 0)
581 bool rc = setStepDelay(
MOTOR_FOCUS,
static_cast<uint32_t
>(values[0]));
584 FocusStepDelayN[0].value = values[0];
588 else if (strcmp(name, RotatorStepDelayNP.
name) == 0)
590 bool rc = setStepDelay(
MOTOR_ROTATOR,
static_cast<uint32_t
>(values[0]));
593 RotatorStepDelayN[0].value = values[0];
597 else if (strcmp(name, AuxStepDelayNP.
name) == 0)
599 bool rc = setStepDelay(
MOTOR_AUX,
static_cast<uint32_t
>(values[0]));
602 AuxStepDelayN[0].value = values[0];
606 else if (strcmp(name, BrightnessNP.
name) == 0)
609 bool rcDisplay = setDisplayBrightness(
static_cast<uint8_t
>(BrightnessN[BRIGHTNESS_DISPLAY].value));
610 bool rcSleep = setSleepBrightness(
static_cast<uint8_t
>(BrightnessN[BRIGHTNESS_SLEEP].value));
611 if (rcDisplay && rcSleep)
619 else if (strcmp(name, GotoAuxNP.
name) == 0)
621 bool rc = gotoMotor(
MOTOR_AUX,
static_cast<int32_t
>(values[0]));
624 LOGF_INFO(
"Aux moving to %.f...", values[0]);
627 else if (strcmp(name, RotatorAbsPosNP.
name) == 0)
632 LOGF_INFO(
"Rotator moving to %.f ticks...", values[0]);
637 CustomRotatorStepNP.
update(values, names, n);
639 CustomRotatorStepNP.
apply();
641 auto customValue = CustomRotatorStepNP[0].getValue();
644 RotatorAbsPosN[0].min = customValue / 2.0;
645 RotatorAbsPosN[0].max = customValue / 2.0;
646 m_RotatorStepsPerRevolution = customValue;
647 m_RotatorTicksPerDegree = m_RotatorStepsPerRevolution / 360.0;
650 LOGF_INFO(
"Custom steps per revolution updated to %.f. Ticks per degree %.2f", customValue,
651 m_RotatorTicksPerDegree);
656 else if (strstr(name,
"ROTATOR"))
668 targetPosition = targetTicks;
684 double newPosition = 0;
716 if (isHomingComplete())
734 rc = getTemperature();
737 lastTemperature = TemperatureN[0].value;
745 lastVoltage = VoltageN[0].value;
750 rc = getLimitSwitchStatus();
751 if (rc && (LimitSwitchL[ROTATION_SWITCH].s != rotationLimit || LimitSwitchL[OUT_SWITCH].s != outSwitchLimit
752 || LimitSwitchL[IN_SWITCH].s != inSwitchLimit))
754 rotationLimit = LimitSwitchL[ROTATION_SWITCH].s;
755 outSwitchLimit = LimitSwitchL[OUT_SWITCH].s;
756 inSwitchLimit = LimitSwitchL[IN_SWITCH].s;
761 bool absFocusUpdated =
false;
774 absFocusUpdated =
true;
781 absFocusUpdated =
true;
787 bool absRotatorUpdated =
false;
796 absRotatorUpdated =
true;
797 LOG_INFO(
"Rotator motion complete.");
803 while (RotatorAbsPosN[0].value < -m_RotatorStepsPerRevolution || RotatorAbsPosN[0].value > m_RotatorStepsPerRevolution)
806 const auto newOffset =
static_cast<int32_t
>(RotatorAbsPosN[0].value) % m_RotatorStepsPerRevolution;
807 LOGF_INFO(
"Out of bounds value detected. Syncing rotator position to %d", newOffset);
813 lastRotatorPosition = RotatorAbsPosN[0].value;
818 absRotatorUpdated =
true;
820 if (absRotatorUpdated)
827 bool absAuxUpdated =
false;
835 absAuxUpdated =
true;
842 lastAuxPosition = GotoAuxN[0].value;
843 absAuxUpdated =
true;
856 bool NightCrawler::syncMotor(MotorType
type, uint32_t position)
861 int nbytes_written = 0, nbytes_read = 0, rc = -1;
864 snprintf(
cmd, 16,
"%dSP %d#",
type + 1, position);
868 tcflush(
PortFD, TCIOFLUSH);
880 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
884 res[nbytes_read] =
'\0';
888 return (res[0] ==
'#');
891 bool NightCrawler::startMotor(MotorType
type)
896 int nbytes_written = 0, nbytes_read = 0, rc = -1;
899 snprintf(
cmd, 16,
"%dSM#",
type + 1);
903 tcflush(
PortFD, TCIOFLUSH);
915 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
919 res[nbytes_read] =
'\0';
923 return (res[0] ==
'#');
926 bool NightCrawler::stopMotor(MotorType
type)
931 int nbytes_written = 0, nbytes_read = 0, rc = -1;
934 snprintf(
cmd, 16,
"%dSQ#",
type + 1);
938 tcflush(
PortFD, TCIOFLUSH);
950 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
954 res[nbytes_read] =
'\0';
958 return (res[0] ==
'#');
961 bool NightCrawler::isMotorMoving(MotorType
type)
966 int nbytes_written = 0, nbytes_read = 0, rc = -1;
969 snprintf(
cmd, 16,
"%dGM#",
type + 1);
973 tcflush(
PortFD, TCIOFLUSH);
978 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
985 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
989 res[nbytes_read - 1] =
'\0';
993 return (strcmp(
"01", res) == 0);
996 bool NightCrawler::getTemperature()
998 char cmd[16] =
"GT#";
1001 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1006 tcflush(
PortFD, TCIOFLUSH);
1011 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1018 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1022 res[nbytes_read - 1] =
'\0';
1026 TemperatureN[0].value = atoi(res) / 10.0;
1031 bool NightCrawler::getVoltage()
1033 char cmd[16] =
"GV#";
1036 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1041 tcflush(
PortFD, TCIOFLUSH);
1046 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1053 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1057 res[nbytes_read - 1] =
'\0';
1061 VoltageN[0].value = atoi(res) / 10.0;
1066 bool NightCrawler::setTemperatureOffset(
double offset)
1070 int nbytes_written = 0, rc = -1;
1073 snprintf(
cmd, 16,
"Pt %03d#",
static_cast<int>(offset * 10));
1077 tcflush(
PortFD, TCIOFLUSH);
1082 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1089 bool NightCrawler::getStepDelay(MotorType
type)
1094 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1097 snprintf(
cmd, 16,
"%dSR#",
type + 1);
1101 tcflush(
PortFD, TCIOFLUSH);
1113 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1117 res[nbytes_read - 1] =
'\0';
1122 FocusStepDelayN[0].value = atoi(res);
1124 RotatorStepDelayN[0].value = atoi(res);
1126 AuxStepDelayN[0].value = atoi(res);
1131 bool NightCrawler::setStepDelay(MotorType
type, uint32_t delay)
1136 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1139 snprintf(
cmd, 16,
"%dSR %03d#",
type + 1, delay);
1143 tcflush(
PortFD, TCIOFLUSH);
1148 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1155 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1159 res[nbytes_read] =
'\0';
1163 return (res[0] ==
'#');
1166 bool NightCrawler::getLimitSwitchStatus()
1168 char cmd[16] =
"GS#";
1171 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1176 tcflush(
PortFD, TCIOFLUSH);
1181 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1188 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1192 res[nbytes_read - 1] =
'\0';
1196 int value = atoi(res);
1205 bool NightCrawler::findHome(uint8_t motorTypes)
1210 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1213 snprintf(
cmd, 16,
"SH %02d#", motorTypes);
1217 tcflush(
PortFD, TCIOFLUSH);
1222 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1229 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1233 res[nbytes_read] =
'\0';
1237 return (res[0] ==
'#');
1240 bool NightCrawler::isHomingComplete()
1243 int nbytes_read = 0, rc = -1;
1248 LOG_DEBUG(
"Waiting for NightCrawler to complete homing...");
1252 res[nbytes_read - 1] =
'\0';
1256 return (strcmp(
"OK", res) == 0);
1259 bool NightCrawler::setEncodersEnabled(
bool enable)
1264 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1267 snprintf(
cmd, 16,
"PE %s#", enable ?
"01" :
"00");
1271 tcflush(
PortFD, TCIOFLUSH);
1276 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1283 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1287 res[nbytes_read] =
'\0';
1294 bool NightCrawler::setDisplayBrightness(uint8_t value)
1299 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1302 snprintf(
cmd, 16,
"PD %03d#", value);
1306 tcflush(
PortFD, TCIOFLUSH);
1311 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1318 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1322 res[nbytes_read] =
'\0';
1326 return (res[0] ==
'#');
1329 bool NightCrawler::setSleepBrightness(uint8_t value)
1334 int nbytes_written = 0, nbytes_read = 0, rc = -1;
1337 snprintf(
cmd, 16,
"PL %03d#", value);
1341 tcflush(
PortFD, TCIOFLUSH);
1346 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1353 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
1357 res[nbytes_read] =
'\0';
1361 return (res[0] ==
'#');
1366 Focuser::saveConfigItems(fp);
1373 CustomRotatorStepNP.
save(fp);
1385 LOG_WARN(
"Homing process can take up to 10 minutes. You cannot control the unit until the process is fully complete.");
1393 LOG_ERROR(
"Failed to start homing process.");
1404 auto newAngle = ( angle > 180 ? angle - 360 : angle);
1408 auto newTarget = newAngle * m_RotatorTicksPerDegree;
1409 if (newTarget < RotatorAbsPosN[0].
min)
1410 newTarget = RotatorAbsPosN[0].min;
1411 else if (newTarget > RotatorAbsPosN[0].
max)
1412 newTarget = RotatorAbsPosN[0].max;
1414 bool rc = gotoMotor(
MOTOR_ROTATOR,
static_cast<int32_t
>(newTarget));
1429 auto newAngle = ( angle > 180 ? angle - 360 : angle);
1433 auto newTarget = newAngle * m_RotatorTicksPerDegree;
1434 if (newTarget < RotatorAbsPosN[0].
min)
1435 newTarget = RotatorAbsPosN[0].min;
1436 else if (newTarget > RotatorAbsPosN[0].
max)
1437 newTarget = RotatorAbsPosN[0].max;
1439 return syncMotor(
MOTOR_ROTATOR,
static_cast<int32_t
>(newTarget));
1445 if (rc && RotatorAbsPosNP.
s !=
IPS_OK)
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
const char * getDeviceName() const
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
virtual bool Disconnect()
Disconnect from device.
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
virtual void setConnected(bool status, IPState state=IPS_OK, const char *msg=nullptr)
Set connection switch status in the client.
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 setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool Connect()
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
uint16_t getDriverInterface() const
void addDebugControl()
Add Debug control to the driver.
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Connection::Serial * serialConnection
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
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 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
INumberVectorProperty GotoRotatorNP
void initProperties(const char *groupName)
Initilize Rotator properties. It is recommended to call this function within initProperties() of your...
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.
ISwitchVectorProperty HomeRotatorSP
ISwitch ReverseRotatorS[2]
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process Rotator number properties.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual IPState MoveRotator(double angle) override
MoveRotator Go to specific angle.
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 AbortRotator() override
AbortRotator Abort all motion.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual IPState HomeRotator() override
HomeRotator Go to home position.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
virtual bool Handshake() override
perform handshake with device to check communication
static void abnormalDisconnectCallback(void *userpointer)
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool SyncRotator(double angle) override
SyncRotator Set current angle as the supplied angle without moving the rotator.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ReverseRotator(bool enabled) override
ReverseRotator Reverse the direction of the rotator. CW is usually the normal direction,...
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Provides interface to implement Rotator functionality.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
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
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Implementations for common driver routines.
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
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 IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
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 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.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
#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,...)
@ value
the parser finished reading a JSON value
#define NIGHTCRAWLER_TIMEOUT
#define NIGHTCRAWLER_THRESHOLD