co2minimon

Get temperature and CO2 concentration data from a CO2Mini sensor.
git clone git://git.amin.space/co2minimon.git
Log | Files | Refs | README | LICENSE

commit be9e7a3db765ad5bc860b8a6311725996756f0e1
parent f215c8bfb3234cf083fb492cf27b8cbf8fd8fe4e
Author: amin <dev@aminmesbah.com>
Date:   Sat, 15 Jan 2022 06:41:34 +0000

Get data from co2mini and write it to tmp files

FossilOrigin-Name: 63c61e3c471aff0e29b97813ff1bd255a466fe24d8b84f3e127cc1b974f9d4de
Diffstat:
Mmain.c | 148++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 83 insertions(+), 65 deletions(-)

diff --git a/main.c b/main.c @@ -4,98 +4,116 @@ #include <stdio.h> #include <stdint.h> -#include <fcntl.h> // open() -#include <sys/ioctl.h> // ioctl() -#include <unistd.h> // close() +#include <fcntl.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <unistd.h> +// https://www.kernel.org/doc/Documentation/hid/hidraw.txt #include <linux/hidraw.h> -typedef uint8_t buffer[8]; +static bool running = true; + +void stop_running(int sig) +{ + running = false; +} // Made possible by Henryk Plötz' excellent work: // https://hackaday.io/project/5301-reverse-engineering-a-low-cost-usb-co-monitor +int main(void) +{ + { + struct sigaction act = {0}; + act.sa_handler = stop_running; + sigaction(SIGINT, &act, NULL); + sigaction(SIGKILL, &act, NULL); + sigaction(SIGTERM, &act, NULL); + } -// references -// https://www.kernel.org/doc/Documentation/hid/hidraw.txt -int main(void) { // NOTE: Included udev rules create this symlink to the appropriate hidraw // entry. int device_handle = open("/dev/co2mini0", O_RDWR); - if (device_handle < 0) { - printf("ERROR: Failed to open hid\n"); + if (device_handle < 0) + { + printf("ERROR: Failed to open HID.\n"); return 1; } - buffer key = {0}; - int result = ioctl(device_handle, HIDIOCSFEATURE(sizeof(key)), key); - if (result < 0 || result != sizeof(buffer)) { - printf("ERROR: Failed to send feature report\n"); - return 1; + { + uint8_t key[8] = {0}; + int result = ioctl(device_handle, HIDIOCSFEATURE(sizeof(key)), key); + if (result < 0 || result != sizeof(key)) + { + printf("ERROR: Failed to send feature report.\n"); + return 1; + } } - while (true) { - buffer data = {0}; - int bytes_read = read(device_handle, &data, sizeof(buffer)); - if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) { + const char *temperature_file_path = "/tmp/co2mini_temp"; + const char *co2_file_path = "/tmp/co2mini_co2"; + + while (running) + { + uint8_t data[8] = {0}; + int bytes_read = read(device_handle, &data, sizeof(data)); + if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) + { bytes_read = 0; - } else { - assert(bytes_read == sizeof(buffer)); } - if (bytes_read == sizeof(buffer)) { - buffer decoded = {0}; - { - { - uint8_t tmp; - tmp = data[0]; data[0] = data[2]; data[2] = tmp; - tmp = data[1]; data[1] = data[4]; data[4] = tmp; - tmp = data[3]; data[3] = data[7]; data[7] = tmp; - tmp = data[5]; data[5] = data[6]; data[6] = tmp; - } + uint8_t item = data[0]; + uint8_t msb = data[1]; + uint8_t lsb = data[2]; + uint8_t checksum = data[3]; + uint8_t end = data[4]; - for (int i = 0; i < sizeof(buffer); ++i) { - data[i] ^= key[i]; - } + if (bytes_read == sizeof(data) + && end == 0x0d + && (item == 0x42 || item == 0x50) + && item + msb + lsb == checksum) + { - { - uint8_t tmp = (data[7] << 5); - decoded[7] = (data[6] << 5) | (data[7] >> 3); - decoded[6] = (data[5] << 5) | (data[6] >> 3); - decoded[5] = (data[4] << 5) | (data[5] >> 3); - decoded[4] = (data[3] << 5) | (data[4] >> 3); - decoded[3] = (data[2] << 5) | (data[3] >> 3); - decoded[2] = (data[1] << 5) | (data[2] >> 3); - decoded[1] = (data[0] << 5) | (data[1] >> 3); - decoded[0] = tmp | (data[0] >> 3); - } + uint16_t value = (((uint16_t)msb) << 8) | lsb; + char buf[1024] = {0}; + int str_len = 0; + mode_t create_mode = S_IRUSR | S_IWUSR; + int open_mode = O_WRONLY | O_CREAT | O_TRUNC; - buffer dumb_proprietary_bullshit_secret_word = "Htemp99e"; - for (int i = 0; i < sizeof(buffer); ++i) + switch(item) + { + case 0x42: { - decoded[i] -= (dumb_proprietary_bullshit_secret_word[i] << 4) | (dumb_proprietary_bullshit_secret_word[i] >> 4); - } - } + double t_celsius = value / 16.0 - 273.15; + str_len = snprintf(buf, sizeof(buf), "%.2f", t_celsius); + assert(str_len > 0); + int f = open(temperature_file_path, open_mode, create_mode); + if (f == -1) + { + return 1; + } + write(f, buf, str_len); + close(f); + } break; - if (decoded[4] != 0x0d) { - printf("BAD DATA: "); - } else { - switch(decoded[0]) { - case 0x42: - printf("Temperature: "); - break; case 0x50: - printf("CO2: "); - break; - } - } - - for (int i = 0; i < sizeof(buffer); i++) { - printf("[%i]: %X ", i, decoded[i]); + case 0x50: + { + str_len = snprintf(buf, sizeof(buf), "%d", value); + assert(str_len > 0); + int f = open(co2_file_path, open_mode, create_mode); + if (f == -1) + { + return 1; + } + write(f, buf, str_len); + close(f); + } break; } - - printf("\n"); } } + unlink(co2_file_path); + unlink(temperature_file_path); close(device_handle); return 0; }