LBPプリンタの状態を取得する
大雑把に作成したコントローラーとモデルとビューを紹介してみる。
controllers/lpr/host_controller.rb
class Lpr::HostController < ApplicationController verify :redirect_to => { :action => :index } def listall @page_title = "全てのプリンタ" @hosts = Lpr::Lprhost.paginate(:page=>params[:page], :per_page=>25, :order=>"id, back_day IS NULL") end def destroy Lpr::Lprhost.find(params[:id]).destroy flash[:notice] = "削除しますた" redirect_to :action => 'index' end def update @page_title = "プリンタの更新" @host = Lpr::Lprhost.find(params[:id]) if @host.update_attributes(params[:host]) flash[:notice] = "プリンタの更新は完了しました" redirect_to :action =>'index' else render :action =>'edit' end end def edit @page_title = "プリンタの編集" @host = Lpr::Lprhost.find(params[:id]) end def show @page_title = "プリンタの詳細" @host = Lpr::Lprhost.find(params[:id]) end def create @page_title = "プリンタの新規登録中" @host = Lpr::Lprhost.new(params[:host]) if @host.save flash[:notice] = 'プリンタが正しく作成されました。' redirect_to :action=>'index' else render :action=>'new' end end def new @page_title = "プリンタの新規登録" @host = Lpr::Lprhost.new end def index @page_title = "プリンタの登録状況のTOP" @hosts = Lpr::Lprhost.paginate(:page=>params[:page], :conditions=>"back_day IS NULL", :per_page=>25, :order=>"id, back_day IS NULL") end end
controllers/lpr/state_controller.rb
checkを定期的に実行する方法はまだ模索中。だって重いんだもん。
class Lpr::StateController < ApplicationController verify :redirect_to => { :action => :index } def gruff_line g = Gruff::Line.new 500 g.title = "Print Paper" conditions = params[:cond] unless params[:cond].nil? lprs = Lpr::Lprstate.find(:all, :conditions => conditions, :include => :lprhost) #ホスト名の配列を作る host_arry = Array.new lprs.each{|host| host_arry << host.lprhost.host_name } #ホスト毎の印刷枚数を取得する host_arry.uniq.each{|host| total_arry = Array.new lprs.each{|name| if name.lprhost.host_name == host total_arry << name.total_print #nullとかお構いなしなので、データをプロットしたときに表示位置が変になる end } g.data(host, total_arry) } send_data(g.to_blob, :type => 'image/png') end def export_csv(conditions) find_search lprstates = Lpr::Lprstate.find(:all, :conditions => conditions, :include => :lprhost, :order => 'lprstates.id DESC') filename = DateTime.now.strftime('%Y%m%d_%H%M_lprstate') + ".csv" stream_csv(filename) do |csv| csv << [ "id".tosjis, "ホスト名".tosjis, "IP".tosjis, "総印刷".tosjis, "MSG".tosjis, "作成日".tosjis] lprstates.each do |s| csv << [s.id.to_s.tosjis, s.lprhost.host_name.to_s.tosjis, s.lprhost.ip.to_s.tosjis, s.total_print.to_s.tosjis, s.msg.to_s.tosjis, s.created_at.to_s(:jp).tosjis] end end end def search @page_title = "プリンタの状況の検索" find_search if request.get? if params[:page].nil? @lprstate_cond.empty! @lprstate_cond.host_name = params[:host_name] unless params[:host_name].nil? @lprstate_cond.dayfrom = params[:dayfrom].nil? ? Date.today : params[:dayfrom] @lprstate_cond.dayto = params[:dayto].nil? ? Date.today : params[:dayto] end else @lprstate_cond.set_params(params) end @conditions = @lprstate_cond.get_conditions @lprstates = Lpr::Lprstate.paginate( :page=>params[:page], :per_page=>50, :conditions=>@conditions, :include => :lprhost, :order=>"lprstates.id" ) export_csv(@conditions) if params[:export] == "CSV" end def index @page_title = "プリンタの状況のTOP" end def check @hosts = Lpr::Lprhost.find(:all, :conditions=>"back_day IS NULL", :order=>"host_name") require 'ping' count = 0 @hosts.each{|host_name| @state = Lpr::Lprstate.new if Ping.pingecho(host_name.ip, timeout = 1, "80") if host_name.model_name == "LBP1820" lprset = lpr_state1820(host_name.ip) elsif host_name.model_name == "LBP5900" lprset = lpr_state5900(host_name.ip) @state.toner_b_rest = lprset['toner_b_rest'] @state.toner_black = lprset['toner_black'] @state.toner_y_rest = lprset['toner_y_rest'] @state.toner_yellow = lprset['toner_yellow'] @state.toner_m_rest = lprset['toner_m_rest'] @state.toner_magenta = lprset['toner_magenta'] @state.toner_c_rest = lprset['toner_c_rest'] @state.toner_cyan = lprset['toner_cyan'] else break end @state.lprhost_id = host_name.id @state.total_print = lprset['total_print'] @state.image_name = lprset['image_name'] @state.msg = lprset['msg'] else msg = "Ping応答がありまんでした" @state.lprhost_id = host_name.id #この辺のエラー処理はテキトー @state.msg = msg end @state.save count += 1 } redirect_to :controller=>"lpr/state", :action=>"index" end private #テキトーな正規表現、プリンタのモデルによって書き換えないといけないので不便 def lpr_state5900(ip) #LBP-5900用 require 'net/http' Net::HTTP.version_1_2 # おまじない $proxy_addr = 'proxy-address' $proxy_port = 80 lpr = Hash.new lpr['url'] = "http://"+ip env_path = '/dstatus.cgi' stat_path = '/dfeature.cgi' begin http = Net::HTTP::Proxy($proxy_addr, $proxy_port).new( ip ) http.open_timeout = 2 http.read_timeout = 5 http.start do #総印刷ページ数 response = http.get(stat_path) find_flag = 0 response.body.toutf8.each{|l| #総印刷ページ数を取得する if find_flag == 1 s = l.index("<td>") e = l.rindex("</td>") lpr['total_print'] = l.slice(s+4..e-1) break end find_flag = 1 if /総印刷ページ数/ =~ l.toutf8 } #カセットの画像res.cgi?cass_42 response = http.get(env_path) find_flag = 0 response.body.toutf8.each{|l| #画像のファイル名 if /res.cgi\?cass_/ =~ l lpr['image_name'] = lpr_state5900_image(l) end #メッセージ if /statusinfo/ =~ l if find_flag == 0 s = l.index("\"") e = l.rindex("\"") lpr['msg'] = l.slice(s+1..e-1).gsub(";","") find_flag = 1 end end #トナーblack if /ink_b/ =~ l lpr['toner_b_rest'] = lpr_state5900_rest(l) lpr['toner_black'] = lpr_state5900_image(l) end #トナーyellow if /ink_y/ =~ l lpr['toner_y_rest'] = lpr_state5900_rest(l) lpr['toner_yellow'] = lpr_state5900_image(l) end #トナーmagenta if /ink_m/ =~ l lpr['toner_m_rest'] = lpr_state5900_rest(l) lpr['toner_magenta'] = lpr_state5900_image(l) end #トナーcyan if /ink_c/ =~ l lpr['toner_c_rest'] = lpr_state5900_rest(l) lpr['toner_cyan'] = lpr_state5900_image(l) end } end rescue lpr['msg'] = "exception on HTTP: StandardError #{$!}" rescue Timeout::Error lpr['msg'] = "exception on HTTP: TimeoutError" rescue Exception lpr['msg'] = "exception on HTTP: #{$!}" end return lpr end def lpr_state5900_rest(line) s = line.index("alt") e = line.index("border") return line.slice(s+5..e-4) end def lpr_state5900_image(line) s = line.index("res.cgi\?") e = line.rindex("gif") return line.slice(s+8..e+2) end def lpr_state1820(ip) #LBP-1820用 require 'net/http' Net::HTTP.version_1_2 # おまじない $proxy_addr = 'proxy-address' $proxy_port = 80 lpr = Hash.new lpr['url'] = "http://"+ip env_path = '/dev/dev_env.shtml' stat_path = '/dev/dev_stat.shtml' begin http = Net::HTTP::Proxy($proxy_addr, $proxy_port).new( ip ) http.open_timeout = 2 http.read_timeout = 5 http.start do response = http.get(env_path) find_flag = 0 response.body.toutf8.each{|l| #総印刷ページ数を取得する if find_flag == 1 s = l.index("<td>") e = l.rindex("</td>") lpr['total_print'] = l.slice(s+4..e-1) break end find_flag = 1 if /総印刷ページ数/ =~ l.toutf8 } #用紙の状態を表す画像のURLを取得する。(状態によって、パスが変わる) response = http.get(stat_path) response.body.toutf8.each{|l| if /cassette/ =~ l s = l.index("image") e = l.index("gif") lpr['image_name'] = l.slice(s+6,e-s-3) end } #デバイスの状態を取得する find_flag = 0 response.body.toutf8.each{|l| if find_flag == 1 s = l.index("><b>") e = l.index("/b>") lpr['msg'] = l.slice(s+4..e-2) break end find_flag = 1 if /デバイス状態/ =~ l.toutf8 } end rescue lpr['msg'] = "exception on HTTP: StandardError #{$!}" rescue Timeout::Error lpr['msg'] = "exception on HTTP: TimeoutError" rescue Exception lpr['msg'] = "exception on HTTP: #{$!}" end return lpr end def find_search @lprstate_cond = (session[:lprstate_cond] ||= Lpr::LprstateCond.new) end end
models/lpr/lprhost.rb
class Lpr::Lprhost < ActiveRecord::Base has_many :lprstate validates_presence_of :host_name, :room_name, :model_name validates_format_of :room_id, :with=>/\A[0-9]+\Z/ validates_format_of :intro_day, :with=>/\d{4}-\d{2}-\d{2}/ #IPアドレスのvalidate(ナイショ) attr_human_name :id=>'ID', :ip=> "IPアドレス", :host_name=>"ホスト名", :room_name=>"設置場所", :room_id=>"部屋ID", :model_name=>"機種名", :intro_day=>"導入日", :back_day=>"返却日", :memo=>"メモ", :created_at=>"作成日", :updated_at=>"更新日" protected def validate #IPアドレスの検証をするところ(ナイショ) unless host_name.blank? errors.add(:host_name, "半角英数のみです") unless /\w+/ =~ host_name end end end
models/lpr/lprstate.rb
class Lpr::Lprstate < ActiveRecord::Base belongs_to :lprhost attr_human_name :id=>'ID', :lprhost_id=>'ホストID', :total_print=>'総印刷数', :toner_black=>'黒残量', :toner_b_rest=>'黒%', :toner_yellow=>'黄残量', :toner_y_rest=>'黄%', :toner_magenta=>'マゼンタ残量', :toner_m_rest=>'マゼンタ%', :toner_cyan=>'シアン残量', :toner_c_rest=>'シアン%', :image_name=>'紙残量', :msg=>'メッセージ', :memo=>'メモ', :created_at=>'作成日', :updated_at=>'更新日' end
models/lpr/lprstate_cond.rb
class Lpr::LprstateCond < Cond attr_accessor :host_name, :dayfrom, :dayto def empty! @host_name = "" @dayfrom = Date.today @dayto = Date.today end def set_params(params) @host_name = params[:lprstate_cond][:host_name] @dayfrom = params[:lprstate_cond][:dayfrom] @dayto = params[:lprstate_cond][:dayto] end def get_conditions w = Where.new unless @dayfrom.nil? && @dayto.nil? w.and('lprstates.created_at between ? AND ?', @dayfrom.to_date, (@dayto.to_date+1).to_date) end w.and('lprhosts.host_name LIKE ?', '%'+@host_name+'%') if !@host_name.blank? w.to_s end end
ビューで重要なのが
views/lpr/state/search.html.erb
<%= javascript_include_tag('lpr') %> <div id="table_area"> <div id="edit_dialog"> <h3><%= @page_title %></h3> <%= link_to '検索', :controller => 'lpr/state', :action=>'search' %><br /> <%= link_to '登録', :controller => 'lpr/host', :action=>'index' %><br /> <%= ja_error_messages_for(:lprstate) -%> <img src="<%= url_for :controller=>'lpr/state', :action=>'gruff_line', :cond=>@conditions %>"> <div class='iftb_doc'> <%= form_tag({:action=>"search"}, {:name=>"frm"}) %> <%= render :partial=> "lpr/state/any/search" %> <INPUT type="button" name="cmdReset" value="検索条件リセット" onclick="clearSearchFormLprstate();"> <%= submit_tag "検索する" %> <%= submit_tag("CSV", {'name'=>'export', 'value'=>'CSV'}) %> </form> </div> </div> </div> <%- unless @lprstates.total_entries == 0 %> <div class='iftb_pagenate'>検索結果: <%=h @lprstates.total_entries %> 件 <%= will_paginate @lprstates, :prev_label => '<<前' , :next_label => '次>>' -%></div> <%= render :partial=> "lpr/state/any/result" %> <div class='iftb_pagenate'>検索結果: <%=h @lprstates.total_entries %> 件 <%= will_paginate @lprstates, :prev_label => '<<前' , :next_label => '次>>' -%></div> <%- else %> <p>指定された条件に適合する結果はありませんでした。(´・ω・`)ショボーン</p> <%- end %>
グラフを書き出すところの検索用のパラメータを渡しています。