162 lines
4.6 KiB
C++
162 lines
4.6 KiB
C++
#include "humireader.h"
|
|
|
|
|
|
HumiReader::HumiReader(const std::string devPath) : devPath(std::move(devPath)) {
|
|
|
|
}
|
|
|
|
HumiReader::~HumiReader() {
|
|
closeDevice();
|
|
}
|
|
|
|
void HumiReader::closeDevice() {
|
|
if (fd > 0) close(fd);
|
|
fd = -1;
|
|
}
|
|
|
|
int HumiReader::setupDevice() {
|
|
const int speed = B2400;
|
|
|
|
fd = open(devPath.c_str(), O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
|
|
if (fd <= 0) {
|
|
throw std::runtime_error("Can't open device\n");
|
|
//fprintf(stderr, "Can't open device\n");
|
|
//return 0;
|
|
}
|
|
|
|
struct termios tty;
|
|
|
|
if (tcgetattr(fd, &tty) < 0) {
|
|
throw std::runtime_error(std::string("Error from tcgetattr: ")
|
|
.append(strerror(errno))
|
|
.append(std::string("\n")));
|
|
//fprintf(stderr, "Error from tcgetattr: %s\n", strerror(errno));
|
|
//return 0;
|
|
}
|
|
|
|
cfsetospeed(&tty, (speed_t)speed);
|
|
cfsetispeed(&tty, (speed_t)speed);
|
|
|
|
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
|
|
tty.c_cflag &= ~CSIZE;
|
|
tty.c_cflag |= CS8; /* 8-bit characters */
|
|
tty.c_cflag &= ~PARENB; /* no parity bit */
|
|
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
|
|
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
|
|
|
|
|
|
/* fetch bytes as they become available */
|
|
tty.c_cc[VMIN] = 1;
|
|
tty.c_cc[VTIME] = 1;
|
|
|
|
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
|
|
throw std::runtime_error(std::string("Error from tcsetattr: ")
|
|
.append(strerror(errno))
|
|
.append(std::string("\n")));
|
|
//fprintf(stderr, "Error from tcsetattr: %s\n", strerror(errno));
|
|
//fflush(0);
|
|
//return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int HumiReader::parseLine(const char* buf) {
|
|
if (buf) {
|
|
//printf("Got: %s\n", buf);
|
|
int len = strlen(buf);
|
|
if (len > 15 && buf[0] == '.') {
|
|
char t=buf[2];
|
|
|
|
errno = 0;
|
|
int tempRes = strtol(&buf[5], nullptr, 10);
|
|
if (errno != 0) return -1;
|
|
|
|
int humiRes = strtol(&buf[10], nullptr, 10);
|
|
if (errno != 0) return -1;
|
|
|
|
//printf ("\t- %c %i %i\n", t, tempRes, humiRes);
|
|
if (t == 'A') {
|
|
currentResult.sensorATemp = tempRes;
|
|
currentResult.sensorARelHumi = humiRes;
|
|
hasAResult = true;
|
|
}
|
|
else {
|
|
currentResult.sensorITemp = tempRes;
|
|
currentResult.sensorIRelHumi = humiRes;
|
|
hasIResult = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void HumiReader::setCallback(std::function<bool(const HumiResult&)> cb) {
|
|
this->cb = cb;
|
|
}
|
|
|
|
void HumiReader::run() {
|
|
if (!setupDevice()) {
|
|
throw std::runtime_error("Can't setup device\n");
|
|
//throw "Can't setup device";
|
|
}
|
|
cancelLoop = false;
|
|
hasIResult = false;
|
|
hasAResult = false;
|
|
|
|
char buf[32+1];
|
|
char outbuf[256];
|
|
unsigned int outbufsiz =0;
|
|
unsigned int sleepMax = 10000;
|
|
|
|
while(!cancelLoop) {
|
|
int siz = read(fd, buf, sizeof(buf)-1);
|
|
if (siz < 0) {
|
|
if (errno != EAGAIN) {
|
|
throw "Read failed";
|
|
}
|
|
else {
|
|
if (sleepMax <= 0) {
|
|
throw "Timeout";
|
|
}
|
|
usleep(10*1000);
|
|
sleepMax -= 10;
|
|
}
|
|
}
|
|
else if (siz > 0) {
|
|
sleepMax = 10000;
|
|
buf[siz] = 0;
|
|
//printf("Got: %s", buf);
|
|
|
|
for (int i=0; i < siz; i++) {
|
|
char ch = buf[i];
|
|
if ((ch != 10) && (ch != 13)) {
|
|
outbuf[outbufsiz] = ch;
|
|
outbufsiz++;
|
|
outbuf[outbufsiz] = 0;
|
|
}
|
|
else {
|
|
ch = 13;
|
|
}
|
|
|
|
if (((outbufsiz > 0) && (ch == 13)) || (outbufsiz > sizeof(outbuf)-1)) {
|
|
parseLine((const char*) outbuf);
|
|
outbufsiz = 0;
|
|
|
|
// Both sensor read? then send to output
|
|
if (hasIResult && hasAResult) {
|
|
if (cb != nullptr) {
|
|
bool res = this->cb(currentResult);
|
|
if (!res) cancelLoop=true;
|
|
}
|
|
hasIResult = false;
|
|
hasAResult = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
closeDevice();
|
|
}
|