You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
3.0 KiB
C
155 lines
3.0 KiB
C
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <linux/i2c-dev.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/file.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
|
|
typedef struct
|
|
{
|
|
const char *name;
|
|
int address;
|
|
double value;
|
|
int valid;
|
|
} sensor_t;
|
|
|
|
static int select_sensor(int fd, int address)
|
|
{
|
|
return ioctl(fd, I2C_SLAVE, address);
|
|
}
|
|
|
|
static int request_reading(int fd, sensor_t *sensor)
|
|
{
|
|
const char command = 'R';
|
|
|
|
if (select_sensor(fd, sensor->address) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (write(fd, &command, 1) != 1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
sensor->valid = -1;
|
|
return 0;
|
|
}
|
|
|
|
static int receive_reading(int fd, sensor_t *sensor)
|
|
{
|
|
unsigned char response[64] = {0};
|
|
|
|
if (select_sensor(fd, sensor->address) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int bytes_read = read(fd, response, sizeof(response) - 1);
|
|
|
|
for (int retry = 0;
|
|
bytes_read > 0 && response[0] == 254 && retry < 10;
|
|
retry++)
|
|
{
|
|
usleep(100000);
|
|
memset(response, 0, sizeof(response));
|
|
bytes_read = read(fd, response, sizeof(response) - 1);
|
|
}
|
|
|
|
if (bytes_read < 2 || response[0] != 1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
response[bytes_read] = '\0';
|
|
char *end = NULL;
|
|
errno = 0;
|
|
double value = strtod((char *)&response[1], &end);
|
|
|
|
if (errno != 0 || end == (char *)&response[1])
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
sensor->value = value;
|
|
sensor->valid = 1;
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc != 2)
|
|
{
|
|
fprintf(stderr, "Uso: EZO_ACQUIRE /dev/i2c-1\n");
|
|
return 2;
|
|
}
|
|
|
|
sensor_t sensors[] = {
|
|
{"temperature", 0x66, 0.0, 0},
|
|
{"ph", 0x63, 0.0, 0},
|
|
{"do", 0x61, 0.0, 0},
|
|
{"ec", 0x64, 0.0, 0}};
|
|
const size_t sensor_count = sizeof(sensors) / sizeof(sensors[0]);
|
|
int lock_fd = open(
|
|
"/tmp/photobioreactor-i2c.lock",
|
|
O_CREAT | O_RDWR,
|
|
0660);
|
|
|
|
if (lock_fd < 0 || flock(lock_fd, LOCK_EX) < 0)
|
|
{
|
|
fprintf(stderr, "No se pudo bloquear el bus I2C\n");
|
|
return 3;
|
|
}
|
|
|
|
int fd = open(argv[1], O_RDWR);
|
|
|
|
if (fd < 0)
|
|
{
|
|
fprintf(stderr, "No se pudo abrir %s\n", argv[1]);
|
|
flock(lock_fd, LOCK_UN);
|
|
close(lock_fd);
|
|
return 4;
|
|
}
|
|
|
|
for (size_t index = 0; index < sensor_count; index++)
|
|
{
|
|
request_reading(fd, &sensors[index]);
|
|
}
|
|
|
|
usleep(1000000);
|
|
|
|
for (size_t index = 0; index < sensor_count; index++)
|
|
{
|
|
if (sensors[index].valid == -1)
|
|
{
|
|
receive_reading(fd, &sensors[index]);
|
|
}
|
|
}
|
|
|
|
printf("{");
|
|
for (size_t index = 0; index < sensor_count; index++)
|
|
{
|
|
printf(
|
|
"%s\"%s\":",
|
|
index == 0 ? "" : ",",
|
|
sensors[index].name);
|
|
if (sensors[index].valid == 1)
|
|
{
|
|
printf("%.6f", sensors[index].value);
|
|
}
|
|
else
|
|
{
|
|
printf("null");
|
|
}
|
|
}
|
|
printf("}\n");
|
|
|
|
close(fd);
|
|
flock(lock_fd, LOCK_UN);
|
|
close(lock_fd);
|
|
return 0;
|
|
}
|