diff options
-rw-r--r-- | README | 9 | ||||
-rwxr-xr-x | create-db.rb | 50 | ||||
-rwxr-xr-x | fill-db.rb | 71 | ||||
-rwxr-xr-x | query-db.rb | 20 | ||||
-rwxr-xr-x | receive-test.py | 16 | ||||
-rwxr-xr-x | receive.py | 65 | ||||
-rwxr-xr-x | run | 5 | ||||
-rwxr-xr-x | weather-logger | 26 |
8 files changed, 262 insertions, 0 deletions
@@ -0,0 +1,9 @@ +Dependencies: + Ruby + sqlite3 + Python + pyRFXtrx + +``` +./create-db.rb +`` diff --git a/create-db.rb b/create-db.rb new file mode 100755 index 0000000..12326c0 --- /dev/null +++ b/create-db.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby + +require 'sqlite3' + +db = SQLite3::Database.new("weather.db") + +db.execute <<-SQL + create table rain( + id INTEGER PRIMARY KEY, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + device_type TEXT, + device_id TEXT, + battery INTEGER, + rssi INTEGER, + rain_rate FLOAT, + rain_total FLOAT + ); + SQL +db.execute <<-SQL + create table wind( + id INTEGER PRIMARY KEY, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + device_type TEXT, + device_id TEXT, + battery INTEGER, + rssi INTEGER, + chill FLOAT, + temperature FLOAT, + average_speed FLOAT, + direction INTEGER, + gust FLOAT + ); + SQL +db.execute <<-SQL + create table temp( + id INTEGER PRIMARY KEY, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + device_type TEXT, + device_id TEXT, + battery INTEGER, + rssi INTEGER, + humidity FLOAT, + humidity_status TEXT, + humidity_status_numeric INTEGER, + temperature FLOAT + ); + SQL + +db.close + diff --git a/fill-db.rb b/fill-db.rb new file mode 100755 index 0000000..199db42 --- /dev/null +++ b/fill-db.rb @@ -0,0 +1,71 @@ +#!/usr/bin/env ruby + +require 'sqlite3' + +int = Proc.new do |x| + x.to_i +end +float = Proc.new do |x| + x.to_f +end +str = Proc.new do |x| + x.to_s +end +common_conv = { "db" => str, "timestamp"=>float, "device_type"=>str, "device_id"=>str, "battery" => int, "rssi" => int } +rain_conv = {"rain_rate"=>float, "rain_total"=>float}.merge(common_conv) +wind_conv = {"chill"=>float, "temperature"=>float,"average_speed"=>float,"direction"=>int,"gust"=>float}.merge(common_conv) +temp_conv = {"humidity"=>float, "humidity_status"=>str,"humidity_status_numeric"=>int,"temperature"=>float}.merge(common_conv) +conv = { "rain" => rain_conv, "wind" => wind_conv, "temp" => temp_conv } + +$db = SQLite3::Database.new("weather.db") + +def parse_to_hash s, conv + h = {} + s.split("\t").map { |i| i=i.split("::"); h[i[0]] = conv[i[0]].call(i[1]) } + return h +end + +def db_execute s, d + begin + $db.execute(s, d) + rescue SQLite3::BusyException + sleep 3 + begin + $db.execute(s, d) + rescue SQLite3::BusyException + STDERR.write "db busy, skipping data point '#{d.to_s}'\n" + end + end +end + +def insert_rain h + #db::rain type::PCR800 device_id::eb:00 battery::9 rain_rate::0.0 rain_total::0.9 rssi::6 + db_execute("INSERT INTO rain(timestamp, device_type, device_id, battery, rssi, rain_rate, rain_total) VALUES(?,?,?,?,?,?,?)", [h["timestamp"], h["device_type"],h["device_id"], h["battery"], h["rssi"], h["rain_rate"], h["rain_total"]]) +end + +def insert_wind h + # db::wind type::WGR800 device_id::04:00 battery::9 chill::0.0 rssi::5 temperature::0.0 average_speed::0.0 direction::270gust::0.0 + db_execute("INSERT INTO wind(timestamp, device_type, device_id, battery, rssi, chill, temperature, average_speed, direction, gust) VALUES(?,?,?,?,?,?,?,?,?,?)", [h["timestamp"], h["device_type"],h["device_id"], h["battery"], h["rssi"], h["chill"], h["temperature"], h["average_speed"], h["direction"], h["gust"]]) +end + +def insert_temp h + #db::temp type::THGR810, THGN800 device_id::10:02 battery::9 humidity::80 humidity_status::wet humidity_status_numeric::3 rssi::5 temperature::2.6 + #db::temp type::THGR810, THGN800 device_id::25:01 battery::0 humidity::94 humidity_status::wet humidity_status_numeric::3 rssi::6 temperature::1.1 + db_execute("INSERT INTO temp(timestamp, device_type, device_id, battery, rssi, humidity, humidity_status, humidity_status_numeric, temperature) VALUES(?,?,?,?,?,?,?,?,?)",[h["timestamp"], h["device_type"],h["device_id"], h["battery"], h["rssi"], h["humidity"], h["humidity_status"], h["humidity_status_numeric"], h["temperature"]]) +end + +while line = STDIN.gets + break if line.strip=="stop" + db = line.split("\t").first.split("::")[1] + h = parse_to_hash(line, conv[db]) + if db == "rain" + insert_rain h + elsif db == "wind" + insert_wind h + elsif db == "temp" + insert_temp h + end +end + +$db.close + diff --git a/query-db.rb b/query-db.rb new file mode 100755 index 0000000..2418c7d --- /dev/null +++ b/query-db.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby + +require 'sqlite3' + +db = SQLite3::Database.new("weather.db") + +db.execute("select * from rain") do |result| + puts result.to_s +end + +#db.execute("select * from wind") do |result| +# puts result.to_s +#end + +#db.execute("select * from temp") do |result| +# puts result.to_s +#end + +db.close + diff --git a/receive-test.py b/receive-test.py new file mode 100755 index 0000000..663f7a5 --- /dev/null +++ b/receive-test.py @@ -0,0 +1,16 @@ +#!./bin/python3 + +from RFXtrx import PySerialTransport +import sys, datetime, os + +transport = PySerialTransport('/dev/ttyUSB0') +transport.reset() + +while True: + if os.path.isfile('./stop'): + break + + timestamp = datetime.datetime.timestamp(datetime.datetime.now()) + recv = transport.receive_blocking() + print(str(recv)) + diff --git a/receive.py b/receive.py new file mode 100755 index 0000000..4836809 --- /dev/null +++ b/receive.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +from RFXtrx import PySerialTransport +import sys, datetime, os + +#WIND ['04:00'] +#RAIN ['eb:00', '7d:00', '02:00'] +#TEMP ['10:02', 'ec:01', '25:01', '62:02', 'd9:00', '2a:0e', '60:01'] +#KNOWN_DEVICES = [''] + +if __name__ == "__main__": + transport = PySerialTransport('/dev/ttyUSB0') + transport.reset() + + while True: + if os.path.isfile('/home/pi/weather/stop'): + break + + recv = transport.receive_blocking() + + if not recv: + continue + + timestamp = datetime.datetime.timestamp(datetime.datetime.now()) + + sys.stderr.write("Raw: %s\n"%str(recv)) + + try: + device_id = recv.device.id_string + device_type = recv.device.type_string + except Exception as e: + sys.stderr.write("Cannot find device id, exception %s." % str(e)) + continue + + data = {} + for k,v in recv.values.items(): + data[k.lower().replace(" ", "_")] = v + + data_type = None + if "rain_rate" in data: + data_type = "rain" + elif "wind_gust" in data: + data_type = "wind" + elif "temperature" in data: + data_type = "temp" + else: + sys.stderr.write("Unknown device '%s' with id '%s', ignoring.\n"%(device_type, device_id)) + continue + + + out = [ "type::%s" % data_type, + "timestamp::%f" % timestamp, + "device_type::%s" % device_type, + "device_id::%s" % device_id ] + + for key in sorted(data.keys()): + out.append("%s::%s" % (key, data[key])) + + print("\t".join(out)) + sys.stderr.flush() + sys.stdout.flush() + +sys.stderr.write("stop\n") +sys.stdout.flush() + @@ -0,0 +1,5 @@ +#!/usr/bin/zsh -x + +source bin/activate +python receive.py 2>received.err | tee received | ./fill-db.rb 2>db.err > db.out + diff --git a/weather-logger b/weather-logger new file mode 100755 index 0000000..a2c957b --- /dev/null +++ b/weather-logger @@ -0,0 +1,26 @@ +#! /bin/sh +# /etc/init.d/weather-logger +# + +export SUFFIX=$(date +'%Y-%m-%d-%H:%M:%S') +export DIR=/home/pi/weather/ + +# Carry out specific functions when asked to by the system +case "$1" in + start) + echo "Starting weather-logger" + rm -f $DIR/stop + runuser -l pi -c "source $DIR/env/bin/activate && python $DIR/receive.py 2>$DIR/weather.$SUFFIX.err > $DIR/weather.$SUFFIX.out" + ;; + stop) + echo "Stopping weather-logger" + runuser -l pi -c "touch $DIR/stop" + ;; + *) + echo "Usage: /etc/init.d/weather-logger {start|stop}" + exit 1 + ;; +esac + +exit 0 + |