274 lines
6.1 KiB
Ruby
Executable File
274 lines
6.1 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
#
|
|
# huec - Philips (friends of) hue command-line utility
|
|
#
|
|
# Hued is Copyright © 2011 Paul van Tilburg <paul@luon.net>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by the
|
|
# Free Software Foundation; either version 2 of the License, or (at your
|
|
# option) any later version.
|
|
|
|
require "hued/version"
|
|
require "huey"
|
|
require "logger"
|
|
require "optparse"
|
|
require "pp"
|
|
require "pry"
|
|
require "rainbow"
|
|
|
|
include Huey
|
|
|
|
def status_line(blb)
|
|
mode = []
|
|
if blb.reachable
|
|
on_off = blb.on ? Rainbow("on").bright.green : Rainbow("off").red
|
|
case blb.colormode
|
|
when "xy"
|
|
mode << "xy: #{blb.xy.inspect}"
|
|
when "hs"
|
|
mode << "hue: #{blb.hue}" << "sat: #{blb.sat}"
|
|
when "ct"
|
|
mode << "ct: #{blb.ct}"
|
|
end
|
|
mode << "bri: #{blb.bri}"
|
|
else
|
|
on_off = Rainbow("unreachable").bright.red
|
|
end
|
|
|
|
line = "%2d: %-30s (%-12s" % [blb.id, blb.name, on_off, mode]
|
|
if mode.empty?
|
|
line += ")"
|
|
else
|
|
line += ", #{mode.join(', ')})"
|
|
end
|
|
|
|
return line
|
|
end
|
|
|
|
def prompt_status
|
|
reload_needed = Time.now - @prompt_stamp > 10
|
|
prompt_str = Huey::Bulb.all.map do |blb|
|
|
blb.reload if reload_needed
|
|
if blb.reachable
|
|
blb.on ? Rainbow("o").bright.green : Rainbow("o").red
|
|
else
|
|
Rainbow("x").bright.red
|
|
end
|
|
end.join
|
|
@prompt_stamp = Time.now if reload_needed
|
|
prompt_str
|
|
end
|
|
|
|
def lights
|
|
Huey::Bulb.all.each do |blb|
|
|
puts status_line(blb)
|
|
end
|
|
true
|
|
end
|
|
|
|
def groups
|
|
Huey::Group.all.each do |grp|
|
|
puts "%2d: %s (%s)" % [grp.id, grp.name, grp.bulbs.map(&:id).join(', ')]
|
|
end
|
|
true
|
|
end
|
|
|
|
def events
|
|
events_cfg = File.join(@options[:config_dir], "events.yml")
|
|
Huey::Event.import(events_cfg).each_with_index do |ev, idx|
|
|
puts "%2d: %s" % [idx, ev.name]
|
|
end
|
|
true
|
|
end
|
|
|
|
def scenes
|
|
@scenes = {}
|
|
scenes_cfg = File.join(@options[:config_dir], "scenes.yml")
|
|
YAML.load_file(scenes_cfg).each_with_index do |(name, entry), idx|
|
|
puts "%2d: %s" % [idx, name]
|
|
@scenes[name] = entry.map do |ev_options|
|
|
# Keys should be symbols
|
|
options = ev_options.inject({}) { |opts, (k, v)| opts[k.to_sym] = v; opts }
|
|
event = Huey::Event.new(options)
|
|
event.actions["on"] = true if event.actions["on"].nil?
|
|
event
|
|
end
|
|
end
|
|
true
|
|
end
|
|
|
|
def refresh!
|
|
Huey::Bulb.all.each do |blb|
|
|
blb.reload
|
|
puts status_line(blb)
|
|
end
|
|
true
|
|
end
|
|
|
|
def get(*names_or_ids)
|
|
names_or_ids.map do |name_or_id|
|
|
blb = Huey::Bulb.find(name_or_id)
|
|
puts status_line(blb)
|
|
true
|
|
end
|
|
end
|
|
|
|
def set(*names_or_ids, opts)
|
|
blb = nil
|
|
names_or_ids.map do |name_or_id|
|
|
blb = Huey::Bulb.find(name_or_id)
|
|
blb.update(opts)
|
|
end
|
|
rescue Huey::Errors::BulbOff
|
|
blb.update(on: true)
|
|
retry
|
|
rescue Huey::Errors::Error => e
|
|
puts "Error: #{e.message}"
|
|
end
|
|
|
|
def getgrp(*names_or_ids)
|
|
names_or_ids.map do |name_or_id|
|
|
Huey::Group.find(name_or_id).each do |blb|
|
|
puts status_line(blb)
|
|
end
|
|
true
|
|
end
|
|
end
|
|
|
|
def setgrp(*names_or_ids, opts)
|
|
names_or_ids.map do |name_or_id|
|
|
grp = Huey::Group.find(name_or_id)
|
|
grp.update(opts)
|
|
end
|
|
end
|
|
|
|
def event(name_or_id)
|
|
ev = case name_or_id
|
|
when Fixnum
|
|
Huey::Event.all[name_or_id]
|
|
when String
|
|
Huey::Event.find(name_or_id)
|
|
end
|
|
ev.execute
|
|
end
|
|
|
|
def scene(name_or_id)
|
|
sc = case name_or_id
|
|
when Fixnum
|
|
@scenes.values[name_or_id]
|
|
when String
|
|
@scenes[name_or_id]
|
|
end
|
|
sc.map { |ev| ev.execute }
|
|
end
|
|
|
|
def alert(*names_or_ids)
|
|
names_or_ids.map do |name_or_id|
|
|
blb = Huey::Bulb.find(name_or_id)
|
|
blb.alert!
|
|
end
|
|
end
|
|
|
|
def off(*names_or_ids)
|
|
set(*names_or_ids, on: false)
|
|
end
|
|
|
|
def on(*names_or_ids)
|
|
set(*names_or_ids, on: true)
|
|
end
|
|
|
|
def commands
|
|
puts <<EOT
|
|
Lights
|
|
lights shows the list of all lights
|
|
(ID, name and state)
|
|
get [name/ID] get the setting of a light
|
|
set [name/ID], [update] update the setting of a light
|
|
alert [name/ID] show an alert/blink a light
|
|
on [name/ID] turn a light on
|
|
off [name/ID] turn a light off
|
|
refresh! refresh the setting of all lights
|
|
|
|
Groups
|
|
groups shows the list of all groups
|
|
(ID, name, IDs of member lights)
|
|
getgrp [name/ID] get the settings of the lights in a group
|
|
setgrp [name/ID], [update] set the settings of the lights in a group
|
|
|
|
Events
|
|
events shows the list of all events
|
|
event [name/ID] execute an event
|
|
|
|
Scenes
|
|
scenes shows the list of all scenes
|
|
scenes [name/ID] activate an scene
|
|
|
|
EOT
|
|
end
|
|
|
|
# Option parsing
|
|
@options = {:config_dir => "config"}
|
|
opt_parser = OptionParser.new do |opts|
|
|
opts.banner = "Usage: huec [options]"
|
|
opts.separator ""
|
|
|
|
opts.on("-c", "--config-dir [CONFDIR] ",
|
|
"set an alternative configuration directory") do |cd|
|
|
@options[:config_dir] = cd
|
|
end
|
|
|
|
opts.on("--hue-debug", "log hue bridge communication output") do
|
|
@options[:hue_debug] = true
|
|
end
|
|
|
|
opts.on_tail("-h", "--help", "show this help message") do
|
|
puts opts
|
|
exit
|
|
end
|
|
|
|
opts.on_tail("-v", "--version", "show version") do
|
|
puts "Hued version #{Hued::VERSION}"
|
|
exit
|
|
end
|
|
end
|
|
|
|
begin
|
|
opt_parser.parse!
|
|
rescue OptionParser::InvalidOption => e
|
|
warn e.message
|
|
abort opt_parser.to_s
|
|
end
|
|
|
|
puts "Starting huec #{Hued::VERSION}..."
|
|
bridge_cfg = YAML.load_file(File.join(@options[:config_dir], "bridge.yml"))
|
|
Huey.configure do |cfg|
|
|
cfg.hue_ip = bridge_cfg["ip"]
|
|
cfg.uuid = bridge_cfg["user"]
|
|
end
|
|
Huey.logger.level = @options[:hue_debug] ? Logger::DEBUG : Logger::FATAL
|
|
puts "Configured bridge connection"
|
|
|
|
puts "Discovering lights..."
|
|
lights
|
|
puts
|
|
|
|
puts "Discovering groups..."
|
|
groups
|
|
puts
|
|
|
|
puts "Loading events..."
|
|
events
|
|
puts
|
|
|
|
puts "Loading scenes..."
|
|
scenes
|
|
puts
|
|
|
|
puts "All done!"
|
|
puts "Use 'commands' to see a list of additional commands to pry's."
|
|
puts
|
|
@prompt_stamp = Time.now
|
|
Pry.config.prompt = proc { "#{prompt_status}> " }
|
|
binding.pry(quiet: true)
|