humireader/humireader.cpp

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