From 0771ed48c729f70e197b0ca999917477eab6a908 Mon Sep 17 00:00:00 2001 From: EMOTIONS-HUNTER Date: Tue, 23 Jun 2026 13:03:13 -0600 Subject: [PATCH] Permitir adquisicion parcial de sensores EZO --- README.md | 13 +++++++++ api/acquisition-service.js | 14 +++++++++- deployment/photobioreactor.env | 2 ++ sensors/EZOCommand/acquire.c | 48 +++++++++++++++++++++++++++++----- test/static.test.js | 3 +++ 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7ad1b12..cb35e0b 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,19 @@ sudo ./scripts/install-raspberry-pi.sh La guía de preparación, detección I2C, calibración y prueba integral está en [`docs/RASPBERRY_PI_DEPLOYMENT.md`](docs/RASPBERRY_PI_DEPLOYMENT.md). +## Sensores conectados parcialmente + +Para pruebas con solo EZO-RTD conectado, limite la adquisicion al sensor de +temperatura: + +```bash +EZO_MODE=hardware EZO_ENABLED_SENSORS=temperature npm run acquire +``` + +En produccion puede dejar `EZO_ENABLED_SENSORS=temperature` en +`/etc/default/photobioreactor`. Cuando esten conectados los cuatro circuitos, +deje la variable vacia para consultar RTD, pH, DO y EC. + ## Archivos de datos - Lecturas actuales: `data/EZORTD.json`, `EZOPH.json`, `EZODO.json`, diff --git a/api/acquisition-service.js b/api/acquisition-service.js index 35a5212..5c5cdb9 100644 --- a/api/acquisition-service.js +++ b/api/acquisition-service.js @@ -32,6 +32,13 @@ const SENSOR_FILES = { }; const ALLOWED_LOGGING_RATES = new Set([1, 5, 10, 60]); +const SENSOR_ALIASES = { + rtd: 'temperature', + temperature: 'temperature', + ph: 'ph', + do: 'do', + ec: 'ec' +}; async function atomicWriteFile(filePath, content) { await fsPromises.mkdir(path.dirname(filePath), { recursive: true }); @@ -104,9 +111,14 @@ function buildDemoReadings() { } async function readHardwareSensors() { + const enabledSensors = String(process.env.EZO_ENABLED_SENSORS || '') + .split(',') + .map((sensor) => SENSOR_ALIASES[sensor.trim().toLowerCase()]) + .filter(Boolean); + const helperArguments = ['/dev/i2c-1', ...new Set(enabledSensors)]; const { stdout } = await execFileAsync( ACQUISITION_HELPER, - ['/dev/i2c-1'], + helperArguments, { timeout: 5000, windowsHide: true } ); const readings = JSON.parse(stdout.trim()); diff --git a/deployment/photobioreactor.env b/deployment/photobioreactor.env index 9a66a20..82773c7 100644 --- a/deployment/photobioreactor.env +++ b/deployment/photobioreactor.env @@ -2,3 +2,5 @@ NODE_ENV=production PORT=3000 HOST=127.0.0.1 EZO_MODE=hardware +# Deje vacio para consultar todos. Use "temperature" durante pruebas con solo RTD. +EZO_ENABLED_SENSORS= diff --git a/sensors/EZOCommand/acquire.c b/sensors/EZOCommand/acquire.c index 7b93862..4415572 100644 --- a/sensors/EZOCommand/acquire.c +++ b/sensors/EZOCommand/acquire.c @@ -14,8 +14,38 @@ typedef struct int address; double value; int valid; + int enabled; } sensor_t; +static int sensor_matches(const sensor_t *sensor, const char *name) +{ + return strcmp(sensor->name, name) == 0 || + (strcmp(sensor->name, "temperature") == 0 && strcmp(name, "rtd") == 0); +} + +static void enable_requested_sensors(sensor_t *sensors, size_t sensor_count, int argc, char *argv[]) +{ + if (argc == 2) + { + for (size_t index = 0; index < sensor_count; index++) + { + sensors[index].enabled = 1; + } + return; + } + + for (int arg = 2; arg < argc; arg++) + { + for (size_t index = 0; index < sensor_count; index++) + { + if (sensor_matches(&sensors[index], argv[arg])) + { + sensors[index].enabled = 1; + } + } + } +} + static int select_sensor(int fd, int address) { return ioctl(fd, I2C_SLAVE, address); @@ -81,18 +111,19 @@ static int receive_reading(int fd, sensor_t *sensor) int main(int argc, char *argv[]) { - if (argc != 2) + if (argc < 2) { - fprintf(stderr, "Uso: EZO_ACQUIRE /dev/i2c-1\n"); + fprintf(stderr, "Uso: EZO_ACQUIRE /dev/i2c-1 [temperature|ph|do|ec]\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}}; + {"temperature", 0x66, 0.0, 0, 0}, + {"ph", 0x63, 0.0, 0, 0}, + {"do", 0x61, 0.0, 0, 0}, + {"ec", 0x64, 0.0, 0, 0}}; const size_t sensor_count = sizeof(sensors) / sizeof(sensors[0]); + enable_requested_sensors(sensors, sensor_count, argc, argv); int lock_fd = open( "/tmp/photobioreactor-i2c.lock", O_CREAT | O_RDWR, @@ -116,7 +147,10 @@ int main(int argc, char *argv[]) for (size_t index = 0; index < sensor_count; index++) { - request_reading(fd, &sensors[index]); + if (sensors[index].enabled) + { + request_reading(fd, &sensors[index]); + } } usleep(1000000); diff --git a/test/static.test.js b/test/static.test.js index 209621b..88fe814 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -56,9 +56,12 @@ test('dashboard uses locally installed chart and spreadsheet libraries', () => { test('hardware acquisition batches all EZO addresses under the shared lock', () => { const source = read('sensors/EZOCommand/acquire.c'); + const acquisitionService = read('api/acquisition-service.js'); for (const address of ['0x61', '0x63', '0x64', '0x66']) { assert.match(source, new RegExp(address)); } assert.match(source, /photobioreactor-i2c\.lock/); + assert.match(source, /EZO_ACQUIRE \/dev\/i2c-1 \[temperature\|ph\|do\|ec\]/); + assert.match(acquisitionService, /EZO_ENABLED_SENSORS/); });