ウェザーニューズから受信した緊急地震速報をeew_parserに通して何かする

WNIから受信した緊急地震速報をeew_parserに通して色々するクラス
WNI_EEW.newにWNIのメールアドレスとパスワードとブロックを渡すと、WNIから緊急地震速報を受信した時にその緊急地震速報から生成したEEWParserオブジェクトをブロックに渡して実行してくれる。

require 'socket'
require 'eew_parser'
require 'digest/md5'
require 'open-uri'

class WNI_EEW
  DEBUG = true

  trap(:INT) do
    exit
  end

  def initialize(user_id, pass, &b)
    http = TCPSocket.open(get_server_addr, 80)
    http.print "GET /login HTTP/1.0\r\nX-WNI-Account: #{user_id}\r\nX-WNI-Password: #{Digest::MD5.hexdigest(pass)}\r\n\r\n"
    begin
      if WNI_HTTPHeader.new(http.readline("\n\n"))["X-WNI-Result"] == "OK"
        debug "[#{Time.now.strftime("%F %T")}] #{get_server_addr} との接続を確立しました"
      else
        abort "認証に失敗しました。"
      end
    rescue => ex
      abort "接続に失敗しました。#{ex.message}"
    end
    loop do
      case WNI_HTTPHeader.new(http.readline("\n\n"))["X-WNI-ID"]
      when "Keep-Alive"
        debug "[#{Time.now.strftime("%F %T")}] Keep-Alive"
      when "Data"
        http.readline("\n\x02\n\x02\n")
        yield EEWParser.new(http.readline("9999=").strip)
      end
    end
    http.close
  end

  def debug(str)
    puts str if DEBUG
  end

  def get_server_addr
    open('http://lst10s-sp.wni.co.jp/server_list.txt') do |list|
      list.read.lines.to_a.sample[0..-5]
    end
  end

  class WNI_HTTPHeader
    def initialize(str)
      @lines = str.lines.to_a
    end

    def [](key)
      @lines[1..-2].each do |line|
        field = line.split(":", 2)
        return field.last.strip if field.first == key
      end
    end
  end
end

WNI_EEW.new('WNIのメールアドレス', 'WNIのパスワード') do |eew|
  # ここで何かする
end

WNIのサーバはHTTPのヘッダフィールド名の大文字小文字を区別するので、net/httpは使えない。
仕方が無いのでTCPSocketを使って通信している。