class WinkScheduler::Schedule

Public Class Methods

new(context, opts) click to toggle source
# File lib/wink_scheduler/schedule.rb, line 9
def initialize(context, opts)
  @last_time = nil
  @logger = context[:logger]
  devices = context[:devices]
  groups = context[:groups]

  if opts["device"]
    @object = devices.select { |d| next if d == nil; d.name == opts["device"] }[0]
    raise "device \"#{opts["device"]}\" not found" unless @object
    @type = :device
  elsif opts["group"]
    @object = groups.select { |g| next if g == nil; g.name == opts["group"] }[0]
    raise "group \"#{opts["group"]}\" not found" unless @object
    @type = :group
  else
    raise "Schedule must define either a 'device' or a 'group' option"
  end

  if opts["days"]
    @days = get_days(opts["days"])
  else
    raise "Schedule must define 'days' option"
  end

  if opts["method"]
    @method = opts["method"]
    raise "#{@method} is not a supported function of #{@object.name}" unless @object.respond_to?(@method)
  else
    raise "Schedule must define 'method' option"
  end

  @method_args = []
  if opts["method_args"]
    arity = @object.method(@method).arity
    if arity == 0
      raise "#{@method} does not take arguments. 'method_args' must be nil"
    elsif arity > 0
      if opts["method_args"].length == arity
        @method_args = opts["method_args"]
      else
        raise "#{@method} requires #{arity} argument(s). Invalid 'method_args' option"
      end
    elsif arity < 0
      if opts["method_args"].length >= arity.abs
        @method_args = opts["method_args"]
      else
        raise "#{@method} requires at least #{arity} argument(s). Invalid 'method_args' option"
      end
    end
  end

  if opts["time"]
    @time = opts["time"]
  else
    raise "Schedule must define 'time' option"
  end

  if opts["offset"]
    @offset = opts["offset"] * 60
  else
    @offset = 0
  end

  @window = opts["window"]

  if (@time == :sunrise || @time == :sunset)
    if opts["location"]
      @woeid = get_woeid(opts["location"])
    else
      raise "Schedule must define 'location' option if time used is sunrise or sunset"
    end
  end
end

Public Instance Methods

run() click to toggle source
# File lib/wink_scheduler/schedule.rb, line 83
def run
  while true
    execute
  end
end

Private Instance Methods

execute() click to toggle source
# File lib/wink_scheduler/schedule.rb, line 111
def execute
  cur_time = Time.now
  next_time = get_next_time

  @logger.info "Scheduled \"#{@method}#{"(" + @method_args.join(",") + ")" if @method_args}\" on #{@type} \"#{@object.name}\" at #{next_time}."
  sleep next_time - cur_time
  @object.send(@method, *@method_args)
  @logger.info "Executed \"#{@method}#{"(" + @method_args.join(",") + ")" if @method_args}\" on #{@type} \"#{@object.name}\"."
end
get_days(days) click to toggle source
# File lib/wink_scheduler/schedule.rb, line 90
def get_days(days)
  if days.class == Array
    map = { "Sunday" => 0, "Monday" => 1, "Tuesday" => 2, "Wednesday" => 3, "Thursday" => 4, "Friday" => 5, "Saturday" => 6,
            "sunday" => 0, "monday" => 1, "tuesday" => 2, "wednesday" => 3, "thursday" => 4, "friday" => 5, "saturday" => 6,
            :sunday  => 0, :monday  => 1, :tuesday  => 2, :wednesday  => 3, :thursday  => 4, :friday  => 5, :saturday  => 6 }
    if (days - map.keys).size > 0 || days.size == 0
      raise "Schedule 'days' option is invalid"
    else
      days.map { |d| map[d] }.uniq.sort
    end
  elsif days == :daily
    return (0..6).to_a
  else
    raise "Schedule 'days' option is invalid"
  end
end
get_next_time() click to toggle source
# File lib/wink_scheduler/schedule.rb, line 121
def get_next_time
  now = Time.now
  time = case @time
  when :sunset
    Weather.lookup(@woeid).astronomy.sunset
  when :sunrise
    Weather.lookup(@woeid).astronomy.sunrise
  else
    Time.parse(@time)
  end
  time += @offset
  randomness = @window ? rand(@window*60) - @window*60/2 : 0
  adj_time = time + randomness
  while adj_time < now || !@days.include?(adj_time.wday) || (@last_time && adj_time - @last_time < @window)
    adj_time += 86400
  end
  @last_time = adj_time
  return adj_time
end
get_woeid(location) click to toggle source
# File lib/wink_scheduler/schedule.rb, line 107
def get_woeid(location)
  HTTParty.get("http://where.yahooapis.com/v1/places.q('#{location}')?appid=dj0yJmk9V3pRYU83TjVYRVlNJmQ9WVdrOWEwVTNTM0oxTkdjbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD05NQ--").parsed_response["places"]["place"]["woeid"]
end