From d8f77f4312f713443d5b369432ab4b0413bfb8ec Mon Sep 17 00:00:00 2001 From: pks Date: Tue, 22 Nov 2022 22:11:11 +0100 Subject: 2022-11-22 --- power-logger | 119 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 48 deletions(-) (limited to 'power-logger') diff --git a/power-logger b/power-logger index 827451f..dd94bb3 100755 --- a/power-logger +++ b/power-logger @@ -1,52 +1,59 @@ #!/usr/bin/env ruby # FIXME -$LOAD_PATH << "/home/pks/.local/lib/ruby/gems/json-2.3.1/lib/" -$LOAD_PATH << "/home/pks/.local/lib/ruby/gems/mqtt-0.5.0/lib/" -$LOAD_PATH << "/home/pks/.local/lib/ruby/gems/optimist-3.0.1/lib/" -$LOAD_PATH << "/home/pks/.local/lib/ruby/gems/sqlite3-1.4.2/lib/" -$LOAD_PATH << "/home/pks/.local/lib/ruby/gems/zipf-1.2.6/lib/" +$LOAD_PATH << '/usr/local/lib/ruby/gems/mqtt-0.5.0/lib/' +$LOAD_PATH << '/usr/local/lib/ruby/gems/optimist-3.0.1/lib/' + +$stdout.sync = true +$stderr.sync = true require 'json' require 'mqtt' require 'optimist' require 'sqlite3' require 'time' -require 'zipf' + +$handles = { + 'baker' => 'fridge', + 'batum' => 'microwave', + 'bembry' => 'modem+printer', + 'crowder' => 'desk-2', + 'davis' => 'hifi', + 'doncic' => 'desk-1', + 'fournier' => 'air_washer', + 'gibson' => 'dishwasher', + 'gooden' => 'couch', + 'grant' => 'washing_machine', + 'kukoc' => 'rack', + 'nogueira' => 'kitchen_tech', + 'world-peace' => 'kettle+toaster' +} def shutdown - STDERR.write "Shutting down ...\n" + STDERR.write 'Shutting down ...' $db.close - $logfile.close - STDERR.write "Done!\n" + STDERR.write " done!\n" exit end -Signal.trap("INT") { shutdown } -Signal.trap("TERM") { shutdown } +Signal.trap('INT') { shutdown } +Signal.trap('TERM') { shutdown } -def db_open_or_new filename +def db_open_or_create filename if File.exists? filename $db = SQLite3::Database.open filename else $db = SQLite3::Database.new filename $db.execute <<-SQL - create table power_log( + create table power( id INTEGER PRIMARY KEY, timestamp DATETIME, - device_name TEXT, - device_location TEXT, + device TEXT, + handle TEXT, total FLOAT, total_start_time DATETIME ); SQL - $db.execute <<-SQL - create table power_meter( - id INTEGER PRIMARY KEY, - timestamp DATETIME, - total FLOAT - ); - SQL end end @@ -57,45 +64,55 @@ def db_execute sql, data break rescue SQLite3::BusyException STDERR.write "DB busy, skipping data point '#{d.to_s}'\n" - sleep 1 + sleep rand end } end +def db_insert device, handle, data + timestamp = Time.parse(data['Time']).utc.to_i + total_start_time = Time.parse(data['ENERGY']['TotalStartTime']).utc.to_i + db_execute \ + "INSERT INTO power(timestamp, device, handle, total, total_start_time) VALUES(?,?,?,?,?)", \ + [timestamp, device, handle, data['ENERGY']['Total'], total_start_time] +end + def parse_topic topic - parts = topic.split "/" - else - _, device_name, _, device_location_1, device_location_2, _ = parts - end - device_location = [device_location_1, device_location_2] - return device_name, device_location + parts = topic.split '/' + _, device, _ = parts + handle = $handles[device] + + return device, handle end def parse_message message return JSON.parse message end -def insert_power device_name, device_location, data - if data.has_key? "ENERGY" - timestamp = Time.parse(data["Time"]).utc.to_i - total_start_time = Time.parse(data["ENERGY"]["TotalStartTime"]).utc.to_i - db_execute \ - "INSERT INTO power(timestamp, device_name, device_location_primary, device_location_secondary, total, total_start_time) VALUES(?,?,?,?,?,?)", \ - [timestamp, device_name, device_location[0], device_location[1], data["ENERGY"]["Total"], total_start_time] +def check_and_maybe_create_pidfile filename + if File.exists? filename + File.open filename, 'r' do |f| + STDERR.write "Possibly already running as PID #{f.read}, exiting" + end + else + File.open filename, 'w' do |f| + puts "Running as PID #{Process.pid}" + f.write "#{Process.pid}\n" + end end end def main options = Optimist::options do - opt :host, "MQTT hostname", :type => :string, :default => 'localhost', :short => '-h' - opt :port, "MQTT port", :type => :int, :default => 1883, :short => '-p' - opt :db, "SQLite3 database file", :type => :string, :required => true, :short => '-d' - opt :log, "Logfile", :type => :string, :required => true, :short => '-l' + opt :host, 'MQTT hostname', :type => :string, :default => 'localhost', :short => '-h' + opt :port, 'MQTT port', :type => :int, :default => 1883, :short => '-p' + opt :db, 'SQLite3 database file', :type => :string, :default => '/usr/local/share/power_logger/power.db', :short => '-d' + opt :pidfile, 'PID file', :type => :string, :default => '/run/power_logger/logger.pid', :short => '-P' end - db_open_or_new options[:db] + check_and_maybe_create_pidfile options[:pidfile] - $logfile = WriteFile.new options[:log] + db_open_or_create options[:db] $mqtt_client = MQTT::Client.connect( :host => options[:host], @@ -105,13 +122,19 @@ def main $mqtt_client.get do |topic,message| begin - puts "#{topic}\t#{message} - #device_name, device_location = parse_topic topic - #data = parse_message message - #insert_power device_name, device_location, data - #$logfile.write "#{topic}\t#{message}\n" + logged = false + if topic.end_with? '/SENSOR' + data = parse_message message + if data.keys.include? 'ENERGY' + puts "[logged] topic=#{topic} message=#{message}" + device, handle = parse_topic topic + db_insert device, handle, data + logged = true + end + end + if not logged then STDERR.write "[ignored] topic=#{topic} message=#{message}\n" end rescue => exception - $logfile.write "[Ignoring]\t#{topic}\t#{message}\n" + STDERR.write "Exception: #{exception}\n" end end -- cgit v1.2.3