summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2020-07-05 21:43:08 +0200
committerDaniel Friesel <derf@finalrewind.org>2020-07-05 21:43:08 +0200
commitce0cd4bdafacbaee74eba78f15acccf5488a5a36 (patch)
tree6f132917ed056d9ebcd7f9d5f73fa1c387f03204 /src
parent9942173a2b46d5eb28fc41faf1627afc9929902d (diff)
add anemometer app
Diffstat (limited to 'src')
-rw-r--r--src/app/wetterstation/Makefile.inc1
-rwxr-xr-xsrc/app/wetterstation/client.py108
-rw-r--r--src/app/wetterstation/main.cc44
3 files changed, 153 insertions, 0 deletions
diff --git a/src/app/wetterstation/Makefile.inc b/src/app/wetterstation/Makefile.inc
new file mode 100644
index 0000000..2cb8a42
--- /dev/null
+++ b/src/app/wetterstation/Makefile.inc
@@ -0,0 +1 @@
+loop ?= 1
diff --git a/src/app/wetterstation/client.py b/src/app/wetterstation/client.py
new file mode 100755
index 0000000..5bc2afc
--- /dev/null
+++ b/src/app/wetterstation/client.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+
+import numpy as np
+import re
+import requests
+import serial
+import serial.threaded
+import sys
+import time
+
+class SerialReader(serial.threaded.Protocol):
+ """
+ Character- to line-wise data buffer for serial interfaces.
+
+ Reads in new data whenever it becomes available and exposes a line-based
+ interface to applications.
+ """
+ def __init__(self, callback):
+ """Create a new SerialReader object."""
+ self.callback = callback
+ self.recv_buf = ''
+
+ def __call__(self):
+ return self
+
+ def data_received(self, data):
+ """Append newly received serial data to the line buffer."""
+ try:
+ str_data = data.decode('UTF-8')
+ self.recv_buf += str_data
+
+ # We may get anything between \r\n, \n\r and simple \n newlines.
+ # We assume that \n is always present and use str.strip to remove leading/trailing \r symbols
+ # Note: Do not call str.strip on lines[-1]! Otherwise, lines may be mangled
+ lines = self.recv_buf.split('\n')
+ if len(lines) > 1:
+ self.recv_buf = lines[-1]
+ for line in lines[:-1]:
+ self.callback(str.strip(line))
+
+ except UnicodeDecodeError:
+ pass
+ #sys.stderr.write('UART output contains garbage: {data}\n'.format(data = data))
+
+class SerialMonitor:
+ """SerialMonitor captures serial output for a specific amount of time."""
+
+ def __init__(self, port: str, baud: int, callback):
+ """
+ Create a new SerialMonitor connected to port at the specified baud rate.
+
+ Communication uses no parity, no flow control, and one stop bit.
+ Data collection starts immediately.
+ """
+ self.ser = serial.serial_for_url(port, do_not_open=True)
+ self.ser.baudrate = baud
+ self.ser.parity = 'N'
+ self.ser.rtscts = False
+ self.ser.xonxoff = False
+
+ try:
+ self.ser.open()
+ except serial.SerialException as e:
+ sys.stderr.write('Could not open serial port {}: {}\n'.format(self.ser.name, e))
+ sys.exit(1)
+
+ self.reader = SerialReader(callback = callback)
+ self.worker = serial.threaded.ReaderThread(self.ser, self.reader)
+ self.worker.start()
+
+ def close(self):
+ """Close serial connection."""
+ self.worker.stop()
+ self.ser.close()
+
+if __name__ == '__main__':
+
+ got_data = False
+ step = 0
+
+ def parse_line(line):
+
+ global got_data
+
+ match = re.match('Anemometer Count = ([^ ]+)', line)
+ if match:
+ got_data = True
+ wind_clicks = float(match.group(1))
+ windspeed_kmh = wind_clicks * 2.4 / 10
+ requests.post('http://influxdb:8086/write?db=sensors', data='anemometer,area=hm17_,location=balkon windspeed_kmh={}'.format(windspeed_kmh))
+
+ monitor = SerialMonitor('/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.1:1.0-port0', 57600, parse_line)
+
+ try:
+ while True:
+ time.sleep(5)
+
+ step += 1
+
+ if step == 4:
+ if not got_data:
+ print('Error: received no data for 20 seconds', file=sys.stderr)
+ sys.exit(1)
+ got_data = False
+ step = 0
+
+ except KeyboardInterrupt:
+ monitor.close()
diff --git a/src/app/wetterstation/main.cc b/src/app/wetterstation/main.cc
new file mode 100644
index 0000000..2c47d78
--- /dev/null
+++ b/src/app/wetterstation/main.cc
@@ -0,0 +1,44 @@
+#include "arch.h"
+#include "driver/gpio.h"
+#include "driver/stdout.h"
+
+#include <avr/interrupt.h>
+
+volatile uint16_t anemometer_count = 0;
+
+void loop(void)
+{
+ static uint8_t loop_count = 0;
+ static uint16_t anemometer_copy;
+ if (++loop_count == 10) {
+
+ cli();
+ anemometer_copy = anemometer_count;
+ anemometer_count = 0;
+ sei();
+
+ kout << "Anemometer Count = " << anemometer_copy << endl;
+ loop_count = 0;
+ }
+}
+
+int main(void)
+{
+ arch.setup();
+ gpio.setup();
+ kout.setup();
+
+ gpio.output(GPIO::pd2, 0);
+ gpio.input(GPIO::pd3, 1);
+
+ EICRA = _BV(ISC11);
+ EIMSK = _BV(INT1);
+
+ arch.idle_loop();
+
+ return 0;
+}
+
+ISR(INT1_vect) {
+ anemometer_count++;
+}