/* * Copyright 2025 Edward V. Emelianov . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include // for NaN #include #include #include #include #include #include "i2csensorsPTH.h" typedef struct{ char *device; char *Tlog; char *Hlog; char *Plog; double interval; int mul_addr; int presmm; // pressure in mm instead of hPa int help; } glob_pars; static glob_pars G = { .device = "/dev/i2c-6", .mul_addr = 0x70, .interval = 10., }; static sl_option_t cmdlnopts[] = { {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"}, {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), "I2C device path"}, {"presmm", NO_ARGS, NULL, 'm', arg_int, APTR(&G.presmm), "pressure in mmHg instead of hPa"}, {"tlog", NEED_ARG, NULL, 'T', arg_string, APTR(&G.Tlog), "temperature logging file"}, {"hlog", NEED_ARG, NULL, 'H', arg_string, APTR(&G.Hlog), "humidity logging file"}, {"plog", NEED_ARG, NULL, 'P', arg_string, APTR(&G.Plog), "pressure logging file"}, {"interval",NEED_ARG, NULL, 'i', arg_double, APTR(&G.interval), "logging interval, seconds (default: 10)"}, {"muladdr", NEED_ARG, NULL, 'a', arg_int, APTR(&G.mul_addr), "multiplexer I2C address"}, end_option }; static FILE *tlogf = NULL, *hlogf = NULL, *plogf = NULL; static FILE *openlog(const char *name){ FILE *l = fopen(name, "w"); if(!l) ERR("Can't open %s", name); return l; } void signals(int s){ DBG("Got sig %d", s); sensors_close(); if(tlogf != stdout) fclose(tlogf); if(hlogf != stdout) fclose(hlogf); if(plogf != stdout) fclose(plogf); exit(s); } typedef struct{ const char *name; // name - for header in log const char *type; // sensor's name for `sensor_new` uint8_t nch; // channel number uint8_t address; // address (0 for default) sensor_t *sensor; // pointer to sensor itself } sd_t; // amount of all sensors connected #define SENSORS_AMOUNT 8 // list of sensors - must be sorted by channel number static sd_t all_sensors[SENSORS_AMOUNT] = { {.name = "AHT15", .type = "AHT15", .nch = 0}, {.name = "SI7005", .type = "SI7005", .nch = 0}, {.name = "AHT10", .type = "AHT10", .nch = 1}, {.name = "BMP180", .type = "BMP180", .nch = 1}, {.name = "BME280a", .type = "BME280", .nch = 1}, {.name = "BME280b", .type = "BME280", .nch = 2}, {.name = "AHT21b", .type = "AHT21", .nch = 2}, {.name = "SHT30", .type = "SHT3x", .nch = 2}, }; /* static int chsort(const void *v1, const void *v2){ const sd_t *s1 = (const sd_t*)v1; const sd_t *s2 = (const sd_t*)v2; return s1->nch - s2->nch; }*/ static int setchan(uint8_t N){ if(N > 7){ WARNX("Wrong channel number: %d", N); return FALSE; } N = 1<=1s"); if(G.mul_addr < 1 || G.mul_addr > 0x7f) ERRX("Wrong multiplexer address"); if(G.Tlog) tlogf = openlog(G.Tlog); else tlogf = stdout; if(G.Hlog) hlogf = openlog(G.Hlog); else hlogf = stdout; if(G.Plog) plogf = openlog(G.Plog); else plogf = stdout; if(!sensors_open(G.device)) ERRX("Can't open device %s", G.device); signal(SIGINT, signals); signal(SIGQUIT, signals); signal(SIGABRT, signals); signal(SIGTERM, signals); signal(SIGHUP, SIG_IGN); signal(SIGTSTP, SIG_IGN); initsensors(); writeheader(); startlogs(); signals(0); return 0; // never reached }