36 #define MBOX_TIMEOUT 6
40 static std::unique_ptr<MBox> mbox(
new MBox());
56 addParameter(
"WEATHER_TEMPERATURE",
"Temperature (C)", -10, 30, 15);
57 addParameter(
"WEATHER_BAROMETER",
"Barometer (mbar)", 20, 32.5, 15);
58 addParameter(
"WEATHER_HUMIDITY",
"Humidity %", 0, 100, 15);
59 addParameter(
"WEATHER_DEWPOINT",
"Dew Point (C)", 0, 100, 15);
69 IUFillNumber(&CalibrationN[CAL_TEMPERATURE],
"CAL_TEMPERATURE",
"Temperature",
"%.f", -50, 50, 1, 0);
70 IUFillNumber(&CalibrationN[CAL_PRESSURE],
"CAL_PRESSURE",
"Pressure",
"%.f", -100, 100, 10, 0);
71 IUFillNumber(&CalibrationN[CAL_HUMIDITY],
"CAL_HUMIDITY",
"Humidity",
"%.f", -50, 50, 1, 0);
76 IUFillText(&FirmwareT[0],
"VERSION",
"Version",
"--");
111 AckResponse rc = ACK_ERROR;
113 for (
int i = 0; i < 3; i++)
120 if (rc == ACK_OK_STARTUP)
122 getCalibration(
false);
125 else if (rc == ACK_OK_INIT)
141 if (getCalibration(
true))
152 strncpy(response,
"$PXDR,P,96276.0,P,0,C,31.8,C,1,H,40.8,P,2,C,16.8,C,3,1.1*31\r\n",
MBOX_BUF);
153 nbytes_read = strlen(response);
162 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
166 tcflush(
PortFD, TCIOFLUSH);
170 response[nbytes_read - 2] =
'\0';
174 if (verifyCRC(response) ==
false)
181 char *end = strstr(response,
"*");
185 std::vector<std::string> result = split(response,
",");
187 setParameterValue(
"WEATHER_BAROMETER", std::stod(result[SENSOR_PRESSURE]) / 100.0);
191 if (strcmp(result[FIRMWARE].c_str(), FirmwareT[0].text))
193 IUSaveText(&FirmwareT[0], result[FIRMWARE].c_str());
201 MBox::AckResponse MBox::ack()
208 strncpy(response,
"MBox by Astromi.ch\r\n", 64);
209 nbytes_read = strlen(response);
219 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
224 if (response[0] ==
'\n')
229 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
236 response[nbytes_read - 2] =
'\0';
240 if (strstr(response,
"MBox"))
241 return ACK_OK_STARTUP;
243 else if (strstr(response,
"PXDR"))
249 bool MBox::ISNewNumber(
const char *dev,
const char *name,
double values[],
char *names[],
int n)
253 if (!strcmp(name, CalibrationNP.
name))
255 double prevPressure = CalibrationN[CAL_PRESSURE].value;
256 double prevTemperature = CalibrationN[CAL_TEMPERATURE].value;
257 double prevHumidaty = CalibrationN[CAL_HUMIDITY].value;
259 double targetPressure = CalibrationN[CAL_PRESSURE].value;
260 double targetTemperature = CalibrationN[CAL_TEMPERATURE].value;
261 double targetHumidity = CalibrationN[CAL_HUMIDITY].value;
264 if (targetPressure != prevPressure)
266 rc = setCalibration(CAL_PRESSURE);
269 if (targetTemperature != prevTemperature)
271 rc = setCalibration(CAL_TEMPERATURE);
274 if (targetHumidity != prevHumidaty)
276 rc = setCalibration(CAL_HUMIDITY);
292 if (!strcmp(name, ResetSP.
name))
294 if (resetCalibration())
298 LOG_INFO(
"Calibration values are reset.");
300 CalibrationN[CAL_PRESSURE].value = 0;
301 CalibrationN[CAL_TEMPERATURE].value = 0;
302 CalibrationN[CAL_HUMIDITY].value = 0;
320 bool MBox::getCalibration(
bool sendCommand)
322 int nbytes_written = 0, nbytes_read = 0;
324 const char *command =
":calget*";
332 strncpy(response,
"$PCAL,P,20,T,50,H,-10*79\r\n", 64);
333 nbytes_read = strlen(response);
342 tcflush(
PortFD, TCIOFLUSH);
347 LOGF_ERROR(
"%s write error: %s.", __FUNCTION__, errstr);
355 LOGF_ERROR(
"%s read error: %s.", __FUNCTION__, errstr);
360 if (strstr(response,
"$PCAL") ==
nullptr)
365 LOGF_ERROR(
"%s read error: %s.", __FUNCTION__, errstr);
372 response[nbytes_read - 2] =
'\0';
376 if (verifyCRC(response) ==
false)
383 char *end = strstr(response,
"*");
387 std::vector<std::string> result = split(response,
",");
388 CalibrationN[CAL_PRESSURE].value = std::stod(result[SENSOR_PRESSURE]) / 10.0;
389 CalibrationN[CAL_TEMPERATURE].value = std::stod(result[SENSOR_PRESSURE + 2]) / 10.0;
390 CalibrationN[CAL_HUMIDITY].value = std::stod(result[SENSOR_PRESSURE + 4]) / 10.0;
394 bool MBox::setCalibration(CalibrationType
type)
396 int nbytes_written = 0, rc = -1;
398 char command[16] = {0};
400 if (
type == CAL_PRESSURE)
403 snprintf(command, 16,
":calp,%d*",
static_cast<int32_t
>(CalibrationN[CAL_PRESSURE].value * 10.0));
409 tcflush(
PortFD, TCIOFLUSH);
414 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
420 else if (
type == CAL_TEMPERATURE)
423 snprintf(command, 16,
":calt,%d*",
static_cast<int32_t
>(CalibrationN[CAL_TEMPERATURE].value * 10.0));
429 tcflush(
PortFD, TCIOFLUSH);
434 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
442 snprintf(command, 16,
":calh,%d*",
static_cast<int32_t
>(CalibrationN[CAL_HUMIDITY].value * 10.0));
448 tcflush(
PortFD, TCIOFLUSH);
453 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
460 return getCalibration(
false);
463 bool MBox::resetCalibration()
465 const char *command =
":calreset*";
470 int nbytes_written = 0, rc = -1;
471 tcflush(
PortFD, TCIOFLUSH);
477 LOGF_ERROR(
"%s error: %s.", __FUNCTION__, errstr);
485 bool MBox::verifyCRC(
const char *response)
488 uint8_t calculated_checksum = 0, response_checksum = 0;
490 char checksum_string[
MBOX_BUF] = {0};
491 strncpy(checksum_string, response + 1,
MBOX_BUF);
493 std::vector<std::string> result = split(checksum_string, R
"(\*)");
498 response_checksum = std::stoi(result[1],
nullptr, 16);
507 for (
auto oneByte : result[0])
508 calculated_checksum ^= oneByte;
510 return (calculated_checksum == response_checksum);
516 std::vector<std::string> MBox::split(
const std::string &input,
const std::string ®ex)
519 std::regex re(regex);
520 std::sregex_token_iterator
521 first{input.begin(), input.end(), re, -1},
523 return {first, last};
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
const char * getDeviceName() const
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)
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
bool setCriticalParameter(std::string param)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning)
addParameter Add a physical weather measurable parameter to the weather driver. The weather value has...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Connection::Serial * serialConnection
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual IPState updateWeather() override
updateWeather Update weather conditions from device or service. The function should not change the st...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual const char * getDefaultName() override
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
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.
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 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 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,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
void IDSetText(const ITextVectorProperty *tvp, const char *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,...)