class Huebot::Compiler
Public Class Methods
new(device_mapper)
click to toggle source
# File lib/huebot/compiler.rb, line 3 def initialize(device_mapper) @device_mapper = device_mapper end
Public Instance Methods
build(ir, default_name = nil)
click to toggle source
Build a huebot program from an intermediate representation (a Hash).
@param ir [Hash] @param default_name [String] A name to use if one isn't specified @return [Huebot::Program]
# File lib/huebot/compiler.rb, line 14 def build(ir, default_name = nil) ir = ir.clone prog = Huebot::Program.new prog.name = ir.delete("name") || default_name # loop/loops val_loop = ir.delete("loop") || ir.delete(:loop) prog.errors << "'loop' must be 'true' or 'false'." if !val_loop.nil? and ![true, false].include?(val_loop) prog.loop = val_loop == true val_loops = ir.delete("loops") || ir.delete(:loops) prog.errors << "'loops' must be a positive integer." if !val_loops.nil? and val_loops.to_i < 0 prog.loops = val_loops.to_i prog.errors << "'loop' and 'loops' are mutually exclusive." if prog.loop? and prog.loops > 0 # initial state if (val_init = ir.delete("initial") || ir.delete(:initial)) errors, warnings, state = build_transition val_init prog.initial_state = state prog.errors += errors prog.warnings += warnings end # transitions if (val_trns = ir.delete("transitions") || ir.delete(:transitions)) val_trns.each do |val_trn| errors, warnings, state = if val_trn["parallel"] || val_trn[:parallel] build_parallel_transition val_trn else build_transition val_trn end prog.transitions << state prog.errors += errors prog.warnings += warnings end end # final state if (val_fnl = ir.delete("final") || ir.delete(:final)) errors, warnings, state = build_transition val_fnl prog.final_state = state prog.errors += errors prog.warnings += warnings end # be strict about extra crap if (unknown = ir.keys.map(&:to_s)).any? prog.errors << "Unrecognized values: #{unknown.join ', '}." end # Add any warnings prog.warnings << "'final' is defined but will never be reached because 'loop' is 'true'." if prog.final_state and prog.loop? prog end
Private Instance Methods
build_parallel_transition(t)
click to toggle source
# File lib/huebot/compiler.rb, line 73 def build_parallel_transition(t) errors, warnings = [], [] transition = Huebot::Program::ParallelTransition.new(0, []) transition.wait = t.delete("wait") || t.delete(:wait) errors << "'wait' must be a positive integer." if transition.wait and transition.wait.to_i <= 0 parallel = t.delete("parallel") || t.delete(:parallel) if !parallel.is_a? Array errors << "'parallel' must be an array of transitions" else parallel.each do |sub_t| sub_errors, sub_warnings, sub_transition = build_transition(sub_t) errors += sub_errors warnings += sub_warnings transition.children << sub_transition end end return errors, warnings, transition end
build_transition(t)
click to toggle source
# File lib/huebot/compiler.rb, line 95 def build_transition(t) errors, warnings = [], [] transition = Huebot::Program::Transition.new transition.devices = [] map_devices(t, :light, :lights, :light!) { |map_errors, devices| errors += map_errors transition.devices += devices } map_devices(t, :group, :groups, :group!) { |map_errors, devices| errors += map_errors transition.devices += devices } map_devices(t, :device, :devices, :var!) { |map_errors, devices| errors += map_errors transition.devices += devices } errors << "Missing light/lights, group/groups, or device/devices" if transition.devices.empty? transition.wait = t.delete("wait") || t.delete(:wait) errors << "'wait' must be a positive integer." if transition.wait and transition.wait.to_i <= 0 state = {} switch = t.delete("switch") switch = t.delete(:switch) if switch.nil? if !switch.nil? state[:on] = case switch when true, :on then true when false, :off then false else errors << "Unrecognized 'switch' value '#{switch}'." nil end end state[:transitiontime] = t.delete("time") || t.delete(:time) || t.delete("transitiontime") || t.delete(:transitiontime) || 4 transition.state = t.merge(state).reduce({}) { |a, (key, val)| a[key.to_sym] = val a } return errors, warnings, transition end
map_devices(t, singular_key, plural_key, ref_type) { |errors, devices| ... }
click to toggle source
# File lib/huebot/compiler.rb, line 142 def map_devices(t, singular_key, plural_key, ref_type) errors, devices = [], [] key = t[singular_key.to_s] || t[singular_key] keys = t[plural_key.to_s] || t[plural_key] (Array(key) + Array(keys)).each { |x| begin devices += Array(@device_mapper.send(ref_type, x)) rescue Huebot::DeviceMapper::Unmapped => e errors << e.message end } yield errors, devices end