#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 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(); }