From 1cbcdf6f3ae5c53721b5d912acd48d3ce34c6522 Mon Sep 17 00:00:00 2001 From: Alexander Gabriel Date: Sun, 10 Jan 2021 14:55:58 +0100 Subject: [PATCH] Added Code --- airsensor | Bin 0 -> 13236 bytes airsensor.c | 247 +++++++++++++++++++++++++++++++++++++++++++ display_airsensor.py | 38 +++++++ get_airsensor.sh | 7 ++ plotImage.gnuplot | 16 +++ 5 files changed, 308 insertions(+) create mode 100755 airsensor create mode 100755 airsensor.c create mode 100755 display_airsensor.py create mode 100755 get_airsensor.sh create mode 100644 plotImage.gnuplot diff --git a/airsensor b/airsensor new file mode 100755 index 0000000000000000000000000000000000000000..27a05eb3e3ecbcbccf7ea152e1015f83b3aad0ab GIT binary patch literal 13236 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 +#include +#include +#include +#include +#include +#include + +/* Device-Handle fuer den Airsensor */ +struct usb_dev_handle *devh; + +void usage() + { + printf("\nAirSensor [options]\n"); + printf("Options:\n"); + printf("-d = Debug-Ausgabe einschalten\n"); + printf("-v = Nur den VOC ausgeben; '0', falls Wert ausserhalb (450..2000)\n"); + printf("-o = Nur einen Wert ausgeben und beenden\n"); + printf("-m = Nur Wert fuer MRTG formatiert ausgeben\n"); + printf("-h = Dieser Hilfe-Text\n\n"); + exit(0); + } + +/* Text und Messwert (falls > 0) mit Datum/Uhrzeit ausgeben */ +void printout(char *str, int value) + { + time_t t = time(NULL); /* aktuelle Zeit (Epoche) */ + struct tm tm = *localtime(&t); /* aktuelles Datum/Zeit */ + + printf("%04d-%02d-%02d %02d:%02d:%02d, ", tm.tm_year + 1900, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + if (value == 0) + { printf("%s\n", str); } + else { printf("%s %d\n", str, value); } + } + +/* USB-Device schliessen, Programm beenden */ +void release_usb_device(int dummy) + { + int ret; + ret = usb_release_interface(devh, 0); + usb_close(devh); + exit(ret); + } + +/* USB-Device zu Vendor- und Product suchen */ +struct usb_device* find_device(int vendor, int product) + { + struct usb_bus *bus; + struct usb_device *dev; + + usb_set_debug(0); + usb_find_busses(); + usb_find_devices(); + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == vendor + && dev->descriptor.idProduct == product) + return dev; /* Erfolg: Device zurueckgeben */ + } + } + return NULL; /* bei Misserfolg NULL retournieren */ + } + +int main(int argc, char *argv[]) + { + int ret, vendor, product, counter; /* Hilfsvariable */ + int debug; /* Debug-Ausgabe ein/aus */ + int one_read, voc_only, mrtg_only; /* Flags fuer Optionen */ + struct usb_device *dev; /* USB-Geraet; Airsensor */ + char buf[1000]; /* Datenpuffer */ + unsigned short voc = 0; + + /* Variablen und Flags initialisieren */ + dev = NULL; /* Device init */ + counter = 10; /* Startwert Zaehler */ + debug = 0; /* keine Debug-Ausgabe */ + voc_only = 0; /* normale Ausgabe */ + mrtg_only = 0; /* normale Ausgabe */ + one_read = 0; /* Endlosschleife */ + + vendor = 0x03eb; /* Vendor-ID Airsensor */ + product = 0x2013; /* Product-ID Airsensor */ + + /* Strg-C abfangen */ + signal(SIGTERM, release_usb_device); + + /* Kommandozeilen-Optionen einlesen */ + while ((argc > 1) && (argv[1][0] == '-')) + { + switch (argv[1][1]) + { + case 'd': debug = 1; break; + case 'v': voc_only = 1; break; + case 'm': mrtg_only = 1; break; + case 'o': one_read = 1; break; + case 'h': usage(); break; + } + ++argv; + --argc; + } + + if (debug) + { + printout("DEBUG: Active", 0); + printout("DEBUG: Init USB", 0); + } + usb_init(); + + do { + /* Airsensor suchen */ + dev = find_device(vendor, product); + sleep(1); + + /* Falls Airsensor nicht gefunden, mehrmals versuchen */ + if (dev == NULL && debug) + printout("DEBUG: No device found, wait 10sec...", 0); + sleep(10); + counter--; + } while (dev == NULL && counter > 0); + if (dev == 0) + { + printout("Error: Device not found", 0); + exit(1); + } + + if (debug) + printout("DEBUG: USB device found", 0); + + /* Airsensor oeffnen */ + devh = usb_open(dev); + assert(devh); + + /* Device belegen */ + ret = usb_get_driver_np(devh, 0, buf, sizeof(buf)); + if (ret == 0) + ret = usb_detach_kernel_driver_np(devh, 0); + + ret = usb_claim_interface(devh, 0); + if (ret != 0) + { + printout("Error: claim failed with error: ", ret); + exit(1); + } + + if (debug) + printout("DEBUG: Read any remaining data from USB", 0); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000); + if (debug) + printout("DEBUG: Return code from USB read: ", ret); + + for(;;) + { + /* USB COMMAND TO REQUEST DATA - @h*TR */ + if (debug) + printout("DEBUG: Write data to device", 0); + + memcpy(buf, "\x40\x68\x2a\x54\x52\x0a\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40", 0x0000010); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000010, 1000); + + if (debug) + { + printout("DEBUG: Return code from USB write: ", ret); + printout("DEBUG: Read USB", 0); + } + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000); + if (debug) + printout("DEBUG: Return code from USB read: ", ret); + + if ( !((ret == 0) || (ret == 16))) + { + if (voc_only) + { printf("0\n"); } + else if (mrtg_only) + { printf("0\n0\n0\nairsensor\n"); } + else + { printout("ERROR: Invalid result code: ", ret); } + } + + if (ret == 0) + { + if (debug) + printout("DEBUG: Read USB", 0); + sleep(1); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000); + if (debug) + printout("DEBUG: Return code from USB read: ", ret); + } + + voc = (buf[3] << 8) + buf[2]; + sleep(1); + if (debug) + printout("DEBUG: Read USB [flush]", 0); + + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000); + if (debug) + printout("DEBUG: Return code from USB read: ", ret); + + // According to AppliedSensor specifications the output range is between 450 and 2000 + // So only printout values between this range + + if (voc >= 450 && voc <= 2001) + { + if (voc_only) + { printf("%d\n", voc); } + else if (mrtg_only) + { printf("%d\n0\n0\nairsensor\n", voc); } + else + { printout("RESULT: OK, VOC: ",voc); } + } + else + { + if (voc_only) + { printf("0\n"); } + else if (mrtg_only) + { printf("0\n0\n0\nairsensor\n"); } + else + { printout("RESULT: Error value out of range, VOC: ",voc); } + } + + /* Falls nur einmal Lesen eingestellt, exit */ + if (one_read) + release_usb_device(0); + + /* Pause, dann neuer Schleifendurchlauf */ + sleep(10); + } + } + diff --git a/display_airsensor.py b/display_airsensor.py new file mode 100755 index 0000000..0fd2919 --- /dev/null +++ b/display_airsensor.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 +# -*- coding:utf-8 -*- +import sys +import os +picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic') +libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib') +if os.path.exists(libdir): + sys.path.append(libdir) + +import logging +from waveshare_epd import epd2in9 +import time +from PIL import Image,ImageDraw,ImageFont +import traceback + +logging.basicConfig(level=logging.DEBUG) + +try: + epd = epd2in9.EPD() + logging.info("init and Clear") + epd.init(epd.lut_full_update) + epd.Clear(0xFF) + + logging.info("3.read bmp file") + Himage = Image.open('airsensorimage.bmp') + epd.display(epd.getbuffer(Himage)) + + logging.info("Goto Sleep...") + epd.sleep() + epd.Dev_exit() + +except IOError as e: + logging.info(e) + +except KeyboardInterrupt: + logging.info("ctrl + c:") + epd2in9.epdconfig.module_exit() + exit() diff --git a/get_airsensor.sh b/get_airsensor.sh new file mode 100755 index 0000000..908ab4d --- /dev/null +++ b/get_airsensor.sh @@ -0,0 +1,7 @@ +#!/bin/sh +cd /root/vocsensor +echo $(date +"%Y-%m-%d %H:%M:%S"),$(./airsensor -v -o) >> airsensordata.txt +gnuplot plotImage.gnuplot +convert -gravity south -fill black -annotate 0 "$(date +"%Y-%m-%d %H:%M:%S")" airsensorimage.png -compress none airsensorimage.bmp +#convert airsensorimage.png -compress none airsensorimage.bmp +./display_airsensor.py diff --git a/plotImage.gnuplot b/plotImage.gnuplot new file mode 100644 index 0000000..5f22e3d --- /dev/null +++ b/plotImage.gnuplot @@ -0,0 +1,16 @@ +#set title "VOC/Flüchtige organische Verbindungen" +unset multiplot +set xdata time +set style data lines +set term png size 296,128 +set timefmt "%Y-%m-%d %H:%M:%S" +set format x "" +#set format x "%H:%M" +#set xlabel "Time" +#set ylabel "VOC" +set datafile separator "," +set autoscale y +set xrange [time(0) - 60*60:] +set output "airsensorimage.png" +set tics font ",10" +plot "airsensordata.txt" using 1:($2 == 0 ? NaN : $2) w lines notitle