diff options
Diffstat (limited to 'power-logger')
| -rwxr-xr-x | power-logger | 119 | 
1 files changed, 71 insertions, 48 deletions
| 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 | 
