def __init__(self, configDir, osnInstance): AbstractAgent.__init__(self, configDir, osnInstance) log="Info" # should be read from config later configChanged = False if "zwave_device" not in self.configData: self.configData["zwave_device"] = "/dev/ttyACM0" configChanged = True if configChanged: self.serializeConfig() # handle zwave default device configurations self.zwaveDefaultConfigs = {} self.zwaveDefaultConfigFile = os.path.join(self.configDir, "zwavedefaultconfigs.config.json") self.readZwaveDefaultConfigs() self.device = self.configData["zwave_device"] self.logger.debug("Initiating ZWaveAgent with device %s." % self.device) self.zwaveOptions = "" try: self.zwaveOptions = ZWaveOption(self.device.encode('ascii'), \ config_path=expanduser("~")+"/ozw-install/python-open-zwave/openzwave/config", \ user_path=self.configDir, cmd_line="") self.zwaveOptions.set_log_file("../log/openzwave.log") # Todo: don't hardcode openzwave-path self.zwaveOptions.set_append_log_file(False) self.zwaveOptions.set_console_output(False) self.zwaveOptions.set_save_log_level(log) self.zwaveOptions.set_logging(False) self.zwaveOptions.lock() except BaseException as e: self.logger.info("Error setting up ZWave network. Correct device? Device properly connected? Device is: %s Exception message: %s" % (self.device, e)) self.inDiscoveryMode = False #scanning for available devices and sensors is slightly more complicated here...
def test_000_network_start_stop(self): self.driver_ready = False self.driver_removed = False self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Debug") self.options.set_logging(True) self.options.lock() dispatcher.connect(self.driver_ready_message, ZWaveNetwork.SIGNAL_DRIVER_READY) dispatcher.connect(self.driver_removed_message, ZWaveNetwork.SIGNAL_DRIVER_REMOVED) self.network = ZWaveNetwork(self.options) for i in range(0, SLEEP): if self.network.state>=self.network.STATE_AWAKED: break else: time.sleep(1.0) self.assertTrue(self.driver_ready) self.network.stop() for i in range(0, SLEEP): if self.network.state==self.network.STATE_STOPPED: break else: time.sleep(1.0) self.assertEqual(self.network.state, self.network.STATE_STOPPED) #self.assertTrue(self.driver_removed) self.network = None
def start(self, controllerDevice, config_path="./config", user_path=".", cmd_line=""): self.options = ZWaveOption(controllerDevice, config_path, user_path, cmd_line) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("None") self.options.set_logging(True) self.options.lock() dispatcher.connect(self.zwave_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) dispatcher.connect(self.zwave_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(self.zwave_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) dispatcher.connect(self.zwave_node_update, ZWaveNetwork.SIGNAL_NODE) dispatcher.connect(self.zwave_value_update, ZWaveNetwork.SIGNAL_VALUE) self.network = ZWaveNetwork(self.options, autostart=False) self.network.start()
def set_options(self): opts = self.raw_opts self.opts = ZWaveOption(device=opts.get("device"), config_path=opts.get("config_path"), user_path=opts.get("user_path"), cmd_line=opts.get("cmd_line")) for key, val in opts.items(): if key not in ["device", "config_path", "user_path", "cmd_line"]: getattr(self.opts, "set_" + key)(val) self.opts.lock() self.opts_locked = True
def __init__(self, device="/dev/ttyAMA0", config_path="/usr/local/etc/openzwave"): threading.Thread.__init__(self) self.__device = device self.__config_path = config_path self.__options = ZWaveOption(device, config_path=self.__config_path) self.__options.set_console_output(False) self.__options.lock() self.__network = None self.__network_ready = False self.__event_listen = None
def _start_network(self): #Define some manager options self.options = ZWaveOption(self.device, \ config_path="openzwave/config", \ user_path=".", cmd_line="") self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Internal") self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options, self.log) self.status_bar.update(status='Start Network')
def _start_network(self): #Define some manager options self.options = ZWaveOption(self.device, \ config_path=self.config_path, \ user_path=self.user_path, cmd_line="") self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level(self.loglevel_ow) self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options, self.log, kvals=False) self.status_bar.update(status='Start Network')
def __init__(self, stdscr): self._curAlert = False self._alertStack = list() self._driverInitialized = False self._options = None self._network = None self._listMode = True self._screen = stdscr self._version = '0.1 Beta 1' self._listtop = 0 self._listindex = 0 self._listcount = 0 self._selectedNode = None self._stop = threading.Event() self._keys = { 'A': 'Add', 'B': 'About', 'D': 'Delete', 'R': 'Refresh', 'S': 'Setup', '+': 'Increase', '-': 'Decrease', '1': 'On', '0': 'Off', 'Q': 'Quit' } #self._network = ZWaveWrapper.getInstance(device=self._config['device'], config=self._config['config'], log=None) self._options = ZWaveOption( \ device="/dev/zwave-aeon-s2", \ config_path="openzwave/config", \ user_path=".", \ cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_save_log_level('Debug') self._options.set_console_output(False) self._options.set_logging(True) self._options.lock() # TODO: add log level to config # TODO: add log enable/disable to config # TODO: logging - can ozw log be redirected to file? If so, we can add ability to view/tail log FORMAT = '%(asctime)s\t%(levelname)s\t%(name)s\t%(message)s' logging.basicConfig(filename='zwaveCommander.log', level=logging.DEBUG, format=FORMAT) self._log = logging.getLogger('ZWaveCommander') self._logbar = '\n%s\n' % ('-' * 60)
def setUpClass(self): super(TestApi, self).setUpClass() self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Debug") self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options) self.ctrl_command_result = None dispatcher.connect(self.ctrl_message, ZWaveController.SIGNAL_CONTROLLER) self.node_result = None dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)
def setUpClass(self): super(TestApi, self).setUpClass() self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(self.ozwout) self.options.set_save_log_level(self.ozwlog) self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options) self.node_result = None self.ctrl_command_result = None self.ctrl_command_signal = None #dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND) time.sleep(1.0)
def init_manager(): globals.options = ZWaveOption(globals.device, config_path=globals.config_folder, user_path=globals.data_folder, cmd_line="") globals.options.set_log_file("../../../log/openzwaved") globals.options.set_append_log_file(False) globals.options.set_console_output(False) if globals.log_level == 'notice': globals.options.set_save_log_level('Warning') else: globals.options.set_save_log_level(globals.log_level[0].upper() + globals.log_level[1:]) globals.options.set_logging(True) globals.options.set_associate(True) globals.options.set_save_configuration(True) globals.options.set_poll_interval(globals.default_poll_interval) globals.options.set_interval_between_polls(False) globals.options.set_notify_transactions(True) globals.options.set_suppress_value_refresh(False) globals.options.set_driver_max_attempts(5) globals.options.addOptionBool("AssumeAwake", globals.assumeAwake) globals.options.addOptionString("NetworkKey", "0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10", True) globals.options.set_security_strategy('SUPPORTED') globals.options.addOptionBool('EnforceSecureReception', False) globals.options.addOptionBool('RefreshAllUserCodes', False) globals.options.addOptionInt('ThreadTerminateTimeout', 5000) globals.options.addOptionBool('EnableSIS', True) globals.options.lock() globals.files_manager = FilesManager(globals.data_folder, globals.not_supported_nodes, logging) globals.files_manager.check_config_files()
def __init__(self): self.sensor_events = [] self.device = "/dev/ttyACM0" config_path = "plugins/python-openzwave/openzwave/config" user_path = "plugins/python-openzwave/config" # If using older Z-sticks, use the below device: # self.device = "/dev/ttyUSB0" # Change config paths where appropriate self.options = ZWaveOption(self.device, config_path=config_path, user_path=user_path, cmd_line="") # Turn off ozw console output self.options.set_console_output(False) self.options.set_save_log_level("Info") self.options.set_logging(False) self.options.lock() self.manager = libopenzwave.PyManager() self.manager.create() self.manager.addWatcher(self.event_callback) self.manager.addDriver(self.device) print("Starting Z-Wave Network...") self.network = ZWaveNetwork(self.options, log=None) # Wait for network to start while not self.network.state >= self.network.STATE_AWAKED: time.sleep(1) print("Z-Wave Network Started")
def connect(self) -> None: options = ZWaveOption( self.__zwave_config.port, config_path=self.__zwave_config.openzwave_config_path, user_path=".", cmd_line="") options.set_console_output(False) options.set_save_log_level("None") options.set_logging(False) options.lock() self.__network = ZWaveNetwork(options, autostart=False) dispatcher.connect(self.__network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) dispatcher.connect(self.__network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) dispatcher.connect(self.__value_update, ZWaveNetwork.SIGNAL_VALUE) self.__network.start()
def __init__(self, name, location, nodefilename="/opt/seciot/nodenames.json"): IOTDeviceController.__init__(self, name) # Restore node stuff nodefile = open(nodefilename, "r") nodejson = nodefile.read() self.node_dict = json.loads(nodejson) # Init options device = "/dev/ttyACM0" sniff = 300.0 options = ZWaveOption(device, config_path="/opt/openzwave/config", user_path=".", cmd_line="") options.set_logging(False) options.set_console_output(False) options.lock() # Create a network object self.network = ZWaveNetwork(options, autostart=False) self.network.set_poll_interval(10, True) # We connect to the louie dispatcher dispatcher.connect(self.louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(self.louie_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) self.network.start() # We wait for the network. print "***** Waiting for network to become ready : " for i in range(0, 300): if self.network.state >= self.network.STATE_READY: print "***** Network is ready" break else: sys.stdout.write(".") sys.stdout.flush() time.sleep(1.0) # We update the name of the controller self.network.controller.node.name = name self.network.controller.node.location = location
def __init__(self, *args, **kwargs): self._serialDevicePath = kwargs.get('serialDevicePath', None) self._options = ZWaveOption(self._serialDevicePath, \ config_path="/usr/local/etc/openzwave/", \ user_path=".", cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_console_output(False) #self._options.set_save_log_level(log) self._options.set_save_log_level('Info') self._options.set_logging(True) self._options.set_notify_transactions(True) self._options.lock() self._network = ZWaveNetwork(self._options, log=None,autostart=False) dispatcher.connect(self.louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) self._network.start() super(Open_zwave, self).__init__(self, *args, **kwargs)
def test_000_api_network(self): self.touchFile('ttyUSBO_fake') self.options = ZWaveOption(device='ttyUSBO_fake', user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Debug") self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options, autostart=False) self.rmFile('ttyUSBO_fake')
def initZwave(self): self.options = ZWaveOption(self.device, config_path=self.config_path, user_path=".", cmd_line="") self.options.set_log_file("MyZWave_log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) #self.options.set_console_output(True) self.options.set_save_log_level(self.log) self.options.set_logging(False) self.options.lock() self.network = ZWaveNetwork(self.options, log=None) time_started=0 print("*** Waiting for network to awake: ") for i in range(0,300): if self.network.state >= self.network.STATE_AWAKED: print(" done") break else: sys.stdout.write(".") sys.stdout.flush() time_started += 1 time.sleep(1.0) if self.network.state < self.network.STATE_AWAKED: print(".") print("Network is not awaked") for i in range(0,300): if self.network.state >= self.network.STATE_READY: print(" done in{} seconds".format(time_started)) break else: sys.stdout.write(".") sys.stdout.flush() time_started += 1 time.sleep(1.0) if not self.network.is_ready: print(".") print("Network is not ready")
def startup_zwave(self, args={}): ffEvent(self._id,{'zwave':'starting_up'}) zwaveSetup = ZWaveOption(self._port, self._configFile) zwaveSetup.set_console_output(False) zwaveSetup.lock() network = ZWaveNetwork(zwaveSetup, autostart=False) network.start() stdout.write("Waking up Zwave (This can take up to 5 minutes)") for i in xrange(3): if network.state >= network.STATE_AWAKED: logging.info('Zwave Network Awake') break else: stdout.write(".") stdout.flush() sleep(1) for x in xrange(3): if network.state >= network.STATE_READY: ffEvent(self._id,{'zwave':'network_ready'}) else: stdout.write(".") stdout.flush() sleep(.5) return network
def _start_network(self): #Define some manager options self.options = ZWaveOption(self.device, \ config_path=self.config_path, \ user_path=self.user_path, cmd_line="") self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level(self.loglevel_ow) self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options, self.log, kvals = False) self.status_bar.update(status='Start Network')
def __init__(self, *args, **kwargs): self._serialDevicePath = kwargs.get('serialDevicePath', None) self._options = ZWaveOption(self._serialDevicePath, \ config_path="/usr/share/python-openzwave/config", \ user_path=".", cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_console_output(True) #self._options.set_save_log_level(log) self._options.set_save_log_level('Info') self._options.set_logging(False) self._options.lock() self._network = ZWaveNetwork(self._options, log=None) super(Open_zwave, self).__init__(self, *args, **kwargs)
def setUpClass(self): super(TestApi, self).setUpClass() self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(self.ozwout) self.options.set_save_log_level(self.ozwlog) self.options.set_logging(True) self.options.lock() self.node_result = None dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE) self.network = ZWaveNetwork(self.options) self.ctrl_command_result = None self.ctrl_command_signal = None #dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND) time.sleep(1.0)
def __init__(self, stdscr): self._curAlert = False self._alertStack = list() self._driverInitialized = False self._options = None self._network = None self._listMode = True self._screen = stdscr self._version = '0.1 Beta 1' self._listtop = 0 self._listindex = 0 self._listcount = 0 self._selectedNode = None self._stop = threading.Event() self._keys = { 'A' : 'Add', 'B' : 'About', 'D' : 'Delete', 'R' : 'Refresh', 'S' : 'Setup', '+' : 'Increase', '-' : 'Decrease', '1' : 'On', '0' : 'Off', 'Q' : 'Quit' } #self._network = ZWaveWrapper.getInstance(device=self._config['device'], config=self._config['config'], log=None) self._options = ZWaveOption( \ device="/dev/zwave-aeon-s2", \ config_path="openzwave/config", \ user_path=".", \ cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_save_log_level('Debug') self._options.set_console_output(False) self._options.set_logging(True) self._options.lock() # TODO: add log level to config # TODO: add log enable/disable to config # TODO: logging - can ozw log be redirected to file? If so, we can add ability to view/tail log FORMAT='%(asctime)s\t%(levelname)s\t%(name)s\t%(message)s' logging.basicConfig(filename='zwaveCommander.log', level=logging.DEBUG, format=FORMAT) self._log = logging.getLogger('ZWaveCommander') self._logbar ='\n%s\n' % ('-'*60)
def __init__(self, device, isac_node): self.isac_node = isac_node self.signals = {} self._ozw_notif_queue = Queue() self._running = True green.spawn(self._notif_reader) self.options = ZWaveOption( device, config_path='/usr/share/openzwave/config', user_path='./user-dir', cmd_line='' ) self.options.set_log_file("./user-dir/OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level('Info') self.options.set_logging(False) self.options.lock() self.network = ZWaveNetwork(self.options, log=None) notif_to_func = [ (ZWaveNetwork.SIGNAL_NETWORK_STARTED, self.notif_network_started), (ZWaveNetwork.SIGNAL_NETWORK_RESETTED, self.notif_network_resetted), (ZWaveNetwork.SIGNAL_NETWORK_READY, self.notif_network_ready), (ZWaveNetwork.SIGNAL_NODE_ADDED, self.notif_node_added), (ZWaveNetwork.SIGNAL_NODE_NAMING, self.notif_node_named), (ZWaveNetwork.SIGNAL_NODE_REMOVED, self.notif_node_removed), (ZWaveNetwork.SIGNAL_VALUE_ADDED, self.notif_value_added), (ZWaveNetwork.SIGNAL_VALUE_CHANGED, self.notif_value_update), (ZWaveNetwork.SIGNAL_VALUE_REMOVED, self.notif_value_removed), (ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND, self.notif_ctrl_message), (ZWaveNetwork.SIGNAL_CONTROLLER_WAITING, self.notif_ctrl_message), ] for notif, func in notif_to_func: dispatcher.connect(self._notif_wrapper(func), notif, weak=False) # dispatcher.connect(self._notif_wrapper_all, All) self.isac_node.add_rpc(self.network_heal) self.isac_node.add_rpc(self.controller_add_node, name='add_node') self.isac_node.add_rpc(self.controller_remove_node, name='remove_node') self.isac_node.add_rpc(self.controller_cancel_command, name='cancel_command')
def create_zwave_options( device, config_path="/usr/local/etc/openzwave", # TODO: Auto-discover user_path=".", cmd_line=""): try: options = ZWaveOption(device, config_path=config_path, user_path=user_path, cmd_line=cmd_line) options.set_console_output(False) options.set_logging(False) options.lock() return options except ZWaveOption: # TODO: Seems device can only be used by one process at the time. If so, # try to give a meaningful error message raise
def create_zwave_options( device, config_path = "/usr/local/etc/openzwave", # TODO: Auto-discover user_path = ".", cmd_line = ""): try: options = ZWaveOption( device, config_path=config_path, user_path=user_path, cmd_line=cmd_line) options.set_console_output(False) options.set_logging(False) options.lock() return options except ZWaveOption: # TODO: Seems device can only be used by one process at the time. If so, # try to give a meaningful error message raise
def start_network(self): if self.network and self.network.state >= self.network.STATE_AWAKED: self.logger.info('Z-Wave network already started') return from openzwave.network import ZWaveNetwork, dispatcher from openzwave.option import ZWaveOption network_ready.clear() logging.getLogger('openzwave').addHandler(self.logger) opts = ZWaveOption(self.device, config_path=self.config_path, user_path=self.user_path) opts.set_console_output(False) opts.lock() self.network = ZWaveNetwork(opts, log=None) dispatcher.connect(_zwcallback) ready = network_ready.wait(self.ready_timeout) if not ready: self.logger.warning( 'Driver not ready after {} seconds: continuing anyway'.format( self.ready_timeout))
class MainWindow(Screen): def __init__(self, device=None, footer=False, name=None): Screen.__init__(self) self.device = device self.footer_display = footer self._define_log() self._define_screen() self._connect_louie() self._start_network() def _define_log(self): hdlr = logging.FileHandler('/tmp/urwidcmd.log') formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') hdlr.setFormatter(formatter) self.log = logging.getLogger('openzwave') self.log.addHandler(hdlr) self.log.setLevel(logging.DEBUG) self.log.info("="*15 + " start " + "="*15) def _define_screen(self): self._palette = [("title", "yellow", "dark cyan"), ("keys", "dark blue", "light gray"), ("message", "light cyan", "dark green"), ("linenr", "light blue", "dark cyan"), ("input", "light gray", "black"), ("input2", "dark red", "light gray"), ("focus", "black", "light gray", "bold"), ("dialog", "black", "light gray", "bold"), ("file", "light green", "dark blue"), ("errortxt", "dark red", "dark blue"), ("selectedfile", "yellow", "dark blue"), ("selectedfocus", "yellow", "light gray", "bold"), ("dir", "light gray", "dark blue"), ("fileedit", "light green", "dark red"), ('edit', 'yellow', 'dark blue'), ('body','default', 'default'), ('foot','dark cyan', 'dark blue', 'bold'), ('shadow','white','black'), ('border','black','dark blue'), ('error','black','dark red'), ('FxKey','light cyan', 'dark blue', 'underline')] self.network = None self.controller = None self.root_box = RootBox(self, None, "body") self.stat_box = StatBox(self, self.root_box, "body") self.controller_box = ControllerBox(self, self.root_box, "body") self.scenes_box = ScenesBox(self, self.root_box, "body") self.scene_box = SceneBox(self, self.scenes_box, "body") self.nodes_box = NodesBox(self, self.root_box, "body") self.switches_box = SwitchesBox(self, self.nodes_box, "body") self.dimmers_box = DimmersBox(self, self.nodes_box, "body") self.sensors_box = SensorsBox(self, self.nodes_box, "body") self.node_box = NodeBox(self, self.nodes_box, "body") self.values_box = ValuesBox(self, self.node_box, "body") self.groups_box = GroupsBox(self, self.node_box, "body") self.status_bar = StatusBar(self) self.header_bar = HeaderBar(self) self.framefocus = 'footer' self._active_box = self.root_box self.frame = urwid.Frame(urwid.AttrWrap(self.active_box, 'body'), \ header=self.header_bar,\ footer=self.status_bar, \ focus_part=self.framefocus) self.active_box = self.root_box self.loop = urwid.MainLoop(self.frame, \ self._palette, \ unhandled_input=self._unhandled_input) @property def active_box(self): """ Gets the number of association groups reported by this node. :rtype: int """ return self._active_box @active_box.setter def active_box(self,value): """ Gets the number of association groups reported by this node. :rtype: int """ self._active_box = value self.frame.set_body(self._active_box) self.header_bar.update(self._active_box.walker.fullpath()) def exit(self): """ Quit the programm Clean network properly and exit """ self.network.write_config() self.network.stop() raise urwid.ExitMainLoop() def execute(self, command): """ Parse an execute a commande """ command = command.strip() if command.startswith('ls') : if ' ' in command : cmd,options = command.split(' ') else: options = "" options = options.strip() self.active_box.walker.ls(options) self.status_bar.set_command("") return True elif command.startswith('exit') : self.exit() elif command.startswith('cd') : if ' ' in command : cmd,path = command.split(' ',1) else: path = "/" path = path.strip() if self.active_box.walker.exist(path): self.active_box = self.active_box.walker.cd(path) self.active_box.walker.ls("") self.status_bar.set_command("") self.log.info(" self.active_box %s" % self.active_box.walker.path) return True elif path == "/" : self.active_box = self.root_box self.active_box.walker.ls("") self.status_bar.set_command("") self.log.info(" self.active_box %s" % self.active_box.walker.path) return True else: self.status_bar.update(status='Unknown directory "%s"' % path) return False elif command.startswith('send') : if ' ' in command : cmd,value = command.split(' ',1) else: self.status_bar.update(status='Usage : send <command>') return False value = value.strip() if len(value) == 0 : self.status_bar.update(status='Usage : send <command>') return False if self.active_box.walker.send(value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False elif command.startswith('create') : if ' ' in command : cmd,value = command.split(' ',1) else: self.status_bar.update(status='Usage : create <value>') return False value = value.strip() if len(value) == 0 : self.status_bar.update(status='Usage : create <value>') return False if self.active_box.walker.create(value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False elif command.startswith('delete') : if ' ' in command : cmd,value = command.split(' ',1) else: self.status_bar.update(status='Usage : delete <value>') return False value = value.strip() if len(value) == 0 : self.status_bar.update(status='Usage : delete <value>') return False if self.active_box.walker.delete(value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False elif command.startswith('activate') : if ' ' in command : cmd,value = command.split(' ',1) else: self.status_bar.update(status='Usage : activate <value>') return False value = value.strip() if len(value) == 0 : self.status_bar.update(status='Usage : activate <value>') return False if self.active_box.walker.activate(value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False elif command.startswith('set') : if ' ' in command : cmd,end = command.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : set <field> to <value>') return False end = end.strip() field,end = end.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : set <field> to <value>') return False end = end.strip() to,value = end.split(' ',1) if len(value) == 0 or to != "to" : self.status_bar.update(status='Usage : set <field> to <value>') return False value = value.strip() if self.active_box.walker.set(field, value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False else : self.status_bar.update(status='Usage : set <field> to <value>') return False elif command.startswith('poll') : if ' ' in command : cmd,end = command.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : poll <value> to <intensity>') return False end = end.strip() field,end = end.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : poll <value> to <intensity>') return False end = end.strip() to,value = end.split(' ',1) if len(value) == 0 or to != "to" : self.status_bar.update(status='Usage : poll <value> to <intensity>') return False value = value.strip() if self.active_box.walker.poll(field, value): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False else : self.status_bar.update(status='Usage : poll <value> to <intensity>') return False elif command.startswith('add') : if ' ' in command : cmd,end = command.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : add <value> to <list>') return False end = end.strip() field,end = end.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : add <value> to <list>') return False end = end.strip() to,value = end.split(' ',1) if len(value) == 0 or to != "to" : self.status_bar.update(status='Usage : add <value> to <list>') return False value = value.strip() if self.active_box.walker.add(value, field): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False else : self.status_bar.update(status='Usage : add <value> to <list>') return False elif command.startswith('remove') : if ' ' in command : cmd,end = command.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : remove <value> from <list>') return False end = end.strip() field,end = end.split(' ',1) if len(end) == 0 or ' ' not in end : self.status_bar.update(status='Usage : remove <value> from <list>') return False end = end.strip() to,value = end.split(' ',1) if len(value) == 0 or to != "from" : self.status_bar.update(status='Usage : remove <value> from <list>') return False value = value.strip() if self.active_box.walker.remove(value, field): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : return False else : self.status_bar.update(status='Usage : remove <value> from <list>') return False elif command.startswith('reset') : if ' ' in command : cmd,state = command.split(' ',1) state = state.strip() if len(state) == 0 : self.status_bar.update(status='Usage : reset soft|hard') return False if self.active_box.walker.reset(state): self.active_box.walker.ls("") self.status_bar.set_command("") return True else : self.status_bar.update(status='Unknowm state "%s"' % state) return False else: self.status_bar.update(status='Unknown command "%s"' % command) return False def _unhandled_input(self, key): if key == 'esc': self.exit() elif key == 'tab' or key == 'shift tab': if self.framefocus == 'footer': self.framefocus = 'body' else: self.framefocus = 'footer' self.frame.set_focus(self.framefocus) return True elif key == 'enter': self.log.info('handled: %s' % repr(key)) cmd = self.status_bar.get_command() self.execute(cmd) return True elif key == 'f5': self.refresh_nodes() return True else: self.log.info('unhandled: %s' % repr(key)) def _start_network(self): #Define some manager options self.options = ZWaveOption(self.device, \ config_path="openzwave/config", \ user_path=".", cmd_line="") self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Internal") self.options.set_logging(True) self.options.lock() self.network = ZWaveNetwork(self.options, self.log) self.status_bar.update(status='Start Network') def _connect_louie(self): dispatcher.connect(self._louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(self._louie_network_resetted, ZWaveNetwork.SIGNAL_NETWORK_RESETTED) dispatcher.connect(self._louie_network_awaked, ZWaveNetwork.SIGNAL_NETWORK_AWAKED) dispatcher.connect(self._louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) dispatcher.connect(self._louie_network_stopped, ZWaveNetwork.SIGNAL_NETWORK_STOPPED) def _louie_network_started(self, network): self.log.info('OpenZWave network is started : homeid %0.8x - %d nodes were found.' % \ (network.home_id, network.nodes_count)) self.network = network self.status_bar.update(status='OpenZWave network is started ... Waiting ...') self.loop.draw_screen() def _louie_network_resetted(self, network): self.log.info('OpenZWave network is resetted.') self.network = None #self._disconnect_louie_node_and_value() self.status_bar.update(status='OpenZWave network was resetted ... Waiting ...') self.loop.draw_screen() def _louie_network_stopped(self, network): self.log.info('OpenZWave network is stopped.') self.network = None self.status_bar.update(status='OpenZWave network was stopped ... please quit') self.loop.draw_screen() def _louie_network_awaked(self, network): self.log.info('OpenZWave network is awaked.') self.network = network self.status_bar.update(status='OpenZWave network is awaked ... Waiting ...') self.loop.draw_screen() def _louie_network_ready(self, network): self.log.info('ZWave network is ready : %d nodes were found.' % network.nodes_count) self.log.info('Controller name : %s' % network.controller.node.product_name) self.network = network self.status_bar.update(status='ZWave network is ready') self.loop.draw_screen() self._connect_louie_node_and_value() def _disconnect_louie_node_and_value(self): #pass dispatcher.disconnect(self._louie_group, ZWaveNetwork.SIGNAL_GROUP) dispatcher.disconnect(self._louie_node_update, ZWaveNetwork.SIGNAL_NODE) dispatcher.disconnect(self._louie_value_update, ZWaveNetwork.SIGNAL_VALUE) dispatcher.disconnect(self._louie_ctrl_message, ZWaveController.SIGNAL_CONTROLLER) def _connect_louie_node_and_value(self): #pass dispatcher.connect(self._louie_group, ZWaveNetwork.SIGNAL_GROUP) dispatcher.connect(self._louie_node_update, ZWaveNetwork.SIGNAL_NODE) dispatcher.connect(self._louie_value_update, ZWaveNetwork.SIGNAL_VALUE) dispatcher.connect(self._louie_ctrl_message, ZWaveController.SIGNAL_CONTROLLER) def _louie_node_update(self, network, node): self.loop.draw_screen() def _louie_value_update(self, network, node, value): self.loop.draw_screen() def _louie_group(self, network, node): self.loop.draw_screen() def _louie_ctrl_message(self, state, message, network, controller): #self.status_bar.update(status='Message from controller: %s : %s' % (state,message)) self.status_bar.update(status='Message from controller: %s' % (message)) self.loop.draw_screen()
class ZWaveAgent(AbstractAgent): """A Zwave Agent for directly collecting data from a ZWave network. Requires openzwave to be installed (see tools folder) and ZWave Stick to be plugged in""" def __init__(self, configDir, osnInstance): AbstractAgent.__init__(self, configDir, osnInstance) log="Info" # should be read from config later configChanged = False if "zwave_device" not in self.configData: self.configData["zwave_device"] = "/dev/ttyACM0" configChanged = True if configChanged: self.serializeConfig() # handle zwave default device configurations self.zwaveDefaultConfigs = {} self.zwaveDefaultConfigFile = os.path.join(self.configDir, "zwavedefaultconfigs.config.json") self.readZwaveDefaultConfigs() self.device = self.configData["zwave_device"] self.logger.debug("Initiating ZWaveAgent with device %s." % self.device) self.zwaveOptions = "" try: self.zwaveOptions = ZWaveOption(self.device.encode('ascii'), \ config_path=expanduser("~")+"/ozw-install/python-open-zwave/openzwave/config", \ user_path=self.configDir, cmd_line="") self.zwaveOptions.set_log_file("../log/openzwave.log") # Todo: don't hardcode openzwave-path self.zwaveOptions.set_append_log_file(False) self.zwaveOptions.set_console_output(False) self.zwaveOptions.set_save_log_level(log) self.zwaveOptions.set_logging(False) self.zwaveOptions.lock() except BaseException as e: self.logger.info("Error setting up ZWave network. Correct device? Device properly connected? Device is: %s Exception message: %s" % (self.device, e)) self.inDiscoveryMode = False #scanning for available devices and sensors is slightly more complicated here... def networkStarted(self, network): self.logger.info("Network %0.8x started" % network.home_id) def networkFailed(self, network): self.logger.warning("Sorry, Network couldn't be started...") if self.inDiscoveryMode: self.logger("Discovery failed - terminating.") self.stop() def networkReady(self, network): self.logger.info("Network %0.8x is ready - %d nodes were found." % (self.network.home_id, self.network.nodes_count)) self.logger.info("Network controller %s is connected to %s" % (self.network.controller.node.product_name, self.device)) self.logger.info("\nNodes List:") self.logger.info("===========") configChanged = False for node in network.nodes: self.logger.info("Node %s: %s (battery: %s)" % (node, network.nodes[node].product_name, network.nodes[node].get_battery_level())) self.logger.info("Available Command Classes: %s" % network.nodes[node].command_classes) modelString = network.nodes[node].manufacturer_name + " " + network.nodes[node].product_name if node != self.network.controller.node_id: # not for controller node # Should usually only be necessary once in a lifetime for a given network, but repeating it on every startup doesn't ha$ self.configureNode(network, node) for sensor in network.nodes[node].get_sensors(): if ((not self.sensorConfigured(sensor)) and (self.inDiscoveryMode)): # we are in discovery mode and sensor is not configured yet, add default self.addDefaultSensor(sensor, network.nodes[node].get_sensors()[sensor].label, network.nodes[node].get_sensors()[sensor].units, {"sensorModel":modelString}) configChanged = True self.logger.debug("Sensor %s has %s of %s (Unit: %s)" % (sensor, network.nodes[node].get_sensors()[sensor].label, \ network.nodes[node].get_sensor_value(sensor), network.nodes[node].get_sensors()[sensor].units)) if self.inDiscoveryMode: # as discovery is more complicated for Zwave, we have to do it this way. # in discovery Mode, the config including new default configurations is serialized, then the agent Is stopped. if configChanged: # serialize for having all new sensors in config self.serializeConfig() self.isRunning = False # this ensures that runner stops this agent after discovery is completed else: dispatcher.connect(self.nodeUpdate, ZWaveNetwork.SIGNAL_NODE) dispatcher.connect(self.valueUpdate, ZWaveNetwork.SIGNAL_VALUE) def nodeUpdate(self, network, node): # maybe do something valuable here later... self.logger.debug('Received node update from node : %s.' % node) pass def valueUpdate(self, network, node, value): # not sure whether this might produce redundancies in case of one value_id appearing for multiple nodes... # nonetheless, staying with this for the moment self.sendValue(value.value_id, value.data) def configureNode(self,network, node): # Model-specific configuration of node. This definitely needs a complete rewrite later... self.logger.info("Setting specific configuration for product %s (Product ID: %s)..." % (network.nodes[node].product_name, network.nodes[node].product_id)) productId = network.nodes[node].product_id defaultConfig = self.getDefaultDeviceConfiguration(productId) if defaultConfig: # could also be empty in case this product has no default config yet self.logger.debug("Got default config.") for param in network.nodes[node].values.values(): # traverse through available parameters self.logger.debug("Checking if default config exists for %s" % param.value_id) if defaultConfig.has_key("%s" % param.value_id): # is this parameter specified in default config? we take the long value id as key to avoid misinterpretations self.logger.debug("Default config found. Now checking if default config contains a value") if defaultConfig["%s" % param.value_id].has_key("value"): self.logger.debug("Found value. Setting parameter <%s> to %s as specified in default config" % (param.label, defaultConfig["%s" % param.value_id]["value"])) param.data = defaultConfig["%s" % param.value_id]["value"] else: self.logger.info("No default configuration found for device with product id %s - creating dumb template from what is reported..." % productId) newConfig = {} for param in network.nodes[node].values.values(): # traverse through available parameters newConfig["product name"] = network.nodes[node].manufacturer_name + " " + network.nodes[node].product_name newConfig[param.value_id] = {} note = param.label if param.units: note = note + " (" + param.units + ")" newConfig[param.value_id]["note"] = note newConfig[param.value_id]["parameter index"] = param.index newConfig[param.value_id]["value"] = param.data self.zwaveDefaultConfigs["products"][productId] = newConfig self.serializeZwaveDefaultConfigs() def getDefaultDeviceConfiguration(self, productId): self.logger.debug("getting zwave default configs for product id %s" % productId) if self.zwaveDefaultConfigs["products"].has_key(productId): return self.zwaveDefaultConfigs["products"][productId] else: return {} def readZwaveDefaultConfigs(self): self.logger.debug("reading zwave default device configs from %s" % self.zwaveDefaultConfigFile) configChanged = False if os.path.isfile(self.zwaveDefaultConfigFile): # If configFile does not exist yet, default configs will be created and serialized later with open(self.zwaveDefaultConfigFile) as configFileHandle: self.zwaveDefaultConfigs = json.load(configFileHandle) if "products" not in self.zwaveDefaultConfigs: self.zwaveDefaultConfigs["products"]={} configChanged = True if (configChanged): self.serializeZwaveDefaultConfigs() def serializeZwaveDefaultConfigs(self): with open(self.zwaveDefaultConfigFile, "w") as configFileHandle: self.logger.info("Serializing zwave default device configs to %s." % self.zwaveDefaultConfigFile) json.dump(self.zwaveDefaultConfigs, configFileHandle, sort_keys = False, indent = 4, ensure_ascii=False) # data_file.close def run(self): self.isRunning = True #Create a network object self.network = ZWaveNetwork(self.zwaveOptions, autostart=False) #and connect our above handlers to respective events dispatcher.connect(self.networkStarted, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(self.networkFailed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) dispatcher.connect(self.networkReady, ZWaveNetwork.SIGNAL_NETWORK_READY) self.network.start() def discoverSensors(self): self.inDiscoveryMode = True # In this case, stuff is slightly more complicated as we have to manage the zwave network, too. # We thus here use the thread's run()-method and terinate once the discovery is complete. self.run() def stop(self): self.network.stop() self.isRunning = False
async def async_setup_entry(hass, config_entry): """Set up Z-Wave from a config entry. Will automatically load components to support devices found on the network. """ from pydispatch import dispatcher # pylint: disable=import-error from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork from openzwave.group import ZWaveGroup # Merge config entry and yaml config config = config_entry.data if DATA_ZWAVE_CONFIG in hass.data: config = {**config, **hass.data[DATA_ZWAVE_CONFIG]} # Update hass.data with merged config so we can access it elsewhere hass.data[DATA_ZWAVE_CONFIG] = config # Load configuration use_debug = config.get(CONF_DEBUG, DEFAULT_DEBUG) autoheal = config.get(CONF_AUTOHEAL, DEFAULT_CONF_AUTOHEAL) device_config = EntityValues( config.get(CONF_DEVICE_CONFIG), config.get(CONF_DEVICE_CONFIG_DOMAIN), config.get(CONF_DEVICE_CONFIG_GLOB), ) usb_path = config[CONF_USB_STICK_PATH] _LOGGER.info("Z-Wave USB path is %s", usb_path) # Setup options options = ZWaveOption( usb_path, user_path=hass.config.config_dir, config_path=config.get(CONF_CONFIG_PATH), ) options.set_console_output(use_debug) if config.get(CONF_NETWORK_KEY): options.addOption("NetworkKey", config[CONF_NETWORK_KEY]) await hass.async_add_executor_job(options.lock) network = hass.data[DATA_NETWORK] = ZWaveNetwork(options, autostart=False) hass.data[DATA_DEVICES] = {} hass.data[DATA_ENTITY_VALUES] = [] registry = await async_get_registry(hass) wsapi.async_load_websocket_api(hass) if use_debug: # pragma: no cover def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in ( ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD, ): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Handle new added value to a node on the network.""" # Check if this value should be tracked by an existing entity for values in hass.data[DATA_ENTITY_VALUES]: values.check_value(value) for schema in DISCOVERY_SCHEMAS: if not check_node_schema(node, schema): continue if not check_value_schema( value, schema[const.DISC_VALUES][const.DISC_PRIMARY]): continue values = ZWaveDeviceEntityValues(hass, schema, value, config, device_config, registry) # We create a new list and update the reference here so that # the list can be safely iterated over in the main thread new_values = hass.data[DATA_ENTITY_VALUES] + [values] hass.data[DATA_ENTITY_VALUES] = new_values platform = EntityPlatform( hass=hass, logger=_LOGGER, domain=DOMAIN, platform_name=DOMAIN, platform=None, scan_interval=DEFAULT_SCAN_INTERVAL, entity_namespace=None, async_entities_added_callback=lambda: None, ) platform.config_entry = config_entry def node_added(node): """Handle a new node on the network.""" entity = ZWaveNodeEntity(node, network) async def _add_node_to_component(): if hass.data[DATA_DEVICES].get(entity.unique_id): return name = node_name(node) generated_id = generate_entity_id(DOMAIN + ".{}", name, []) node_config = device_config.get(generated_id) if node_config.get(CONF_IGNORED): _LOGGER.info("Ignoring node entity %s due to device settings", generated_id) return hass.data[DATA_DEVICES][entity.unique_id] = entity await platform.async_add_entities([entity]) if entity.unique_id: hass.async_add_job(_add_node_to_component()) return @callback def _on_ready(sec): _LOGGER.info("Z-Wave node %d ready after %d seconds", entity.node_id, sec) hass.async_add_job(_add_node_to_component) @callback def _on_timeout(sec): _LOGGER.warning( "Z-Wave node %d not ready after %d seconds, " "continuing anyway", entity.node_id, sec, ) hass.async_add_job(_add_node_to_component) hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout) def node_removed(node): node_id = node.node_id node_key = f"node-{node_id}" _LOGGER.info("Node Removed: %s", hass.data[DATA_DEVICES][node_key]) for key in list(hass.data[DATA_DEVICES]): if not key.startswith(f"{node_id}-"): continue entity = hass.data[DATA_DEVICES][key] _LOGGER.info("Removing Entity - value: %s - entity_id: %s", key, entity.entity_id) hass.add_job(entity.node_removed()) del hass.data[DATA_DEVICES][key] entity = hass.data[DATA_DEVICES][node_key] hass.add_job(entity.node_removed()) del hass.data[DATA_DEVICES][node_key] def network_ready(): """Handle the query of all awake nodes.""" _LOGGER.info("Z-Wave network is ready for use. All awake nodes " "have been queried. Sleeping nodes will be " "queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) def network_complete_some_dead(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried, but some nodes are marked dead") hass.bus.fire(const.EVENT_NETWORK_COMPLETE_SOME_DEAD) dispatcher.connect(value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect(node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False) dispatcher.connect(node_removed, ZWaveNetwork.SIGNAL_NODE_REMOVED, weak=False) dispatcher.connect(network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect(network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) dispatcher.connect( network_complete_some_dead, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD, weak=False, ) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Z-Wave add_node have been initialized") network.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Z-Wave add_node_secure have been initialized") network.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Z-Wave remove_node have been initialized") network.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running Z-Wave command") network.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("Z-Wave heal running") network.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Z-Wave soft_reset have been initialized") network.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Z-Wave test_network have been initialized") network.test() def stop_network(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping Z-Wave network") network.stop() if hass.state == CoreState.running: hass.bus.fire(const.EVENT_NETWORK_STOP) async def rename_node(service): """Rename a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info("Renamed Z-Wave node %d to %s", node_id, name) update_ids = service.data.get(const.ATTR_UPDATE_IDS) # We want to rename the device, the node entity, # and all the contained entities node_key = f"node-{node_id}" entity = hass.data[DATA_DEVICES][node_key] await entity.node_renamed(update_ids) for key in list(hass.data[DATA_DEVICES]): if not key.startswith(f"{node_id}-"): continue entity = hass.data[DATA_DEVICES][key] await entity.value_renamed(update_ids) async def rename_value(service): """Rename a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] name = service.data.get(const.ATTR_NAME) value.label = name _LOGGER.info("Renamed Z-Wave value (Node %d Value %d) to %s", node_id, value_id, name) update_ids = service.data.get(const.ATTR_UPDATE_IDS) value_key = f"{node_id}-{value_id}" entity = hass.data[DATA_DEVICES][value_key] await entity.value_renamed(update_ids) def set_poll_intensity(service): """Set the polling intensity of a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] intensity = service.data.get(const.ATTR_POLL_INTENSITY) if intensity == 0: if value.disable_poll(): _LOGGER.info("Polling disabled (Node %d Value %d)", node_id, value_id) return _LOGGER.info("Polling disabled failed (Node %d Value %d)", node_id, value_id) else: if value.enable_poll(intensity): _LOGGER.info( "Set polling intensity (Node %d Value %d) to %s", node_id, value_id, intensity, ) return _LOGGER.info("Set polling intensity failed (Node %d Value %d)", node_id, value_id) def remove_failed_node(service): """Remove failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to remove zwave node %d", node_id) network.controller.remove_failed_node(node_id) def replace_failed_node(service): """Replace failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to replace zwave node %d", node_id) network.controller.replace_failed_node(node_id) def set_config_parameter(service): """Set a config parameter to a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) selection = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE) for value in node.get_values( class_id=const.COMMAND_CLASS_CONFIGURATION).values(): if value.index != param: continue if value.type == const.TYPE_BOOL: value.data = int(selection == "True") _LOGGER.info( "Setting config parameter %s on Node %s " "with bool selection %s", param, node_id, str(selection), ) return if value.type == const.TYPE_LIST: value.data = str(selection) _LOGGER.info( "Setting config parameter %s on Node %s " "with list selection %s", param, node_id, str(selection), ) return if value.type == const.TYPE_BUTTON: network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info( "Setting config parameter %s on Node %s " "with button selection %s", param, node_id, selection, ) return value.data = int(selection) _LOGGER.info( "Setting config parameter %s on Node %s " "with selection %s", param, node_id, selection, ) return node.set_config_param(param, selection, size) _LOGGER.info( "Setting unknown config parameter %s on Node %s " "with selection %s", param, node_id, selection, ) def refresh_node_value(service): """Refresh the specified value from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] node.values[value_id].refresh() _LOGGER.info("Node %s value %s refreshed", node_id, value_id) def set_node_value(service): """Set the specified value on a node.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) value = service.data.get(const.ATTR_CONFIG_VALUE) node = network.nodes[node_id] node.values[value_id].data = value _LOGGER.info("Node %s value %s set to %s", node_id, value_id, value) def print_config_parameter(service): """Print a config parameter from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) _LOGGER.info( "Config parameter %s on Node %s: %s", param, node_id, get_config_value(node, param), ) def print_node(service): """Print all information about z-wave node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] nice_print_node(node) def set_wakeup(service): """Set wake-up interval of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] value = service.data.get(const.ATTR_CONFIG_VALUE) if node.can_wake_up(): for value_id in node.get_values( class_id=const.COMMAND_CLASS_WAKE_UP): node.values[value_id].data = value _LOGGER.info("Node %s wake-up set to %d", node_id, value) else: _LOGGER.info("Node %s is not wakeable", node_id) def change_association(service): """Change an association in the zwave network.""" association_type = service.data.get(const.ATTR_ASSOCIATION) node_id = service.data.get(const.ATTR_NODE_ID) target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) group = service.data.get(const.ATTR_GROUP) instance = service.data.get(const.ATTR_INSTANCE) node = ZWaveGroup(group, network, node_id) if association_type == "add": node.add_association(target_node_id, instance) _LOGGER.info( "Adding association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance, ) if association_type == "remove": node.remove_association(target_node_id, instance) _LOGGER.info( "Removing association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance, ) async def async_refresh_entity(service): """Refresh values that specific entity depends on.""" entity_id = service.data.get(ATTR_ENTITY_ID) async_dispatcher_send(hass, SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id)) def refresh_node(service): """Refresh all node info.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] node.refresh_info() def reset_node_meters(service): """Reset meter counters of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) instance = service.data.get(const.ATTR_INSTANCE) node = network.nodes[node_id] for value in node.get_values( class_id=const.COMMAND_CLASS_METER).values(): if value.index != const.INDEX_METER_RESET: continue if value.instance != instance: continue network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info("Resetting meters on node %s instance %s....", node_id, instance) return _LOGGER.info( "Node %s on instance %s does not have resettable " "meters.", node_id, instance, ) def heal_node(service): """Heal a node on the network.""" node_id = service.data.get(const.ATTR_NODE_ID) update_return_routes = service.data.get(const.ATTR_RETURN_ROUTES) node = network.nodes[node_id] _LOGGER.info("Z-Wave node heal running for node %s", node_id) node.heal(update_return_routes) def test_node(service): """Send test messages to a node on the network.""" node_id = service.data.get(const.ATTR_NODE_ID) messages = service.data.get(const.ATTR_MESSAGES) node = network.nodes[node_id] _LOGGER.info("Sending %s test-messages to node %s.", messages, node_id) node.test(messages) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting Z-Wave network...") network.start() hass.bus.fire(const.EVENT_NETWORK_START) async def _check_awaked(): """Wait for Z-wave awaked state (or timeout) and finalize start.""" _LOGGER.debug("network state: %d %s", network.state, network.state_str) start_time = dt_util.utcnow() while True: waited = int((dt_util.utcnow() - start_time).total_seconds()) if network.state >= network.STATE_AWAKED: # Need to be in STATE_AWAKED before talking to nodes. _LOGGER.info("Z-Wave ready after %d seconds", waited) break elif waited >= const.NETWORK_READY_WAIT_SECS: # Wait up to NETWORK_READY_WAIT_SECS seconds for the Z-Wave # network to be ready. _LOGGER.warning( "Z-Wave not ready after %d seconds, continuing anyway", waited) _LOGGER.info("final network state: %d %s", network.state, network.state_str) break else: await asyncio.sleep(1) hass.async_add_job(_finalize_start) hass.add_job(_check_awaked) def _finalize_start(): """Perform final initializations after Z-Wave network is awaked.""" polling_interval = convert(config.get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: network.set_poll_interval(polling_interval, False) poll_interval = network.get_poll_interval() _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_network) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RENAME_VALUE, rename_value, schema=RENAME_VALUE_SCHEMA) hass.services.register( DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, schema=SET_CONFIG_PARAMETER_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_SET_NODE_VALUE, set_node_value, schema=SET_NODE_VALUE_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_REFRESH_NODE_VALUE, refresh_node_value, schema=REFRESH_NODE_VALUE_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_PRINT_CONFIG_PARAMETER, print_config_parameter, schema=PRINT_CONFIG_PARAMETER_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_REMOVE_FAILED_NODE, remove_failed_node, schema=NODE_SERVICE_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_REPLACE_FAILED_NODE, replace_failed_node, schema=NODE_SERVICE_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_CHANGE_ASSOCIATION, change_association, schema=CHANGE_ASSOCIATION_SCHEMA, ) hass.services.register(DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, schema=SET_WAKEUP_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_NODE, print_node, schema=NODE_SERVICE_SCHEMA) hass.services.register( DOMAIN, const.SERVICE_REFRESH_ENTITY, async_refresh_entity, schema=REFRESH_ENTITY_SCHEMA, ) hass.services.register(DOMAIN, const.SERVICE_REFRESH_NODE, refresh_node, schema=NODE_SERVICE_SCHEMA) hass.services.register( DOMAIN, const.SERVICE_RESET_NODE_METERS, reset_node_meters, schema=RESET_NODE_METERS_SCHEMA, ) hass.services.register( DOMAIN, const.SERVICE_SET_POLL_INTENSITY, set_poll_intensity, schema=SET_POLL_INTENSITY_SCHEMA, ) hass.services.register(DOMAIN, const.SERVICE_HEAL_NODE, heal_node, schema=HEAL_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_TEST_NODE, test_node, schema=TEST_NODE_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("Z-Wave network autoheal is enabled") async_track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_zwave) hass.services.async_register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave) for entry_component in SUPPORTED_PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup( config_entry, entry_component)) return True
def setup(hass, config): """ Setup Z-wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork use_debug = str(config[DOMAIN].get(CONF_DEBUG)) == '1' # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH), user_path=hass.config.config_dir) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """ Log all the signals. """ print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """ Called when a value is added to a node on the network. """ for component, discovery_service, command_ids in DISCOVERY_COMPONENTS: if value.command_class in command_ids: # Ensure component is loaded bootstrap.setup_component(hass, component, config) # Fire discovery event hass.bus.fire(EVENT_PLATFORM_DISCOVERED, { ATTR_SERVICE: discovery_service, ATTR_DISCOVERED: { ATTR_NODE_ID: node.node_id, ATTR_VALUE_ID: value.value_id, } }) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) def stop_zwave(event): """ Stop Z-wave. """ NETWORK.stop() def start_zwave(event): """ Called when Home Assistant starts up. """ NETWORK.start() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
def __init__(self, **kwargs): """Attrs initialized here have names as in :dict:`_initials` Doctests ++++++++ >>> t.start() (True, 'OK') # >>> t.hard_reset(force=True) # (True, 'OK') # >>> print("*** Action needed for node to be _added_ ***") # doctest:+ELLIPSIS # *** ... # >>> t.add_node() # doctest:+ELLIPSIS # {...} """ if self._initialized: raise RuntimeErr("[Bug] backend already initialized!?") self._initialized = True # set defaults for attr in self._initials.keys(): setattr(self, attr, self._initials[attr]) # ...remainder. for k in kwargs.keys(): if not hasattr(self, k): raise AttributeError( "{}: no such attribute in definition of class {}.".format( k, self.__class__.__name__)) else: setattr(self, k, kwargs[k]) # we put all artifacts here user_path = os.path.expanduser(os.path.expandvars(self.ozw_user_path)) try: os.makedirs(self.ozw_user_path, exist_ok=True) except Exception as e: raise RuntimeError("Can't create user_path: {}".format(e)) self.logger = logging.getLogger(__name__) self.logger.setLevel(self.log_level) fh = logging.FileHandler("{}/{}.log".format(self.ozw_user_path, __name__), mode='w') fh.setLevel(self.log_level) fh.setFormatter( logging.Formatter(self.log_format_dbg if self.log_level <= logging. DEBUG else self.log_format)) self.logger.addHandler(fh) self.logger.debug('initializing OZW backend...') options = ZWaveOption(self.device, config_path=self.ozw_config_path, user_path=self.ozw_user_path) options.set_log_file('OZW.log') options.set_append_log_file(False) options.set_console_output(False) options.set_save_log_level( 'Debug' if self.log_level <= logging.DEBUG else 'Warning') options.set_logging(True) options.lock() self.network = ZWaveNetwork(options, autostart=False) # A dispatcher associates a callback method to a signal. Signals # are generated by the library python-openzwave. Once a signal is # received, its associated callback is executed (see "_node_added" # example below in "_network_started" method) dispatcher.connect(self._network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(self._network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) # Yep! It's really 'RESETTED', wanna file a bug for bad english usage? ;-) dispatcher.connect(self._network_reset, ZWaveNetwork.SIGNAL_NETWORK_RESETTED) # dynamically set on add/remove events. See notification handlers below. self.node_added = None self.node_removed = None self.timestamps = { } # times of the last values' update for each sensor # The different stages that a node object gets through before being # ready. [BUG] Why do we need to explicitly list them? Anyway to get # them from the lib? self.queryStages = { "None": 1, # Query process hasn't started for this node "ProtocolInfo": 2, # Retrieve protocol information "Probe": 3, # Ping node to see if alive "WakeUp": 4, # Start wake up process if a sleeping node "ManufacturerSpecific1": 5, # Retrieve manufacturer name and product ids if ProtocolInfo lets us "NodeInfo": 6, # Retrieve info about supported, controlled command classes "NodePlusInfo": 7, # Retrieve Z-Wave+ info and update device classes (Added by Edin et Daniel) "SecurityReport": 8, # Retrieve a list of Command Classes that require Security "ManufacturerSpecific2": 9, # Retrieve manufacturer name and product ids "Versions": 10, # Retrieve version information "Instances": 11, # Retrieve information about multiple command class instances "Static": 12, # Retrieve static information (doesn't change) "Probe1": 13, # Ping a node upon starting with configuration "Associations": 14, # Retrieve information about associations "Neighbors": 15, # Retrieve node neighbor list "Session": 16, # Retrieve session information (changes infrequently) "Dynamic": 17, # Retrieve dynamic information (changes frequently) "Configuration": 18, # Retrieve configurable parameter information (only done on request) "Complete": 19 # Query process is completed for this node }
def setup(hass, config): """ Setup Z-wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork # Load configuration use_debug = str(config[DOMAIN].get(CONF_DEBUG)) == '1' customize = config[DOMAIN].get(CONF_CUSTOMIZE, {}) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get('config_path', DEFAULT_ZWAVE_CONFIG_PATH), ) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """ Log all the signals. """ print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """ Called when a value is added to a node on the network. """ for (component, discovery_service, command_ids, value_type, value_genre) in DISCOVERY_COMPONENTS: if value.command_class not in command_ids: continue if value_type is not None and value_type != value.type: continue if value_genre is not None and value_genre != value.genre: continue # Ensure component is loaded bootstrap.setup_component(hass, component, config) # Configure node name = "{}.{}".format(component, _object_id(value)) node_config = customize.get(name, {}) polling_intensity = convert( node_config.get(CONF_POLLING_INTENSITY), int) if polling_intensity is not None: value.enable_poll(polling_intensity) # Fire discovery event hass.bus.fire( EVENT_PLATFORM_DISCOVERED, { ATTR_SERVICE: discovery_service, ATTR_DISCOVERED: { ATTR_NODE_ID: node.node_id, ATTR_VALUE_ID: value.value_id, } }) def scene_activated(node, scene_id): """ Called when a scene is activated on any node in the network. """ name = _node_name(node) object_id = "{}_{}".format(slugify(name), node.node_id) hass.bus.fire(EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: object_id, ATTR_SCENE_ID: scene_id }) dispatcher.connect(value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect(scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) def add_node(event): """ Switch into inclusion mode """ NETWORK.controller.begin_command_add_device() def remove_node(event): """ Switch into exclusion mode""" NETWORK.controller.begin_command_remove_device() def stop_zwave(event): """ Stop Z-wave. """ NETWORK.stop() def start_zwave(event): """ Called when Home Assistant starts up. """ NETWORK.start() polling_interval = convert(config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: NETWORK.set_poll_interval(polling_interval, False) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) # register add / remove node services for zwave sticks without # hardware inclusion button hass.services.register(DOMAIN, SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, SERVICE_REMOVE_NODE, remove_node) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
class MyZwave: device="/dev/ttyACM0" config_path="/home/pi/Documents/Development/Python/python-openzwave-0.3.2/openzwave/config" log="Debug" network = None options = None def __init__(self): self.device="/dev/ttyACM0" self.config_path="/home/pi/Documents/Development/Python/python-openzwave-0.3.2/openzwave/config" self.log="Debug" self.network = None self.options = None def initZwave(self): self.options = ZWaveOption(self.device, config_path=self.config_path, user_path=".", cmd_line="") self.options.set_log_file("MyZWave_log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) #self.options.set_console_output(True) self.options.set_save_log_level(self.log) self.options.set_logging(False) self.options.lock() self.network = ZWaveNetwork(self.options, log=None) time_started=0 print("*** Waiting for network to awake: ") for i in range(0,300): if self.network.state >= self.network.STATE_AWAKED: print(" done") break else: sys.stdout.write(".") sys.stdout.flush() time_started += 1 time.sleep(1.0) if self.network.state < self.network.STATE_AWAKED: print(".") print("Network is not awaked") for i in range(0,300): if self.network.state >= self.network.STATE_READY: print(" done in{} seconds".format(time_started)) break else: sys.stdout.write(".") sys.stdout.flush() time_started += 1 time.sleep(1.0) if not self.network.is_ready: print(".") print("Network is not ready") def toggleSwitch(self,nodeNum): node=self.network.nodes[nodeNum] print("Node: {}".format(node)) val=node.get_switches().keys()[0] print("Values: {}".format(val)) state = node.get_switch_state(val) print("State: {}".format(state)) node.set_switch(val,not state) time.sleep(0.2) state = node.get_switch_state(val) return "on" if state else "off" def getSwitchStatus(self, nodeNum): node = self.network.nodes[nodeNum] val = node.get_switches().keys()[0] state = node.get_switch_state(val) return "on" if state else "off" def getInt(self, strNo): if strNo == None: return 0 else: try: temp = int(strNo) except ValueError: temp = 0 return temp
def __init__(self, object_group, config): Plugin.__init__(self, config=config, object_group=object_group, plugin_name=PLUGIN_NAME) # Get parameters from the config file if not self.is_enabled(): return # Initialize zwave library # Options try: opts = ZWaveOption(device="/dev/ttyUSB0", config_path="/home/mlamonta/git/python-openzwave/openzwave/config/", user_path="logs") opts.set_log_file("./logs/zwave.log") opts.set_save_log_level("Alert") opts.set_append_log_file(False) opts.set_console_output(False) opts.set_logging(True) opts.lock() except ZWaveException as e: self.logger.error(str(e)) return # Network self.net = ZWaveNetwork(opts) self.logger.info("------------------------------------------------------------") self.logger.info("Waiting for network awake : ") self.logger.info("------------------------------------------------------------") for i in range(0, 300): if self.net.state >= self.net.STATE_AWAKED: self.logger.info("done") break else: time.sleep(1.0) if self.net.state < self.net.STATE_AWAKED: self.logger.warning("Network is not awake") return self.logger.info("------------------------------------------------------------") for node in self.net.nodes: self.logger.info("%s - %s / %s" % (self.net.nodes[node].node_id, self.net.nodes[node].manufacturer_name, self.net.nodes[node].product_name) ) self._initialized = True
def setup(hass, config): """Setup Z-Wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK descriptions = conf_util.load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) try: import libopenzwave except ImportError: _LOGGER.error("You are missing required dependency Python Open " "Z-Wave. Please follow instructions at: " "https://home-assistant.io/components/zwave/") return False from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork default_zwave_config_path = os.path.join(os.path.dirname( libopenzwave.__file__), 'config') # Load configuration use_debug = config[DOMAIN].get(CONF_DEBUG) customize = config[DOMAIN].get(CONF_CUSTOMIZE) autoheal = config[DOMAIN].get(CONF_AUTOHEAL) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get( CONF_CONFIG_PATH, default_zwave_config_path)) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Called when a value is added to a node on the network.""" for (component, generic_device_class, specific_device_class, command_class, value_type, value_genre) in DISCOVERY_COMPONENTS: _LOGGER.debug("Component=%s Node_id=%s query start", component, node.node_id) if node.generic not in generic_device_class and \ None not in generic_device_class: _LOGGER.debug("node.generic %s not None and in " "generic_device_class %s", node.generic, generic_device_class) continue if node.specific not in specific_device_class and \ None not in specific_device_class: _LOGGER.debug("node.specific %s is not None and in " "specific_device_class %s", node.specific, specific_device_class) continue if value.command_class not in command_class and \ None not in command_class: _LOGGER.debug("value.command_class %s is not None " "and in command_class %s", value.command_class, command_class) continue if value_type != value.type and value_type is not None: _LOGGER.debug("value.type %s != value_type %s", value.type, value_type) continue if value_genre != value.genre and value_genre is not None: _LOGGER.debug("value.genre %s != value_genre %s", value.genre, value_genre) continue # Configure node _LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, " "Specific_command_class=%s, " "Command_class=%s, Value type=%s, " "Genre=%s", node.node_id, node.generic, node.specific, value.command_class, value.type, value.genre) name = "{}.{}".format(component, _object_id(value)) node_config = customize.get(name, {}) polling_intensity = convert( node_config.get(CONF_POLLING_INTENSITY), int) if polling_intensity: value.enable_poll(polling_intensity) else: value.disable_poll() discovery.load_platform(hass, component, DOMAIN, { const.ATTR_NODE_ID: node.node_id, const.ATTR_VALUE_ID: value.value_id, }, config) def scene_activated(node, scene_id): """Called when a scene is activated on any node in the network.""" hass.bus.fire(const.EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: _node_object_id(node), const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_SCENE_ID: scene_id }) def node_event_activated(node, value): """Called when a nodeevent is activated on any node in the network.""" hass.bus.fire(const.EVENT_NODE_EVENT, { const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_BASIC_LEVEL: value }) def network_ready(): """Called when all awake nodes have been queried.""" _LOGGER.info("Zwave network is ready for use. All awake nodes" " have been queried. Sleeping nodes will be" " queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Called when all nodes on network have been queried.""" _LOGGER.info("Zwave network is complete. All nodes on the network" " have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) dispatcher.connect( node_event_activated, ZWaveNetwork.SIGNAL_NODE_EVENT, weak=False) dispatcher.connect( network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect( network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Zwave add_node have been initialized.") NETWORK.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Zwave add_node_secure have been initialized.") NETWORK.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Zwave remove_node have been initialized.") NETWORK.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running ZWave command.") NETWORK.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("ZWave heal running.") NETWORK.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Zwave soft_reset have been initialized.") NETWORK.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Zwave test_network have been initialized.") NETWORK.test() def stop_zwave(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping ZWave network.") NETWORK.stop() hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): """Rename a node.""" state = hass.states.get(service.data.get(ATTR_ENTITY_ID)) node_id = state.attributes.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info( "Renamed ZWave node %d to %s", node_id, name) def set_config_parameter(service): """Set a config parameter to a node.""" state = hass.states.get(service.data.get(ATTR_ENTITY_ID)) node_id = state.attributes.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) value = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE, 2) node.set_config_param(param, value, size) _LOGGER.info("Setting config parameter %s on Node %s " "with value %s and size=%s", param, node_id, value, size) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting ZWave network.") NETWORK.start() hass.bus.fire(const.EVENT_NETWORK_START) # Need to be in STATE_AWAKED before talking to nodes. # Wait up to NETWORK_READY_WAIT_SECS seconds for the zwave network # to be ready. for i in range(const.NETWORK_READY_WAIT_SECS): _LOGGER.debug( "network state: %d %s", NETWORK.state, NETWORK.state_str) if NETWORK.state >= NETWORK.STATE_AWAKED: _LOGGER.info("zwave ready after %d seconds", i) break time.sleep(1) else: _LOGGER.warning( "zwave not ready after %d seconds, continuing anyway", const.NETWORK_READY_WAIT_SECS) _LOGGER.info( "final network state: %d %s", NETWORK.state, NETWORK.state_str) polling_interval = convert( config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: NETWORK.set_poll_interval(polling_interval, False) poll_interval = NETWORK.get_poll_interval() _LOGGER.info("zwave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node, descriptions[const.SERVICE_ADD_NODE]) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure, descriptions[const.SERVICE_ADD_NODE_SECURE]) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node, descriptions[const.SERVICE_REMOVE_NODE]) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command, descriptions[const.SERVICE_CANCEL_COMMAND]) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network, descriptions[const.SERVICE_HEAL_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset, descriptions[const.SERVICE_SOFT_RESET]) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network, descriptions[const.SERVICE_TEST_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_zwave, descriptions[const.SERVICE_STOP_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave, descriptions[const.SERVICE_START_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, descriptions[const.SERVICE_RENAME_NODE], schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, descriptions[ const.SERVICE_SET_CONFIG_PARAMETER], schema=SET_CONFIG_PARAMETER_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("ZWave network autoheal is enabled.") track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
class Open_zwave(HAInterface): VERSION = '0.0.1' awake = False ready = False nodesdisplayed = False def __init__(self, *args, **kwargs): self._serialDevicePath = kwargs.get('serialDevicePath', None) self._options = ZWaveOption(self._serialDevicePath, \ config_path="/usr/share/python-openzwave/config", \ user_path=".", cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_console_output(True) #self._options.set_save_log_level(log) self._options.set_save_log_level('Info') self._options.set_logging(False) self._options.lock() self._network = ZWaveNetwork(self._options, log=None) super(Open_zwave, self).__init__(self, *args, **kwargs) def _printNetwork(self, node): print print "------------------------------------------------------" print "%s - Name : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].name) print "%s - Manufacturer name / id : %s / %s" % ( self._network.nodes[node].node_id, self._network.nodes[node].manufacturer_name, self._network.nodes[node].manufacturer_id) print "%s - Product name / id / type : %s / %s / %s" % ( self._network.nodes[node].node_id, self._network.nodes[node].product_name, self._network.nodes[node].product_id, self._network.nodes[node].product_type) print "%s - Version : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].version) print "%s - Command classes : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].command_classes_as_string) print "%s - Capabilities : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].capabilities) print "%s - Neighbors : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].neighbors) print "%s - Can sleep : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].can_wake_up()) def _init(self, *args, **kwargs): super(Open_zwave, self)._init(self, *args, **kwargs) def _readInterface(self, lastPacketHash): if (self._network.state >= self._network.STATE_AWAKED and not self.awake): self.awake = True self._logger.info("Network Awaked") if (self._network.state >= self._network.STATE_READY and not self.ready): self.ready = True self._logger.info("Network Ready") if not self.awake: time.sleep(1.0) self._logger.debug("Not awaked") return if self.awake and not self.ready: time.sleep(1.0) self._logger.debug("Not ready") return if not self.nodesdisplayed and self.ready: for node in self._network.nodes: self._printNetwork(node) self.nodesdisplayed = True def version(self): self._logger.info("Open_zwave Pytomation Driver version " + self.VERSION) self._logger.info("Use openzwave library : %s" % self._network.controller.ozw_library_version) self._logger.info("Use python library : %s" % self._network.controller.python_library_version) self._logger.info("Use ZWave library : %s" % self._network.controller.library_description)
def start_zwnetwork(app): options = ZWaveOption(device=app.config['ZWAVE_DEVICE'], config_path=app.config['ZWAVE_DIR'], user_path=app.config['USER_DIR']) options.set_log_file("OZW_Log.log") options.set_append_log_file(False) options.set_console_output(False) options.set_save_log_level(app.config['ZWAVE_DEBUG']) options.set_logging(app.config['ZWAVE_LOGGING']) options.lock() zwnetwork = ZWaveNetwork(options) return zwnetwork
class TestApi(TestPyZWave): """ Parent test class for api """ @classmethod def setUpClass(self): super(TestApi, self).setUpClass() self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(False) self.options.set_save_log_level("Debug") self.options.set_logging(True) self.options.lock() self.ctrl_command_result = None dispatcher.connect(self.ctrl_message, ZWaveController.SIGNAL_CONTROLLER) self.node_result = None dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE) self.network = ZWaveNetwork(self.options) time.sleep(1.0) @classmethod def tearDownClass(self): self.network.stop() time.sleep(2.0) super(TestApi, self).tearDownClass() self.network=None def setUp(self): self.wait_for_network_state(self.network.STATE_AWAKED, 1) def wait_for_queue(self): for i in range(0,60): if self.network.controller.send_queue_count <= 0: break else: time.sleep(0.5) def wait_for_network_state(self, state, multiply=1): for i in range(0,SLEEP*multiply): if self.network.state>=state: break else: #sys.stdout.write(".") #sys.stdout.flush() time.sleep(1.0) def ctrl_message(self, state, message, network, controller): self.ctrl_command_result = state def node_update(self, network, node): self.node_result = node
def setup(hass, config): """ Setup Z-wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork # Load configuration use_debug = str(config[DOMAIN].get(CONF_DEBUG)) == '1' customize = config[DOMAIN].get(CONF_CUSTOMIZE, {}) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get('config_path', DEFAULT_ZWAVE_CONFIG_PATH),) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """ Log all the signals. """ print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """ Called when a value is added to a node on the network. """ for (component, discovery_service, command_ids, value_type, value_genre) in DISCOVERY_COMPONENTS: if value.command_class not in command_ids: continue if value_type is not None and value_type != value.type: continue if value_genre is not None and value_genre != value.genre: continue # Ensure component is loaded bootstrap.setup_component(hass, component, config) # Configure node name = "{}.{}".format(component, _object_id(value)) node_config = customize.get(name, {}) polling_intensity = convert( node_config.get(CONF_POLLING_INTENSITY), int) if polling_intensity is not None: value.enable_poll(polling_intensity) # Fire discovery event hass.bus.fire(EVENT_PLATFORM_DISCOVERED, { ATTR_SERVICE: discovery_service, ATTR_DISCOVERED: { ATTR_NODE_ID: node.node_id, ATTR_VALUE_ID: value.value_id, } }) def scene_activated(node, scene_id): """ Called when a scene is activated on any node in the network. """ name = _node_name(node) object_id = "{}_{}".format(slugify(name), node.node_id) hass.bus.fire(EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: object_id, ATTR_SCENE_ID: scene_id }) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) def add_node(event): """ Switch into inclusion mode """ NETWORK.controller.begin_command_add_device() def remove_node(event): """ Switch into exclusion mode""" NETWORK.controller.begin_command_remove_device() def stop_zwave(event): """ Stop Z-wave. """ NETWORK.stop() def start_zwave(event): """ Called when Home Assistant starts up. """ NETWORK.start() polling_interval = convert( config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: NETWORK.set_poll_interval(polling_interval, False) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) # register add / remove node services for zwave sticks without # hardware inclusion button hass.services.register(DOMAIN, SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, SERVICE_REMOVE_NODE, remove_node) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
def setup(hass, config): """Setup Z-Wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK try: import libopenzwave except ImportError: _LOGGER.error("You are missing required dependency Python Open " "Z-Wave. Please follow instructions at: " "https://home-assistant.io/components/zwave/") return False from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork default_zwave_config_path = os.path.join(os.path.dirname( libopenzwave.__file__), 'config') # Load configuration use_debug = str(config[DOMAIN].get(CONF_DEBUG)) == '1' customize = config[DOMAIN].get(CONF_CUSTOMIZE, {}) autoheal = config[DOMAIN].get(CONF_AUTOHEAL, DEFAULT_CONF_AUTOHEAL) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get('config_path', default_zwave_config_path),) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Called when a value is added to a node on the network.""" for (component, generic_device_class, specific_device_class, command_class, value_type, value_genre) in DISCOVERY_COMPONENTS: _LOGGER.debug("Component=%s Node_id=%s query start", component, node.node_id) if node.generic not in generic_device_class and \ None not in generic_device_class: _LOGGER.debug("node.generic %s not None and in \ generic_device_class %s", node.generic, generic_device_class) continue if node.specific not in specific_device_class and \ None not in specific_device_class: _LOGGER.debug("node.specific %s is not None and in \ specific_device_class %s", node.specific, specific_device_class) continue if value.command_class not in command_class and \ None not in command_class: _LOGGER.debug("value.command_class %s is not None \ and in command_class %s", value.command_class, command_class) continue if value_type != value.type and value_type is not None: _LOGGER.debug("value.type %s != value_type %s", value.type, value_type) continue if value_genre != value.genre and value_genre is not None: _LOGGER.debug("value.genre %s != value_genre %s", value.genre, value_genre) continue # Configure node _LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, \ Specific_command_class=%s, \ Command_class=%s, Value type=%s, \ Genre=%s", node.node_id, node.generic, node.specific, value.command_class, value.type, value.genre) name = "{}.{}".format(component, _object_id(value)) node_config = customize.get(name, {}) polling_intensity = convert( node_config.get(CONF_POLLING_INTENSITY), int) if polling_intensity: value.enable_poll(polling_intensity) else: value.disable_poll() discovery.load_platform(hass, component, DOMAIN, { ATTR_NODE_ID: node.node_id, ATTR_VALUE_ID: value.value_id, }, config) def scene_activated(node, scene_id): """Called when a scene is activated on any node in the network.""" name = _node_name(node) object_id = "{}_{}".format(slugify(name), node.node_id) hass.bus.fire(EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: object_id, ATTR_SCENE_ID: scene_id }) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) def add_node(service): """Switch into inclusion mode.""" NETWORK.controller.add_node() def remove_node(service): """Switch into exclusion mode.""" NETWORK.controller.remove_node() def heal_network(service): """Heal the network.""" _LOGGER.info("ZWave heal running.") NETWORK.heal() def soft_reset(service): """Soft reset the controller.""" NETWORK.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" NETWORK.test() def stop_zwave(event): """Stop Z-Wave.""" NETWORK.stop() def start_zwave(event): """Startup Z-Wave.""" NETWORK.start() # Need to be in STATE_AWAKED before talking to nodes. # Wait up to NETWORK_READY_WAIT_SECS seconds for the zwave network # to be ready. for i in range(NETWORK_READY_WAIT_SECS): _LOGGER.debug( "network state: %d %s", NETWORK.state, NETWORK.state_str) if NETWORK.state >= NETWORK.STATE_AWAKED: _LOGGER.info("zwave ready after %d seconds", i) break time.sleep(1) else: _LOGGER.warning( "zwave not ready after %d seconds, continuing anyway", NETWORK_READY_WAIT_SECS) _LOGGER.info( "final network state: %d %s", NETWORK.state, NETWORK.state_str) polling_interval = convert( config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: NETWORK.set_poll_interval(polling_interval, False) poll_interval = NETWORK.get_poll_interval() _LOGGER.info("zwave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) # Register add / remove node services for Z-Wave sticks without # hardware inclusion button hass.services.register(DOMAIN, SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, SERVICE_REMOVE_NODE, remove_node) hass.services.register(DOMAIN, SERVICE_HEAL_NETWORK, heal_network) hass.services.register(DOMAIN, SERVICE_SOFT_RESET, soft_reset) hass.services.register(DOMAIN, SERVICE_TEST_NETWORK, test_network) # Setup autoheal if autoheal: _LOGGER.info("ZWave network autoheal is enabled.") track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
def _init_openzwave(self, zwave_device, zwave_config_path, zwave_user_path): """Initialise the OpenZWave client, leaving it ready to start.""" # Configure OpenZWave options = ZWaveOption(zwave_device, config_path=zwave_config_path, user_path=zwave_user_path, cmd_line="") options.set_log_file(os.path.join(zwave_user_path, "zwave.log")) options.set_append_log_file(True) options.set_console_output(True) options.set_save_log_level("Warning") options.set_logging(True) options.lock() self._ozw_network = ZWaveNetwork(options, autostart=False)
class ZWaveCommander: def __init__(self, stdscr): self._curAlert = False self._alertStack = list() self._driverInitialized = False self._options = None self._network = None self._listMode = True self._screen = stdscr self._version = '0.1 Beta 1' self._listtop = 0 self._listindex = 0 self._listcount = 0 self._selectedNode = None self._stop = threading.Event() self._keys = { 'A' : 'Add', 'B' : 'About', 'D' : 'Delete', 'R' : 'Refresh', 'S' : 'Setup', '+' : 'Increase', '-' : 'Decrease', '1' : 'On', '0' : 'Off', 'Q' : 'Quit' } #self._network = ZWaveWrapper.getInstance(device=self._config['device'], config=self._config['config'], log=None) self._options = ZWaveOption( \ device="/dev/zwave-aeon-s2", \ config_path="openzwave/config", \ user_path=".", \ cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_save_log_level('Debug') self._options.set_console_output(False) self._options.set_logging(True) self._options.lock() # TODO: add log level to config # TODO: add log enable/disable to config # TODO: logging - can ozw log be redirected to file? If so, we can add ability to view/tail log FORMAT='%(asctime)s\t%(levelname)s\t%(name)s\t%(message)s' logging.basicConfig(filename='zwaveCommander.log', level=logging.DEBUG, format=FORMAT) self._log = logging.getLogger('ZWaveCommander') self._logbar ='\n%s\n' % ('-'*60) def main(self): '''Main run loop''' self._log.info('%sZWaveCommander Version %s Starting%s', self._logbar, self._version, self._logbar) self._initCurses(self._screen) try: self._startNetwork() self._runLoop() finally: self._shutdown() def _delayloop(self, context, duration, callback): self._log.debug('thread %s sleeping...', context) time.sleep(duration) self._log.debug('timer %s expired, executing callback %s', context, callback) if context == 'alert': self._curAlert = False if self._alertStack: self._alert(self._alertStack.pop()) if callback is not None: callback() def _handleQuit(self): # TODO: exit confirmation dialog self._log.info('Stop requested') self._stop.set() def _handleRefresh(self): if self._selectedNode: self._network.refresh(self._selectedNode) def _handleOn(self): if self._selectedNode: self._network.setNodeOn(self._selectedNode) def _handleOff(self): if self._selectedNode: self._network.setNodeOff(self._selectedNode) def _handleIncrease(self): if self._selectedNode: curLevel = self._selectedNode.level newLevel = curLevel + 10 if newLevel > 99: newLevel = 99 self._network.setNodeLevel(self._selectedNode, newLevel) def _handleDecrease(self): if self._selectedNode: curLevel = self._selectedNode.level newLevel = curLevel - 10 if newLevel < 0: newLevel = 0 self._network.setNodeLevel(self._selectedNode, newLevel) def _setTimer(self, context, duration, callback): newTimer = threading.Thread(None, self._delayloop, 'cb-thread-%s' % context, (context, duration, callback), {}) newTimer.setDaemon(True) newTimer.start() def _alert(self, text): '''perform program alert''' if not self._curAlert: self._curAlert = True curses.flash() self._screen.addstr(self._screensize[0] - 1, 0, ' {0:{width}}'.format(text, width=self._screensize[1] - 2), curses.color_pair(self.COLOR_ERROR)) self._screen.refresh() self._setTimer('alert', 1, self._redrawMenu) else: self._alertStack.append(text) def _layoutScreen(self): # TODO: handle screen resize on curses.KEY_RESIZE in loop (tear down, re-calculate, and re-build) # top 5 lines (fixed): system info (including list header) # bottom line (fixed): menu/status # remaining top half: item list (scrolling) # remaining bottom half: split - left half=static info, right half=detail (scrolling) # item list: 8 columns. All column widths here are padded with 1 char space (except col 0, which is always 1 char) # c0=1 char fixed (select indicator) # c1=4 char fixed (id) # c2=10 char min (name) # c3=10 char min (location) # c4=20 char min (type) # c5=9 char fixed (state) # c6=7 char fixed (batt) # c7=7 char fixed (signal) # last three columns: 23 chars: are optional and can fall off if space requires it (min width 45) # "min" columns expand evenly to fit remaining space self._screen.clear() self._log.debug("Laying out screen") self._colwidths=[1,4,10,10,15,12,8,8] self._colheaders=['','ID','Name','Location','Type','State','Batt','Signal'] self._detailheaders=['Info','Values','Classes','Groups','Events'] self._flexcols=[2,3,4] self._rowheights=[5,5,10,1] self._flexrows=[1,2] self._deviceValueColumns=['id','commandClass','instance','index','type','label','value','units'] self._deviceValueWidths= [10,20,9,6,10,20,10,10] self._sortcolumn = self._colheaders[1] self._detailview = self._detailheaders[0] self._screensize = self._screen.getmaxyx() width = self._screensize[1] height = self._screensize[0] self._log.debug('Screen is %d wide by %d high', width, height) # Update dynamic column widths for device list self._log.debug('Initial column widths are: %s', self._colwidths) cwid = 0 for i in self._colwidths: cwid += i flexwidth = width - cwid if flexwidth > 0: adder = divmod(flexwidth, len(self._flexcols)) for i in self._flexcols: self._colwidths[i] += adder[0] self._colwidths[self._flexcols[-1]] += adder[1] self._log.debug('Adjusted column widths are: %s' ,self._colwidths) # Update dynamic row heights for screen sections self._log.debug('Initial row heights are: %s' , self._rowheights) cht = 0 for i in self._rowheights: cht += i flexheight = height - cht if flexheight > 0: adder = divmod(flexheight, len(self._flexrows)) for i in self._flexrows: self._rowheights[i] += adder[0] self._rowheights[self._flexrows[-1]] += adder[1] self._log.debug('Adjusted row heights are: %s' , self._rowheights) if curses.has_colors(): self._log.debug('Curses initialized: %d colors and %d color pairs available', curses.COLORS, curses.COLOR_PAIRS) else: self._log.debug('Curses initialized, but no colors are available') self._listpad = curses.newpad(256,256) self._detailpads = { 'Info': curses.newpad(self._rowheights[2], self._screensize[1]), 'Values': curses.newpad(128, self._screensize[1]), 'Classes': curses.newpad(128, self._screensize[1]), 'Groups': curses.newpad(self._rowheights[2], self._screensize[1]), 'Events': curses.newpad(256, self._screensize[1]) } self._detailpos = dict() for k in self._detailpads.iterkeys(): self._detailpos[k] = 0 self._detailtop = self._rowheights[0] + self._rowheights[1] + 2 self._detailbottom = self._detailtop + self._rowheights[2] - 3 self._updateColumnHeaders() def _initCurses(self, stdscr): '''Configure ncurses application-specific environment (ncurses has already been initialized)''' curses.curs_set(0) # Re-define color attributes... self.COLOR_NORMAL=1 self.COLOR_HEADER_NORMAL=2 self.COLOR_HEADER_HI=3 self.COLOR_ERROR=4 self.COLOR_CRITICAL=5 self.COLOR_WARN=6 self.COLOR_OK=7 curses.init_pair(self.COLOR_NORMAL, curses.COLOR_WHITE, curses.COLOR_BLACK) # normal (selected row is inverted, disabled/sleep is dim) curses.init_pair(self.COLOR_HEADER_NORMAL, curses.COLOR_BLACK, curses.COLOR_GREEN) # header normal curses.init_pair(self.COLOR_HEADER_HI, curses.COLOR_WHITE, curses.COLOR_CYAN) # header hi curses.init_pair(self.COLOR_ERROR, curses.COLOR_YELLOW, curses.COLOR_RED) # error text curses.init_pair(self.COLOR_CRITICAL, curses.COLOR_RED, curses.COLOR_BLACK) # critical curses.init_pair(self.COLOR_WARN, curses.COLOR_YELLOW, curses.COLOR_BLACK) # warn curses.init_pair(self.COLOR_OK, curses.COLOR_GREEN, curses.COLOR_BLACK) # ok self._layoutScreen() def _handleSetup(self): self._alert('handleSetup not yet implemented') def _checkIfInitialized(self): if not self._driverInitialized: msg = 'Unable to initialize driver - check configuration' self._alert(msg) self._log.warning(msg) self._handleSetup() else: self._log.info('OpenZWave initialized successfully.') def _notifyDriverReady(self, network, controller): self._log.info('OpenZWave Driver is Ready; homeid is %0.8x. %d nodes were found.' % (network.home_id, network.nodes_count)) self._driverInitialized = True self._addDialogText(2,'Driver initialized with homeid %0.8x' % network.home_id) self._addDialogText(3,'Node Count is now %' % network.nodes_count) def _notifyNodeAdded(self, network, node): self._addDialogText(3,'Node Count is now %s'.format(network.nodes_count)) self._updateSystemInfo() def _redrawAll(self): self._clearDialog() self._updateSystemInfo() self._updateDeviceList() self._updateColumnHeaders() self._updateDeviceDetail() def _notifyNetworkReady(self, network, controller): self._log.info('OpenZWave Initialization Complete.') self._alert('OpenZWave Initialization Complete.') self._redrawAll() def _notifyNetworkFailed(self, network): self._log.info('OpenZWave Initialization failed.') self._alert('OpenZWave Initialization failed.') self._redrawAll() def _notifyNodeReady(self, network, node): self._readyNodeCount += 1 self._addDialogText(2, 'OpenZWave is querying associated devices') self._addDialogText(3,'Node %s is now ready' % node.node_id) self._addDialogProgress(5, self._readyNodeCount, network.nodes_count) self._updateDeviceList() def _notifyValueChanged(self, signal, **kw): nodeId = kw['nodeId'] self._log.debug('Got value changed notification for node {0}'.format(nodeId)) # TODO: this is very heavy handed - just update appropriate elements self._updateDeviceList() self._updateDeviceDetail() def _initDialog(self, height, width, buttons=('OK',), caption=None): self._dialogpad = curses.newpad(height, width) self._dialogpad.bkgd(0x94, curses.color_pair(self.COLOR_HEADER_HI)) self._dialogpad.clear() self._dialogpad.box() if caption: lh = (width / 2) - (len(caption) / 2) - 1 self._dialogpad.addstr(0, lh, ' {0} '.format(caption), curses.color_pair(self.COLOR_NORMAL) | curses.A_STANDOUT) if buttons: if len(buttons) > 1: bwid = 0 for bcap in buttons: if len(bcap) > bwid: bwid = len(bcap) cellwid = (width - 4) / len(buttons) lpad = (cellwid - bwid) / 2 - 1 rpad = cellwid - bwid - lpad - 1 self._dialogpad.move(height - 2, 1) else: bwid = len(buttons[0]) lpad = rpad = 1 self._dialogpad.move(height - 2, (width / 2) - (bwid / 2) - 2) for button in buttons: self._dialogpad.addstr('{0:{wlpad}}<{1:^{wbwid}}>{0:{wrpad}}'.format('',button, wlpad=lpad, wbwid=bwid, wrpad=rpad)) dt = (self._screensize[0] / 2) - (height / 2) dl = (self._screensize[1] / 2) - (width / 2) dc = padcoords(sminrow=dt,smincol=dl,smaxrow=dt+height - 1, smaxcol=dl+width - 1) self._dialogcoords = dc self._dialogpad.overlay(self._screen, 0, 0, dc.sminrow, dc.smincol, dc.smaxrow, dc.smaxcol) self._screen.refresh() def _clearDialog(self): del self._dialogpad self._dialogpad = None self._dialogcoords = None self._screen.touchwin() self._screen.refresh() def _updateDialog(self): if self._dialogpad: self._screen.refresh() dc = self._dialogcoords self._dialogpad.refresh(0,0,dc.sminrow, dc.smincol, dc.smaxrow, dc.smaxcol) def _addDialogText(self, row, text, align='^'): if self._dialogpad: self._dialogpad.addstr(row, 1, '{0:{aln}{wid}}'.format(text, aln=align, wid=self._dialogpad.getmaxyx()[1] - 2)) self._updateDialog() def _addDialogProgress(self, row, current, total, showPercent=True, width=None): if self._dialogpad: dc = self._dialogcoords if width is None: width = (dc.smaxcol - dc.smincol) * 2 / 3 pct = float(current) / float(total) filled = int(pct * float(width)) lh = ((dc.smaxcol - dc.smincol) / 2) - (width / 2) self._dialogpad.addch(row, lh - 1, '[', curses.color_pair(self.COLOR_NORMAL) | curses.A_BOLD) self._dialogpad.addch(row, lh + width, ']', curses.color_pair(self.COLOR_NORMAL) | curses.A_BOLD) self._dialogpad.addstr(row, lh, ' '*width, curses.color_pair(self.COLOR_NORMAL)) self._dialogpad.addstr(row, lh, '|'*filled, curses.color_pair(self.COLOR_OK) | curses.A_BOLD) if showPercent: pctstr = '{0:4.0%}'.format(pct) lh = ((dc.smaxcol - dc.smincol) / 2) - (len(pctstr) / 2) self._dialogpad.addstr(row, lh, pctstr, curses.color_pair(self.COLOR_NORMAL) | curses.A_BOLD) self._updateDialog() def _startNetwork(self): dispatcher.connect(self._notifyDriverReady, ZWaveNetwork.SIGNAL_DRIVER_READY) dispatcher.connect(self._notifyNetworkReady, ZWaveNetwork.SIGNAL_NETWORK_READY) dispatcher.connect(self._notifyNetworkFailed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) dispatcher.connect(self._notifyNodeReady, ZWaveNetwork.SIGNAL_NODE_READY) dispatcher.connect(self._notifyValueChanged, ZWaveNetwork.SIGNAL_VALUE_CHANGED) dispatcher.connect(self._notifyNodeAdded, ZWaveNetwork.SIGNAL_NODE_ADDED) self._initDialog(10,60,['Cancel'],'Progress') self._addDialogText(2,'Initializing OpenZWave') self._log.info('Initializing OpenZWave') self._network = ZWaveNetwork(self._options, log=self._log) #self._network = ZWaveWrapper.getInstance(device=self._config['device'], config=self._config['config'], log=None) self._setTimer('initCheck', 3, self._checkIfInitialized) while not self._stop.isSet() and not self._driverInitialized: time.sleep(0.1) # TODO: handle keys here... cancel/etc def _runLoop(self): while not self._stop.isSet(): key = self._screen.getch() if key == curses.KEY_DOWN: self._switchItem(1) elif key == curses.KEY_UP: self._switchItem(-1) elif key == curses.KEY_LEFT: self._switchTab(-1) elif key == curses.KEY_RIGHT: self._switchTab(1) elif key == 0x09: self._nextMode() elif key is not None: self._handleMnemonic(key) def _handleMnemonic(self, key): for mnemonic, func in self._keys.iteritems(): if key == ord(mnemonic[0].lower()) or key == ord(mnemonic[0].upper()): funcname = '_handle%s' % func try: method = getattr(self, funcname) method() except AttributeError as ex: msg = 'No method named [%s] defined!' % funcname self._log.warn('handleMnemonic: %s', msg) self._log.warn('handleMnemonic Exception Details: %s', str(ex)) self._alert(msg) break def _resetDetailPos(self): for p in self._detailpos.iterkeys(): self._detailpos[p] = 0 def _switchItem(self, delta): if self._listMode: n = self._listindex + delta if n in range(0, self._listcount): self._listindex = n self._updateDeviceList() # TODO: we don't really need to redraw everything when selection changes self._resetDetailPos() self._updateDeviceDetail() else: self._detailpos[self._detailview] += delta self._updateDeviceDetail() def _switchTab(self, delta): if self._listMode: i = self._colheaders.index(self._sortcolumn) i += delta if i > len(self._colheaders) - 1: i = 1 elif i < 1: i = len(self._colheaders) - 1 self._sortcolumn = self._colheaders[i] else: i = self._detailheaders.index(self._detailview) i += delta if i > len(self._detailheaders) - 1: i = 0 elif i < 0: i = len(self._detailheaders) - 1 self._detailview = self._detailheaders[i] self._updateColumnHeaders() self._updateDeviceList() self._updateDeviceDetail() def _nextMode(self): self._listMode = not self._listMode self._updateColumnHeaders() def _shutdown(self): # TODO: handle orderly shutdown pass def _rightPrint(self, row, data, attrs=None): if attrs is None: attrs = curses.color_pair(self.COLOR_NORMAL) self._screen.addstr(row, self._screensize[1] - len(data), data, attrs) def _updateSystemInfo(self): self._screen.addstr(0,1,'%s on %s' % \ (self._network.controller.description, self._network.controller.device), \ curses.color_pair(self.COLOR_NORMAL)) self._screen.addstr(1,1,'Home ID 0x%0.8x' % \ (self._network.self._network.home_id), \ curses.color_pair(self.COLOR_NORMAL)) self._screen.move(2,1) self._screen.addstr('%s Registered Nodes' % \ (self._network.nodes_count), \ curses.color_pair(self.COLOR_NORMAL)) self._screen.addstr(' (%s Sleeping)' % \ (self._network.sleeping_nodes_count), \ curses.color_pair(self.COLOR_NORMAL) | curses.A_DIM) self._rightPrint(0, 'Library' % \ (self._network.controller.library_description)) self._rightPrint(1, 'Python Library Version %s' % \ (self._network.controller.python_library_version)) self._screen.refresh() def _updateColumnHeaders(self): self._screen.move(4,0) for text, wid in zip(self._colheaders, self._colwidths): clr = curses.color_pair(self.COLOR_HEADER_NORMAL) if self._listMode else curses.color_pair(self.COLOR_NORMAL) | curses.A_STANDOUT if text == self._sortcolumn: clr = curses.color_pair(self.COLOR_HEADER_HI) | curses.A_BOLD self._screen.addstr('{0:<{width}}'.format(text, width=wid), clr) self._screen.move(self._rowheights[0] + self._rowheights[1] + 1, 0) clr = curses.color_pair(self.COLOR_HEADER_NORMAL) if not self._listMode else curses.color_pair(self.COLOR_NORMAL) | curses.A_STANDOUT self._screen.addstr('{0:{width}}'.format('', width=self._screensize[1]), clr) self._screen.move(self._rowheights[0] + self._rowheights[1] + 1, 0) for text in self._detailheaders: clr = curses.color_pair(self.COLOR_HEADER_NORMAL) if not self._listMode else curses.color_pair(self.COLOR_NORMAL) | curses.A_STANDOUT if text == self._detailview: clr = curses.color_pair(self.COLOR_HEADER_HI) | curses.A_BOLD wid = len(text) self._screen.addstr(' {0:<{width}} '.format(text, width=wid), clr) def _fixColumn(self, text, width, align='<'): retval = '{0:{aln}{wid}}'.format(text, aln=align, wid=width) if len(retval) > width: retval = retval[:width] return retval def _getListItemColor(self, drawSelected): return curses.color_pair(self.COLOR_NORMAL) | curses.A_STANDOUT if drawSelected \ else curses.color_pair(self.COLOR_NORMAL) def _drawMiniBar(self, value, minValue, maxValue, drawWidth, drawSelected, drawPercent=False, colorLevels=None): clr = self._getListItemColor(drawSelected) pct = float(value) / float(maxValue) dw = drawWidth - 2 filled = int(pct * float(dw)) fillcolor = clr if not drawSelected: fillcolor = curses.color_pair(self.COLOR_OK) if colorLevels: if pct <= colorLevels.error: fillcolor = curses.color_pair(self.COLOR_CRITICAL) elif pct <= colorLevels.warning: fillcolor = curses.color_pair(self.COLOR_WARN) self._listpad.addch('[', clr | curses.A_BOLD) self._listpad.addstr('|' * filled, fillcolor) self._listpad.addstr(' ' * (dw - filled), clr) self._listpad.addch(']', clr | curses.A_BOLD) # TODO: draw percent text if requested def _drawNodeStatus(self, node, drawSelected): clr = self._getListItemColor(drawSelected) if node.is_sleeping: self._listpad.addstr(self._fixColumn('(sleeping)', self._colwidths[5]), clr | curses.A_LOW) elif node.has_command_class(0x76): # lock self._listpad.addstr(self._fixColumn('Locked' if node.is_locked else 'Unlocked', self._colwidths[5]), clr) elif node.has_command_class(0x26): # multi-level switch self._drawMiniBar(node.level, 0, 99, self._colwidths[5], drawSelected) elif node.has_command_class(0x25): # binary switch self._listpad.addstr(self._fixColumn('ON' if node.is_on else 'OFF', self._colwidths[5]), clr) else: self._listpad.addstr(self._fixColumn('OK', self._colwidths[5]), clr) def _drawBatteryStatus(self, node, drawSelected): clr = self._getListItemColor(drawSelected) if node.has_command_class(0x80): self._drawMiniBar(node.batteryLevel, 0, 100, self._colwidths[6], drawSelected, colorLevels=colorlevels(error=0.10,warning=0.40)) else: self._listpad.addstr(self._fixColumn('', self._colwidths[6]), clr) def _drawSignalStrength(self, node, drawSelected): clr = self._getListItemColor(drawSelected) self._listpad.addstr(self._fixColumn('', self._colwidths[7]), clr) def _drawDeviceNodeLine(self, node, drawSelected): clr = self._getListItemColor(drawSelected) self._listpad.addstr(' ', clr) self._listpad.addstr(self._fixColumn(node.id, self._colwidths[1]), clr) self._listpad.addstr(self._fixColumn(node.name, self._colwidths[2]), clr) self._listpad.addstr(self._fixColumn(node.location, self._colwidths[3]), clr) self._listpad.addstr(self._fixColumn(node.productType, self._colwidths[4]), clr) self._drawNodeStatus(node, drawSelected) self._drawBatteryStatus(node, drawSelected) self._drawSignalStrength(node, drawSelected) def _updateDeviceList(self): self._listcount = self._network.nodes_count idx = 0 for node in self._network._nodes.itervalues(): if idx == self._listindex: self._selectedNode = node self._listpad.move(idx,0) self._drawDeviceNodeLine(node, idx == self._listindex) idx += 1 ctop = self._rowheights[0] listheight = self._rowheights[1] if self._listindex - self._listtop > listheight: self._listtop = self._listindex - listheight elif self._listindex < self._listtop: self._listtop = self._listindex self._screen.refresh() self._listpad.refresh(self._listtop, 0, ctop, 0, ctop + listheight, self._screensize[1] - 1) self._updateDialog() def _redrawDetailTab(self, pad): self._screen.refresh() pad.refresh(0, 0, self._detailtop, 0, self._detailbottom, self._screensize[1] - 1) def _updateDetail_Values(self, pad): # Draw column header clr = curses.color_pair(self.COLOR_HEADER_HI) | curses.A_BOLD pad.addstr(0,0,'{0:<{width}}'.format(' ', width=self._screensize[1]), clr) pad.move(0,1) for text, wid in zip(self._deviceValueColumns, self._deviceValueWidths): pad.addstr('{0:<{width}}'.format(text.title(), width=wid), clr) node = self._selectedNode if node and node.values: # Grab all items except for configuration values (they have their own tab) vset = list() for value in node.values.itervalues(): if value.valueData: vset.append(value) # Sort the resulting set: (1) command class, (2) instance, (3) index s = sorted(sorted(sorted(vset, key=lambda value: value.getValue('index')), key=lambda value: value.getValue('instance')), key=lambda value: value.getValue('commandClass')) if self._detailpos[self._detailview] >= len(s): self._detailpos[self._detailview]=len(s)-1 i = 0 for value in s: vdic = value.valueData pad.move(i+1,0) # TODO: reset detail position on parent item change drawSelected = self._detailpos['Values'] == i clr = self._getListItemColor(drawSelected) pad.addstr(' ' * self._screensize[1], clr) pad.move(i+1,1) i += 1 for key, wid in zip(self._deviceValueColumns, self._deviceValueWidths): clr = self._getListItemColor(drawSelected) text = value.getValue(key) # strip 'COMMAND_CLASS_' prefix to save some space if key == 'commandClass' and text.startswith('COMMAND_CLASS_'): text = text[14:] # TODO: value decorators (checkbox for Booleans, edit box for others) # decimal: format to 2 places # bool as checkbox # byte as minibar if editable # ints need to be directly edited... # buttons... ? # Draw editable items differently if key == 'value' and not vdic['readOnly'] and drawSelected: clr = curses.color_pair(self.COLOR_ERROR) pad.addstr(self._fixColumn(text, wid), clr) def _updateDetail_Info(self, pad): node = self._selectedNode if node: #baudRate, basic, generic, specific, version, security self._deviceInfoColumns=['id','name','location','capabilities','neighbors','manufacturer','product','productType'] if self._detailpos[self._detailview] >= len(self._deviceInfoColumns): self._detailpos[self._detailview]=len(self._deviceInfoColumns)-1 editableColumns=['name','location','manufacturer','product'] i = maxwid = 0 for name in self._deviceInfoColumns: maxwid = len(name) if len(name) > maxwid else maxwid colwidth = maxwid + 2 clr = self._getListItemColor(False) clr_rw = curses.color_pair(self.COLOR_ERROR) clr_ro = self._getListItemColor(True) clr_col = curses.color_pair(self.COLOR_OK) # TODO: If editable, should be textpad for column in self._deviceInfoColumns: val = str(getattr(node, column)) pad.move(i + 1, 1) pad.addstr('{0:>{width}}'.format(column.title() + ':', width=colwidth), clr_col) selected = i == self._detailpos[self._detailview] thisclr = clr if selected: thisclr = clr_rw if column in editableColumns else clr_ro i += 1 pad.addstr(' ') pad.addstr('{0:<{width}}'.format(val, width=30), thisclr) def _updateDetail_Classes(self, pad): clr = curses.color_pair(self.COLOR_HEADER_HI) | curses.A_BOLD pad.addstr(0,0,'{0:<{width}}'.format(' CommandClass', width=self._screensize[1]), clr) node = self._selectedNode if node: if self._detailpos[self._detailview] >= len(node.commandClasses): self._detailpos[self._detailview]=len(node.commandClasses)-1 i = 0 for cc in node.commandClasses: pad.addstr(i + 1, 0, ' {0:<{width}}'.format(self._network.getCommandClassName(cc), width=30), self._getListItemColor(i == self._detailpos[self._detailview])) i += 1 def _updateDetail_Groups(self, pad): pad.addstr(3,3,'Group view not yet implemented') # groups tab: # index label maxMembers members # 1 my group 4 1, 2, 4 # Members column is editable - enter comma-separated list? def _updateDetail_Events(self, pad): pad.addstr(3,3,'Event view not yet implemented') # event detail tab: # timestamp commandClass notificationType def _updateDeviceDetail(self): # TODO: detail needs to be scrollable, but to accomplish that a couple of changes need to be made. First, the detail header band needs to be moved into a static shared section (above the detail pad); second, a new dict of 'top' positions needs to be created; finally, positioning code needs to be written to correctly offset the pad. pad = self._detailpads[self._detailview] pad.clear() if self._detailpos[self._detailview] < 0: self._detailpos[self._detailview]=0 funcname = '_updateDetail_{0}'.format(self._detailview) try: method = getattr(self, funcname) method(pad) except AttributeError as ex: msg = 'No method named [%s] defined!' % funcname self._log.warn('_updateDeviceDetail: %s', msg) self._log.warn('_updateDeviceDetail Exception Details: %s', str(ex)) self._alert(msg) self._redrawDetailTab(pad) def _updateMenu(self): menurow = self._screensize[0] - 1 self._screen.addstr(menurow, 0, ' ' * (self._screensize[1] - 1), curses.color_pair(self.COLOR_HEADER_NORMAL)) self._screen.move(menurow,4) for mnemonic, text in self._keys.iteritems(): self._screen.addstr(' {0} '.format(mnemonic), curses.color_pair(self.COLOR_NORMAL) | curses.A_BOLD) self._screen.addstr('{0}'.format(text), curses.color_pair(self.COLOR_HEADER_NORMAL)) def _redrawMenu(self): self._updateMenu() self._screen.refresh()
def setup(hass, config): """Set up Z-Wave. Will automatically load components to support devices found on the network. """ descriptions = conf_util.load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) from pydispatch import dispatcher # pylint: disable=import-error from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork from openzwave.group import ZWaveGroup # Load configuration use_debug = config[DOMAIN].get(CONF_DEBUG) autoheal = config[DOMAIN].get(CONF_AUTOHEAL) device_config = EntityValues(config[DOMAIN][CONF_DEVICE_CONFIG], config[DOMAIN][CONF_DEVICE_CONFIG_DOMAIN], config[DOMAIN][CONF_DEVICE_CONFIG_GLOB]) new_entity_ids = config[DOMAIN][CONF_NEW_ENTITY_IDS] if not new_entity_ids: _LOGGER.warning( "ZWave entity_ids will soon be changing. To opt in to new " "entity_ids now, set `new_entity_ids: true` under zwave in your " "configuration.yaml. See the following blog post for details: " "https://home-assistant.io/blog/2017/06/15/zwave-entity-ids/") # Setup options options = ZWaveOption(config[DOMAIN].get(CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get(CONF_CONFIG_PATH)) options.set_console_output(use_debug) if CONF_NETWORK_KEY in config[DOMAIN]: options.addOption("NetworkKey", config[DOMAIN][CONF_NETWORK_KEY]) options.lock() network = hass.data[DATA_NETWORK] = ZWaveNetwork(options, autostart=False) hass.data[DATA_DEVICES] = {} hass.data[DATA_ENTITY_VALUES] = [] if use_debug: # pragma: no cover def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Handle new added value to a node on the network.""" # Check if this value should be tracked by an existing entity for values in hass.data[DATA_ENTITY_VALUES]: values.check_value(value) for schema in DISCOVERY_SCHEMAS: if not check_node_schema(node, schema): continue if not check_value_schema( value, schema[const.DISC_VALUES][const.DISC_PRIMARY]): continue values = ZWaveDeviceEntityValues(hass, schema, value, config, device_config) # We create a new list and update the reference here so that # the list can be safely iterated over in the main thread new_values = hass.data[DATA_ENTITY_VALUES] + [values] hass.data[DATA_ENTITY_VALUES] = new_values component = EntityComponent(_LOGGER, DOMAIN, hass) def node_added(node): """Handle a new node on the network.""" entity = ZWaveNodeEntity(node, network, new_entity_ids) name = node_name(node) if new_entity_ids: generated_id = generate_entity_id(DOMAIN + '.{}', name, []) else: generated_id = entity.entity_id node_config = device_config.get(generated_id) if node_config.get(CONF_IGNORED): _LOGGER.info("Ignoring node entity %s due to device settings", generated_id) return component.add_entities([entity]) def network_ready(): """Handle the query of all awake nodes.""" _LOGGER.info("Zwave network is ready for use. All awake nodes " "have been queried. Sleeping nodes will be " "queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) dispatcher.connect(value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect(node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False) dispatcher.connect(network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect(network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Z-Wave add_node have been initialized") network.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Z-Wave add_node_secure have been initialized") network.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Z-Wwave remove_node have been initialized") network.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running Z-Wave command") network.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("Z-Wave heal running") network.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Z-Wave soft_reset have been initialized") network.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Z-Wave test_network have been initialized") network.test() def stop_network(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping Z-Wave network") network.stop() if hass.state == CoreState.running: hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): """Rename a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info("Renamed Z-Wave node %d to %s", node_id, name) def rename_value(service): """Rename a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] name = service.data.get(const.ATTR_NAME) value.label = name _LOGGER.info("Renamed Z-Wave value (Node %d Value %d) to %s", node_id, value_id, name) def set_poll_intensity(service): """Set the polling intensity of a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] intensity = service.data.get(const.ATTR_POLL_INTENSITY) if intensity == 0: if value.disable_poll(): _LOGGER.info("Polling disabled (Node %d Value %d)", node_id, value_id) return _LOGGER.info("Polling disabled failed (Node %d Value %d)", node_id, value_id) else: if value.enable_poll(intensity): _LOGGER.info("Set polling intensity (Node %d Value %d) to %s", node_id, value_id, intensity) return _LOGGER.info("Set polling intensity failed (Node %d Value %d)", node_id, value_id) def remove_failed_node(service): """Remove failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to remove zwave node %d", node_id) network.controller.remove_failed_node(node_id) def replace_failed_node(service): """Replace failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to replace zwave node %d", node_id) network.controller.replace_failed_node(node_id) def set_config_parameter(service): """Set a config parameter to a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) selection = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE) for value in (node.get_values( class_id=const.COMMAND_CLASS_CONFIGURATION).values()): if value.index != param: continue if value.type in [const.TYPE_LIST, const.TYPE_BOOL]: value.data = selection _LOGGER.info( "Setting config list parameter %s on Node %s " "with selection %s", param, node_id, selection) return value.data = int(selection) _LOGGER.info( "Setting config parameter %s on Node %s " "with selection %s", param, node_id, selection) return node.set_config_param(param, selection, size) _LOGGER.info( "Setting unknown config parameter %s on Node %s " "with selection %s", param, node_id, selection) def print_config_parameter(service): """Print a config parameter from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) _LOGGER.info("Config parameter %s on Node %s: %s", param, node_id, get_config_value(node, param)) def print_node(service): """Print all information about z-wave node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] nice_print_node(node) def set_wakeup(service): """Set wake-up interval of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] value = service.data.get(const.ATTR_CONFIG_VALUE) if node.can_wake_up(): for value_id in node.get_values( class_id=const.COMMAND_CLASS_WAKE_UP): node.values[value_id].data = value _LOGGER.info("Node %s wake-up set to %d", node_id, value) else: _LOGGER.info("Node %s is not wakeable", node_id) def change_association(service): """Change an association in the zwave network.""" association_type = service.data.get(const.ATTR_ASSOCIATION) node_id = service.data.get(const.ATTR_NODE_ID) target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) group = service.data.get(const.ATTR_GROUP) instance = service.data.get(const.ATTR_INSTANCE) node = ZWaveGroup(group, network, node_id) if association_type == 'add': node.add_association(target_node_id, instance) _LOGGER.info( "Adding association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) if association_type == 'remove': node.remove_association(target_node_id, instance) _LOGGER.info( "Removing association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) @asyncio.coroutine def async_refresh_entity(service): """Refresh values that specific entity depends on.""" entity_id = service.data.get(ATTR_ENTITY_ID) async_dispatcher_send(hass, SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id)) def refresh_node(service): """Refresh all node info.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] node.refresh_info() def reset_node_meters(service): """Reset meter counters of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) instance = service.data.get(const.ATTR_INSTANCE) node = network.nodes[node_id] for value in (node.get_values( class_id=const.COMMAND_CLASS_METER).values()): if value.index != const.INDEX_METER_RESET: continue if value.instance != instance: continue network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info("Resetting meters on node %s instance %s....", node_id, instance) return _LOGGER.info( "Node %s on instance %s does not have resettable " "meters.", node_id, instance) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting Z-Wave network...") network.start() hass.bus.fire(const.EVENT_NETWORK_START) # Need to be in STATE_AWAKED before talking to nodes. # Wait up to NETWORK_READY_WAIT_SECS seconds for the zwave network # to be ready. for i in range(const.NETWORK_READY_WAIT_SECS): _LOGGER.debug("network state: %d %s", network.state, network.state_str) if network.state >= network.STATE_AWAKED: _LOGGER.info("Z-Wave ready after %d seconds", i) break time.sleep(1) else: _LOGGER.warning( "zwave not ready after %d seconds, continuing anyway", const.NETWORK_READY_WAIT_SECS) _LOGGER.info("final network state: %d %s", network.state, network.state_str) polling_interval = convert(config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: network.set_poll_interval(polling_interval, False) poll_interval = network.get_poll_interval() _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_network) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node, descriptions[const.SERVICE_ADD_NODE]) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure, descriptions[const.SERVICE_ADD_NODE_SECURE]) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node, descriptions[const.SERVICE_REMOVE_NODE]) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command, descriptions[const.SERVICE_CANCEL_COMMAND]) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network, descriptions[const.SERVICE_HEAL_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset, descriptions[const.SERVICE_SOFT_RESET]) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network, descriptions[const.SERVICE_TEST_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network, descriptions[const.SERVICE_STOP_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave, descriptions[const.SERVICE_START_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, descriptions[const.SERVICE_RENAME_NODE], schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RENAME_VALUE, rename_value, descriptions[const.SERVICE_RENAME_VALUE], schema=RENAME_VALUE_SCHEMA) hass.services.register( DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, descriptions[const.SERVICE_SET_CONFIG_PARAMETER], schema=SET_CONFIG_PARAMETER_SCHEMA) hass.services.register( DOMAIN, const.SERVICE_PRINT_CONFIG_PARAMETER, print_config_parameter, descriptions[const.SERVICE_PRINT_CONFIG_PARAMETER], schema=PRINT_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REMOVE_FAILED_NODE, remove_failed_node, descriptions[const.SERVICE_REMOVE_FAILED_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REPLACE_FAILED_NODE, replace_failed_node, descriptions[const.SERVICE_REPLACE_FAILED_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_CHANGE_ASSOCIATION, change_association, descriptions[const.SERVICE_CHANGE_ASSOCIATION], schema=CHANGE_ASSOCIATION_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, descriptions[const.SERVICE_SET_WAKEUP], schema=SET_WAKEUP_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_NODE, print_node, descriptions[const.SERVICE_PRINT_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_ENTITY, async_refresh_entity, descriptions[const.SERVICE_REFRESH_ENTITY], schema=REFRESH_ENTITY_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_NODE, refresh_node, descriptions[const.SERVICE_REFRESH_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RESET_NODE_METERS, reset_node_meters, descriptions[const.SERVICE_RESET_NODE_METERS], schema=RESET_NODE_METERS_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_POLL_INTENSITY, set_poll_intensity, descriptions[const.SERVICE_SET_POLL_INTENSITY], schema=SET_POLL_INTENSITY_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("Z-Wave network autoheal is enabled") track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
device="/dev/ttyUSB0" log="Debug" for arg in sys.argv: if arg.startswith("--device"): temp,device = arg.split("=") elif arg.startswith("--log"): temp,log = arg.split("=") elif arg.startswith("--help"): print("help : ") print(" --device=/dev/yourdevice ") print(" --log=Info|Debug") #Define some manager options options = ZWaveOption(device, \ config_path="../openzwave/config", \ user_path=".", cmd_line="") options.set_log_file("OZW_Log.log") options.set_append_log_file(False) options.set_console_output(True) options.set_save_log_level(log) #options.set_save_log_level('Info') options.set_logging(False) options.lock() print("Memory use : %s Mo" % (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024.0)) #Create a network object network = ZWaveNetwork(options, log=None) time_started = 0
def _init_controller(): if P.module_imported: device = '{}{}'.format(P.device, P.device_index) L.l.info('Zwave initialising on {}'.format(device)) _stop_net() # Define some manager options try: options = ZWaveOption(device, config_path="../openzwave/config", user_path=".", cmd_line="") options.set_log_file(P.log_file) options.set_append_log_file(True) options.set_console_output(False) # options.set_save_log_level('Debug') # options.set_save_log_level('Info') options.set_save_log_level('Warning') # options.set_save_log_level('Error') options.set_logging(False) #options.set_logging(True) # options.set_poll_interval(5) options.set_save_configuration(True) options.lock() # Create a network object P.network = ZWaveNetwork(options, log=None, autostart=False) dispatcher.connect(louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(louie_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED) dispatcher.connect(louie_network_resetted, ZWaveNetwork.SIGNAL_NETWORK_RESETTED) dispatcher.connect(louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) dispatcher.connect(louie_network_stopped, ZWaveNetwork.SIGNAL_NETWORK_STOPPED) dispatcher.connect(louie_network_awaked, ZWaveNetwork.SIGNAL_NETWORK_AWAKED) P.network.start() L.l.info("Waiting for zwave driver") for i in range(0, 120): if P.network.state >= P.network.STATE_STARTED: L.l.info("Zwave driver started") break else: time.sleep(0.1) if P.network.state < P.network.STATE_STARTED: L.l.info( "Can't initialise zwave driver. Look at the logs in {}". format(P.log_file)) return False L.l.info("Home id : {}, Nodes in network : {}".format( P.network.home_id_str, P.network.nodes_count)) L.l.info("Waiting 120 sec for zwave network to become ready") for i in range(0, 240): if P.network.state >= P.network.STATE_READY: break else: time.sleep(0.5) # L.l.info("state = {}".format(P.network.state)) if not P.network.is_ready: L.l.info( "Can't start network! Look at the logs in OZW_Log.log") P.network.stop() return False else: L.l.info("Zwave network is started!") # print nodes for node_id in P.network.nodes: node = P.network.nodes[node_id] try: L.l.info("Node {}={}".format(node_id, node)) # L.l.info("Node {} attrib: model={} man={} prod_name={} prod_id={}".format( # node_id, node.manufacturer_name, node.product_name, node.product_id)) except Exception as ex: pass # not working # P.network.set_poll_interval(milliseconds=3000, bIntervalBetweenPolls=False) # P.network.test(1) variable.USB_PORTS_IN_USE.append(device) return True except ZWaveException as ze: L.l.error('Unable to init zwave, exception={}'.format(ze)) P.device_index += 1 if P.device_index > 3: P.device_index = 0 return False
async def async_setup_entry(hass, config_entry): """Set up Z-Wave from a config entry. Will automatically load components to support devices found on the network. """ from pydispatch import dispatcher # pylint: disable=import-error from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork from openzwave.group import ZWaveGroup config = {} if DATA_ZWAVE_CONFIG in hass.data: config = hass.data[DATA_ZWAVE_CONFIG] # Load configuration use_debug = config.get(CONF_DEBUG, DEFAULT_DEBUG) autoheal = config.get(CONF_AUTOHEAL, DEFAULT_CONF_AUTOHEAL) device_config = EntityValues( config.get(CONF_DEVICE_CONFIG), config.get(CONF_DEVICE_CONFIG_DOMAIN), config.get(CONF_DEVICE_CONFIG_GLOB)) # Setup options options = ZWaveOption( config_entry.data[CONF_USB_STICK_PATH], user_path=hass.config.config_dir, config_path=config.get(CONF_CONFIG_PATH)) options.set_console_output(use_debug) if CONF_NETWORK_KEY in config_entry.data: options.addOption("NetworkKey", config_entry.data[CONF_NETWORK_KEY]) await hass.async_add_executor_job(options.lock) network = hass.data[DATA_NETWORK] = ZWaveNetwork(options, autostart=False) hass.data[DATA_DEVICES] = {} hass.data[DATA_ENTITY_VALUES] = [] if use_debug: # pragma: no cover def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, ZWaveNetwork .SIGNAL_ALL_NODES_QUERIED_SOME_DEAD): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Handle new added value to a node on the network.""" # Check if this value should be tracked by an existing entity for values in hass.data[DATA_ENTITY_VALUES]: values.check_value(value) for schema in DISCOVERY_SCHEMAS: if not check_node_schema(node, schema): continue if not check_value_schema( value, schema[const.DISC_VALUES][const.DISC_PRIMARY]): continue values = ZWaveDeviceEntityValues( hass, schema, value, config, device_config, registry) # We create a new list and update the reference here so that # the list can be safely iterated over in the main thread new_values = hass.data[DATA_ENTITY_VALUES] + [values] hass.data[DATA_ENTITY_VALUES] = new_values component = EntityComponent(_LOGGER, DOMAIN, hass) registry = await async_get_registry(hass) def node_added(node): """Handle a new node on the network.""" entity = ZWaveNodeEntity(node, network) def _add_node_to_component(): if hass.data[DATA_DEVICES].get(entity.unique_id): return name = node_name(node) generated_id = generate_entity_id(DOMAIN + '.{}', name, []) node_config = device_config.get(generated_id) if node_config.get(CONF_IGNORED): _LOGGER.info( "Ignoring node entity %s due to device settings", generated_id) return hass.data[DATA_DEVICES][entity.unique_id] = entity component.add_entities([entity]) if entity.unique_id: _add_node_to_component() return @callback def _on_ready(sec): _LOGGER.info("Z-Wave node %d ready after %d seconds", entity.node_id, sec) hass.async_add_job(_add_node_to_component) @callback def _on_timeout(sec): _LOGGER.warning( "Z-Wave node %d not ready after %d seconds, " "continuing anyway", entity.node_id, sec) hass.async_add_job(_add_node_to_component) hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout, hass.loop) def network_ready(): """Handle the query of all awake nodes.""" _LOGGER.info("Zwave network is ready for use. All awake nodes " "have been queried. Sleeping nodes will be " "queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) def network_complete_some_dead(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried, but some nodes are marked dead") hass.bus.fire(const.EVENT_NETWORK_COMPLETE_SOME_DEAD) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False) dispatcher.connect( network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect( network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) dispatcher.connect( network_complete_some_dead, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD, weak=False) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Z-Wave add_node have been initialized") network.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Z-Wave add_node_secure have been initialized") network.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Z-Wwave remove_node have been initialized") network.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running Z-Wave command") network.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("Z-Wave heal running") network.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Z-Wave soft_reset have been initialized") network.controller.soft_reset() def update_config(service): """Update the config from git.""" _LOGGER.info("Configuration update has been initialized") network.controller.update_ozw_config() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Z-Wave test_network have been initialized") network.test() def stop_network(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping Z-Wave network") network.stop() if hass.state == CoreState.running: hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): """Rename a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info( "Renamed Z-Wave node %d to %s", node_id, name) def rename_value(service): """Rename a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] name = service.data.get(const.ATTR_NAME) value.label = name _LOGGER.info( "Renamed Z-Wave value (Node %d Value %d) to %s", node_id, value_id, name) def set_poll_intensity(service): """Set the polling intensity of a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] intensity = service.data.get(const.ATTR_POLL_INTENSITY) if intensity == 0: if value.disable_poll(): _LOGGER.info("Polling disabled (Node %d Value %d)", node_id, value_id) return _LOGGER.info("Polling disabled failed (Node %d Value %d)", node_id, value_id) else: if value.enable_poll(intensity): _LOGGER.info( "Set polling intensity (Node %d Value %d) to %s", node_id, value_id, intensity) return _LOGGER.info("Set polling intensity failed (Node %d Value %d)", node_id, value_id) def remove_failed_node(service): """Remove failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to remove zwave node %d", node_id) network.controller.remove_failed_node(node_id) def replace_failed_node(service): """Replace failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to replace zwave node %d", node_id) network.controller.replace_failed_node(node_id) def set_config_parameter(service): """Set a config parameter to a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) selection = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE) for value in ( node.get_values(class_id=const.COMMAND_CLASS_CONFIGURATION) .values()): if value.index != param: continue if value.type in [const.TYPE_LIST, const.TYPE_BOOL]: value.data = str(selection) _LOGGER.info("Setting config parameter %s on Node %s " "with list/bool selection %s", param, node_id, str(selection)) return if value.type == const.TYPE_BUTTON: network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info("Setting config parameter %s on Node %s " "with button selection %s", param, node_id, selection) return value.data = int(selection) _LOGGER.info("Setting config parameter %s on Node %s " "with selection %s", param, node_id, selection) return node.set_config_param(param, selection, size) _LOGGER.info("Setting unknown config parameter %s on Node %s " "with selection %s", param, node_id, selection) def refresh_node_value(service): """Refresh the specified value from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] node.values[value_id].refresh() _LOGGER.info("Node %s value %s refreshed", node_id, value_id) def set_node_value(service): """Set the specified value on a node.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) value = service.data.get(const.ATTR_CONFIG_VALUE) node = network.nodes[node_id] node.values[value_id].data = value _LOGGER.info("Node %s value %s set to %s", node_id, value_id, value) def print_config_parameter(service): """Print a config parameter from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) _LOGGER.info("Config parameter %s on Node %s: %s", param, node_id, get_config_value(node, param)) def print_node(service): """Print all information about z-wave node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] nice_print_node(node) def set_wakeup(service): """Set wake-up interval of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] value = service.data.get(const.ATTR_CONFIG_VALUE) if node.can_wake_up(): for value_id in node.get_values( class_id=const.COMMAND_CLASS_WAKE_UP): node.values[value_id].data = value _LOGGER.info("Node %s wake-up set to %d", node_id, value) else: _LOGGER.info("Node %s is not wakeable", node_id) def change_association(service): """Change an association in the zwave network.""" association_type = service.data.get(const.ATTR_ASSOCIATION) node_id = service.data.get(const.ATTR_NODE_ID) target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) group = service.data.get(const.ATTR_GROUP) instance = service.data.get(const.ATTR_INSTANCE) node = ZWaveGroup(group, network, node_id) if association_type == 'add': node.add_association(target_node_id, instance) _LOGGER.info("Adding association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) if association_type == 'remove': node.remove_association(target_node_id, instance) _LOGGER.info("Removing association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) async def async_refresh_entity(service): """Refresh values that specific entity depends on.""" entity_id = service.data.get(ATTR_ENTITY_ID) async_dispatcher_send( hass, SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id)) def refresh_node(service): """Refresh all node info.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] node.refresh_info() def reset_node_meters(service): """Reset meter counters of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) instance = service.data.get(const.ATTR_INSTANCE) node = network.nodes[node_id] for value in ( node.get_values(class_id=const.COMMAND_CLASS_METER) .values()): if value.index != const.INDEX_METER_RESET: continue if value.instance != instance: continue network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info("Resetting meters on node %s instance %s....", node_id, instance) return _LOGGER.info("Node %s on instance %s does not have resettable " "meters.", node_id, instance) def heal_node(service): """Heal a node on the network.""" node_id = service.data.get(const.ATTR_NODE_ID) update_return_routes = service.data.get(const.ATTR_RETURN_ROUTES) node = network.nodes[node_id] _LOGGER.info("Z-Wave node heal running for node %s", node_id) node.heal(update_return_routes) def test_node(service): """Send test messages to a node on the network.""" node_id = service.data.get(const.ATTR_NODE_ID) messages = service.data.get(const.ATTR_MESSAGES) node = network.nodes[node_id] _LOGGER.info("Sending %s test-messages to node %s.", messages, node_id) node.test(messages) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting Z-Wave network...") network.start() hass.bus.fire(const.EVENT_NETWORK_START) async def _check_awaked(): """Wait for Z-wave awaked state (or timeout) and finalize start.""" _LOGGER.debug( "network state: %d %s", network.state, network.state_str) start_time = dt_util.utcnow() while True: waited = int((dt_util.utcnow()-start_time).total_seconds()) if network.state >= network.STATE_AWAKED: # Need to be in STATE_AWAKED before talking to nodes. _LOGGER.info("Z-Wave ready after %d seconds", waited) break elif waited >= const.NETWORK_READY_WAIT_SECS: # Wait up to NETWORK_READY_WAIT_SECS seconds for the Z-Wave # network to be ready. _LOGGER.warning( "Z-Wave not ready after %d seconds, continuing anyway", waited) _LOGGER.info( "final network state: %d %s", network.state, network.state_str) break else: await asyncio.sleep(1, loop=hass.loop) hass.async_add_job(_finalize_start) hass.add_job(_check_awaked) def _finalize_start(): """Perform final initializations after Z-Wave network is awaked.""" polling_interval = convert( config.get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: network.set_poll_interval(polling_interval, False) poll_interval = network.get_poll_interval() _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_network) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset) hass.services.register(DOMAIN, const.SERVICE_UPDATE_CONFIG, update_config) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RENAME_VALUE, rename_value, schema=RENAME_VALUE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, schema=SET_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_NODE_VALUE, set_node_value, schema=SET_NODE_VALUE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_NODE_VALUE, refresh_node_value, schema=REFRESH_NODE_VALUE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_CONFIG_PARAMETER, print_config_parameter, schema=PRINT_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REMOVE_FAILED_NODE, remove_failed_node, schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REPLACE_FAILED_NODE, replace_failed_node, schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_CHANGE_ASSOCIATION, change_association, schema=CHANGE_ASSOCIATION_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, schema=SET_WAKEUP_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_NODE, print_node, schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_ENTITY, async_refresh_entity, schema=REFRESH_ENTITY_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_NODE, refresh_node, schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RESET_NODE_METERS, reset_node_meters, schema=RESET_NODE_METERS_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_POLL_INTENSITY, set_poll_intensity, schema=SET_POLL_INTENSITY_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_HEAL_NODE, heal_node, schema=HEAL_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_TEST_NODE, test_node, schema=TEST_NODE_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("Z-Wave network autoheal is enabled") async_track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_zwave) hass.services.async_register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave) for entry_component in SUPPORTED_PLATFORMS: hass.async_create_task(hass.config_entries.async_forward_entry_setup( config_entry, entry_component)) return True
class Open_zwave(HAInterface): VERSION = '0.0.2' awake = False ready = False nodesdisplayed = False def louie_network_ready(network): self._logger.info(">>>>>>> Hello from network : I'm ready : %d nodes were found." % self._network.nodes_count) self._logger.info(">>>>>>> Hello from network : my controller is : %s" % self._network.controller) dispatcher.connect(self.louie_node_update, ZWaveNetwork.SIGNAL_NODE) dispatcher.connect(self.louie_value_update, ZWaveNetwork.SIGNAL_VALUE) def louie_node_update(network, node): self._logger.info('>>>>>>> Hello from node : %s.' % node) def louie_value_update(network, node, value): self._logger.info('>>>>>>> Hello from value : %s.' % value) def __init__(self, *args, **kwargs): self._serialDevicePath = kwargs.get('serialDevicePath', None) self._options = ZWaveOption(self._serialDevicePath, \ config_path="/usr/local/etc/openzwave/", \ user_path=".", cmd_line="") self._options.set_log_file("OZW_Log.log") self._options.set_append_log_file(False) self._options.set_console_output(False) #self._options.set_save_log_level(log) self._options.set_save_log_level('Info') self._options.set_logging(True) self._options.set_notify_transactions(True) self._options.lock() self._network = ZWaveNetwork(self._options, log=None,autostart=False) dispatcher.connect(self.louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY) self._network.start() super(Open_zwave, self).__init__(self, *args, **kwargs) def _printNetwork(self, node): print print "------------------------------------------------------" print "%s - Name : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].name) print "%s - Manufacturer name / id : %s / %s" % ( self._network.nodes[node].node_id, self._network.nodes[node].manufacturer_name, self._network.nodes[node].manufacturer_id) print "%s - Product name / id / type : %s / %s / %s" % ( self._network.nodes[node].node_id, self._network.nodes[node].product_name, self._network.nodes[node].product_id, self._network.nodes[node].product_type) print "%s - Version : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].version) print "%s - Command classes : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].command_classes_as_string) print "%s - Capabilities : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].capabilities) print "%s - Neighbors : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].neighbors) print "%s - Can sleep : %s" % (self._network.nodes[node].node_id, self._network.nodes[node].can_wake_up()) def _init(self, *args, **kwargs): super(Open_zwave, self)._init(self, *args, **kwargs) def _readInterface(self, lastPacketHash): if (self._network.state >= self._network.STATE_AWAKED and not self.awake): self.awake = True self._logger.info("Network Awaked") if (self._network.state >= self._network.STATE_READY and not self.ready): self.ready = True self._logger.info("Network Ready") self._logger.info("********************************* NETWORK READY ************************************") if not self.awake: time.sleep(1.0) self._logger.debug("Not awaked") return if self.awake and not self.ready: time.sleep(1.0) self._logger.debug("Not ready") return if not self.nodesdisplayed and self.ready: for node in self._network.nodes: self._printNetwork(node) self.nodesdisplayed = True time.sleep(1) def version(self): self._logger.info("Open_zwave Pytomation Driver version " + self.VERSION) self._logger.info("Use openzwave library : %s" % self._network.controller.ozw_library_version) self._logger.info("Use python library : %s" % self._network.controller.python_library_version) self._logger.info("Use ZWave library : %s" % self._network.controller.library_description) def on(self, address): node = int(address) for val in self._network.nodes[node].get_switches() : self._logger.info("Activate switch") self._network.nodes[node].set_switch(val,True) for val in self._network.nodes[node].get_dimmers() : self._logger.info("Activate dimmer : %s" % self._network.nodes[node]) self._network.nodes[node].set_dimmer(val,99) def off(self, address): node = int(address) for val in self._network.nodes[node].get_switches() : self._logger.info("Activate switch") self._network.nodes[node].set_switch(val,False) for val in self._network.nodes[node].get_dimmers() : self._logger.info("Activate dimmer : %s" % self._network.nodes[node]) self._network.nodes[node].set_dimmer(val,0) def status(self, address): node = int(address) for val in self._network.nodes[node].get_dimmers() : level = self._network.nodes[nodeid].get_dimmer_level(val)
from openzwave.value import ZWaveValue from openzwave.scene import ZWaveScene from openzwave.controller import ZWaveController from openzwave.network import ZWaveNetwork from openzwave.option import ZWaveOption import time device="/dev/zwave-aeon-s2" for arg in sys.argv: if arg.startswith("--device"): temp,device = arg.split("=") #Define some manager options options = ZWaveOption(device, \ config_path="../openzwave/config", \ user_path=".", cmd_line="") options.set_log_file("OZW_Log.log") options.set_append_log_file(False) options.set_console_output(False) options.set_save_log_level('Debug') #options.set_save_log_level('Info') options.set_logging(True) options.lock() #Create a network object network = ZWaveNetwork(options, log=None) print "------------------------------------------------------------" print "Waiting for driver : " print "------------------------------------------------------------"
def setup(hass, config): """Setup Z-Wave. Will automatically load components to support devices found on the network. """ # pylint: disable=global-statement, import-error global NETWORK descriptions = conf_util.load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) try: import libopenzwave except ImportError: _LOGGER.error("You are missing required dependency Python Open " "Z-Wave. Please follow instructions at: " "https://home-assistant.io/components/zwave/") return False from pydispatch import dispatcher from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork from openzwave.group import ZWaveGroup default_zwave_config_path = os.path.join(os.path.dirname( libopenzwave.__file__), 'config') # Load configuration use_debug = config[DOMAIN].get(CONF_DEBUG) autoheal = config[DOMAIN].get(CONF_AUTOHEAL) hass.data[DATA_DEVICE_CONFIG] = EntityValues( config[DOMAIN][CONF_DEVICE_CONFIG], config[DOMAIN][CONF_DEVICE_CONFIG_DOMAIN], config[DOMAIN][CONF_DEVICE_CONFIG_GLOB]) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get( CONF_CONFIG_PATH, default_zwave_config_path)) options.set_console_output(use_debug) options.lock() NETWORK = ZWaveNetwork(options, autostart=False) if use_debug: def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Called when a value is added to a node on the network.""" for (component, generic_device_class, specific_device_class, command_class, value_type, value_genre) in DISCOVERY_COMPONENTS: _LOGGER.debug("Component=%s Node_id=%s query start", component, node.node_id) if node.generic not in generic_device_class and \ None not in generic_device_class: _LOGGER.debug("node.generic %s not None and in " "generic_device_class %s", node.generic, generic_device_class) continue if node.specific not in specific_device_class and \ None not in specific_device_class: _LOGGER.debug("node.specific %s is not None and in " "specific_device_class %s", node.specific, specific_device_class) continue if value.command_class not in command_class and \ None not in command_class: _LOGGER.debug("value.command_class %s is not None " "and in command_class %s", value.command_class, command_class) continue if value_type != value.type and value_type is not None: _LOGGER.debug("value.type %s != value_type %s", value.type, value_type) continue if value_genre != value.genre and value_genre is not None: _LOGGER.debug("value.genre %s != value_genre %s", value.genre, value_genre) continue # Configure node _LOGGER.debug("Adding Node_id=%s Generic_command_class=%s, " "Specific_command_class=%s, " "Command_class=%s, Value type=%s, " "Genre=%s as %s", node.node_id, node.generic, node.specific, value.command_class, value.type, value.genre, component) workaround_component = workaround.get_device_component_mapping( value) if workaround_component and workaround_component != component: if workaround_component == workaround.WORKAROUND_IGNORE: _LOGGER.info("Ignoring device %s due to workaround.", "{}.{}".format(component, object_id(value))) continue _LOGGER.debug("Using %s instead of %s", workaround_component, component) component = workaround_component name = "{}.{}".format(component, object_id(value)) node_config = hass.data[DATA_DEVICE_CONFIG].get(name) if node_config.get(CONF_IGNORED): _LOGGER.info( "Ignoring device %s due to device settings.", name) return polling_intensity = convert( node_config.get(CONF_POLLING_INTENSITY), int) if polling_intensity: value.enable_poll(polling_intensity) else: value.disable_poll() discovery.load_platform(hass, component, DOMAIN, { const.ATTR_NODE_ID: node.node_id, const.ATTR_VALUE_ID: value.value_id, }, config) def scene_activated(node, scene_id): """Called when a scene is activated on any node in the network.""" hass.bus.fire(const.EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: _node_object_id(node), const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_SCENE_ID: scene_id }) def node_event_activated(node, value): """Called when a nodeevent is activated on any node in the network.""" hass.bus.fire(const.EVENT_NODE_EVENT, { const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_BASIC_LEVEL: value }) def network_ready(): """Called when all awake nodes have been queried.""" _LOGGER.info("Zwave network is ready for use. All awake nodes" " have been queried. Sleeping nodes will be" " queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Called when all nodes on network have been queried.""" _LOGGER.info("Zwave network is complete. All nodes on the network" " have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) dispatcher.connect( node_event_activated, ZWaveNetwork.SIGNAL_NODE_EVENT, weak=False) dispatcher.connect( network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect( network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Zwave add_node have been initialized.") NETWORK.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Zwave add_node_secure have been initialized.") NETWORK.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Zwave remove_node have been initialized.") NETWORK.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running ZWave command.") NETWORK.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("ZWave heal running.") NETWORK.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Zwave soft_reset have been initialized.") NETWORK.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Zwave test_network have been initialized.") NETWORK.test() def stop_zwave(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping ZWave network.") NETWORK.stop() if hass.state == 'RUNNING': hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): """Rename a node.""" state = hass.states.get(service.data.get(ATTR_ENTITY_ID)) node_id = state.attributes.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info( "Renamed ZWave node %d to %s", node_id, name) def set_config_parameter(service): """Set a config parameter to a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) selection = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE, 2) i = 0 for value in ( node.get_values(class_id=const.COMMAND_CLASS_CONFIGURATION) .values()): if value.index == param and value.type == const.TYPE_LIST: _LOGGER.debug('Values for parameter %s: %s', param, value.data_items) i = len(value.data_items) - 1 if i == 0: node.set_config_param(param, selection, size) else: if selection > i: _LOGGER.info('Config parameter selection does not exist!' ' Please check zwcfg_[home_id].xml in' ' your homeassistant config directory. ' ' Available selections are 0 to %s', i) return node.set_config_param(param, selection, size) _LOGGER.info('Setting config parameter %s on Node %s ' 'with selection %s and size=%s', param, node_id, selection, size) def print_config_parameter(service): """Print a config parameter from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) _LOGGER.info("Config parameter %s on Node %s : %s", param, node_id, get_config_value(node, param)) def print_node(service): """Print all information about z-wave node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] nice_print_node(node) def set_wakeup(service): """Set wake-up interval of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = NETWORK.nodes[node_id] value = service.data.get(const.ATTR_CONFIG_VALUE) if node.can_wake_up(): for value_id in node.get_values( class_id=const.COMMAND_CLASS_WAKE_UP): node.values[value_id].data = value _LOGGER.info("Node %s wake-up set to %d", node_id, value) else: _LOGGER.info("Node %s is not wakeable", node_id) def change_association(service): """Change an association in the zwave network.""" association_type = service.data.get(const.ATTR_ASSOCIATION) node_id = service.data.get(const.ATTR_NODE_ID) target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) group = service.data.get(const.ATTR_GROUP) instance = service.data.get(const.ATTR_INSTANCE) node = ZWaveGroup(group, NETWORK, node_id) if association_type == 'add': node.add_association(target_node_id, instance) _LOGGER.info("Adding association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) if association_type == 'remove': node.remove_association(target_node_id, instance) _LOGGER.info("Removing association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting ZWave network.") NETWORK.start() hass.bus.fire(const.EVENT_NETWORK_START) # Need to be in STATE_AWAKED before talking to nodes. # Wait up to NETWORK_READY_WAIT_SECS seconds for the zwave network # to be ready. for i in range(const.NETWORK_READY_WAIT_SECS): _LOGGER.debug( "network state: %d %s", NETWORK.state, NETWORK.state_str) if NETWORK.state >= NETWORK.STATE_AWAKED: _LOGGER.info("zwave ready after %d seconds", i) break time.sleep(1) else: _LOGGER.warning( "zwave not ready after %d seconds, continuing anyway", const.NETWORK_READY_WAIT_SECS) _LOGGER.info( "final network state: %d %s", NETWORK.state, NETWORK.state_str) polling_interval = convert( config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: NETWORK.set_poll_interval(polling_interval, False) poll_interval = NETWORK.get_poll_interval() _LOGGER.info("zwave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node, descriptions[const.SERVICE_ADD_NODE]) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure, descriptions[const.SERVICE_ADD_NODE_SECURE]) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node, descriptions[const.SERVICE_REMOVE_NODE]) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command, descriptions[const.SERVICE_CANCEL_COMMAND]) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network, descriptions[const.SERVICE_HEAL_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset, descriptions[const.SERVICE_SOFT_RESET]) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network, descriptions[const.SERVICE_TEST_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_zwave, descriptions[const.SERVICE_STOP_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave, descriptions[const.SERVICE_START_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, descriptions[const.SERVICE_RENAME_NODE], schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, descriptions[ const.SERVICE_SET_CONFIG_PARAMETER], schema=SET_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_CONFIG_PARAMETER, print_config_parameter, descriptions[ const.SERVICE_PRINT_CONFIG_PARAMETER], schema=PRINT_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_CHANGE_ASSOCIATION, change_association, descriptions[ const.SERVICE_CHANGE_ASSOCIATION], schema=CHANGE_ASSOCIATION_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, descriptions[ const.SERVICE_SET_WAKEUP], schema=SET_WAKEUP_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_NODE, print_node, descriptions[ const.SERVICE_PRINT_NODE], schema=PRINT_NODE_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("ZWave network autoheal is enabled.") track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) return True
import time import six if six.PY3: from pydispatch import dispatcher else: from louie import dispatcher # Program options device = "/dev/ttyACM0" log = "None" sniff = 300.0 # manager options options = ZWaveOption(device, \ user_path="/home/pi/Embedded_OS/final/zwave_cfg/", cmd_line="") options.set_log_file("OZW_Log.log") options.set_append_log_file(False) options.set_console_output(False) options.set_save_log_level(log) options.set_logging(True) options.lock() # fill below with more useful things later def louie_network_started(network): print( "Hello from network : I'm started : homeid {:08x} - {} nodes were found." .format(network.home_id, network.nodes_count))
class TestApi(TestPyZWave): """ Parent test class for api """ @classmethod def setUpClass(self): super(TestApi, self).setUpClass() self.options = ZWaveOption(device=self.device, user_path=self.userpath) self.options.set_log_file("OZW_Log.log") self.options.set_append_log_file(False) self.options.set_console_output(self.ozwout) self.options.set_save_log_level(self.ozwlog) self.options.set_logging(True) self.options.lock() dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE) self.network = ZWaveNetwork(self.options) self.node_result = None self.ctrl_command_result = None self.ctrl_command_signal = None #dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND) time.sleep(1.0) @classmethod def tearDownClass(self): self.network.stop() time.sleep(2.0) self.network.destroy() time.sleep(1.0) super(TestApi, self).tearDownClass() self.network = None def setUp(self): self.node_result = None self.ctrl_command_result = None self.ctrl_command_signal = None self.wait_for_network_state(self.network.STATE_AWAKED, 1) time.sleep(1.0) self.wait_for_queue() self.active_nodes = {} for node in self.network.nodes: if self.network.nodes[node].is_info_received: self.active_nodes[node] = self.network.nodes[node] print('active nodes : %s' % self.active_nodes) def wait_for_queue(self): for i in range(0, 60): if self.network.controller.send_queue_count <= 0: break else: time.sleep(0.5) def wait_for_network_state(self, state, multiply=1): for i in range(0, SLEEP * multiply): if self.network.state >= state: break else: time.sleep(1.0) def ctrl_message( self, network, controller, node, node_id, state_int, state, state_full, error_int, error, error_full, ): self.ctrl_state_result = state self.ctrl_command_signal = { 'network': network, 'controller': controller, 'node': node, 'node_id': node_id, 'state_int': state_int, 'state': state, 'state_full': state_full, 'error_int': error_int, 'error': error, 'error_full': error_full, } def ctrl_waiting(self, network, controller, state_int, state, state_full): self.ctrl_state_result = state def node_update(self, network, node): self.node_result = node
def setup(hass, config): """Set up Z-Wave. Will automatically load components to support devices found on the network. """ descriptions = conf_util.load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) from pydispatch import dispatcher # pylint: disable=import-error from openzwave.option import ZWaveOption from openzwave.network import ZWaveNetwork from openzwave.group import ZWaveGroup # Load configuration use_debug = config[DOMAIN].get(CONF_DEBUG) autoheal = config[DOMAIN].get(CONF_AUTOHEAL) device_config = EntityValues( config[DOMAIN][CONF_DEVICE_CONFIG], config[DOMAIN][CONF_DEVICE_CONFIG_DOMAIN], config[DOMAIN][CONF_DEVICE_CONFIG_GLOB]) # Setup options options = ZWaveOption( config[DOMAIN].get(CONF_USB_STICK_PATH), user_path=hass.config.config_dir, config_path=config[DOMAIN].get(CONF_CONFIG_PATH)) options.set_console_output(use_debug) if CONF_NETWORK_KEY in config[DOMAIN]: options.addOption("NetworkKey", config[DOMAIN][CONF_NETWORK_KEY]) options.lock() network = hass.data[DATA_NETWORK] = ZWaveNetwork(options, autostart=False) hass.data[DATA_DEVICES] = {} hass.data[DATA_ENTITY_VALUES] = [] if use_debug: # pragma: no cover def log_all(signal, value=None): """Log all the signals.""" print("") print("SIGNAL *****", signal) if value and signal in (ZWaveNetwork.SIGNAL_VALUE_CHANGED, ZWaveNetwork.SIGNAL_VALUE_ADDED, ZWaveNetwork.SIGNAL_SCENE_EVENT, ZWaveNetwork.SIGNAL_NODE_EVENT, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED): pprint(_obj_to_dict(value)) print("") dispatcher.connect(log_all, weak=False) def value_added(node, value): """Handle new added value to a node on the network.""" # Check if this value should be tracked by an existing entity for values in hass.data[DATA_ENTITY_VALUES]: values.check_value(value) for schema in DISCOVERY_SCHEMAS: if not check_node_schema(node, schema): continue if not check_value_schema( value, schema[const.DISC_VALUES][const.DISC_PRIMARY]): continue values = ZWaveDeviceEntityValues( hass, schema, value, config, device_config) # We create a new list and update the reference here so that # the list can be safely iterated over in the main thread new_values = hass.data[DATA_ENTITY_VALUES] + [values] hass.data[DATA_ENTITY_VALUES] = new_values component = EntityComponent(_LOGGER, DOMAIN, hass) def node_added(node): """Handle a new node on the network.""" entity = ZWaveNodeEntity(node, network) node_config = device_config.get(entity.entity_id) if node_config.get(CONF_IGNORED): _LOGGER.info( "Ignoring node entity %s due to device settings", entity.entity_id) return component.add_entities([entity]) def scene_activated(node, scene_id): """Handle an activated scene on any node in the network.""" hass.bus.fire(const.EVENT_SCENE_ACTIVATED, { ATTR_ENTITY_ID: _node_object_id(node), const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_SCENE_ID: scene_id }) def node_event_activated(node, value): """Handle a nodeevent on any node in the network.""" hass.bus.fire(const.EVENT_NODE_EVENT, { const.ATTR_OBJECT_ID: _node_object_id(node), const.ATTR_BASIC_LEVEL: value }) def network_ready(): """Handle the query of all awake nodes.""" _LOGGER.info("Zwave network is ready for use. All awake nodes " "have been queried. Sleeping nodes will be " "queried when they awake.") hass.bus.fire(const.EVENT_NETWORK_READY) def network_complete(): """Handle the querying of all nodes on network.""" _LOGGER.info("Z-Wave network is complete. All nodes on the network " "have been queried") hass.bus.fire(const.EVENT_NETWORK_COMPLETE) dispatcher.connect( value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) dispatcher.connect( node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False) dispatcher.connect( scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) dispatcher.connect( node_event_activated, ZWaveNetwork.SIGNAL_NODE_EVENT, weak=False) dispatcher.connect( network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False) dispatcher.connect( network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False) def add_node(service): """Switch into inclusion mode.""" _LOGGER.info("Z-Wave add_node have been initialized") network.controller.add_node() def add_node_secure(service): """Switch into secure inclusion mode.""" _LOGGER.info("Z-Wave add_node_secure have been initialized") network.controller.add_node(True) def remove_node(service): """Switch into exclusion mode.""" _LOGGER.info("Z-Wwave remove_node have been initialized") network.controller.remove_node() def cancel_command(service): """Cancel a running controller command.""" _LOGGER.info("Cancel running Z-Wave command") network.controller.cancel_command() def heal_network(service): """Heal the network.""" _LOGGER.info("Z-Wave heal running") network.heal() def soft_reset(service): """Soft reset the controller.""" _LOGGER.info("Z-Wave soft_reset have been initialized") network.controller.soft_reset() def test_network(service): """Test the network by sending commands to all the nodes.""" _LOGGER.info("Z-Wave test_network have been initialized") network.test() def stop_network(_service_or_event): """Stop Z-Wave network.""" _LOGGER.info("Stopping Z-Wave network") network.stop() if hass.state == CoreState.running: hass.bus.fire(const.EVENT_NETWORK_STOP) def rename_node(service): """Rename a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] name = service.data.get(const.ATTR_NAME) node.name = name _LOGGER.info( "Renamed Z-Wave node %d to %s", node_id, name) def rename_value(service): """Rename a node value.""" node_id = service.data.get(const.ATTR_NODE_ID) value_id = service.data.get(const.ATTR_VALUE_ID) node = network.nodes[node_id] value = node.values[value_id] name = service.data.get(const.ATTR_NAME) value.label = name _LOGGER.info( "Renamed Z-Wave value (Node %d Value %d) to %s", node_id, value_id, name) def remove_failed_node(service): """Remove failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to remove zwave node %d", node_id) network.controller.remove_failed_node(node_id) def replace_failed_node(service): """Replace failed node.""" node_id = service.data.get(const.ATTR_NODE_ID) _LOGGER.info("Trying to replace zwave node %d", node_id) network.controller.replace_failed_node(node_id) def set_config_parameter(service): """Set a config parameter to a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) selection = service.data.get(const.ATTR_CONFIG_VALUE) size = service.data.get(const.ATTR_CONFIG_SIZE) for value in ( node.get_values(class_id=const.COMMAND_CLASS_CONFIGURATION) .values()): if value.index != param: continue if value.type in [const.TYPE_LIST, const.TYPE_BOOL]: value.data = selection _LOGGER.info("Setting config list parameter %s on Node %s " "with selection %s", param, node_id, selection) return else: value.data = int(selection) _LOGGER.info("Setting config parameter %s on Node %s " "with selection %s", param, node_id, selection) return node.set_config_param(param, selection, size) _LOGGER.info("Setting unknown config parameter %s on Node %s " "with selection %s", param, node_id, selection) def print_config_parameter(service): """Print a config parameter from a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] param = service.data.get(const.ATTR_CONFIG_PARAMETER) _LOGGER.info("Config parameter %s on Node %s: %s", param, node_id, get_config_value(node, param)) def print_node(service): """Print all information about z-wave node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] nice_print_node(node) def set_wakeup(service): """Set wake-up interval of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] value = service.data.get(const.ATTR_CONFIG_VALUE) if node.can_wake_up(): for value_id in node.get_values( class_id=const.COMMAND_CLASS_WAKE_UP): node.values[value_id].data = value _LOGGER.info("Node %s wake-up set to %d", node_id, value) else: _LOGGER.info("Node %s is not wakeable", node_id) def change_association(service): """Change an association in the zwave network.""" association_type = service.data.get(const.ATTR_ASSOCIATION) node_id = service.data.get(const.ATTR_NODE_ID) target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) group = service.data.get(const.ATTR_GROUP) instance = service.data.get(const.ATTR_INSTANCE) node = ZWaveGroup(group, network, node_id) if association_type == 'add': node.add_association(target_node_id, instance) _LOGGER.info("Adding association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) if association_type == 'remove': node.remove_association(target_node_id, instance) _LOGGER.info("Removing association for node:%s in group:%s " "target node:%s, instance=%s", node_id, group, target_node_id, instance) @asyncio.coroutine def async_refresh_entity(service): """Refresh values that specific entity depends on.""" entity_id = service.data.get(ATTR_ENTITY_ID) async_dispatcher_send( hass, SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id)) def refresh_node(service): """Refresh all node info.""" node_id = service.data.get(const.ATTR_NODE_ID) node = network.nodes[node_id] node.refresh_info() def reset_node_meters(service): """Reset meter counters of a node.""" node_id = service.data.get(const.ATTR_NODE_ID) instance = service.data.get(const.ATTR_INSTANCE) node = network.nodes[node_id] for value in ( node.get_values(class_id=const.COMMAND_CLASS_METER) .values()): if value.index != const.METER_RESET_INDEX: continue if value.instance != instance: continue network.manager.pressButton(value.value_id) network.manager.releaseButton(value.value_id) _LOGGER.info("Resetting meters on node %s instance %s....", node_id, instance) return _LOGGER.info("Node %s on instance %s does not have resettable " "meters.", node_id, instance) def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting Z-Wave network...") network.start() hass.bus.fire(const.EVENT_NETWORK_START) # Need to be in STATE_AWAKED before talking to nodes. # Wait up to NETWORK_READY_WAIT_SECS seconds for the zwave network # to be ready. for i in range(const.NETWORK_READY_WAIT_SECS): _LOGGER.debug( "network state: %d %s", network.state, network.state_str) if network.state >= network.STATE_AWAKED: _LOGGER.info("Z-Wave ready after %d seconds", i) break time.sleep(1) else: _LOGGER.warning( "zwave not ready after %d seconds, continuing anyway", const.NETWORK_READY_WAIT_SECS) _LOGGER.info( "final network state: %d %s", network.state, network.state_str) polling_interval = convert( config[DOMAIN].get(CONF_POLLING_INTERVAL), int) if polling_interval is not None: network.set_poll_interval(polling_interval, False) poll_interval = network.get_poll_interval() _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_network) # Register node services for Z-Wave network hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node, descriptions[const.SERVICE_ADD_NODE]) hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure, descriptions[const.SERVICE_ADD_NODE_SECURE]) hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node, descriptions[const.SERVICE_REMOVE_NODE]) hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command, descriptions[const.SERVICE_CANCEL_COMMAND]) hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network, descriptions[const.SERVICE_HEAL_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset, descriptions[const.SERVICE_SOFT_RESET]) hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network, descriptions[const.SERVICE_TEST_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network, descriptions[const.SERVICE_STOP_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave, descriptions[const.SERVICE_START_NETWORK]) hass.services.register(DOMAIN, const.SERVICE_RENAME_NODE, rename_node, descriptions[const.SERVICE_RENAME_NODE], schema=RENAME_NODE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RENAME_VALUE, rename_value, descriptions[const.SERVICE_RENAME_VALUE], schema=RENAME_VALUE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, set_config_parameter, descriptions[ const.SERVICE_SET_CONFIG_PARAMETER], schema=SET_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_CONFIG_PARAMETER, print_config_parameter, descriptions[ const.SERVICE_PRINT_CONFIG_PARAMETER], schema=PRINT_CONFIG_PARAMETER_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REMOVE_FAILED_NODE, remove_failed_node, descriptions[const.SERVICE_REMOVE_FAILED_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REPLACE_FAILED_NODE, replace_failed_node, descriptions[const.SERVICE_REPLACE_FAILED_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_CHANGE_ASSOCIATION, change_association, descriptions[ const.SERVICE_CHANGE_ASSOCIATION], schema=CHANGE_ASSOCIATION_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, descriptions[ const.SERVICE_SET_WAKEUP], schema=SET_WAKEUP_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_PRINT_NODE, print_node, descriptions[ const.SERVICE_PRINT_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_ENTITY, async_refresh_entity, descriptions[ const.SERVICE_REFRESH_ENTITY], schema=REFRESH_ENTITY_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_REFRESH_NODE, refresh_node, descriptions[ const.SERVICE_REFRESH_NODE], schema=NODE_SERVICE_SCHEMA) hass.services.register(DOMAIN, const.SERVICE_RESET_NODE_METERS, reset_node_meters, descriptions[ const.SERVICE_RESET_NODE_METERS], schema=RESET_NODE_METERS_SCHEMA) # Setup autoheal if autoheal: _LOGGER.info("Z-Wave network autoheal is enabled") track_time_change(hass, heal_network, hour=0, minute=0, second=0) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave) if 'frontend' in hass.config.components: register_built_in_panel(hass, 'zwave', 'Z-Wave', 'mdi:nfc') hass.http.register_view(api.ZWaveNodeValueView) hass.http.register_view(api.ZWaveNodeGroupView) hass.http.register_view(api.ZWaveNodeConfigView) hass.http.register_view(api.ZWaveUserCodeView) hass.http.register_static_path( URL_API_OZW_LOG, hass.config.path(OZW_LOG_FILENAME), False) return True
class ZStickInterface(object): def __init__(self): self.sensor_events = [] self.device = "/dev/ttyACM0" config_path = "plugins/python-openzwave/openzwave/config" user_path = "plugins/python-openzwave/config" # If using older Z-sticks, use the below device: # self.device = "/dev/ttyUSB0" # Change config paths where appropriate self.options = ZWaveOption(self.device, config_path=config_path, user_path=user_path, cmd_line="") # Turn off ozw console output self.options.set_console_output(False) self.options.set_save_log_level("Info") self.options.set_logging(False) self.options.lock() self.manager = libopenzwave.PyManager() self.manager.create() self.manager.addWatcher(self.event_callback) self.manager.addDriver(self.device) print("Starting Z-Wave Network...") self.network = ZWaveNetwork(self.options, log=None) # Wait for network to start while not self.network.state >= self.network.STATE_AWAKED: time.sleep(1) print("Z-Wave Network Started") def toggle_switch(self, node_id): try: in_work_node = self.network.nodes[node_id] switch_val = in_work_node.get_switches().keys()[0] if in_work_node.get_switch_state(switch_val): in_work_node.set_switch(switch_val, False) else: in_work_node.set_switch(switch_val, True) except: print("Invalid node id") def switch(self, node_id, state, function): try: in_work_node = self.network.nodes[node_id] if function == "dimmer": switch_val = in_work_node.get_dimmers().keys()[0] if state == "False": in_work_node.set_dimmer(switch_val, 0) elif state == "True": in_work_node.set_dimmer(switch_val, 99) else: in_work_node.set_dimmer(switch_val, int(state)) elif function == "switch": switch_val = in_work_node.get_switches().keys()[0] if state == "False": in_work_node.set_switch(switch_val, False) else: in_work_node.set_switch(switch_val, True) except: print("Invalid node id") def event_callback(self, args): if args["notificationType"] in ("ValueAdded", "ValueChanged"): cmd_class = args["valueId"]["commandClass"] if cmd_class == "COMMAND_CLASS_SENSOR_BINARY": node_id = args["valueId"]["nodeId"] state = args["valueId"]["value"] data = {"node_id": node_id, "state": state} self.sensor_events.append(data) def get_sensor_events(self): last_events = self.sensor_events self.sensor_events = [] return last_events def stop_network(self): self.network.stop()
else: assert False, "unhandled option" # Check command line if len(args) < 1: usage() device = args[0] # Open the communication with syslogd loglevel = syslog.LOG_PID if logstderr: loglevel |= syslog.LOG_PERROR syslog.openlog(NAME, loglevel, syslog.LOG_USER) # Define some manager options and create a network object options = ZWaveOption(device, config_path = "./openzwave/config", user_path = ".", cmd_line = "") options.set_log_file(NAME + ".log") options.set_append_log_file(False) #options.set_console_output(True) options.set_console_output(False) options.set_save_log_level(log) options.set_logging(True) options.lock() network = ZWaveNetwork(options, log = None) # Add the basic callbacks dispatcher.connect(louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED) dispatcher.connect(louie_network_resetted, ZWaveNetwork.SIGNAL_NETWORK_RESETTED) dispatcher.connect(louie_network_ready,