diff --git a/doc/devices_classes_branch.txt b/doc/devices_classes_branch.txt index a2fabb1..835d0d9 100644 --- a/doc/devices_classes_branch.txt +++ b/doc/devices_classes_branch.txt @@ -212,11 +212,26 @@ KVS implementation completed and all tests pass Registry tests all complete receive sequence counter tested +setup_tool implemented ready for testing to start -------------------------------------------------------------------------------- PLAN UP TO: MERGE BACK TO MASTER +---- DEMO APPS PHASE 1 + +write: setup_tool.py + +fix or deprecate, depending on what setup_tool does, +also depending on what we want to show as a standalone app + +fix: control_legacy.py +fix: control_mihome.py +fix: control_both.py +fix: monitor_mihome.py +fix: discover_mihome.py + + ---- TEST ON REAL HARDWARE Test registry and discovery on real hardware, and make sure it works as expected. @@ -226,7 +241,7 @@ * add back in the loop() call in the monitor_mihome.py program ----- DEMO APPS +---- DEMO APPS PHASE 2 setup_tool.py mihome_energy_monitor.py diff --git a/src/energenie/Devices.py b/src/energenie/Devices.py index 316483e..da66813 100644 --- a/src/energenie/Devices.py +++ b/src/energenie/Devices.py @@ -354,6 +354,7 @@ """An estimate of the next time we expect a message from this device""" pass + @unimplemented def get_readings_summary(self): """Try to get a terse summary of all present readings""" # if self.readings does not exist diff --git a/src/energenie/Registry.py b/src/energenie/Registry.py index fe71dd7..6bbeda4 100644 --- a/src/energenie/Registry.py +++ b/src/energenie/Registry.py @@ -77,7 +77,7 @@ DEFAULT_FILENAME = "registry.kvs" def __init__(self, filename=None): - print("***Opening DeviceRegistry") + ##print("***Opening DeviceRegistry") self.store = KVS(filename) def load_from(self, filename=None): @@ -124,6 +124,15 @@ fsk_router.add(address, c) return c + @untested + def rename(self, old_name, new_name): + """Rename a device in the registry""" + c = self.store[old_name] # get the class instance + self.delete(old_name) # remove from memory and from any disk version + self.add(c, new_name) # Add the same class back, but with the new name + #Note: If rx routes are defined, they will still be correct, + # because they wire directly to the device class instance + def delete(self, name): """Delete the named class instance""" del self.store[name] diff --git a/src/registry.kvs b/src/registry.kvs new file mode 100644 index 0000000..202c072 --- /dev/null +++ b/src/registry.kvs @@ -0,0 +1,12 @@ +IGN tv +type=MIHO005 +device_id=1675 + +ADD fan +type=ENER002 +device_id=[822412, 1] + +ADD fred +type=MIHO005 +device_id=1675 + diff --git a/src/setup_tool.py b/src/setup_tool.py index 9508aaf..288e75d 100644 --- a/src/setup_tool.py +++ b/src/setup_tool.py @@ -64,7 +64,8 @@ energenie.Registry.discovery_ask(energenie.Registry.ask) try: while True: - time.sleep(1) # tick + energenie.loop() # Allow receive processing + time.sleep(0.25) # tick fast enough to get messages in quite quickly except KeyboardInterrupt: print("Discovery stopped") @@ -87,6 +88,8 @@ def do_switch_device(): global quit """Turn the switch on a socket on and off, to test it""" + + #TODO DRY name = select_device() # select the device from a menu of numbered devices names = show_registry() @@ -96,14 +99,21 @@ #TODO: error check #TODO: Ctrl-C check - print("selected: %s" % names[device_index-1]) + name = names[device_index-1] + print("selected: %s" % name) - #TODO could list action methods by introspecting device class?? + device = energenie.registry.get(name) + #TODO: DRY END + + #TODO could list all action methods by introspecting device class + # and build a device specific menu def on(): - print("will turn on") + print("Turning on") + device.turn_on def off(): - print("will turn off") + print("Turning off") + device.turn_off MENU = [ ("on", on), @@ -124,14 +134,25 @@ @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 + #TODO DRY name = select_device() + names = show_registry() + + energenie.loop() # allow receive processing #TODO: not long enough for >1 msg?? + + # 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 + + name = names[device_index-1] + print("selected: %s" % name) + device = energenie.registry.get(name) + #TODO: DRY END + + readings = device.get_readings_summary() + print(readings) @untested @@ -139,6 +160,7 @@ """Repeatedly show readings for all devices""" try: while True: + energenie.loop() # allow receive processing print('-' * 80) names = energenie.registry.names() for name in names: @@ -151,41 +173,73 @@ except KeyboardInterrupt: pass # user exit -@unimplemented + +@untested 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 + + #TODO DRY name = select_device() names = show_registry() - # get a choice 1..num+1 - # ask for a new name - # registry.rename(old_name, new_name) + + # 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 + + name = names[device_index-1] + print("selected: %s" % name) + #TODO: DRY END + + new_name = readin("New name?") + + energenie.registry.rename(name, new_name) -@unimplemented +@untested def do_delete_device(): """Delete a device from the registry so it is no longer recognised""" - pass #TODO + + #TODO DRY name = select_device() names = show_registry() - # get a choice 1..num+1 - # registry.delete(name) + + # 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 + + name = names[device_index-1] + print("selected: %s" % name) + #TODO: DRY END + + energenie.registry.delete(name) - - -@unimplemented +@untested 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 + import Logger + + # provide a default incoming message handler for all fsk messages + def incoming(address, message): + print("\nIncoming from %s" % str(address)) + print(message) + Logger.logMessage(message) + energenie.fsk_router.when_incoming(incoming) + + try: + while True: + energenie.loop() + + except KeyboardInterrupt: + pass #user quit + + finally: + energenie.fsk_router.when_incoming(None) -@log_method def do_quit(): """Finished with the program, so exit""" global quit