# setup_tool.py 28/05/2016 D.J.Whale
#
# A simple menu-driven setup tool for the Energenie Python library.
# Just be a simple menu system.
# This then means you don't have to have all this in the demo apps
# and the demo apps can just refer to object variables names
# from an assumed auto_create registry, that is built using this setup tool.
#TODO: Choose a better way to interrupt other than Ctrl-C
#It's very platform independent
#also, the foreground thread gets the KeyboardInterrupt,
#so as soon as threads are added, its a bad way to terminate user entry
#or processing.
import time
import energenie
from energenie.lifecycle import *
try:
readin = raw_input # Python 2
except NameError:
readin = input # Python 3
quit = False
def do_legacy_learn():
"""Repeatedly broadcast a legacy switch message, so you can learn a socket to the pattern"""
# get house code, default to energenie code
hc = readin("House code? (ENTER for default) ")
if hc == "":
house_code = None
else:
house_code = int(hc, 16)
#TODO: error check
# get switch index, default 1 (0,1,2,3,4)
si = readin("Switch index 1..4? (ENTER for all)")
if si == "":
switch_index = 0 #ALL
else:
switch_index = int(si)
#TODO: error check
device = energenie.Devices.ENER002((house_code, switch_index))
# in a loop until Ctrl-C
try:
while True: #TODO: detect Ctrl-C
print("ON")
device.turn_on()
time.sleep(0.5)
print("OFF")
device.turn_off()
time.sleep(0.5)
except KeyboardInterrupt:
pass # user exit
def do_mihome_discovery():
"""Discover any mihome device when it sends reports"""
print("Discovery mode, press Ctrl-C to stop")
energenie.Registry.discovery_ask(energenie.Registry.ask)
try:
while True:
time.sleep(1) # tick
except KeyboardInterrupt:
print("Discovery stopped")
def show_registry():
"""Show the registry as a numbered list"""
names = energenie.registry.names()
i=1
for name in names:
print("%d. %s %s" % (i, name, energenie.registry.get(name)))
i += 1
return names
def do_list_registry():
"""List the entries in the registry"""
show_registry()
def do_switch_device():
global quit
"""Turn the switch on a socket on and off, to test it"""
# select the device from a menu of numbered devices
names = show_registry()
# ask user for on/off/another/done
i = readin("Which device %s to %s" % (1,len(names)))
device_index = int(i)
#TODO: error check
#TODO: Ctrl-C check
print("selected: %s" % names[device_index-1])
#TODO could list action methods by introspecting device class??
def on():
print("will turn on")
def off():
print("will turn off")
MENU = [
("on", on),
("off", off)
]
try:
while not quit:
show_menu(MENU)
choice = get_choice((1,len(MENU)))
if choice != None:
handle_choice(MENU, choice)
except KeyboardInterrupt:
pass # user exit
quit = False
@untested
def do_show_device_status():
"""Show the readings associated with a device"""
pass #TODO
#TODO: need a way of asking a device for a summary of it's readings
#In a way that Device() could implement it for all devices??
#TODO, not sure might show all devices in a simple table
#note different field names make table display hard, unless there are shorthand names
# for each device in the registry
# show a summary line for that device
@untested
def do_watch_devices():
"""Repeatedly show readings for all devices"""
try:
while True:
print('-' * 80)
names = energenie.registry.names()
for name in names:
device = energenie.registry.get(name)
readings = device.get_readings_summary()
print("%s %s" % (name, readings))
print("")
time.sleep(1)
except KeyboardInterrupt:
pass # user exit
@unimplemented
def do_rename_device():
"""Rename a device in the registry to a different name"""
#This is useful when turning auto discovered names into your own names
#TODO: The registry does not support a rename mode at the moment
#will need to add this by getting the record, deleting it, and appending it again
pass #TODO
names = show_registry()
# get a choice 1..num+1
# ask for a new name
# registry.rename(old_name, new_name)
@unimplemented
def do_delete_device():
"""Delete a device from the registry so it is no longer recognised"""
pass #TODO
names = show_registry()
# get a choice 1..num+1
# registry.delete(name)
@unimplemented
def do_logging():
"""Enter a mode where all communications are logged to screen and a file"""
pass #TODO
# loop until Ctrl-C
# if a device update comes in
# display summary of its data on screen
# add summary of data to energenie.csv using Logging.log_message
@log_method
def do_quit():
"""Finished with the program, so exit"""
global quit
quit = True
def show_menu(menu):
"""Display a menu on the console"""
i = 1
for item in menu:
print("%d. %s" % (i, item[0]))
i += 1
def get_choice(choices):
"""Get and validate a numberic choice from the tuple choices(first, last)"""
first = choices[0]
last = choices[1]
try:
while True:
choice = readin("Choose %d to %d?" % (first, last))
try:
choice = int(choice)
if choice < first or choice > last:
print("Must enter a number between %d and %d" % (first, last))
else:
return choice
except ValueError:
print("Must enter a number")
except KeyboardInterrupt:
do_quit()
def handle_choice(menu, choice):
"""Route to the handler for the given menu choice"""
menu[choice-1][1]()
MAIN_MENU = [
("legacy learn mode", do_legacy_learn),
("mihome discovery mode", do_mihome_discovery),
("list registry", do_list_registry),
("switch device", do_switch_device),
("show device status", do_show_device_status),
("watch devices", do_watch_devices),
("rename device", do_rename_device),
("delete device", do_delete_device),
("logging", do_logging),
("quit", do_quit)
]
def setup_tool():
while not quit:
print("MAIN MENU")
show_menu(MAIN_MENU)
choice = get_choice((1,len(MAIN_MENU)))
if not quit:
handle_choice(MAIN_MENU, choice)
#----- MAIN ENTRY POINT -------------------------------------------------------
if __name__ == "__main__":
energenie.init()
try:
setup_tool()
finally:
energenie.finished()
# END