Here's the (nearly last) refactoring:
(text should word wrap at 80, but the news program wants to wrap earlier---)
#!/usr/bin/ruby -w
#########################################################
#
# log_CID.rb
#
# Ruby CID logging script
#
# Logs all activity at a modem set to decipher CID
# (Caller ID) information. Archives the daily logs as well.
#
##########################################################
require 'zip/zip'
require 'serialport/serialport.so'
require 'yaml'
# name of config file (YAML format)
config_yaml = 'log_CID.yml'
#################################
# script local classes
class ModemCIDMonitor
attr_reader :port_err_count, :config, :log_blank_lines
attr :debug, :port_err_count
def initialize(config_hash, logger)
@port_err_count = config_hash['port_err_count'] || 0
@port_name = config_hash['port_name'] ||
'COM1:'
@port = SerialPort.new(@port_name)
@MAX_PORT_ERRORS = config_hash['MAX_PORT_ERRORS'] || 100
@debug = config_hash['DEBUG'] ||
false
@log_blank_lines = config_hash['log_blank_lines'] ||
false
@logger = logger
@port.read_timeout = 0
@port_err_count = 0
@modem_init_string =
config_hash['modem_init_string'] || "AT+VCID=1\r\n"
@port.puts(@modem_init_string)
end
def log(txt)
print txt if debug
@logger.log_text(txt)
end
def run
print "Starting run with port ", @port_name,
" and logging to dir ", @logger.archive_dir, "\n"
loop do
@port.each_line do | text |
# log text unless it is just spaces
next unless text =~ /\S/ or log_blank_lines
# squeeze double \r, etc to just \n
text.sub!(/[\r\n]+/, "\n")
log(text)
end
msg =
"#{Time.now.to_s}: dropped out of system call, restarting
loop.\n"
log(msg) if debug
@port_err_count += 1
if(@port_err_count > MAX_PORT_ERRORS)
errmsg = "Too many port errors...ending run\n"
log(errmsg)
return errmsg
end
end
end
end
class CID_Config
attr_reader :config_file, :as_hash
def initialize(config_file)
@config_file = config_file
@as_hash = YAML::load( File.open(@config_file))
end
end
class DailyLogWithArchive
attr_reader :archive_dir, :base_log_name, :archive_zip_filename,
:archive_days_secs, :archive_days_interval
attr :debug
def initialize(config_hash)
@archive_dir = config_hash['archive_dir']
|| './'
@base_log_name = config_hash['base_log_name']
|| 'CID'
@debug = config_hash['DEBUG']
|| false
@archive_days_interval = config_hash['archive_days_interval']
|| 1
@archive_zip_filename = config_hash['archive_zip_filename'] ||
'CID_archive.zip'
@last_archive_day = -1
@archive_days_secs = 60 * 60 * 24 * 7
@archive_days_secs =
60 * 60 * 24 * config_hash['days_before_archive'] if
(config_hash['days_before_archive'])
end
def current_fname
"#{archive_dir}/#{base_log_name}#{Time.now.strftime("%Y%m%d")}.log"
end
def archive_old_to_zip
time = Time.now
wd = Dir.getwd
Dir.chdir(@archive_dir)
dir = Dir.open(@archive_dir)
moved = dir.inject(0) do | move_count, logfile |
next unless logfile
next unless logfile =~ /^#{base_log_name}/
next unless time > File.stat(logfile).mtime +
@archive_days_secs
if(move_to_archive(logfile))
log_text("LOGGER: Archiving file " + logfile + "\n") if
@debug
next move_count + 1
else
next move_count
end
end
dir.close
Dir.chdir(wd)
return moved
end
def move_to_archive(fname)
Zip::ZipFile.open(@archive_zip_filename, 1) {
| zfile |
return nil if zfile.exist?(fname)
zfile.add(fname, fname)
}
File.delete(fname)
end
def log_text(txt)
wd = Dir.getwd
Dir.chdir(@archive_dir)
logfile = File.new(current_fname, "a")
logfile.print(txt)
logfile.close
# check if we should do periodic archiving (up to daily)
time = Time.now
yday = time.yday
if(yday != @last_archive_day and
(yday >= @last_archive_day + @archive_days_interval or yday
== 0) )
archive_old_to_zip
@last_archive_day = yday
end
Dir.chdir(wd)
end
end
###############################
# begin main program
# get config from YAML text file
config = CID_Config.new(config_yaml)
# set up the logging class
logger = DailyLogWithArchive.new(config.as_hash)
# set up modem monitor
monitor = ModemCIDMonitor.new(config.as_hash, logger)
# run -- no return from this unless abort on port timeouts or errors
errmsg = monitor.run
print errmsg
return 0
=================================================
log_CID.yml file:
############################################
#
# log_CID YAML config file.
#
# name of archive file--daily logs are moved to this archive
archive_zip_filename: CID_Data.zip
# modem initialization string.
# need to set to log verbose caller ID information (+VCID=1 or #CID=1, etc)
# also need to set to NOT answer, just monitor line (usually the default)
modem_init_string: AT+VCID=1\r\n
# directory to keep log files
archive_dir: c:/USR/log_CID
# base log name for daily log files
# daily log file name is this, plus YYYYMMDD date, plus .log extension
# eg. CID20041004.log
base_log_name: CID
# the comm port having the CID-capable modem
port_name: 'COM3:'
# days that a daily log file is kept prior to archiving the file
days_before_archive: 7
# maximum port read errors allowed before aborting run
MAX_PORT_ERRORS: 3000
# whether to log whitespace-only lines
log_blank_lines: false
# debug on or off?
DEBUG: true
#
# end YAML config file.
#
#####################################################