This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
hued/bin/huec

289 lines
6.2 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 msg(str="")
puts(str) if @interactive
end
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|
msg status_line(blb)
end
true
end
def groups
Huey::Group.all.each do |grp|
msg "%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|
msg "%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|
msg "%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
msg 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)
msg 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
msg "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|
msg 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
msg <<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
@interactive = ARGV.empty?
msg "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
msg "Configured bridge connection"
msg "Discovering lights..."
lights
msg
msg "Discovering groups..."
groups
msg
msg "Loading events..."
events
msg
msg "Loading scenes..."
scenes
msg
msg "Loading sensors..."
sensors
msg
msg "All done!"
msg "Use 'commands' to see a list of additional commands to pry's."
msg
@prompt_stamp = Time.now
if @interactive
Pry.config.prompt = proc { "#{prompt_status}> " }
binding.pry(quiet: true)
else
eval ARGV.join(" ")
end