mirror of https://github.com/sfeakes/AqualinkD.git
239 lines
6.1 KiB
C
239 lines
6.1 KiB
C
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
//#include <errno.h>
|
|
#include <string.h>
|
|
#include <regex.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "aqualink.h"
|
|
//#include "utils.h"
|
|
#include "sensors.h"
|
|
|
|
|
|
/*
|
|
----------
|
|
GPIO and thermal sensors are simply read value in file
|
|
----------
|
|
1Wire is similar to
|
|
/sys/bus/w1/devices/28-011564e2feff/w1_slave
|
|
90 01 4b 46 7f ff 0c 10 33 : crc=33 YES
|
|
90 01 4b 46 7f ff 0c 10 33 t=25000
|
|
read the t= value.
|
|
|
|
regex would be something like .*t=([0-9|\.]*)
|
|
-----------
|
|
*/
|
|
|
|
|
|
/*
|
|
read sensor value from ie /sys/class/thermal/thermal_zone0/temp
|
|
|
|
return true if current reading is different to last value stored
|
|
*/
|
|
|
|
struct sensorthread {
|
|
pthread_t thread_id;
|
|
pthread_mutex_t thread_mutex;
|
|
pthread_cond_t thread_cond;
|
|
struct aqualinkdata *aq_data;
|
|
struct timespec timeout;
|
|
};
|
|
|
|
struct sensorthread *_sthread = NULL;
|
|
|
|
void *sensors_worker( void *ptr );
|
|
|
|
void stop_sensors_thread() {
|
|
LOG(AQUA_LOG, LOG_INFO, "Stopping sensor thread\n");
|
|
|
|
pthread_cond_broadcast(&_sthread->thread_cond);
|
|
}
|
|
|
|
void start_sensors_thread(struct aqualinkdata *aq_data) {
|
|
|
|
_sthread = calloc(1, sizeof(struct sensorthread));
|
|
|
|
_sthread->aq_data = aq_data;
|
|
_sthread->thread_id = 0;
|
|
|
|
if( pthread_create( &_sthread->thread_id , NULL , sensors_worker, (void*)_sthread) < 0) {
|
|
LOG(AQUA_LOG, LOG_ERR, "could not create sensors thread\n");
|
|
free(_sthread);
|
|
return;
|
|
}
|
|
|
|
if ( _sthread->thread_id != 0 ) {
|
|
pthread_detach(_sthread->thread_id);
|
|
}
|
|
}
|
|
|
|
void *sensors_worker( void *ptr )
|
|
{
|
|
struct sensorthread *sthread;
|
|
sthread = (struct sensorthread *) ptr;
|
|
int retval = 0;
|
|
|
|
LOG(AQUA_LOG, LOG_NOTICE, "Started sensor thread\n");
|
|
|
|
pthread_mutex_lock(&sthread->thread_mutex);
|
|
|
|
do {
|
|
if (retval != 0 && retval != ETIMEDOUT) {
|
|
LOG(AQUA_LOG, LOG_ERR, "Sensor thread pthread_cond_timedwait failed for error %d %s\n",retval,strerror(retval));
|
|
break;
|
|
}
|
|
|
|
for (int i=0; i < sthread->aq_data->num_sensors; i++) {
|
|
//LOG(AQUA_LOG, LOG_DEBUG, "Sensor thread reading %s\n",sthread->aq_data->sensors[i].label);
|
|
if (read_sensor(&sthread->aq_data->sensors[i]) ) {
|
|
sthread->aq_data->updated = true;
|
|
}
|
|
}
|
|
|
|
clock_gettime(CLOCK_REALTIME, &sthread->timeout);
|
|
sthread->timeout.tv_sec += _aqconfig_.sensor_poll_time;
|
|
//sthread->started_at = time(0);
|
|
//LOG(AQUA_LOG, LOG_DEBUG, "Sensor thread will sleep for %d seconds\n",_aqconfig_.sensor_poll_time);
|
|
} while ((retval = pthread_cond_timedwait(&sthread->thread_cond, &sthread->thread_mutex, &sthread->timeout)) == ETIMEDOUT);
|
|
|
|
pthread_mutex_unlock(&sthread->thread_mutex);
|
|
|
|
LOG(AQUA_LOG, LOG_DEBUG, "End sensor thread\n");
|
|
|
|
free(sthread);
|
|
pthread_exit(0);
|
|
}
|
|
|
|
#define READ_BUFFER_SIZE 256
|
|
|
|
bool read_sensor(external_sensor *sensor) {
|
|
int fp;
|
|
float value = 0.0;
|
|
char buffer[READ_BUFFER_SIZE];
|
|
char *startptr = &buffer[0];
|
|
char *endptr;
|
|
|
|
fp = open(sensor->path, O_RDONLY, 0);
|
|
if (fp < 0) {
|
|
LOGSystemError(errno, AQUA_LOG, sensor->path);
|
|
LOG(AQUA_LOG,LOG_ERR, "Reading sensor %s %s\n",sensor->label, sensor->path);
|
|
return FALSE;
|
|
}
|
|
|
|
// Read the sensor
|
|
if ( read(fp, buffer, READ_BUFFER_SIZE) <= 0 ) {
|
|
LOG(AQUA_LOG,LOG_ERR, "Reading value from sensor %s %s\n",sensor->label, sensor->path);
|
|
close(fp);
|
|
return FALSE;
|
|
}
|
|
close(fp);
|
|
|
|
// If regex pass that
|
|
if (sensor->regex != NULL) {
|
|
regex_t preg;
|
|
regmatch_t pmatch[2];
|
|
//const char *pattern = ".*t=([0-9|\\.]*)";
|
|
//const char *pattern = ".*([0-9]+).*";
|
|
int status;
|
|
// Compile the regular expression
|
|
status = regcomp(&preg, sensor->regex, REG_EXTENDED);
|
|
if (status != 0) {
|
|
LOG(AQUA_LOG,LOG_ERR, "Compiling sensor regex %s\n",sensor->regex);
|
|
return 1;
|
|
}
|
|
|
|
// Run regex
|
|
if ( (status = regexec(&preg, buffer, 2, pmatch, 0)) == 0) {
|
|
startptr = buffer + pmatch[1].rm_so;
|
|
} else if (status == REG_NOMATCH) {
|
|
//LOG(AQUA_LOG,LOG_DEBUG, "No sensor regex match '%s' on line '%s'\n",sensor->regex,line_buffer);
|
|
} else {
|
|
LOG(AQUA_LOG,LOG_ERR, "regex match error %d using '%s' on line '%s'\n",status,sensor->regex,buffer);
|
|
}
|
|
// Free the compiled regular expression
|
|
regfree(&preg);
|
|
}
|
|
|
|
// Convert value to float
|
|
value = strtof(startptr, &endptr);
|
|
if (endptr == buffer) {
|
|
LOG(AQUA_LOG,LOG_ERR, "Reading sensor value from %s\n", sensor->path);
|
|
}
|
|
|
|
value = value * sensor->factor;
|
|
|
|
LOG(AQUA_LOG,LOG_DEBUG, "Read sensor %s value=%.2f\n",sensor->label, value);
|
|
|
|
if (sensor->value != value) {
|
|
sensor->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
#ifdef DO_NOT_COMPILE
|
|
/* TRY not to use this unless have too, unbuffered is far quicker for sysfs */
|
|
bool read_sensor_buffered(external_sensor *sensor) {
|
|
|
|
FILE *fp;
|
|
float value;
|
|
|
|
fp = fopen(sensor->path, "r");
|
|
if (fp == NULL) {
|
|
LOGSystemError(errno, AQUA_LOG, sensor->path);
|
|
LOG(AQUA_LOG,LOG_ERR, "Reading sensor %s %s\n",sensor->label, sensor->path);
|
|
return FALSE;
|
|
}
|
|
|
|
if (sensor->regex != NULL) {
|
|
char line_buffer[256];
|
|
regex_t preg;
|
|
regmatch_t pmatch[2];
|
|
int status;
|
|
// Compile the regular expression
|
|
status = regcomp(&preg, sensor->regex, REG_EXTENDED);
|
|
if (status != 0) {
|
|
|
|
LOG(AQUA_LOG,LOG_ERR, "Compiling sensor regex %s\n",sensor->regex);
|
|
return 1;
|
|
}
|
|
|
|
while (fgets(line_buffer, sizeof(line_buffer), fp) != NULL) {
|
|
if ( (status = regexec(&preg, line_buffer, 2, pmatch, 0)) == 0) {
|
|
value = atof(line_buffer + pmatch[1].rm_so);
|
|
break;
|
|
} else if (status == REG_NOMATCH) {
|
|
//LOG(AQUA_LOG,LOG_DEBUG, "No sensor regex match '%s' on line '%s'\n",sensor->regex,line_buffer);
|
|
} else {
|
|
LOG(AQUA_LOG,LOG_ERR, "regex match error %d using '%s' on line '%s'\n",status,sensor->regex,line_buffer);
|
|
}
|
|
}
|
|
// Free the compiled regular expression
|
|
regfree(&preg);
|
|
} else {
|
|
fscanf(fp, "%f", &value);
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
value = value * sensor->factor;
|
|
//printf("Converted value %f\n",value);
|
|
LOG(AQUA_LOG,LOG_DEBUG, "Read sensor %s value=%.2f\n",sensor->label, value);
|
|
|
|
if (sensor->value != value) {
|
|
sensor->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|