class Avalon::Miner

Miner is a node encapsulating a single Avalon unit

Constants

FIELDS

Field formats: name => [width, pattern, type/conversion]

Public Class Methods

convert_last(x) click to toggle source

Last share converter (Miner-specific)

# File lib/avalon/miner.rb, line 41
def self.convert_last x
  y = x[/(?<=Last Share Time=)[\d\.]*/]

  if y.nil? || y == '0'
    "never"
  else
    my_time(Time.now.getgm.to_i-y.to_i, :relative_time)
  end
end
new(monitor, ip, min_mhs, worker_name=nil) click to toggle source
Calls superclass method
# File lib/avalon/miner.rb, line 56
def initialize monitor, ip, min_mhs, worker_name=nil
  @ip, @min_mhs, @worker_name = ip, min_mhs*1000 , worker_name
  @monitor = monitor
  @config = Avalon::Config.config # TODO: monitor.config?
  @fails = 0
  super()
end
print_headers() click to toggle source

Public Instance Methods

get_api(call) click to toggle source
# File lib/avalon/miner.rb, line 64
def get_api call
  self[:ping] ? `bash -ic "echo -n '#{call}' | nc #{@ip} 4028"` : ""
end
last() click to toggle source
# File lib/avalon/miner.rb, line 97
def last
  duration(self[:last])
end
poll(verbose=true) click to toggle source
# File lib/avalon/miner.rb, line 68
def poll verbose=true
  self[:ping] = ping @ip

  status = get_api('summary') + get_api('pools') + get_api('devs') + get_api('stats')
  @poll_time = Time.now
  # p get_api('summary')

  data = self.class.extract_data_from(status)

  if data.empty?
    @data = {:ping => self[:ping], :rst => self[:rst]}
  else
    @data.merge! data
    if @config[:monitor][:per_hour]
      [:getwork, :accept, :reject, :stale, :error].each do |key|
        self[key] = (self[key]/upminutes*60).round(1) if self[key]
      end
    end
  end

  self[:pool] = pool_hash

  puts "#{self}" if verbose
end
pool_hash() click to toggle source
# File lib/avalon/miner.rb, line 113
def pool_hash
  if @monitor.pool && @worker_name && @monitor.pool[:workers] && @monitor.pool[:workers][@worker_name]
    @monitor.pool[:workers][@worker_name][:hash_rate].round(0)
  end
end
report() click to toggle source

Check for any exceptional situations in stats, sound alarm if any

# File lib/avalon/miner.rb, line 120
def report
  if data[:ping].nil? || data[:unit].nil?
    @fails += 1
    if @fails >= @config[:alert_after]
      alarm "Miner #{num} did not respond to status query", :failure
    end
  else
    @fails = 0
    @last_restart ||= restart_time

    # Detect Miner reset correctly
    if (restart_time - @last_restart) > 20
      @last_restart = restart_time
      self[:rst] = (self[:rst] || 0) + 1
      alarm "Miner #{num} restarted", :restart
    elsif unit_hash == 0 && last == 'never' && temp == 0
      alarm "Miner #{num} is stuck in error state!!!", :failure
    elsif upminutes > 5 # Miner settled down
      if unit_hash < @min_mhs
        alarm "Miner #{num} performance is #{unit_hash}, should be #{@min_mhs}", :perf_low
      elsif last == 'never' || last > @config[:alert_last_share]
        alarm "Miner #{num} last shares was #{last} min ago", :last_share
      elsif temp && temp >= @config[:alert_temp_high]
        alarm "Miner #{num} too hot at #{temp}°C, needs cooling", :temp_high
      elsif self[:freq] && temp && temp <= @config[:alert_temp_low]
        alarm "Miner #{num} temp low at #{temp}°C, is it hashing at all?", :temp_low
      end
    end
  end
end
reset() click to toggle source

Reset or reboot Miner

# File lib/avalon/miner.rb, line 152
def reset
  `ssh root@#{ip} "reboot"`
end
restart_time() click to toggle source
# File lib/avalon/miner.rb, line 101
def restart_time
  @poll_time - upminutes * 60.0
end
temp() click to toggle source
# File lib/avalon/miner.rb, line 105
def temp
  self[:'°C']
end
to_s() click to toggle source
# File lib/avalon/miner.rb, line 156
def to_s
  num.to_s.rjust(3) + ": " + 
    FIELDS.map {|key, (width, _, _ )| @data[key].to_s.rjust(width)}.join(" ")
end
unit_hash() click to toggle source
# File lib/avalon/miner.rb, line 109
def unit_hash
  self[:unit] || 0
end
upminutes() click to toggle source
# File lib/avalon/miner.rb, line 93
def upminutes
  duration(self[:uptime])
end