module FANUC module Ekg # :stopdoc: LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR # :startdoc: # Returns the version string for the library. # def self.version @version ||= File.read(path('version.txt')).strip end # Returns the library path for the module. If any arguments are given, # they will be joined to the end of the libray path using # File.join. # def self.libpath( *args, &block ) rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten) if block begin $LOAD_PATH.unshift LIBPATH rv = block.call ensure $LOAD_PATH.shift end end return rv end # Returns the lpath for the module. If any arguments are given, # they will be joined to the end of the path using # File.join. # def self.path( *args, &block ) rv = args.empty? ? PATH : ::File.join(PATH, args.flatten) if block begin $LOAD_PATH.unshift PATH rv = block.call ensure $LOAD_PATH.shift end end return rv end # Utility method used to require all files ending in .rb that lie in the # directory below this file that has the same name as the filename passed # in. Optionally, a specific _directory_ name can be passed in such that # the _filename_ does not have to be equivalent to the directory. # def self.require_all_libs_relative_to( fname, dir = nil ) dir ||= ::File.basename(fname, '.*') search_me = ::File.expand_path( ::File.join(::File.dirname(fname), dir, '**', '*.rb')) Dir.glob(search_me).sort.each {|rb| require rb} end # what parser should we use if RUBY_VERSION.to_f >= 1.9 require 'csv' PARSER = CSV else require 'faster_csv' PARSER = FasterCSV end require 'open-uri' #for opening URLs class Bin attr_accessor :collision_counts def initialize @collision_counts = [] end def total @collision_counts.inject {|sum,x| sum+x} end def [](id) @collision_counts[id-1] end end class Alarm attr_reader :occured_at, :error_text, :safety_io, :velocity, :torque, :angle, :disturbance_torque def initialize(options={}) @occured_at = options["DateTime"] @error_text = options["ErrorText"] @safety_io = options["Safety I/O"] @velocity = { :j1 => options["Vel J1\[%\]"], :j2 => options["Vel J2\[%\]"], :j3 => options["Vel J3\[%\]"], :j4 => options["Vel J4\[%\]"], :j5 => options["Vel J5\[%\]"] } @torque = { :j1 => options["Torq J1\[%\]"], :j2 => options["Torq J2\[%\]"], :j3 => options["Torq J3\[%\]"], :j4 => options["Torq J4\[%\]"], :j5 => options["Torq J5\[%\]"] } @angle = { :j1 => options["Angle J1\[rad\]"], :j2 => options["Angle J2\[rad\]"], :j3 => options["Angle J3\[rad\]"], :j4 => options["Angle J4\[rad\]"], :j5 => options["Angle J5\[rad\]"], } @disturbance_torque = { :j1 => options["DistTorq J1\[%\]"], :j2 => options["DistTorq J2\[%\]"], :j3 => options["DistTorq J3\[%\]"], :j4 => options["DistTorq J4\[%\]"], :j5 => options["DistTorq J5\[%\]"] } end end class EkgData attr_accessor :bins, :alarms def initialize @bins = { :zero => Bin.new, :v1t1 => Bin.new, :v2t1 => Bin.new, :v1t2 => Bin.new, :v2t2 => Bin.new } @alarms = { :recent => [], :worst => [] } end def axis(id) @sum = 0 @bins.each do |key,bin| @sum += bin[id] end # should i remove bin 0? @sum end end class << self def split(string) @output = {} @str = "" string.each_line do |line| next if line =~ /Severity(\r)?\n/ next if line =~ /Group,Bin0,BinV1T1,BinV2T1,BinV1T2,BinV2T2(\r)?\n/ next if line =~ /MRA_Num,DateTime,ErrorText,Safety I\/O,Vel J1\[%\],Vel J2\[%\],Vel J3\[%\],Vel J4\[%\],Vel J5\[%\],Vel J6\[%\],Vel J7\[%\],Vel J8\[%\],Torq J1\[%\],Torq J2\[%\],Torq J3\[%\],Torq J4\[%\],Torq J5\[%\],Torq J6\[%\],Torq J7\[%\],Torq J8\[%\],Angle J1\[rad\],Angle J2\[rad\],Angle J3\[rad\],Angle J4\[rad\],Angle J5\[rad\],Angle J6\[rad\],Angle J7\[rad\],Angle J8\[rad\],DistTorq J1\[%\],DistTorq J2\[%\],DistTorq J3\[%\],DistTorq J4\[%\],DistTorq J5\[%\],DistTorq J6\[%\],DistTorq J7\[%\],DistTorq J8\[%\](\r)?\n/ next if line =~ /Num,DateTime,ErrorText,Safety I\/O,Vel J1\[%\],Vel J2\[%\],Vel J3\[%\],Vel J4\[%\],Vel J5\[%\],Vel J6\[%\],Vel J7\[%\],Vel J8\[%\],Torq J1\[%\],Torq J2\[%\],Torq J3\[%\],Torq J4\[%\],Torq J5\[%\],Torq J6\[%\],Torq J7\[%\],Torq J8\[%\],Angle J1\[rad\],Angle J2\[rad\],Angle J3\[rad\],Angle J4\[rad\],Angle J5\[rad\],Angle J6\[rad\],Angle J7\[rad\],Angle J8\[rad\],DistTorq J1\[%\],DistTorq J2\[%\],DistTorq J3\[%\],DistTorq J4\[%\],DistTorq J5\[%\],DistTorq J6\[%\],DistTorq J7\[%\],DistTorq J8\[%\](\r)?\n/ if line =~ /Most Recent Alarms\(MRA\) for Group 1(\r)?\n/ @output[:bins] = @str @str = "" next end if line =~ /Worst Disturbance Alarms for Group 1(\r)?\n/ @output[:recent] = @str @str = "" next end @str += line end @output[:worst] = @str return @output end def parse(file) @ekg_data = FANUC::Ekg::EkgData.new f = open(file).read output = split(f) # split the output into 3 usable CSV sections # parse bins PARSER.parse(output[:bins],:headers=>"Group,Bin0,BinV1T1,BinV2T1,BinV1T2,BinV2T2") do |line| @ekg_data.bins[:zero].collision_counts << line['Bin0'].to_i @ekg_data.bins[:v1t1].collision_counts << line['BinV1T1'].to_i @ekg_data.bins[:v2t1].collision_counts << line['BinV2T1'].to_i @ekg_data.bins[:v1t2].collision_counts << line['BinV1T2'].to_i @ekg_data.bins[:v2t2].collision_counts << line['BinV2T2'].to_i end # parse recent alarms PARSER.parse(output[:recent],:headers => "MRA_Num,DateTime,ErrorText,Safety I/O,Vel J1\[%\],Vel J2\[%\],Vel J3\[%\],Vel J4\[%\],Vel J5\[%\],Vel J6\[%\],Vel J7\[%\],Vel J8\[%\],Torq J1\[%\],Torq J2\[%\],Torq J3\[%\],Torq J4\[%\],Torq J5\[%\],Torq J6\[%\],Torq J7\[%\],Torq J8\[%\],Angle J1\[rad\],Angle J2\[rad\],Angle J3\[rad\],Angle J4\[rad\],Angle J5\[rad\],Angle J6\[rad\],Angle J7\[rad\],Angle J8\[rad\],DistTorq J1\[%\],DistTorq J2\[%\],DistTorq J3\[%\],DistTorq J4\[%\],DistTorq J5\[%\],DistTorq J6\[%\],DistTorq J7\[%\],DistTorq J8\[%\]") do |line| @ekg_data.alarms[:recent] << Ekg::Alarm.new(line.to_hash) end # parse worst disturbances PARSER.parse(output[:worst],:headers=>"Num,DateTime,ErrorText,Safety I/O,Vel J1\[%\],Vel J2\[%\],Vel J3\[%\],Vel J4\[%\],Vel J5\[%\],Vel J6\[%\],Vel J7\[%\],Vel J8\[%\],Torq J1\[%\],Torq J2\[%\],Torq J3\[%\],Torq J4\[%\],Torq J5\[%\],Torq J6\[%\],Torq J7\[%\],Torq J8\[%\],Angle J1\[rad\],Angle J2\[rad\],Angle J3\[rad\],Angle J4\[rad\],Angle J5\[rad\],Angle J6\[rad\],Angle J7\[rad\],Angle J8\[rad\],DistTorq J1\[%\],DistTorq J2\[%\],DistTorq J3\[%\],DistTorq J4\[%\],DistTorq J5\[%\],DistTorq J6\[%\],DistTorq J7\[%\],DistTorq J8\[%\]") do |line| @ekg_data.alarms[:worst] << Ekg::Alarm.new(line.to_hash) end @ekg_data end end end # module Ekg end # module FANUC FANUC::Ekg.require_all_libs_relative_to(__FILE__)