예제 #1
0
class HomeManager(object):
    def __init__(self, device_path, ozw_log_level, logger):
        self.logger = logger

        options = ZWaveOption(device_path,
                              config_path="./venv/lib/python3.6/site-packages/python_openzwave/ozw_config",
                              user_path=".", cmd_line="")
        options.set_log_file("OZW.log")
        options.set_append_log_file(False)
        options.set_save_log_level(ozw_log_level)
        options.set_console_output(False)
        options.set_logging(True)
        options.lock()
        self.options = options
        self.network = ZWaveNetwork(options, log=None, autostart=False)
        self.client = InfluxDBClient(database=DATABASE)

    def start(self):
        self.logger.info("Starting network...")
        self.network.start()

    def stop_signal(self, signum, frame):
        self.stop()

    def stop(self):
        self.logger.info("Stopping network...")
        self.network.nodes[3].values[72057594098484979].data = 3600
        self.network.stop()
        self.logger.info("Stopped")

    def connect_signals(self):
        dispatcher.connect(self.signal_network_ready, self.network.SIGNAL_NETWORK_READY)
        signal.signal(signal.SIGINT, self.stop_signal)

    # Note -- the name of the network parameter must not change!
    def signal_network_ready(self, network):
        if self.network is not network:
            return
        else:
            del network
        ozw_debug(self.logger, self.network)
        self.logger.info("Network is ready!")
        self.network.nodes[3].values[72057594098484979].data = 15
        self.start_polling()


    @staticmethod
    def is_sensor(node):
        return isinstance(node, ZWaveNodeSensor) and not len(node.get_sensors()) is 0

    def start_polling(self):
        Timer(TIME_INTERVAL, self.start_polling).start()
        labels_to_be_polled = {'Luminance', 'Relative Humidity', 'Temperature', 'Ultraviolet', 'Alarm Level', 'Burglar'}
        for node_id, node in self.network.nodes.items():
            if self.is_sensor(node):
                for val_id in self.network.nodes[node_id].values:
                    val = self.network.nodes[node_id].values[val_id]
                    if val.label in labels_to_be_polled:
                        self.logger.info("Received value refresh %s: %s", val.id_on_network, val)
                        self.client.write_points(value_refresh_to_influxdb_json(node, val))
예제 #2
0
def createNetwork(options, log=None, autostart=True, kvals=True):
    network = ZWaveNetwork(options, log=None)
    time_started = 0
    for i in range(0, 100):
        if network.state >= network.STATE_AWAKED:
            break
        else:
            time_started += 1
            time.sleep(1.0)
    if network.state < network.STATE_AWAKED:
        print("Network is not awake but continue anyway")

    for i in range(0, 300):
        if network.state >= network.STATE_READY:
            print("home ID {}".format(home_id))
            break
        else:
            sys.stdout.write(".")
            time_started += 1
            #sys.stdout.write(network.state_str)
            #sys.stdout.write("(")
            #sys.stdout.write(str(network.nodes_count))
            #sys.stdout.write(")")
            #sys.stdout.write(".")
            sys.stdout.flush()
            time.sleep(1.0)

    if not network.is_ready:
        print("network is not ready but start anyway")
    network.start()
    return network
예제 #3
0
  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
예제 #4
0
파일: home.py 프로젝트: cslarsen/home-zwave
def main():
  global LIGHT, PUSHOVER

  logging.basicConfig(level=logging.INFO,
    format="%(asctime)-15s %(levelno)d %(message)s")

  # TODO: Put in argparse
  device = None
  if device is None:
    device = discover_device()
  check_device(device)

  CONFIG = read_config("config.json")
  if CONFIG.pushover.apikey is not None:
    logging.info("Setting up Pushover")
    PUSHOVER = Pushover(CONFIG.pushover.apikey, CONFIG.pushover.userkeys)

  connect_signals()

  options = create_zwave_options(device=device)
  network = ZWaveNetwork(options, log=None, autostart=False)

  queue = threading.Thread(target=DataQueue.worker,
      kwargs={"location": "home.db"},
      name="db")
  queue.start()

  try:
    network.start()

    # Start REPL with a union where globals override locals
    local = locals().copy()
    local.update(globals())
    code.interact(local=local)
  except KeyboardInterrupt:
    pass
  finally:
    logging.info("\nStopping network ...")
    network.stop()

    logging.info("Stopping data queue ...")
    DataQueue.stop()
    queue.join()
예제 #5
0
파일: home.py 프로젝트: cslarsen/home-zwave
def main():
    global LIGHT, PUSHOVER

    logging.basicConfig(level=logging.INFO,
                        format="%(asctime)-15s %(levelno)d %(message)s")

    # TODO: Put in argparse
    device = None
    if device is None:
        device = discover_device()
    check_device(device)

    CONFIG = read_config("config.json")
    if CONFIG.pushover.apikey is not None:
        logging.info("Setting up Pushover")
        PUSHOVER = Pushover(CONFIG.pushover.apikey, CONFIG.pushover.userkeys)

    connect_signals()

    options = create_zwave_options(device=device)
    network = ZWaveNetwork(options, log=None, autostart=False)

    queue = threading.Thread(target=DataQueue.worker,
                             kwargs={"location": "home.db"},
                             name="db")
    queue.start()

    try:
        network.start()

        # Start REPL with a union where globals override locals
        local = locals().copy()
        local.update(globals())
        code.interact(local=local)
    except KeyboardInterrupt:
        pass
    finally:
        logging.info("\nStopping network ...")
        network.stop()

        logging.info("Stopping data queue ...")
        DataQueue.stop()
        queue.join()
예제 #6
0
class Backend():

    def __init__(self):

	###################  instanciation de l'objet backend ########################################################


	###### options needed for python openzwave library like config files path, logging, 
        device = configpi.interface
        options = ZWaveOption(device, config_path="/home/pi/git-repo/python-openzwave/openzwave/config", user_path=".", cmd_line="")
        options.set_log_file("OZW.log")
        options.set_append_log_file(False)
        options.set_console_output(False)
        options.set_save_log_level('Warning')
        options.set_logging(True)
        options.lock()

        # creation of the object network using the options entity already created
        self.network = ZWaveNetwork(options, autostart=False)

	###### 	 These dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
	######   Once the signal is reveived. It's associated method is executed (see "_node_added" example below in "_network_started" method)
        dispatcher.connect(self._network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
        dispatcher.connect(self._network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)
        dispatcher.connect(self._network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)

	###### backend object attributes
#        self.devices = OrderedDict()  ### will contain the list of nodes in the network
#        self.sensors = OrderedDict()  ### will contain the list of sensors (only) in the network
        self.node_added = False
        self.node_removed = False
	self.timestamps = {}	      ### will contain the time of the last values' update for each sensor
        self.queryStages = {	      ### the diffrent stages that a node object gets through before being ready 
                "None"                  :  1, # Query process hasn't started for this node
                "ProtocolInfo"          :  2, # Retrieve protocol information
                "Probe"                 :  3, # Ping device 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
                "SecurityReport"        :  7, # Retrieve a list of Command Classes that require Security
                "ManufacturerSpecific2" :  8, # Retrieve manufacturer name and product ids
                "Versions"              :  9, # Retrieve version information
                "Instances"             : 10, # Retrieve information about multiple command class instances
                "Static"                : 11, # Retrieve static information (doesn't change)
                "Probe1"                : 12, # Ping a device upon starting with configuration
                "Associations"          : 13, # Retrieve information about associations
                "Neighbors"             : 14, # Retrieve node neighbor list
                "Session"               : 15, # Retrieve session information (changes infrequently)
                "Dynamic"               : 16, # Retrieve dynamic information (changes frequently)
                "Configuration"         : 17, # Retrieve configurable parameter information (only done on request)
                "Complete"              : 18  # Query process is completed for this node
        }

#######################################################################################################################
############# NETWORK #################################################################################################
#######################################################################################################################

    def _network_started(self, network):

	# executed once the software representation is started. the discovery of the network components has begun. they will be mapped into objects

        print("network started - %d nodes were found." % network.nodes_count)

	# these dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
	# a signal may contain a number of parameters that are passed to the method associated to the signal.
	# for exemple, the dispatcher below associates the signal "SIGNAL_NODE_ADDED" to the method "_node_added" that is implemented below (line 111).
	# the signal "SIGNAL_NODE_ADDED" transports two parameters which are the objects network and node.
	# once this signal is received, these two parameters will be passed to the method "_node_added" and the method will be executed.

        dispatcher.connect(self._node_added, ZWaveNetwork.SIGNAL_NODE_ADDED)
        dispatcher.connect(self._node_removed, ZWaveNetwork.SIGNAL_NODE_REMOVED)
        dispatcher.connect(self._debug_node_naming, ZWaveNetwork.SIGNAL_NODE_NAMING)
        dispatcher.connect(self._debug_node_new, ZWaveNetwork.SIGNAL_NODE_NEW)
        dispatcher.connect(self._debug_node_protocol_info, ZWaveNetwork.SIGNAL_NODE_PROTOCOL_INFO)
        
    def _network_failed(self, network):

	# executed once the software representation has failed

        print("network failed :(")

    def _network_ready(self, network):

	# executed once the software representation is ready

        print("network : ready : %d nodes were found." % network.nodes_count)
        print("network : controller is : %s" % network.controller)
#        dispatcher.connect(self._node_update, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(self._node_event, ZWaveNetwork.SIGNAL_NODE_EVENT)
        dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)

    def _node_added(self, network, node):

	# executed when node is added to the software representation. it's executed after the method "_debug_node_new" (see below)

        print('node added: %s.' % node.node_id)
	self.timestamps["timestamp" + str(node.node_id)] = "No Measurement received yet"
        self.node_added = True

    def _node_removed(self, network, node):

	# executed when node is removed from the software representation

        print('node removed: %s.' % node.name)
        self.node_removed = True
        
    def _debug_node_naming(self, network, node):

	# executed when node is named

        print('node %s named: %s.' % (node.node_id, node.name))

    def _debug_node_new(self, network, node_id):

	# executed when a new node is detected in the network

        print('New node is node: %s.' % node_id)

    def _debug_node_protocol_info(self, network, node):

	# executed when discovering the features of a new node 

        print('node Protocol Info: %s.' % node.node_id)which

    def _node_update(self, network, node):

	# executed when the nodes features are received : product_name, manufacturer_id, ...
        print('node update: %s.' % node)

    def _node_event(self, network, node, signal, sender):

	# executed when the motion sensor's state is changed 

        print('node event %s from node %s.' % (signal, node.node_id))
        if node.isReady and node.product_name == "MultiSensor 6":
            values = node.get_values("All","User","All",True,"All")
            for value in values.itervalues():
                if value.label == "Sensor":
                    motion_value = value.data

        print('motion sensor value is now %s' %motion_value)

    def _value_update(self, network, node, value):

	# executed when a new value from a node is received

        print('Node %s: value update: %s is %s.' % (node.node_id, value.label, value.data))
        self.timestamps["timestamp" + str(node.node_id)] = int(time.time())
        

    def ordered_nodes_dict(self):

	#this method returns an ordered list of the network's nodes

        return OrderedDict(sorted(self.network.nodes.items()))


################################################################################################################
######################## START AND STOP THE SOFTWARE REPRESENTATION ############################################
################################################################################################################

    def start(self):

	# this method starts the software representation
        global started


        if started:
            print "Already started"
            return 
        started = True
        self.network.start()
        print "Z-Wave Network Starting..."
        for i in range(0, 300):
            if self.network.is_ready:
                break
            else:
                time.sleep(1.0)
        if not self.network.is_ready:
            print "Network is not ready but continue anyway"
        print "------------------------------------------------------------"
        print "Nodes in network : %s" % self.network.nodes_count
        print "------------------------------------------------------------"
            
    def stop(self):

	# this method stops the software representation

        global started
	started = False
        print "Stopping Z-Wave Network... "
        self.network.stop()
        
    def reset(self):
        
	# this method resets the controller node 
        self.network.controller.hard_reset()
        return "Hard Reset Done"








#########################################################################################################################
############## YOUR WORK STARTS HERE ####################################################################################
#########################################################################################################################
#########################################################################################################################







        
        
    def network_preview(self):

        #### COMPLETE THIS METHOD ##############

        return "this method returns a JSON that lists all network nodes and gives some informations about each one of them like the ID, neighbors, ..."




###########################################################################################################################
########## Configuration of multisensors ##################################################################################
###########################################################################################################################

    def set_sensor(self, Grp_interval, Grp_reports, Wakeup_interval):

        #### COMPLETE THIS METHOD ##############

        return "this method configures the nodes whit a specific configuration set by us"

    def network_nodesConfiguration(self):

        #### COMPLETE THIS METHOD ##############

	return "this method returns a html containing the configuration of the network's nodes"


    def set_node_config_param(self, n, param, value):

        #### COMPLETE THIS METHOD ##############

	return "this method sets a configuration parameter to a precise value"


    def get_node_config_param(self, n, param):

        #### COMPLETE THIS METHOD ##############

	 return "this method gets the value of a configuration parameter"




#######################################################################################################################
############# SENSORS #################################################################################################
#######################################################################################################################        

    def get_sensors(self):

        #### COMPLETE THIS METHOD ##############

	return "this method returns the list of sensors"


    def addNode(self):

        #### COMPLETE THIS METHOD ##############

	return "this method passes the controller to inclusion mode and gets it out of it after 20 seconds "




    def removeNode(self):

        #### COMPLETE THIS METHOD ##############

	return "this method passes the controller to exclusion mode and gets it out of it after 20 seconds "



    def allMeasures(self, n):

        #### COMPLETE THIS METHOD ##############

        return "this method gets all the measures of a specific sensor node"

        
    def temperature(self, n):

        #### HERE'S AN EXAMPLE OF A METHOD THAT GETS THE TEMPERATURE OF A SPECIFIC SENSOR NODE ##############
        
        for node in self.network.nodes.itervalues():
            if node.node_id == n and node.isReady and n != 1 :
                values = node.get_values(0x31, "User", "All", True, False)
                for value in values.itervalues():
                    if value.label == "Temperature":
                        val = round(value.data,1)
                        return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
        return "Node not ready or wrong sensor node !"						

    def humidity(self, n):

         #### HERE'S AN EXAMPLE OF A METHOD THAT GETS THE HUMIDITY OF A SPECIFIC SENSOR NODE ##############
        
        for node in self.network.nodes.itervalues():
            if node.node_id == n and node.isReady and n != 1 :
                values = node.get_values(0x31, "User", "All", True, False)
                for value in values.itervalues():
                    if value.label == "Relative Humidity":
                        val = int(value.data)
                        return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
        return "Node not ready or wrong sensor node !"

    def luminance(self, n):
		for node in self.network.nodes.itervalues():
            if node.node_id == n and node.isReady and n != 1 :
                values = node.get_values(0x31, "User", "All", True, False)
                for value in values.itervalues():
                    if value.label == "Luminance":
                        val = int(value.data)
                        return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
        return "Node not ready or wrong sensor node !"


    def motion(self, n):
		for node in self.network.nodes.itervalues():
            if node.node_id == n and node.isReady and n != 1 :
                values = node.get_values(0x31, "User", "All", True, False)
                for value in values.itervalues():
                    if value.label == "Motion":
                        val = int(value.data)
                        return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
        return "Node not ready or wrong sensor node !"


    def battery(self, n):
		for node in self.network.nodes.itervalues():
            if node.node_id == n and node.isReady and n != 1 :
                values = node.get_values(0x31, "User", "All", True, False)
                for value in values.itervalues():
                    if value.label == "Battery":
                        val = int(value.data)
                        return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
        return "Node not ready or wrong sensor node !"
    
    def get_nodes(self):

        #### COMPLETE THIS METHOD ##############

	return "this method returns the list of nodes "


    def set_node_location(self, n, value):

        #### COMPLETE THIS METHOD ##############
        
        return " this method sets the location of a specific sensor node"


    def set_node_name(self, n, value):

        #### COMPLETE THIS METHOD ##############
        
        return "this method sets the name of a specific sensor node"


    def get_node_location(self, n):

        #### COMPLETE THIS METHOD ##############
        
        return "this method gets the location of a specific sensor node"


    def get_node_name(self, n):

        #### COMPLETE THIS METHOD ##############
        
        return "this method gets the name of a specific sensor node"


    def get_neighbors(self, n):

        #### COMPLETE THIS METHOD ##############
        
        return "this method gets the list of neighbours of a specific sensor node"
class HomeManager(object):
    def __init__(self, device_path, ozw_log_level, logger):
        self.logger = logger

        options = ZWaveOption(
            device_path,
            config_path=
            "./venv/lib/python3.%d/site-packages/python_openzwave/ozw_config" %
            sys.version_info[1],
            user_path=".",
            cmd_line="")
        options.set_log_file("OZW.log")
        options.set_append_log_file(False)
        options.set_save_log_level(ozw_log_level)
        options.set_console_output(False)
        options.set_logging(True)
        options.lock()
        self.options = options
        self.network = ZWaveNetwork(options, log=None, autostart=False)
        self.csvfile = open('output.csv', 'a')
        self.writer = csv.writer(self.csvfile)
        self.stopping = False

    def start(self):
        self.logger.info("Starting network...")
        self.network.start()

    def stop_signal(self, signum, frame):
        self.stop()

    def stop(self):
        if self.stopping:
            return
        else:
            self.stopping = True
        self.logger.info("Stopping network...")
        self.network.stop()
        self.csvfile.close()
        self.logger.info("Stopped")

    def connect_signals(self):
        dispatcher.connect(self.signal_network_ready,
                           self.network.SIGNAL_NETWORK_READY)
        signal.signal(signal.SIGINT, self.stop_signal)

    # Note -- the name of the network parameter must not change!
    def signal_network_ready(self, network):
        if self.network is not network:
            return
        else:
            del network
        ozw_debug(self.logger, self.network)
        self.logger.info("Network is ready!")
        dispatcher.connect(self.signal_node_update, self.network.SIGNAL_NODE)
        dispatcher.connect(self.signal_value_refreshed,
                           self.network.SIGNAL_VALUE)

    # Note -- the names of the network/node/value parameters must not change!
    def signal_value_refreshed(self, network, node, value):
        if self.network is not network:
            return
        else:
            del network
        self.logger.info("Received value refresh %s: %s", value.id_on_network,
                         value)
        self.writer.writerow(value_refresh_to_csv(node, value))
        self.csvfile.flush()

    # Note -- the names of the network/node parameters must not change!
    def signal_node_update(self, network, node):
        return

    @staticmethod
    def is_sensor(node):
        return isinstance(node,
                          ZWaveNodeSensor) and not len(node.get_sensors()) is 0
예제 #8
0
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)
예제 #9
0
class ZWave(SmartPlugin):
    """
    Main class of the Plugin. Does all plugin specific stuff and provides
    the update functions for the items
    """

    PLUGIN_VERSION = '1.4.2'

    def __init__(self, sh):
        """
        Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf.

        :param sh:  **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**!
        :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**!
        :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**!

        If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for
        a reference to the sh object any more.

        The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented
        to support older plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values:
        use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get
        the configured (and checked) value for a parameter by calling `self.get_parameter_value(parameter_name)`. It
        returns the value in the datatype that is defined in the metadata.
        """

        if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
            self.logger = logging.getLogger(__name__)

        try:
            self._sh = sh
            self.listenOn = {}
            self._device = self.get_parameter_value('device')
            self._config_path = self.get_parameter_value('config_path')
            self._logging = self.get_parameter_value('zlogging')
            logfile = self.get_parameter_value('loglevel')
            try:
                self._logfile = '{}/log/{}'.format(self.get_vardir(), logfile)
            except Exception:
                self._logfile = '{}/var/log/{}'.format(self._sh.get_basedir(),
                                                       logfile)
            self._loglevel = self.get_parameter_value('loglevel')
            self._sec_strategy = self.get_parameter_value('sec_strategy')
            self._ready = False
            self.logger.debug(
                'Initialized: logpath={}, loglevel={}, configpath={}, device={}, sec_strategy={}'
                .format(self._logfile, self._loglevel, self._config_path,
                        self._device, self._sec_strategy))
        except Exception as err:
            self.logger.error(err)
            self._init_complete = False
            return

        if not REQUIRED_PACKAGE_IMPORTED:
            self.logger.warning("Unable to import Python package 'openzwave'")
            self._init_complete = False

    def run(self):
        """
        Run method for the plugin
        """
        self.logger.debug('run method called')
        self.alive = True

        try:
            options = ZWaveOption(self._device,
                                  config_path=self._config_path,
                                  user_path='./var/ozw',
                                  cmd_line='')
        except Exception as e:
            self.logger.error('error on create ZWaveOption - {}'.format(e))
            self.alive = False
            return

        try:
            options.set_log_file(self._logfile)
            options.set_save_log_level(self._loglevel)
            options.set_logging(self._logging)
            options.set_append_log_file(False)
            options.set_console_output(False)
            options.set_security_strategy(self._sec_strategy)
            options.lock()
        except Exception as e:
            self.logger.error('error on option.set_* - {}'.format(e))

        self.logger.debug('run -> create network')
        try:
            self._network = ZWaveNetwork(options, autostart=False)
        except Exception as e:
            self.logger.error('error on create Network Object - {}'.format(e))

        self.logger.debug('run -> connect event handler')
        try:
            dispatcher.connect(self.zwave_value_update,
                               ZWaveNetwork.SIGNAL_VALUE_CHANGED)
        except Exception as e:
            self.logger.error('error on connect event handler - {}'.format(e))

        self.logger.debug('run -> start network')
        try:
            self._network.start()
        except Exception as e:
            self.alive = False
            self.logger.error('error on start network - {}'.format(e))

        self.logger.info('use openzwave library: {}'.format(
            self._network.controller.ozw_library_version))
        self.logger.info('use python library: {}'.format(
            self._network.controller.python_library_version))
        self.logger.info('use ZWave library: {}'.format(
            self._network.controller.library_description))

        while self.alive:

            if self._network.state != self._network.STATE_READY:

                self.logger.debug(
                    'wait until network is ready... current state is: {}'.
                    format(self._network.state_str))
                if self._network.state == self._network.STATE_FAILED:
                    self.alive = False
                    return

            # Dump network information on STATE_READY
            if self._network.state == self._network.STATE_READY and self._ready is False:
                self.logger.info(
                    'controller ready : {} nodes were found.'.format(
                        self._network.nodes_count))
                self.logger.info('controller node id : {}'.format(
                    self._network.controller.node.node_id))
                self.logger.info('controller node version : {}'.format(
                    self._network.controller.node.version))
                self.logger.info('Network home id : {}'.format(
                    self._network.home_id_str))
                self.logger.info('Nodes in network : {}'.format(
                    self._network.nodes_count))

                self.logger.info("zwave: Start refresh values")
                for __id in self.listenOn:
                    __val = self._network.get_value(__id)
                    self.logger.info("zwave: id : '{}', val: '{}'".format(
                        __id, __val))
                    for __item in self.listenOn[__id][ITEMS]:
                        __item(__val.data, 'ZWave')

                self._ready = True

            time.sleep(3.0)

    def stop(self):
        """
        Stop method for the plugin
        """
        self.logger.debug("zwave: stop method called")
        self._network.stop()
        self.alive = False

    def parse_item(self, item):
        """
        Default plugin parse_item method. Is called when the plugin is initialized.
        The plugin can, corresponding to its attribute keywords, decide what to do with
        the item in future, like adding it to an internal array for future reference
        :param item:    The item to process.
        :return:        If the plugin needs to be informed of an items change you should return a call back function
                        like the function update_item down below. An example when this is needed is the knx plugin
                        where parse_item returns the update_item function when the attribute knx_send is found.
                        This means that when the items value is about to be updated, the call back function is called
                        with the item, caller, source and dest as arguments and in case of the knx plugin the value
                        can be sent to the knx with a knx write function within the knx plugin.
        """
        if self.has_iattr(item.conf, 'zwave_node') and self.has_iattr(
                item.conf, 'zwave_value'):
            node_id = int(
                self.get_iattr_value(item.conf, 'zwave_node').strip())
            value_id = int(
                self.get_iattr_value(item.conf, 'zwave_value').strip())
            self.logger.debug('connecting item {} to node {} value {}'.format(
                item, node_id, value_id))
            if value_id not in self.listenOn:
                self.listenOn[value_id] = {
                    NID: node_id,
                    ITEMS: [item],
                    LOGICS: []
                }
            elif item not in self.listenOn[value_id][ITEMS]:
                self.listenOn[value_id][ITEMS].append(item)
            return self.update_item

    def parse_logic(self, logic):
        """
        Default plugin parse_logic method
        """
        if 'xxx' in logic.conf:
            # self.function(logic['name'])
            pass

    def update_item(self, item, caller=None, source=None, dest=None):
        """
        Write items values
        :param item: item to be updated towards the plugin
        :param caller: if given it represents the callers name
        :param source: if given it represents the source
        :param dest: if given it represents the dest
        """
        if self.has_iattr(item.conf, 'zwave_node') and self.has_iattr(
                item.conf, 'zwave_value'):
            self.logger.debug(
                "zwave: update_item was called with item '{}' from caller '{}', source '{}' and dest '{}'"
                .format(item, caller, source, dest))
            self.logger.debug(
                "zwave: item value is '{}' from type '{}'".format(
                    item(), type(item())))
        try:
            self._network._manager.setValue(int(item.conf['zwave_value']),
                                            item())
        except Exception as e:
            self.logger.error('update_item error - {}'.format(e))

    def zwave_value_update(self, network, node, value):
        """
        Dispatcher to Trigger Item Updates
        :param network: the network object
        :param node: the node object which is updated
        :param value: the value object which is updated
        """
        value_id = value.value_id
        self.logger.debug(
            'zwave_value_update called for value_id={} and value={}'.format(
                value_id, value.data))
        self.logger.debug('self.listenOn={}'.format(self.listenOn))
        if value_id in self.listenOn:
            if self.listenOn[value_id][ITEMS] is not None:
                for item in self.listenOn[value_id][ITEMS]:
                    try:
                        item(value.data, 'ZWave')
                    except Exception as e:
                        self.logger.error(
                            'zwave_value_update error - {}'.format(e))
            else:
                self.logger.debug('listener found, but no items bound')
        else:
            self.logger.debug('no listener defined')
예제 #10
0
class ZWaveDevice(DeviceLifetimeCycles):
    @typechecked()
    def __init__(self, zwave_config: ZwaveCommunicationCfg,
                 root_logger: RootLogger) -> None:
        self.__zwave_config = zwave_config
        self.__root_logger = root_logger
        self.__network = None
        self.__state_change_callback = None

    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 disconnect(self) -> None:
        self.__root_logger.info('Disconnectiong Zwave device')
        self.__network.stop()

    @typechecked()
    def attach_state_change_callback(self, callback: Callable[[str, Any],
                                                              None]):
        self.__state_change_callback = callback

    @typechecked()
    def change_switch(self, actuator_name: str, state: bool) -> bool:
        node, val = self.__get_node(actuator_name, 'switch')
        try:
            node.set_switch(val, state)
        except Exception as e:
            return False
        return True

    @typechecked()
    def change_dimmer(self, actuator_name: str, state: int) -> bool:
        try:
            node, val = self.__get_node(actuator_name, 'dimmer')
            node.set_dimmer(val, state)
        except Exception as e:
            return False
        return True

    @typechecked()
    def __get_node(self, actuator_name: str, type: str):
        for node in self.__network.nodes:
            for val in self.__get_device_by_type(self.__network.nodes[node],
                                                 type):
                self.__root_logger.info('Zwave node: {0}'.format(
                    self.__network.nodes[node].values[val].id_on_network))
                if self.__network.nodes[node].values[
                        val].id_on_network != actuator_name:
                    continue
                self.__root_logger.info(
                    'Changing zwave switch: {0}'.format(actuator_name))
                return self.__network.nodes[node], val

        raise Exception(
            'Zwave node with id {0} not found'.format(actuator_name))

    @typechecked()
    def __get_device_by_type(self, node, type: str):
        if type == 'switch':
            return node.get_switches()
        elif type == 'dimmer':
            return node.get_dimmers()

    def __network_failed(self, network):
        self.__root_logger.info('Zwave network failed loading')

    def __network_ready(self, network):
        self.__root_logger.info(
            'Zwave network ready, contoller name: {0}'.format(
                network.controller))

    def __value_update(self, network, node, value):
        self.__root_logger.info('Id {0} for value: {1}'.format(
            value.id_on_network, value.data))
        if None is self.__state_change_callback:
            return
        self.__state_change_callback(value.id_on_network, value.data)
예제 #11
0

def louie_value_update(network, node, value):
    print("Hello from value : {}.".format(value))


#Create a network object
network = ZWaveNetwork(options, autostart=False)

# We connect to the louie dispatcher
dispatcher.connect(louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
dispatcher.connect(louie_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)
dispatcher.connect(louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)

# Start the network
network.start()

# Wait for network
print("***** Waiting for network to become ready : ")
for i in range(0, 90):
    if network.state >= network.STATE_READY:
        print("***** Network is ready")
        break
    else:
        sys.stdout.write(".")
        sys.stdout.flush()
        time.sleep(1.0)

time.sleep(5.0)

####################################
예제 #12
0
class Backend():
    def __init__(self):

        ###################  instanciation de l'objet backend ########################################################

        ###### options needed for python openzwave library like config files path, logging,
        device = configpi.interface
        options = ZWaveOption(
            device,
            config_path="/home/pi/IoTLab/python-openzwave/openzwave/config",
            user_path=".",
            cmd_line="")
        #options = ZWaveOption(device, config_path="/home/iosis/IoTLab/python-openzwave/openzwave/config", user_path=".", cmd_line="")
        options.set_log_file("OZW.log")
        options.set_append_log_file(False)
        options.set_console_output(False)
        options.set_save_log_level('Warning')
        options.set_logging(True)
        options.lock()

        # creation of the object network using the options entity already created
        self.network = ZWaveNetwork(options, autostart=False)

        ###### 	 These dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
        ######   Once the signal is received. It's associated method 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)

        ###### backend object attributes
        #        self.devices = OrderedDict()  ### will contain the list of nodes in the network
        #        self.sensors = OrderedDict()  ### will contain the list of sensors (only) in the network
        self.node_added = False
        self.node_removed = False
        self.timestamps = {
        }  ### will contain the time of the last values' update for each sensor
        self.queryStages = {  ### the diffrent stages that a node object gets through before being ready
            "None": 1,  # Query process hasn't started for this node
            "ProtocolInfo": 2,  # Retrieve protocol information
            "Probe": 3,  # Ping device 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
            "SecurityReport":
            7,  # Retrieve a list of Command Classes that require Security
            "ManufacturerSpecific2":
            8,  # Retrieve manufacturer name and product ids
            "Versions": 9,  # Retrieve version information
            "Instances":
            10,  # Retrieve information about multiple command class instances
            "Static": 11,  # Retrieve static information (doesn't change)
            "Probe1": 12,  # Ping a device upon starting with configuration
            "Associations": 13,  # Retrieve information about associations
            "Neighbors": 14,  # Retrieve node neighbor list
            "Session":
            15,  # Retrieve session information (changes infrequently)
            "Dynamic": 16,  # Retrieve dynamic information (changes frequently)
            "Configuration":
            17,  # Retrieve configurable parameter information (only done on request)
            "Complete": 18  # Query process is completed for this node
        }

#######################################################################################################################
############# LAUNCH  #################################################################################################
#######################################################################################################################

    def _network_started(self, network):

        # executed once the software representation is started. the discovery of the network components has begun. they will be mapped into objects

        print("network started - %d nodes were found." % network.nodes_count)

        # these dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
        # a signal may contain a number of parameters that are passed to the method associated to the signal.
        # for exemple, the dispatcher below associates the signal "SIGNAL_NODE_ADDED" to the method "_node_added" that is implemented below (line 111).
        # the signal "SIGNAL_NODE_ADDED" transports two parameters which are the objects network and node.
        # once this signal is received, these two parameters will be passed to the method "_node_added" and the method will be executed.

        dispatcher.connect(self._node_added, ZWaveNetwork.SIGNAL_NODE_ADDED)
        dispatcher.connect(self._node_removed,
                           ZWaveNetwork.SIGNAL_NODE_REMOVED)

    def _network_ready(self, network):

        # executed once the software representation is ready

        print("network : ready : %d nodes were found." % network.nodes_count)
        print("network : controller is : %s" % network.controller)
        dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)

    def _node_added(self, network, node):

        # executed when node is added to the software representation. it's executed after the method "_debug_node_new" (see below)

        print('node added: %s.' % node.node_id)
        self.timestamps["timestamp" + str(node.node_id)] = "None"
        self.node_added = True

    def _node_removed(self, network, node):

        # executed when node is removed from the software representation

        print('node removed: %s.' % node.name)
        self.node_removed = True

    def _value_update(self, network, node, value):

        # executed when a new value from a node is received

        print('Node %s: value update: %s is %s.' %
              (node.node_id, value.label, value.data))
        self.timestamps["timestamp" + str(node.node_id)] = int(time.time())

################################################################################################################
######################## START AND STOP THE SOFTWARE REPRESENTATION ############################################
################################################################################################################

    def start(self):

        # this method starts the software representation
        global started

        if started:
            print "Already started"
            return
        started = True
        self.network.start()
        print "Z-Wave Network Starting..."
        for i in range(0, 300):
            if self.network.state == self.network.STATE_READY:
                break
            else:
                time.sleep(1.0)
        if not self.network.is_ready:
            print "Network is not ready but continue anyway"
        print "------------------------------------------------------------"
        print "Nodes in network : %s" % self.network.nodes_count
        print "------------------------------------------------------------"

    def stop(self):

        # this method stops the software representation

        global started
        started = False
        print "Stopping Z-Wave Network... "
        self.network.stop()

    def reset(self):
        if self.network.nodes_count == 1:
            self.network.controller.hard_reset()
            return "Hard Reset Done"
        return "Cannot make Hard Reset while nodes included in network"

#########################################################################################################################
############## YOUR WORK STARTS HERE ####################################################################################
#########################################################################################################################
#########################################################################################################################

#######################################################################################################################
############# NETWORK #################################################################################################
#######################################################################################################################

    def network_info(self):

        #### COMPLETE THIS METHOD ##############

        return "this method returns a JSON that lists all network nodes and gives some informations about each one of them like the ID, neighbors, ..."

#######################################################################################################################
############# NODES #################################################################################################
#######################################################################################################################

    def ordered_nodes_dict(self):

        # returns an ordered list of the network's nodes sorted by node's id

        return OrderedDict(sorted(self.network.nodes.items()))

    def addNode(self):

        #### COMPLETE THIS METHOD ##############

        return "this method passes the controller to inclusion mode and gets it out of it after 20 seconds "

    def removeNode(self):

        #### COMPLETE THIS METHOD ##############

        return "this method passes the controller to exclusion mode and gets it out of it after 20 seconds "

    def get_nodes_list(self):
        return jsonify(self.network.nodes_to_dict())

    def set_node_location(self, n, value):

        #### COMPLETE THIS METHOD ##############

        return " this method sets the location of a specific sensor node"

    def set_node_name(self, n, value):

        for node in self.network.nodes.itervalues():
            if node.node_id == n and isReady(node) and n != 1:
                node.set_name(value)
                return jsonify(node_id=node.node_id, name=node.name)

        return "Node not ready or wrong sensor node !"

    def get_node_location(self, n):

        #### COMPLETE THIS METHOD ##############

        return "this method gets the location of a specific sensor node"

    def get_node_name(self, n):

        for node in self.network.nodes.itervalues():
            if node.node_id == n and isReady(node) and n != 1:
                return jsonify(node_id=node.node_id, name=node.name)

        return "Node not ready or wrong sensor node !"

    def get_neighbours_list(self, n):

        nodes = []
        for node in self.network.nodes.itervalues():
            if node.node_id == n and isReady(node) and n != 1 and len(
                    node.neighbors) > 0:
                for neighbor_id in node.neighbors:
                    nodes.append(self.network.nodes[neighbor_id].to_dict())

        response = dict((k, v) for k, v in enumerate(nodes))
        return jsonify(response)

    def set_node_config_parameter(self, n, param, value, size):

        #### COMPLETE THIS METHOD ##############

        return "this method sets a configuration parameter to a given value"

    def get_node_config_parameter(self, n, param):

        #### COMPLETE THIS METHOD ##############

        return "this method gets the value of a configuration parameter"

    def get_nodes_Configuration(self):
        configurations = {'Network Home ID': self.network.home_id}
        for node in self.network.nodes.itervalues():
            if isReady(node) and node.node_id != 1:
                key = "Node_" + str(node.node_id)
                configurations[key] = {}
                configurations[key]["Node ID"] = node.node_id
                values = node.get_values("All", "All", "All", "All", "All")
                for value in values.itervalues():
                    if value.label == "Enable Motion Sensor":
                        configurations[key][
                            "Enable Motion Sensor"] = value.data
                    if value.label == "Group 1 Interval":
                        configurations[key]["Group 1 Interval"] = value.data
                    if value.label == "Group 1 Reports":
                        configurations[key]["Group 1 Reports"] = value.data
                    if value.label == "Group 2 Interval":
                        configurations[key]["Group 2 Interval"] = value.data
                    if value.label == "Group 2 Reports":
                        configurations[key]["Group 2 Reports"] = value.data
                    if value.label == "Group 3 Interval":
                        configurations[key]["Group 3 Interval"] = value.data
                    if value.label == "Group 3 Reports":
                        configurations[key]["Group 3 Reports"] = value.data
                    if value.label == "Wake-up Interval":
                        configurations[key]["Wake-up Interval"] = value.data

        return jsonify(configurations)
예제 #13
0
파일: zwservice.py 프로젝트: aakatz3/seciot
class ZWDeviceController(IOTDeviceController):
    def louie_network_started(network):
        print (
            "Hello from network : I'm started : homeid %0.8x - %d nodes were found."
            % (network.home_id, network.nodes_count)
        )

    def louie_network_failed(network):
        print ("Hello from network : can't load :(.")

    def louie_network_ready(network):
        print ("Hello from network : I'm ready : %d nodes were found." % network.nodes_count)
        print ("Hello from network : my controller is : %s" % network.controller)
        dispatcher.connect(louie_node_update, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(louie_value_update, ZWaveNetwork.SIGNAL_VALUE)

    def louie_node_update(network, node):
        print ("Hello from node : %s." % node)

    def louie_value_update(network, node, value):
        print ("Hello from value : %s." % value)

    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 export(self):
        # list of devices
        # each device has zwavename, friendly name, device type, statepool, currentstates (timestamped)
        # return self.network.nodes
        return self.node_dict.keys()

    def readState(self, node):
        print "read", self.node_dict
        print "read", node
        if type(node) in [str, unicode]:
            nodenum = self.node_dict[node]
        else:
            print type(node)
            nodenum = node
        mynode = self.network.nodes[nodenum]
        state = None
        for switch in mynode.get_switches():
            state = mynode.get_switch_state(switch)
            print node
            print state
        return state

    def setState(self, node, state):
        print "set", self.node_dict
        print "set", node
        if type(node) in [str, unicode]:
            nodenum = self.node_dict[node]
        else:
            nodenum = node
        if state in [1, "1", u"1", True]:
            boolstate = True
        elif state in [0, "0", u"0", False]:
            boolstate = False
        else:
            print state
            print type(state)
            raise error("bad")
        print state
        for switch in self.network.nodes[nodenum].get_switches():
            self.network.nodes[nodenum].set_switch(switch, boolstate)
예제 #14
0
class Backend():
    """Root parent backend class
    """
    CONTROLLER_NODE_ID = 1

    logger = None
    network = None

    _labels_xref = {
        # us => OZW
        'battery': 'Battery Level',
        'burglar': 'Burglar',
        'humidity': 'Relative Humidity',
        'level': 'Level',
        'luminance': 'Luminance',
        'motion': 'Sensor',
        'temperature': 'Temperature',
        'ultraviolet': 'Ultraviolet',
    }

    _rooms_location = {
        # roomId => roomLocation
        '31126': 'room1',
        '19547': 'room2'
    }

    _initials = {
        # all optional... These are used asr args for __init__()
        # public
        'device': configpi.device,
        'ozw_config_path': configpi.config_path,
        'ozw_user_path': configpi.user_path,
        'log_level': configpi.log_level,
        'log_format': configpi.log_format,
        'log_format_dbg': configpi.log_format_dbg,
        're_dimmer': configpi.re_dimmer,
        're_sensor': configpi.re_sensor,
        'controller_name': configpi.name,
        'network_ready_timeout': configpi.network_ready_timeout,
        'controller_operation_timeout': configpi.controller_operation_timeout,
    }

    _initialized = False

    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 _is_network_started(self):
        """Check if self.network is started. See <http://openzwave.github.io/python-openzwave/network.html?highlight=state#openzwave.network.ZWaveNetwork.state>

        :returns: bool
        """
        return self.network.state >= self.network.STATE_STARTED

    def _lookup_node(self, nid):
        """Look up a node in `self.network.nodes` by its ID.

        :param int nid: the wanted node's ID

        :returns: object: a :class:`openzwave.node` or None if the wanted node
                is not found
        """
        self.logger.debug("nodes: {}".format(self.network.nodes))
        return next(
            # index i is discarded
            (node
             for i, node in self.network.nodes.items() if node.node_id == nid),
            None  # default
        )

    def _lookup_sensor_node(self, nid):
        """Look up a sensor node in `self.network.nodes` by its ID.

        :param int nid: the wanted node's ID

        :returns: object: a :class:`openzwave.node` or None if the wanted node
                is not found

        :raises: RuntimeError: if the node is not {found | ready | sensor}
        """
        node = self._lookup_node(nid)

        if not node:
            raise RuntimeError("No such node")

        if not (node.is_ready or self._has_timestamp(node)):
            raise RuntimeError("Not ready")

        if not self._is_sensor(node):
            raise RuntimeError("Not a sensor")

        return node

    def _lookup_dimmer_node(self, nid):
        """Look up a dimmer node in `self.network.nodes` by its ID.

        :param int nid: the wanted node's ID

        :returns: object: a :class:`openzwave.node` or None if the wanted node
                is not found

        :raises: RuntimeError: if the node is not {found | ready | dimmer}
        """
        node = self._lookup_node(nid)

        if not node:
            raise RuntimeError("No such node")

        if not (node.is_ready or self._has_timestamp(node)):
            raise RuntimeError("Not ready")

        if not self._is_dimmer(node):
            raise RuntimeError("Not a dimmer")

        return node

    def _network_reset(self, network):
        """Callback executed when the controller is hard reset.

        :returns: None
        """
        self.logger.info(
            "Network hard reset: home ID {:08x}, {} nodes found".format(
                network.home_id, network.nodes_count))

    def _network_started(self, network):
        """Callback executed once the OZW network is _started_ (SIGNAL_NETWORK_STARTED
        is raised). The discovery of the network components has begun: they
        will be mapped into objects.

        WARNING! No guarantee of atomic execution. Avoid ANY I/O here (I'm
        looking at you, logger), unless it's the _last_ statement executed...

        :returns: None
        """
        self.logger.info(
            "Network started: home ID {:08x}, {} nodes found".format(
                network.home_id, network.nodes_count))

    def _network_ready(self, network):
        """Callback executed once the OZW network is ready for opertion
        (SIGNAL_NETWORK_READY is raised).

        WARNING! No guarantee of atomic execution. Avoid ANY I/O here (I'm
        looking at you, logger), unless it's the _last_ statement executed...

        :returns: None
        """
        dispatcher.connect(self._node_added, ZWaveNetwork.SIGNAL_NODE_ADDED)
        dispatcher.connect(self._node_removed,
                           ZWaveNetwork.SIGNAL_NODE_REMOVED)
        dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)

    def _node_added(self, network, node):
        """Callback executed when a node is added to the network (signal
        SIGNAL_NODE_ADDED is raised). On execution, `self.node_added` is set
        to the newly added node, an :class:`openzwave.node` obect.

        WARNING! No guarantee of atomic execution. Avoid ANY I/O here (I'm
        looking at you, logger), unless it's the _last_ statement executed...

        :returns: None
        """
        self.node_added = node
        self._set_node_timestamp(node, None)
        self.logger.info('node added: {}'.format(node.node_id))

    def _node_removed(self, network, node):
        """Callback executed when node is removed from the network (signal
        SIGNAL_NODE_REMOVED is raised). On execution, `self.node_removed` is set
        with the removed node, an :class:`openzwave.node` obect.

        WARNING! No guarantee of atomic execution. Avoid ANY I/O here (I'm
        looking at you, logger), unless it's the _last_ statement executed...

        :returns: None
        """
        self.node_removed = node
        self.timestamps.pop(_tstamp_label(node), None)
        self._del_node_timestamp(node)
        self.logger.info('node removed: {}'.format(node.node_id))

    def _value_update(self, network, node, value):
        """Callback executed whenever a node's reading value is changed, added,
        removed, etc. Node's timestamp is also updated.

        WARNING! No guarantee of atomic execution. Avoid ANY I/O here (I'm
        looking at you, logger), unless it's the _last_ statement executed...

        :returns: None        """
        self._set_node_timestamp(node, int(time.time()))
        self.logger.debug("timestamp: {}".format(
            self.get_node_timestamp(node)))

    ############################################################################
    # @network
    ############################################################################
    def start(self):
        """Start the software representation. It won't restart an already started
        network -- use `reset()` instead.

        :returns: tuple(bool, string): (status, reason) where:

                status: True on success, False if the network was already start
                reason: a textual explanation
        """
        global started

        if started:
            msg = "System already started. Skipping..."
            self.logger.warning(msg)
            return (False, msg)

        self.network.start()

        self.logger.info(
            "Z-Wave Network Starting -- timeout in {}s. Please wait...".format(
                self.network_ready_timeout))

        # [BUG] why this f***in polling? Must file an RFE for a callback-based
        # notification
        timeout = True
        for i in range(0, self.network_ready_timeout):
            if self.network.is_ready:
                self.logger.debug("Network ready after {}s".format(i))
                timeout = False
                break
            else:
                time.sleep(1.0)

        if not self.network.is_ready:
            self.logger.warning((
                "Network is not ready after {}s. " +
                "You should increase `network_ready_timeout`. Continuing anyway..."
            ).format(self.network_ready_timeout))

        self.logger.info("Network _{}_ ready. Nodes discovered: {}".format(
            'possibly' if timeout else 'really',
            self.network.nodes_count,
        ))

        started = True

        return (True, 'OK')

    def stop(self):
        """Stop the software representation

        :returns: tuple(bool, string): (status, reason) where:

                status: True on success, False otherwise
                reason: a textual explanation

        Doctests
        ++++++++

        # >>> print("*** Action needed for node to be _removed_ ***") # doctest:+ELLIPSIS
        # *** ...
        # >>> t.remove_node() # doctest:+ELLIPSIS
        # {...}
        """
        global started

        self.logger.info("Z-Wave Network stopping...")
        try:
            self.network.stop()
        except Exception as e:
            return (False, str(e))

        started = False

        return (True, 'OK')

    def hard_reset(self, force=False):
        """Resets the controller and erases its network configuration settings.  The
        controller becomes a primary controller ready to add nodes to a new
        network. Warning! This basically destroys the network -- use with care!

        :returns: tuple(bool, string): (status, reason) where:

        :raises: RuntimeError exception if network is not empty (nodes are
                included) while `force=False`
        """
        if self.network.nodes_count == 1:
            self.network.controller.hard_reset()
            return (True, 'OK')
        elif force:
            self.logger.warning(
                "Forcing hard reset on a network with included nodes.")
            self.network.controller.hard_reset()
            return (True, 'OK')
        else:
            raise RuntimeError(
                "Cannot hard reset while network has included nodes.")

    def soft_reset(self):
        """Soft reset the controller. The software representation is untouched.

        :returns: tuple(bool, string): (status, reason) where:
        """
        try:
            self.network.controller.soft_reset()
        except Exception as e:
            return (False, str(e))

        return (True, 'OK')

    def network_info(self):
        """Get network's structure information summary.

        :returns: dict: with various info about the network and currently
                associated nodes
        """
        result = {
            'Network Home ID': self.network.home_id_str,
        }
        nodes = self.network.nodes
        for k, node in nodes.items():
            percentage = round((self.queryStages[node.query_stage] / 19) * 100,
                               2)
            node = {
                k: {
                    "Is Ready": node.is_ready,
                    "Neighbours": self.get_neighbours_list(k),
                    "Node ID": k,
                    "Node location": node.location,
                    "Node name": node.name,
                    "Node type": node.product_type,
                    "Product name": node.product_name,
                    "Query Stage": node.query_stage,
                    "Query Stage (%)": percentage
                }
            }

            result.update(node)

        return result

    def get_nodes_configuration(self):
        """Get an overview of the network and its nodes' configuration parameters (ID,
        Wake-up Interval, Group 1 Reports, Group 1 Interval, ...).

        :returns: dict: the nodes's configuration parameters
        """
        result = {'Network Home ID': self.network.home_id_str}

        self.logger.debug("looking for nodes...")
        for node in self._my_nodes().values():
            if node.is_ready and not self._is_controller(node):
                # Update of the software representation: retreive the last
                # status of the Z-Wave network
                node.request_all_config_params()

                # Get Config + System values
                values = node.get_values(class_id="All",
                                         genre="Config",
                                         readonly="All",
                                         writeonly=False,
                                         label="All")

                # de-obectify for json serialization. `values` is something like:
                # int(ID): {
                #     'label': str,
                #     'value_id': int(ID), # same as master key
                #     'node_id': int,
                #     'units': str,
                #     'genre': str,
                #     'data': str,
                #     'data_items': set(...), # this is not jsonify-able!
                #     'command_class': int,
                #     'is_read_only': bool,
                #     'is_write_only': bool,
                #     'type': str,
                #     'index': int
                # }
                # which must be inspected for deep serialization
                nodeValues = {
                    clsid: json_prepare(data)
                    for clsid, data in values.items()
                }
                nodeValues['Node type'] = str(node.type)
                result[node.node_id] = nodeValues

        return result

    def get_nodes_list(self):
        """Get a list of all the nodes in the network, where indexes are
        node IDs and values are product names.

        :returns: object: an `OrderedDict` indexed by node IDs with product
                names (or a "[not ready]" note) as values:

            {
              "1": "Z-Stick Gen5",
              "2": "MultiSensor 6",
              "3": "ZE27",
              "4": "[not ready]"
            }
        """

        nodes = self.network.nodes
        values = OrderedDict()
        for k, node in nodes.items():
            values[k] = node.name

        return values

    def get_sensors_list(self):
        """Get a list of sensor nodes in the network, where indexes are
        node IDs and values are product names.

        :returns: object: an `OrderedDict` indexed by node IDs with product
                names (or a "[not ready]" note) as values:

            {
                "2": "MultiSensor 6",
                "3": "MultiSensor 6"
            }
        """
        nodes = self.network.nodes
        values = OrderedDict()
        for k, node in nodes.items():
            if self._is_sensor(node):
                values[k] = node.name

        return values

    def get_dimmers_list(self):
        """Get a list of dimmer nodes in the network, where indexes are
        node IDs and values are product names.

        :returns: object: an `OrderedDict` indexed by node IDs with product
                names (or a "[not ready]" note) as values:

            {
                "2": "???",
                "3": ""
            }
        """

        nodes = self.network.nodes
        values = OrderedDict()
        for k, node in nodes.items():
            if self._is_dimmer(node):
                values[k] = node.name

        return values

    def set_dimmers_by_room(self, roomId, value):
        room = self._rooms_location[roomId]

        nodes = self.network.nodes
        for k, node in nodes.items():
            if self._is_dimmer(node) and node.location == room:
                self.set_dimmer_level(node.node_id, value)

        return True

    ############################################################################
    # @nodes
    ############################################################################

    def _my_nodes(self):
        """Returns an ordered list of the all network's nodes sorted by node's
        ID.

        :returns: object: an :class:`OrderedDict`

        """
        return OrderedDict(sorted(self.network.nodes.items()))

    def _is_controller(self, node):
        """Check if node is a controller.

        :param object node: a :class:`openzwave.node`

        :returns: bool
        """
        return node.node_id == self.CONTROLLER_NODE_ID

    def _is_dimmer(self, node):
        """Check if node is a dimmer by matching its type against
        :attr:`self.re_dimmer`.

        :param object node: a :class:`openzwave.node`

        :returns: bool

        """
        return re.search(self.re_dimmer, node.type, re.I)

    def _is_sensor(self, node):
        """Check if node is a sensor by matching its type against
        :attr:`self.re_sensor`.

        :param object node: a :class:`openzwave.node`

        :returns: bool

        """
        return re.search(self.re_sensor, node.type, re.I)

    @staticmethod
    def _lookup_value(values, label):
        """Look up a (node's) value by label in a list of values.

        :param string label: the wanted value's label
        :param values set: a value set as returned by :func:`node.get_values()`

        :returns: depends on the value's type or None if the wanted value
                is not found
        """
        return next(
            (value.date for value in values if value.label == label),
            None  # default
        )

    def _has_timestamp(self, node):
        """Check if a node has a timestamp, meaning that it should be ready and has
        received a first value update.

        :param object node: a :class:`openzwave.node`

        :returns: bool: True if an entry exists in `self.timestamps`
        """
        self.logger.debug("timestamps: {}".format(self.timestamps))
        return _tstamp_label(node) in self.timestamps

    def _get_node_timestamp(self, node):
        """Get the last update time of a node.

        :param object node: a :class:`openzwave.node`

        :returns: int: time as seconds-since-th-epoch ([FIX-ME] to be verfied)
                or None if no timestamp exists for `node`
        """
        try:
            return self.timestamps[_tstamp_label(node)]
        except KeyError:
            return None

    def _set_node_timestamp(self, node, value):
        """Set the last update time of a node.

        :param object node: a :class:`openzwave.node`
        :param int value: time as seconds-since-the-epoch

        :returns: None
        """
        self.timestamps[_tstamp_label(node)] = value

    def _del_node_timestamp(self, node):
        """Remove the last update time of a node.

        :param object node: a :class:`openzwave.node`

        :returns: int: time as seconds-since-th-epoch ([FIX-ME] to be verfied)
                or None if no timestamp exists for `node`
        """
        return self.timestamps.pop(_tstamp_label(node), None)

    def add_node(self):
        # source pour la boucle de 20 secondes : https://stackoverflow.com/questions/24374620/python-loop-to-run-for-certain-amount-of-seconds/24374857
        """Adds a node to the network by switching the controller into
        inclusion mode for 20 seconds. The node to add can not be a
        controller. Physical action is required on the node to be added.

        :returns: object: the added node's :class:`openzwave.node` object

        :raises: RuntimeError exception if
                * timeout occurs, or
                * network is not started
        """
        if (started == False):
            raise RuntimeError("Network is not started")

        self.network.controller.add_node()
        t_end = time.time() + 20
        while time.time() < t_end:
            if self.node_added != None:
                return self.node_added.to_dict()

        raise RuntimeError("Timeout")

    def remove_node(self):
        """Removes a node from the network by switching the controller into
        exclusion mode for 20 seconds. The node to remove can not be a
        controller. Physical action is required on the node to be removed.

        :returns: object: the removed node's :class:`openzwave.node` object

        :raises: RuntimeError exception if
                * timeout occurs, or
                * network is not started
        """
        self.network.controller.remove_node()
        t_end = time.time() + 20
        while time.time() < t_end:
            if self.node_removed != None:
                return self.node_removed.to_dict()

    def set_node_location(self, n, value):
        """Set a node's location.

        :param int n: the node's ID
        :param str value: the new location value

        :returns: str: The previous location value

        :raises: RuntimeError: if the node is not found
        """
        node = self._lookup_node(n)
        if not node:
            raise RuntimeError("No such node")

        prev_loc = node.location
        node.location = value

        return prev_loc

    def set_node_name(self, n, value):
        """Set a node's name.

        :param int n: the node's ID
        :param str value: the new name value

        :returns: str: The previous name value

        :raises: RuntimeError: if the node is not found
        """
        node = self._lookup_node(n)
        if not node:
            raise RuntimeError("No such node")

        prev_name = node.name
        node.name = value
        return prev_name

    def get_node_location(self, n):
        """Get a node's location.

        :param int n: the node's ID

        :returns: str: the location value on succes

        :raises: RuntimeError: if the node is not found
        """
        node = self._lookup_node(n)
        if not node:
            raise RuntimeError("No such node")

        return node.location

    def get_node_name(self, n):
        """Get a node's name.

        :param int n: the node's ID

        :returns: int: the name value on succes

        :raises: RuntimeError: if the node is not found
        """

        node = self._lookup_node(n)
        if (node == None):
            raise RuntimeError("Node not found")
        return node.name

    def get_neighbours_list(self, n):
        """Get a node's llist of neighbors.

        :param int n: the node's ID

        :returns: tuple: the neighbors' numerical ID list (might be empty)

        :raises: RuntimeError: if the node is not found
        """

        node = self._lookup_node(n)
        if (node == None):
            raise RuntimeError("Node not found")
        value = [v for v in node.neighbors]

        return value

    def set_node_parameter(self, n, pindex, value, size):
        """Sets a node's configuration parameter. There's no guarantee that the
        parameter has been set -- you may check with
        `get_node_parameter()`.

        :param int n: the node's ID
        :param int pindex: the parameter's index
        :param int value: the parameter's value
        :param int value: the parameter's size

        :returns: bool: True on success. False if the command wan't sent for
                some reason (see OZW log)

        :raises: RuntimeError: if the node is not found
        """
        node = self._lookup_node(n)
        if node.is_ready:
            node.request_all_config_params()
            node.set_config_param(pindex, value, size)
            return True

        return False

    def get_node_parameter(self, n, pindex):
        """Get a node's configuration parameter.

        :param int n: the node's ID
        :param int pindex: the parameter's index

        :returns: int: the parameter value on succes, or None if the
                parameters is not found

        :raises: RuntimeError: if the node is not {found | ready}
        """
        node = self._lookup_node(n)

        if (node == None):
            raise RuntimeError("Node not found")

        if (node.is_ready == False):
            raise RuntimeError("Node not ready")

        if node.is_ready:
            node.request_all_config_params()
            values = node.get_values(class_id="All",
                                     genre="Config",
                                     type="All",
                                     readonly="All",
                                     writeonly="All",
                                     index=pindex,
                                     label="All")
            value = [v.data for v in values.values()][0]

            return value
예제 #15
0
class zwave(object):

    #Define some manager options
    options = ZWaveOption(device, \
      config_path=constants.zwpath, \
      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(log)
    options.set_logging(True)
    options.lock()
    
    def louie_network_started(self, network):
        dicti = {'Log':'Z-Wave Network started'}
#        mySocket.sendto(str(dicti) ,(constants.server1,constants.broadPort))
        mqtt_publish.mqtt_pub('Inputs/Satellite/' + constants.name + '/Log',dicti)
        print("Hello from network : I'm started : homeid {:08x} - {} nodes were found.".format(network.home_id, network.nodes_count))
    
    def louie_network_failed(self, network):
        pass
        print("Hello from network : can't load :(.")
    
    def louie_network_ready(self, network):
        dicti = {'Log':'Z-Wave Network up running'}
#        mySocket.sendto(str(dicti) ,(constants.server1,constants.broadPort))
        mqtt_publish.mqtt_pub('Inputs/Satellite/' + constants.name + '/Log',dicti)
        dispatcher.connect(self.louie_node_update, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(self.louie_scene_message, ZWaveNetwork.SIGNAL_NODE_EVENT)
        dispatcher.connect(self.louie_value_update, ZWaveNetwork.SIGNAL_VALUE)
        
        print('Dispatcher connected')
    
    def louie_scene_message(self, *args, **kwargs):
        print('scene happening')
        for count, thing in enumerate(args):
            print( '{0}. {1}'.format(count, thing))  
        for name, value in kwargs.items():
            print( '{0} = {1}'.format(name, value))            
    
    def loui_ess_q_comp(self):
        pass
#        print('nodes ess queried')
    
    def loui_mess_comp(self):
        print('mess complete')
    

    def louie_node_update(self, network, node):
        pass
        print("Hello from node : {}.".format(node))
    
    def louie_value_update(self, network, node, value):
        print "value changed"
        try:
#            print zw_config.inputs[node.home_id][value.value_id], int(value.data)
            dicti = {'Value': str(int(value.data))}
            dicti['Name'] = 'ZWave.' + str(node.home_id) + '.' + str(value.value_id)
            #print dicti
#            mySocket.sendto(str(dicti) ,(constants.server1,constants.broadPort))     
            mqtt_publish.mqtt_pub('Inputs/Satellite/' + constants.name + '/ZWave/' + str(int(node.home_id)) +'/'+ str(int(value.value_id)) ,dicti)
        except:
            print 'not understood', node, value.value_id, value.data
#        print("Hello from value : {}.".format( value ))
    #    home_id: [0xeefad666] id: [72057594093060096] parent_id: [3] label: [Switch] data: [False].
    #    home_id: [0xeefad666] id: [72057594093273218] parent_id: [3] label: [Power] data: [0.0].
    #    home_id: [0xeefad666] id: [144115188131201026] parent_id: [3] label: [Energy] data: [0.00999999977648]
    #   value.label = switch

    def __init__(self):
        pass
    
    def start(self):
        #Create a network object
        self.network = ZWaveNetwork(self.options, autostart=False)
        
        
        #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)
        dispatcher.connect(self.louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)
        dispatcher.connect(self.louie_scene_message, ZWaveNetwork.SIGNAL_SCENE_EVENT)
        dispatcher.connect(self.loui_ess_q_comp, ZWaveNetwork.SIGNAL_ESSENTIAL_NODE_QUERIES_COMPLETE)
        dispatcher.connect(self.loui_mess_comp, ZWaveNetwork.SIGNAL_MSG_COMPLETE)
        self.network.start()

        #We wait for the network.
        # print("Waiting for network to become ready : ")
        for i in range(0,900):
            if self.network.state>=self.network.STATE_READY:
                print "Network is ready"
                break
            else:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1.0)

            #time.sleep(5.0)
            
            #We update the name of the controller
            #print("Update controller name")
            #network.controller.node.name = "Hello name"
            
            #time.sleep(5.0)
            
            #We update the location of the controller
            #print("Update controller location")
            #network.controller.node.location = "Hello location"
            
            
#            for node in self.network.nodes:
#                for val in self.network.nodes[node].get_switches() :
#                    print("Switch : {}".format(self.network.nodes[node]))
#                    print("Switch1: {}".format(val))
            #        72057594093060096
            #       144115188130988032
            #        network.nodes[node].set_switch(val,True)
                #We only activate the first switch
                #exit
            
            
#            for node in self.network.nodes:
#                for val in self.network.nodes[node].get_dimmers() :
#                   print("Dimmer : {}".format(self.network.nodes[node]))
#                   print("Switch1: {}".format(val))
            #        72057594093076481
            #        144115188131004513
            #        144115188131004417
            #        72057594093076577 
            #        network.nodes[node].set_dimmer(val,80)
                #We only activate the first dimmer
                #exit

    def end_network(self):
        self.network.stop()

    def _set_switch(self,node_id , switch, wert):
        if wert == 'Toggle':
            cur_val = self.network.nodes[node_id].get_switch_state(switch)
            self.network.nodes[node_id].set_switch(switch, not cur_val)
        else:
            if eval(wert) > 0:
                self.network.nodes[node_id].set_switch(switch, True)
            else:
                self.network.nodes[node_id].set_switch(switch, bool(eval(wert)))
        return True
        
    def _set_dimmer(self,node_id , dimmer, wert):
        if wert == 'Toggle':
            cur_val = self.network.nodes[node_id].get_dimmer_level(dimmer)
            if cur_val == 0:
                self.network.nodes[node_id].set_dimmer(dimmer, 50)
            else:
                self.network.nodes[node_id].set_dimmer(dimmer, 0)
        else:
            self.network.nodes[node_id].set_dimmer(dimmer, eval(wert))
        return True       
        
    def set_device(self, data_ev): 
#       TODO do threaded with stop criteria
        if data_ev.get('Device') in zw_config.switches:
            print data_ev
            return self._set_switch(zw_config.switches[data_ev['Device']][0],zw_config.switches[data_ev['Device']][1],data_ev['Value'])
        if data_ev.get('Device') in zw_config.dimmer:
            print data_ev
            return self._set_dimmer(zw_config.dimmer[data_ev['Device']][0],zw_config.dimmer[data_ev['Device']][1],data_ev['Value'])
예제 #16
0
class Open_zwave(HAInterface):
    VERSION = '0.0.4'

    def louie_network_ready(self, network):
        self._logger.info(
            ">>>>>>> Hello from network : I'm ready : %d nodes were found.".
            format(self._network.nodes_count))
        self._logger.info(
            ">>>>>>> Hello from network : my controller is : {}".format(
                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(self, network, node):
        self._logger.debug('>>>>>>> Hello from node : {}.'.format(node))

    def louie_value_update(self, network, node, value):
        self._logger.debug('>>>>>>> Hello from value : {}'.format(value))
        for lockvalue in self.get_door_locks(node.node_id).values():
            if lockvalue.value_id == value.value_id:
                if value.data:
                    self._onCommand(address=str(node.node_id),
                                    command=Command.LOCK)
                else:
                    self._onCommand(address=str(node.node_id),
                                    command=Command.UNLOCK)
        for val in self._network.nodes[node.node_id].get_switches():
            if val == value.value_id:
                if value.data:
                    self._onCommand(address=str(node.node_id),
                                    command=Command.ON)
                else:
                    self._onCommand(address=str(node.node_id),
                                    command=Command.OFF)
        for val in self._network.nodes[node.node_id].get_dimmers():
            if val == value.value_id:
                #Poll dimmer to ensure ramp up/down completes
                level = value.data
                if self.dimmer_polled_value.has_key(val):
                    self._logger.debug(
                        '>>>>>>> Hello from level : {} {}'.format(
                            level, self.dimmer_polled_value[val]))
                    if level == self.dimmer_polled_value[val]:
                        del self.dimmer_polled_value[val]
                        if level < 2:
                            self._onCommand(address=str(node.node_id),
                                            command=Command.OFF)
                        elif level > 98:
                            self._onCommand(address=str(node.node_id),
                                            command=Command.ON)
                        else:
                            self._onCommand(address=str(node.node_id),
                                            command=(Command.LEVEL, level))
                    else:
                        self.dimmer_polled_value[val] = level
                        time.sleep(1)
                        value.refresh()
                else:
                    time.sleep(1)
                    self.dimmer_polled_value[val] = level
                    value.refresh()

    def __init__(self, *args, **kwargs):
        self._serialDevicePath = kwargs.get('serialDevicePath', None)
        self._configpath = kwargs.get('config_path', "/etc/openzwave/")
        super(Open_zwave, self).__init__(self, *args, **kwargs)
        self.dimmer_polled_value = {}

    def _init(self, *args, **kwargs):
        self.awake = False
        self.ready = False
        self.nodesdisplayed = False
        self._options = ZWaveOption(self._serialDevicePath, \
          config_path=self._configpath, \
          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):
        node = self._network.nodes[node]
        self._logger.info(
            "------------------------------------------------------")
        self._logger.info("{} - Name : {}".format(node.node_id, node.name))
        self._logger.info("{} - Manufacturer name / id : {} / {}".format(
            node.node_id, node.manufacturer_name, node.manufacturer_id))
        self._logger.info(
            "{} - Product name / id / type : {} / {} / {}".format(
                node.node_id, node.product_name, node.product_id,
                node.product_type))
        self._logger.info("{} - Version : {}".format(node.node_id,
                                                     node.version))
        self._logger.info("{} - Command classes : {}".format(
            node.node_id, node.command_classes_as_string))
        self._logger.info("{} - Capabilities : {}".format(
            node.node_id, node.capabilities))
        self._logger.info("{} - Neighbors : {}".format(node.node_id,
                                                       node.neighbors))
        self._logger.info("{} - Can sleep : {}".format(node.node_id,
                                                       node.can_wake_up()))
        for value in self.get_door_locks(node.node_id, 'All').values():
            self._logger.debug("{} - {} : {}".format(node.node_id, value.label,
                                                     value.data))

    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:
            self._logger.debug("Not awaked")
        elif self.awake and not self.ready:
            self._logger.debug("Not ready")
        elif not self.nodesdisplayed and self.ready:
            for node in self._network.nodes:
                self._printNetwork(node)
            self.update_status()
            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 : {}".format(
            self._network.controller.ozw_library_version))
        self._logger.info("Use python library : {}".format(
            self._network.controller.python_library_version))
        self._logger.info("Use ZWave library : {}".format(
            self._network.controller.library_description))

    def get_door_locks(self, node, datatype='Bool'):
        return self._network.nodes[node].get_values(class_id=0x62, genre='User', \
            type=datatype, readonly=False, writeonly=False)

    def lock(self, address):
        node = int(address)
        for value in self.get_door_locks(node).values():
            self._logger.debug("Lock")
            value.data = True

    def unlock(self, address):
        node = int(address)
        for value in self.get_door_locks(node).values():
            self._logger.debug("Unlock")
            value.data = False

    def on(self, address):
        node = int(address)
        for val in self._network.nodes[node].get_switches():
            self._logger.debug("Activate switch")
            self._network.nodes[node].set_switch(val, True)

        for val in self._network.nodes[node].get_dimmers():
            self._logger.debug("Activate dimmer : {}".format(
                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.debug("Deactivate switch")
            self._network.nodes[node].set_switch(val, False)

        for val in self._network.nodes[node].get_dimmers():
            self._logger.debug("Deactivate dimmer : {}".format(
                self._network.nodes[node]))
            self._network.nodes[node].set_dimmer(val, 0)

    def level(self, address, level):
        node = int(address)
        for val in self._network.nodes[node].get_dimmers():
            self._logger.debug("Set dimmer : {}".format(
                self._network.nodes[node]))
            self._network.nodes[node].set_dimmer(val, level)

    def status(self, address):
        node = int(address)
        for val in self._network.nodes[node].get_switches():
            level = self._network.nodes[node].get_switch_state(val)
            if level:
                self._onState(address=address, state=State.ON)
            else:
                self._onState(address=address, state=State.OFF)
        for val in self._network.nodes[node].get_dimmers():
            level = self._network.nodes[node].get_dimmer_level(val)
            if level < 2:
                self._onState(address=address, state=State.OFF)
            elif level > 98:
                self._onState(address=address, state=State.ON)
            else:
                self._onState(address=address, state=(State.LEVEL, level))
        for value in self.get_door_locks(node).values():
            if value.data:
                self._onState(address=address, state=State.LOCKED)
            else:
                self._onState(address=address, state=State.UNLOCKED)

    def update_status(self):
        for d in self._devices:
            self.status(d.address)
예제 #17
0
class ZwaveNetworkController():
    """
    This class is reponsible for starting and communicating with a zwave controller.
    """
    def __init__(self):
        self.is_running = False

    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()

        #self.is_running is set to True on zwave_network_ready()

    def stop(self):
        self.network.stop()
        self.is_running = False

    def send_command(self, command):
        # SWITCH-SET|node-id|val-id||True or False
        print('send_command | {}'.format(command))
        if self.network.is_ready == True:
            fields = command.split("|")
            cCommand = fields[0]
            cNodeId = int(fields[1])
            cValueId = int(fields[2])
            cVal = True if fields[3] == 'True' else False

            if cCommand == 'SWITCH-SET':
                print('switching to {}'.format(cVal))
                self.network.nodes[cNodeId].set_switch(cValueId, cVal)
            else:
                print("send_command : failed.  unsupported command {}".format(
                    cCommand))
        else:
            print("send_command : failed.  network not ready.")

    def zwave_network_started(self, network):
        print("network started : homeid {:08x} - {} nodes were found.".format(
            network.home_id, network.nodes_count))

    def zwave_network_failed(self, network):
        print("network : loading failed.")

    def zwave_network_ready(self, network):
        print("network : ready : {} nodes were found.".format(
            self.network.nodes_count))
        print("network : my controller is : {}".format(
            self.network.controller))
        self.network.controller.node.name = "HomeSweetHome"
        self.network.controller.node.location = "Room1"

        self.is_running = True

        print('Switches are')
        for node in self.network.nodes:
            for val in self.network.nodes[node].get_switches():
                zNode = self.network.nodes[node]
                netReadyEvent = Event()
                netReadyEvent.timestamp = time.time()
                netReadyEvent.source = 'zw_net'
                netReadyEvent.destination = 'aws_iot'
                netReadyEvent.payload = "NET-READY|{}|{}|{}".format(
                    zNode.node_id, val, zNode.get_switch_state(val))
                print('to: {}, payload = {}'.format(netReadyEvent.source,
                                                    netReadyEvent.payload))
                main_queue.put(netReadyEvent)

    def zwave_node_update(self, network, node):
        print("Hello from node : {}.".format(node))

    def zwave_value_update(self, network, node, value):
        print("Hello from value : {}.".format(value))

    @property
    def is_running(self):
        return self._is_running

    @is_running.setter
    def is_running(self, value):
        self._is_running = value
예제 #18
0
class ZWave:
    def __init__(self, error_handler, sig_handler):
        self.ctrl = []
        self.net = None
        self.home_id = None
        self.uid2node_val = {}

        self.raw_opts = reqparse.Namespace()
        self.opts = None
        self.opts_locked = False

        self.err_handler = error_handler

        #self.node_cache = {}

        for sig, handler in net_signals:
            if handler is None:
                dispatcher.connect(sig_handler,
                                   signal=sig,
                                   sender=dispatcher.Any)

    def get_node(self, node_id, silentfail=False):
        if not self.net:
            self.err_handler(414)

        #out = None
        #if not node_id in self.node_cache:
        #    out = ZWaveCoreNode(self.net.nodes.get(node_id))
        #self.node_cache[node_id] = out

        #if out is None:
        #    raise Exception("shit")

        #print (f"soifjoidsojidf: {node_id}")
        inner = self.net.nodes.get(node_id)
        out = ZWaveCoreNode(inner)
        return out

    def get_main_ctrl(self):
        return None if len(self.ctrl) == 0 else self.ctrl[0]

    def __contains__(self, node_id):
        return node_id in self.net.nodes

    def __getitem__(self, node_id):
        return self.get_node(node_id)

    def get_node_details(self, node_id, fields=None, silentfail=False):
        if not self.net:
            self.err_handler(414)

        node = self.get_node(node_id)
        fields = fields or ["node_id", "name", "query_stage"]

        return dict((f, getattr(node, f)) for f in fields if hasattr(node, f))

    def update_options(self, opts):
        self.raw_opts.update(opts)

    def clear_options(self):
        self.opts_locked = False
        self.opts = None
        self.raw_apts = reqparse.Namespace()

    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 start(self):
        if not self.opts_locked:
            raise ZWaveCentralException("ZWave options not locked")
        self.net = ZWaveNetwork(self.opts, autostart=False)
        self.ctrl.append(self.net.controller)

        self.home_id = self.net.home_id
        self.net.start()
예제 #19
0
class ZWaveController():
    network = None

    def setup(self, updateCallback):
        dispatcher.connect(self.onNetworkReady, ZWaveNetwork.SIGNAL_NETWORK_READY)
        dispatcher.connect(self.onNetworkStart, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
        dispatcher.connect(self.onNetworkFailed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)

        # TODO: make udev.symlink rule to a specific port (USB0/1)
        # Uncomment this to run on PC (remember to update the zwave config path)
        #options = ZWaveOption("/dev/ttyUSB0", \
        #  config_path="/home/<USER>/software/python-openzwave-0.2.6/openzwave/config", \
        options = ZWaveOption("/dev/serial/by-path/platform-bcm2708_usb-usb-0:1.2:1.0-port0", \
          config_path="/home/pi/software/python-openzwave-0.2.6/openzwave/config", \
          user_path=".", cmd_line="")
        options.set_append_log_file(False)
        options.set_console_output(False)
        options.set_save_log_level('Debug')
        options.set_poll_interval(30);
        options.set_suppress_value_refresh(False)
        options.addOptionBool("AssumeAwake", True)
        options.set_logging(False)
        options.lock()
        self.network = ZWaveNetwork(options, autostart=False)
        self.onDeviceUpdateCallback = updateCallback
        self.network.start()
        self.addedConnections = False
        Timer(2*60, self.setupConnections).start()


    def tearDown(self):
        network.stop()

    def getDeviceList(self):
        devices = []
        for node in self.network.nodes:
            if node == 1: continue # don't add the controller
            devices.append(self.buildDevice(node))
        return devices

    def buildDevice(self, node):
        dev = {}
        dev['id'] = int(self.network.home_id)*1000 + node
        dev['type'] = 'unknown'
        dev['product_name'] = self.network.nodes[node].product_name
        if self.getValueForLabel(node, 'Switch'):
            dev['type'] = 'appliance'
            val = self.getValueForLabel(node, 'Energy')
            dev['consumption_accumulated'] = type(val) != "None" and val or 0
            val = self.getValueForLabel(node, 'Power')
            dev['consumption_current'] =  type(val) != "None" and val or 0
            if self.getValueForLabel(node, 'Switch') == 'True':
                dev['state'] = 'on'
            else:
                dev['state'] = 'off'
        if self.getValueForLabel(node, 'Sensor'):
            dev['type'] = 'sensor'
            dev['temperature'] = self.getValueForLabel(node, 'Temperature')
            dev['luminance']   = self.getValueForLabel(node, 'Luminance')
            dev['presence']    = "undetected"
        dev['battery_level'] = self.getValueForLabel(node, 'Battery Level')
        return dev

    def getValueForLabel(self, node, label):
        for v in self.network.nodes[node].values: 
            if self.network.nodes[node].values[v].label == label:
                #self.network.nodes[node].refresh_value(v);
                return str(self.network.nodes[node].values[v].data_as_string)
        return None

    def setDeviceState(self, device_id, state):
        node = device_id%1000
        if not self.network.nodes[node]: return
        for val in self.network.nodes[node].get_switches() :
            self.network.nodes[node].set_switch(val, True if state=='on' else False)
        
    def setupConnections(self):
        self.addedConnections = True
        dispatcher.connect(self.onNodeUpdate, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(self.onNodeUpdateValue, ZWaveNetwork.SIGNAL_VALUE)
        dispatcher.connect(self.onNodeUpdateValue, ZWaveNetwork.SIGNAL_NODE_EVENT)
        dispatcher.connect(self.onNodeUpdateValue, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
        dispatcher.connect(self.onNodeUpdateValue, ZWaveNetwork.SIGNAL_VALUE_REFRESHED)

    # Event Handlers

    def onNetworkStart(self, network):
        print("network started : homeid %0.8x - %d nodes were found." % \
            (network.home_id, network.nodes_count))

    def onNetworkFailed(self, network):
        print("network can't load :(")

    def onNetworkReady(self, network):
        print("network : I'm ready : %d nodes were found." % network.nodes_count)
        print("network : my controller is : %s" % network.controller)
        self.network = network
        if not self.addedConnections:
            self.setupConnections()

    def onNodeUpdate(self, network, node):
        print('node UPDAAAATEEE : %s.' % node)
        self.network = network

    def onNodeUpdateValue(self, network, node, value):
        print('node : %s.' % node)
        print('value: %s.' % value)
        if node.node_id == 1: return # don't send controller notifications
        dev = self.buildDevice(node.node_id)

        if type(value) is int:
            if dev['type'] == 'sensor' and value == 255:
                dev['presence'] = 'detected'
                self.network = network
                self.onDeviceUpdateCallback(dev)

        if type(value) is ZWaveValue:
            if dev['type'] == 'appliance' and value.label == 'Switch':
                state = value.data and 'on'  or 'off'
                dev['state'] = state
                self.network = network
                self.onDeviceUpdateCallback(dev)

            if dev['type'] == 'appliance' and value.label == 'Power':
                power = str(value.data)
                if dev['state'] == 'off' or (dev['state'] == 'on' and float(power) != 0):
                    dev['consumption_current'] = power
                    self.network = network
                    self.onDeviceUpdateCallback(dev)
                else:
                    self.network = network
                    print('WHAATF do i do with this? %s', power)

            if dev['type'] == 'appliance' and value.label == 'Energy':
                energy = str(value.data)
                dev['consumption_accumulated'] = energy
                self.network = network
                self.onDeviceUpdateCallback(dev)

            if dev['type'] == 'sensor' and value.label == 'Temperature':
                temperature = str(value.data)
                dev['temperature'] = temperature
                self.network = network
                self.onDeviceUpdateCallback(dev)

            if dev['type'] == 'sensor' and value.label == 'Luminance':
                luminance = str(value.data)
                dev['luminance'] = luminance 
                self.network = network
                self.onDeviceUpdateCallback(dev)
        
            if value.label == 'Battery Level':
                battery = str(value.data)
                dev['battery_level'] = battery
                self.network = network
                self.onDeviceUpdateCallback(dev)
예제 #20
0
class Open_zwave(HAInterface):
    VERSION = '0.0.4'

    def louie_network_ready(self, network):
        self._logger.info(">>>>>>> Hello from network : I'm ready : %d nodes were found.".format(self._network.nodes_count))
        self._logger.info(">>>>>>> Hello from network : my controller is : {}".format(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(self, network, node):
        self._logger.debug('>>>>>>> Hello from node : {}.'.format(node))

    def louie_value_update(self, network, node, value):
        self._logger.debug('>>>>>>> Hello from value : {}'.format(value))
        for lockvalue in self.get_door_locks(node.node_id).values():
            if lockvalue.value_id == value.value_id:
                if value.data:
                    self._onCommand(address=str(node.node_id), command=Command.LOCK)
                else:
                    self._onCommand(address=str(node.node_id), command=Command.UNLOCK)
        for val in self._network.nodes[node.node_id].get_switches():
            if val == value.value_id:
                if value.data:
                    self._onCommand(address=str(node.node_id), command=Command.ON)
                else:
                    self._onCommand(address=str(node.node_id), command=Command.OFF)
        for val in self._network.nodes[node.node_id].get_dimmers() :
            if val == value.value_id:
                #Poll dimmer to ensure ramp up/down completes
                level = value.data
                if self.dimmer_polled_value.has_key(val):
                    self._logger.debug('>>>>>>> Hello from level : {} {}'.format(level, self.dimmer_polled_value[val]))
                    if level == self.dimmer_polled_value[val]:
                        del self.dimmer_polled_value[val]
                        if level < 2:
                            self._onCommand(address=str(node.node_id), command=Command.OFF)
                        elif level > 98:
                            self._onCommand(address=str(node.node_id), command=Command.ON)
                        else:
                            self._onCommand(address=str(node.node_id), command=(Command.LEVEL,level))
                    else:
                        self.dimmer_polled_value[val] = level
                        time.sleep(1)
                        value.refresh()
                else:
                    time.sleep(1)
                    self.dimmer_polled_value[val] = level
                    value.refresh()

    def __init__(self, *args, **kwargs):
        self._serialDevicePath = kwargs.get('serialDevicePath', None)
        self._configpath = kwargs.get('config_path', "/etc/openzwave/")
        super(Open_zwave, self).__init__(self, *args, **kwargs)
        self.dimmer_polled_value = {}

    def _init(self, *args, **kwargs):
        self.awake = False
        self.ready = False
        self.nodesdisplayed = False
        self._options = ZWaveOption(self._serialDevicePath, \
          config_path=self._configpath, \
          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):
        node = self._network.nodes[node]
        self._logger.info("------------------------------------------------------")
        self._logger.info("{} - Name : {}".format(node.node_id,
            node.name))
        self._logger.info("{} - Manufacturer name / id : {} / {}".format(
            node.node_id,
            node.manufacturer_name,
            node.manufacturer_id))
        self._logger.info("{} - Product name / id / type : {} / {} / {}".format(
            node.node_id,
            node.product_name,
            node.product_id,
            node.product_type))
        self._logger.info("{} - Version : {}".format(node.node_id,
            node.version))
        self._logger.info("{} - Command classes : {}".format(node.node_id,
            node.command_classes_as_string))
        self._logger.info("{} - Capabilities : {}".format(node.node_id,
            node.capabilities))
        self._logger.info("{} - Neighbors : {}".format(node.node_id,
            node.neighbors))
        self._logger.info("{} - Can sleep : {}".format(node.node_id,
            node.can_wake_up()))
        for value in self.get_door_locks(node.node_id, 'All').values():
            self._logger.debug("{} - {} : {}".format(node.node_id,value.label,value.data))

    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:
            self._logger.debug("Not awaked")
        elif self.awake and not self.ready:
            self._logger.debug("Not ready")
        elif not self.nodesdisplayed and self.ready:
            for node in self._network.nodes:
                self._printNetwork(node)
            self.update_status()
            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 : {}".format(self._network.controller.ozw_library_version))
        self._logger.info("Use python library : {}".format(self._network.controller.python_library_version))
        self._logger.info("Use ZWave library : {}".format(self._network.controller.library_description))
        
    def get_door_locks(self, node, datatype = 'Bool'):
        return self._network.nodes[node].get_values(class_id=0x62, genre='User', \
            type=datatype, readonly=False, writeonly=False)
        
    def lock(self, address):
        node = int(address)
        for value in self.get_door_locks(node).values():
            self._logger.debug("Lock")
            value.data = True
    
    def unlock(self, address):
        node = int(address)
        for value in self.get_door_locks(node).values():
            self._logger.debug("Unlock")
            value.data = False

    def on(self, address):
        node = int(address)
        for val in self._network.nodes[node].get_switches() :
            self._logger.debug("Activate switch")
            self._network.nodes[node].set_switch(val,True)

        for val in self._network.nodes[node].get_dimmers() :
            self._logger.debug("Activate dimmer : {}".format(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.debug("Deactivate switch")
            self._network.nodes[node].set_switch(val,False)

        for val in self._network.nodes[node].get_dimmers() :
            self._logger.debug("Deactivate dimmer : {}".format(self._network.nodes[node]))
            self._network.nodes[node].set_dimmer(val,0)

    def level(self, address, level):
        node = int(address)
        for val in self._network.nodes[node].get_dimmers() :
            self._logger.debug("Set dimmer : {}".format(self._network.nodes[node]))
            self._network.nodes[node].set_dimmer(val, level)

    def status(self, address):
        node = int(address)
        for val in self._network.nodes[node].get_switches() :
            level = self._network.nodes[node].get_switch_state(val)
            if level:
                self._onState(address=address, state=State.ON)
            else:
                self._onState(address=address, state=State.OFF)
        for val in self._network.nodes[node].get_dimmers() :
            level = self._network.nodes[node].get_dimmer_level(val)
            if level < 2:
                self._onState(address=address, state=State.OFF)
            elif level > 98:
                self._onState(address=address, state=State.ON)
            else:
                self._onState(address=address, state=(State.LEVEL,level))
        for value in self.get_door_locks(node).values():
            if value.data:
                self._onState(address=address, state=State.LOCKED)
            else:
                self._onState(address=address, state=State.UNLOCKED)

    def update_status(self):
        for d in self._devices:
            self.status(d.address)
예제 #21
0
class Backend():
    def __init__(self):
        ###### options needed for python openzwave library like config files path, logging,
        device = configpi.interface
        options = ZWaveOption(
            device,
            config_path="/home/pi/IoTLab/python-openzwave/openzwave/config",
            user_path=".",
            cmd_line="")
        options.set_log_file("OZW.log")
        options.set_append_log_file(False)
        options.set_console_output(False)
        options.set_save_log_level('Warning')
        options.set_logging(True)
        options.lock()

        # creation of the object network using the options entity already created
        self.network = ZWaveNetwork(options, autostart=False)

        ###### 	 These dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
        ######   Once the signal is received. It's associated method 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)

        ###### backend object attributes
        #        self.devices = OrderedDict()  ### will contain the list of nodes in the network
        #        self.sensors = OrderedDict()  ### will contain the list of sensors (only) in the network
        self.node_added = False
        self.node_removed = False
        self.timestamps = {
        }  ### will contain the time of the last values' update for each sensor
        self.queryStages = {  ### the diffrent stages that a node object gets through before being ready
            "None": 1,  # Query process hasn't started for this node
            "ProtocolInfo": 2,  # Retrieve protocol information
            "Probe": 3,  # Ping device 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
            "SecurityReport":
            7,  # Retrieve a list of Command Classes that require Security
            "ManufacturerSpecific2":
            8,  # Retrieve manufacturer name and product ids
            "Versions": 9,  # Retrieve version information
            "Instances":
            10,  # Retrieve information about multiple command class instances
            "Static": 11,  # Retrieve static information (doesn't change)
            "Probe1": 12,  # Ping a device upon starting with configuration
            "Associations": 13,  # Retrieve information about associations
            "Neighbors": 14,  # Retrieve node neighbor list
            "Session":
            15,  # Retrieve session information (changes infrequently)
            "Dynamic": 16,  # Retrieve dynamic information (changes frequently)
            "Configuration":
            17,  # Retrieve configurable parameter information (only done on request)
            "Complete": 18  # Query process is completed for this node
        }

    #######################################################################################################################
    ############# LAUNCH  #################################################################################################
    #######################################################################################################################

    def _network_started(self, network):
        # executed once the software representation is started. the discovery of the network components has begun. they will be mapped into objects
        print("network started - %d nodes were found." % network.nodes_count)

        # these dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
        # a signal may contain a number of parameters that are passed to the method associated to the signal.
        # for exemple, the dispatcher below associates the signal "SIGNAL_NODE_ADDED" to the method "_node_added" that is implemented below (line 111).
        # the signal "SIGNAL_NODE_ADDED" transports two parameters which are the objects network and node.
        # once this signal is received, these two parameters will be passed to the method "_node_added" and the method will be executed.
        dispatcher.connect(self._node_added, ZWaveNetwork.SIGNAL_NODE_ADDED)
        dispatcher.connect(self._node_removed,
                           ZWaveNetwork.SIGNAL_NODE_REMOVED)

    def _network_ready(self, network):
        # executed once the software representation is ready
        print("network : ready : %d nodes were found." % network.nodes_count)
        print("network : controller is : %s" % network.controller)
        dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)

    def _node_added(self, network, node):
        # executed when node is added to the software representation. it's executed after the method "_debug_node_new" (see below)
        print('node added: %s.' % node.node_id)
        self.timestamps["timestamp" + str(node.node_id)] = "None"
        self.node_added = True

    def _node_removed(self, network, node):
        # executed when node is removed from the software representation
        print('node removed: %s.' % node.name)
        self.node_removed = True

    def _value_update(self, network, node, value):
        # executed when a new value from a node is received
        print('Node %s: value update: %s is %s.' %
              (node.node_id, value.label, value.data))
        self.timestamps["timestamp" + str(node.node_id)] = int(time.time())

    ################################################################################################################
    ######################## START AND STOP THE SOFTWARE REPRESENTATION ############################################
    ################################################################################################################

    def start(self):
        # this method starts the software representation
        global started

        if started:
            print
            "Already started"
            return
        started = True
        self.network.start()
        print
        "Z-Wave Network Starting..."
        for i in range(0, 300):
            if self.network.state == self.network.STATE_READY:
                break
            else:
                time.sleep(1.0)
        if not self.network.is_ready:
            print
            "Network is not ready but continue anyway"
        print
        "------------------------------------------------------------"
        print
        "Nodes in network : %s" % self.network.nodes_count
        print
        "------------------------------------------------------------"

    def stop(self):
        # this method stops the software representation
        global started
        started = False
        print
        "Stopping Z-Wave Network... "
        self.network.stop()

    def reset(self):
        if self.network.nodes_count == 1:
            self.network.controller.hard_reset()
            return "Hard Reset Done"
        return "Cannot make Hard Reset while nodes included in network"
예제 #22
0
class Backend():

    def __init__(self):
        device = "/dev/ttyUSB0"
        options = ZWaveOption(device, config_path="/home/rich/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_logging(True)
        options.lock()

        self.values = {}
        dispatcher.connect(self._network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
        dispatcher.connect(self._network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)
        dispatcher.connect(self._network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)
        self.network = ZWaveNetwork(options, autostart=False)

    def _network_started(self, network):
        print("network started - %d nodes were found." % network.nodes_count)

    def _network_failed(self, network):
        print("network failed :(")

    def _network_ready(self, network):
        print("network : ready : %d nodes were found." % network.nodes_count)
        print("network : controller is : %s" % network.controller)
        dispatcher.connect(self._node_update, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(self._node_event, ZWaveNetwork.SIGNAL_NODE_EVENT)
        dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)

    def _node_update(self, network, node):
        print('node update: %s.' % node)

    def _node_event(self, network, node, signal, sender):
        print('node event %s from node %s.' % (signal, node.node_id))
        value = self.network.get_value(IR_SENSOR_VALUE).data
        print('value is now %s' % value)
        self.log_access_with_value(value)

    def log_access_with_value(self, value):
        print("logging sensor trigger to file")
        with open("triggers.csv", "a") as sensor_log_file:
            sensor_log_file.write("%s,%s\n" % (datetime.today().strftime("%d/%m/%Y %H:%M:%S"), value))

    def _value_update(self, network, node, value):
        print('value update: %s is %s.' % (value.label, value.data))
        self.values[value.label] = value.data
        if value.label == 'Temperature':
            self.process_temp_change(value.data)

    def process_temp_change(self, value):
        if value > 25 and not self.get_switch_status(3):
            print('too hot - turn on fan')
            self.switch_on(3)
        elif value < 25 and self.get_switch_status(3):
            print('cool enough - turn off fan')
            self.switch_off(3)

    def log_values(self):
        print('Writing sensor log')
        try:
            t = self.get_temperature()
            h = self.get_humidity()
            l = self.get_brightness()
            with open("sensors.csv", "a") as sensor_log_file:
                sensor_log_file.write("%s,%s,%s,%s\n" % (datetime.today().strftime("%d/%m/%Y %H:%M:%S"), t, h, l))
        except:
            print('Failed to log values')
        self.start_timer()

    def get_sensor_values(self):
        lines = open("sensors.csv", "r").readlines()
        return_list = []
        for line in lines:
            line = line[:-1]  # remove newline
            d = {'Date': line.split(',')[0], 'Temperature': line.split(',')[1], 'Humidity': line.split(',')[2],
                         'Lux': line.split(',')[3]}
            return_list.append(d)
        return return_list

    def switch_on(self, name):
        print("Activating switch %s" % name)
        parsed_id = 0
        try:
            parsed_id = int(name)
        except ValueError:
            pass
        for key, node in self.network.nodes.iteritems():
            if node.name == name or node.node_id == parsed_id:
                for val in node.get_switches():
                    node.set_switch(val, True)

    def switch_off(self, name):
        print("Deactivating switch %s" % name)
        parsed_id = 0
        try:
            parsed_id = int(name)
        except ValueError:
            pass
        for key, node in self.network.nodes.iteritems():
            if node.name == name or node.node_id == parsed_id:
                for val in node.get_switches():
                    node.set_switch(val, False)

    def get_switch_status(self, name):
        print("Querying switch %s" % name)
        parsed_id = 0
        try:
            parsed_id = int(name)
        except ValueError:
            pass
        for key, node in self.network.nodes.iteritems():
            if node.name == name or node.node_id == parsed_id:
                for val in node.get_switches():
                    state = node.get_switch_state(val)
        return state

    def get_temperature(self):
        return self.network.nodes[2].get_sensor_value(TEMPERATURE_VALUE)

    def get_humidity(self):
        return self.network.nodes[2].get_sensor_value(HUMIDITY_VALUE)

    def get_brightness(self):
        return self.network.nodes[2].get_sensor_value(LUX_VALUE)

    def start_timer(self):
        t = Timer(900, self.log_values)
        t.start()

    def start(self):
        global started
        if started:
            return
        started = True
        self.network.start()
        self.start_timer()
        print "Starting..."
        for i in range(0, 90):
            if self.network.state >= self.network.STATE_READY:
                break
            else:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1.0)

    def stop(self):
        print "Stopping..."
        self.network.stop()
예제 #23
0
class myZWave:
    def __init__(self):
        self.lastReport = {}
        self.startTime = time.time()

    def setup(self):
        self.logs = myLogs('zwave-daemon')

        device = "/dev/ttyUSB0"
        log = "Info"  # Debug

        #Define some manager options
        # see docs at the end of file
        options = ZWaveOption(device, \
          #config_path="openzwave/config", \
          user_path="/home/scripts/zwave/home",\
          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('None')
        #options.set_queue_log_level("None")
        #options.set_save_log_level('Info')
        options.set_logging(False)
        options.lock()

        self.ZWave = ZWaveNetwork(options, log=None, autostart=False)

    def start(self):
        self.setup()
        #self.ZWave.controller.soft_reset();
        #self.logs.log("continue");
        #sys.exit(1);

        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_ready,
                           ZWaveNetwork.SIGNAL_NETWORK_READY)

        self.ZWave.start()

        for i in range(0, 300):
            if self.ZWave.state >= self.ZWave.STATE_STARTED:
                self.logs.log("Startup time: " + str(self.getRunTime()))
                break
            else:
                self.logs.log("***** STARTING *****")
                #sys.stdout.write(".")
                #sys.stdout.write("starting.")
                #sys.stdout.flush()
                time.sleep(1.0)
        if self.ZWave.state < self.ZWave.STATE_STARTED:
            self.logs.log(".")
            self.logs.log(
                "Can't initialise driver! Look at the logs in OZW_Log.log. Runtime: "
                + str(self.getRunTime()))
            sys.exit(1)

        for i in range(0, 600):
            #if self.ZWave.state>=self.ZWave.STATE_AWAKED: # wait fot awaked nodes only:
            if self.ZWave.state >= self.ZWave.STATE_READY:
                self.logs.log("Got ready by " + str(self.getRunTime()))
                break
            else:
                time.sleep(1.0)
        if not self.ZWave.is_ready:
            #if self.ZWave.state < self.ZWave.STATE_AWAKED:
            self.logs.log("Runtime: " + str(self.getRunTime()))
            self.logs.log(
                "Can't start network! Look at the logs in OZW_Log.log")
            self.logs.log("Resetting controller in 5 sec. Then reinit")
            self.ZWave.controller.soft_reset()
            sys.exit(1)

        self.logs.log("Collecting switches...")
        self.collectSwitches()

    def getRunTime(self):
        return (time.time() - self.startTime)

    def stop(self):
        self.ZWave.stop()
        self.logs.log("####### STOPPED ######")

    def nodeCmd(self, id, cmd):
        return getattr(self.ZWave.nodes[id], cmd)()

    def nodeProp(self, id, cmd):
        return getattr(self.ZWave.nodes[id], cmd)

    def switch(self, id, state):
        try:
            node = self.switches[str(id)]
            self.logs.log('Switching node ' + str(node) + ' sw: ' + str(id) +
                          ' to ' + str(state))
            newState = True if state == 1 else False
            self.ZWave.nodes[int(node)].set_switch(int(id), newState)
        except:
            e = sys.exc_info()[0]
            self.logs.log("UNKNOWN SWITCH: " + str(id) + ' Error:' + str(e))
        #self.ZWave.nodes[2].set_switch(216172782152138752, True)

    def collectSwitches(self):
        self.switches = {}
        for node in self.ZWave.nodes:
            for val in self.ZWave.nodes[node].get_switches():
                self.switches[str(val)] = node
                self.logs.log("* Found switch " + str(val) + ' on node ' +
                              str(node))
        self.logs.log(self.switches)

    def logSwitches(self):
        self.logs.log("** List of Swithces ** ")
        self.logs.log(self.switches)

    def logPowerLevels(self):
        _nodes = {}
        for node in self.ZWave.nodes:
            for val in self.ZWave.nodes[node].get_power_levels():
                _nodes[str(val)] = node
        self.logs.log("** List of PowerLevels ** ")
        self.logs.log(_nodes)

    def logSensors(self):
        _nodes = {}
        for node in self.ZWave.nodes:
            for val in self.ZWave.nodes[node].get_sensors():
                _nodes[str(val)] = node
        self.logs.log("** List of Sensors ** ")
        self.logs.log(_nodes)

    # Event Listeners
    def louie_network_started(self):
        self.logs.log('//////////// ZWave network is started ////////////')
        self.logs.log(
            'Louie signal : OpenZWave network is started : homeid {:08x} - {} nodes were found.'
            .format(self.ZWave.home_id, self.ZWave.nodes_count))
        #self.ZWave.controller.soft_reset();

    def louie_network_resetted(self):
        #self.logs.log('Louie signal : OpenZWave network is resetted.')
        pass

    def louie_network_ready(self):
        self.logs.log('//////////// ZWave network is ready ////////////')
        self.logs.log(
            'Louie signal : ZWave network is ready : {} nodes were found.'.
            format(self.ZWave.nodes_count))
        self.logs.log('Louie signal : Controller : {}'.format(
            self.ZWave.controller))
        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)

        dispatcher.connect(self.louie_node_update,
                           ZWaveNetwork.SIGNAL_NODE_READY)
        dispatcher.connect(self.louie_node_update,
                           ZWaveNetwork.SIGNAL_NODE_REMOVED)
        dispatcher.connect(self.louie_node_update,
                           ZWaveNetwork.SIGNAL_SCENE_EVENT)
        dispatcher.connect(self.louie_my_update,
                           ZWaveNetwork.SIGNAL_NOTIFICATION)
        dispatcher.connect(self.louie_my_update,
                           ZWaveNetwork.SIGNAL_VALUE_REFRESHED)

    def louie_node_update(self, network, node):
        #self.logs.log('Louie signal : Node update : {}.'.format(node))
        pass

    def louie_my_update(self, network, node=False, t=False, f=False):
        self.logs.log('Louie signal : Node update : {}.'.format(node))

    def louie_value_update(self, network, node, value):
        now = datetime.datetime.now()
        log = str(now) + 'Value update: {}.'.format(value)
        #if value.data == False and value.value_id != 216172782152138752:
        #self.ZWave.nodes[2].set_switch(216172782152138752, False)
        cmd = '/home/scripts/zwave/event-handler.py'
        state = str(value.data)
        zwaveID = str(value.value_id)
        if (zwaveID not in self.lastReport
                or self.lastReport[zwaveID]['val'] != state
                or (time.time() - self.lastReport[zwaveID]['time']) > 2):
            self.lastReport[zwaveID] = {'time': time.time(), 'val': state}
            subprocess.Popen([cmd, str(value.value_id), state],
                             stdout=open('/dev/null', 'w'),
                             stderr=open('/dev/null', 'w'))
            self.logs.log(log + " ☉")
        else:
            self.logs.log(log)

    def louie_ctrl_message(self, state, message, network, controller):
        #self.logs.log('Louie signal : Controller message : {}.'.format(message))
        pass
예제 #24
0
def louie_node_update(network, node):
    print("Hello from node : {}.".format(node))

def louie_value_update(network, node, value):
    print("Hello from value : {}.".format( value ))

#Create a network object
network = ZWaveNetwork(options, autostart=False)

#We connect to the louie dispatcher
dispatcher.connect(louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
dispatcher.connect(louie_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)
dispatcher.connect(louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)

network.start()

#We wait for the network.
print("***** Waiting for network to become ready : ")
for i in range(0,90):
    if network.state>=network.STATE_READY:
        print("***** Network is ready")
        break
    else:
        sys.stdout.write(".")
        sys.stdout.flush()
        time.sleep(1.0)

time.sleep(5.0)

for node in network.nodes:
예제 #25
0
class Network(object):
    _instance = None

    def _init(self, device, config, timeout):
        self.network = None
        self.status = 1
        self.timeout = timeout
        self.device = device
        self.config = config

        options = ZWaveOption(self.device, config_path=self.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_logging(True)

        options.lock()
        self.network = ZWaveNetwork(options, autostart=False)

        dispatcher.connect(louie_network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
        dispatcher.connect(louie_network_failed, ZWaveNetwork.SIGNAL_NETWORK_FAILED)
        dispatcher.connect(louie_network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)

        self.network.start()

    def __new__(class_, device=None, config=None, timeout=None):
        if not isinstance(class_._instance, class_):
            if not device:
                return None
            class_._instance = object.__new__(class_)
            class_._instance._init(device, config, timeout)
        return class_._instance

    def __del__(self):
        self.network.stop()

    def __iter__(self):
        return self

    def next(self):
        self.timeout -= 1
        if self.timeout == 0:
            self.status = 1
            raise StopIteration
        if self.network.state >= self.network.STATE_READY:
            self.status = 0
            raise StopIteration
        return self.timeout

    def get_timout(self):
        return self.timeout

    def get_status(self):
        return self.status

    def stop(self):
        self.network.stop()

    def get_state(self):
        return self.network.state

    def is_stopped(self):
        return self.network.state == self.network.STATE_STOPPED

    def is_running(self):
        return self.network.state == self.network.STATE_READY
예제 #26
0
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
예제 #27
0
class Main(object):
    config = None
    device_to_node = {}
    node_to_device = {}
    node_to_logger = collections.defaultdict(lambda: default_logger)
    node_ready = {}
    timers = {}

    def network_started(self, network):
        default_logger.info("network started")
        dispatcher.connect(self.node_queries_complete,
                           ZWaveNetwork.SIGNAL_NODE_QUERIES_COMPLETE)

    def network_failed(self, network):
        default_logger.info("network failed")

    def node_queries_complete(self, network, node):
        logger = self.node_to_logger[node.node_id]
        logger.info("node %d queries complete: %s %s", node.node_id,
                    node.product_name, node.manufacturer_name)
        logger.info("- command classes: %s", node.command_classes_as_string)
        logger.info("- capabilities: %s", node.capabilities)
        logger.info("- neighbors: %s", node.neighbors)
        self.node_ready[node.node_id] = True

    def network_ready(self, network):
        default_logger.info("network ready: %d nodes were found",
                            network.nodes_count)
        # connect to updates after initialization has finished
        dispatcher.connect(self.value_update, ZWaveNetwork.SIGNAL_VALUE)
        dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)
        dispatcher.connect(self.node_event, ZWaveNetwork.SIGNAL_NODE_EVENT)
        dispatcher.connect(self.ctrl_message,
                           ZWaveController.SIGNAL_CONTROLLER)

    def node_update(self, network, node):
        logger = self.node_to_logger[node.node_id]
        logger.info("node update: %s", node)

    def node_event(self, network, node, value):
        device = self.node_to_device.get(node.node_id)
        logger = self.node_to_logger[node.node_id]
        logger.info("node event: value: %s", value)
        if not device:
            return
        self.value_basic(logger, node, device, value)

    def value_update(self, network, node, value):
        device = self.node_to_device.get(node.node_id)
        logger = self.node_to_logger[node.node_id]
        logger.info("value update: %s=%s", value.label, value.data_as_string)
        if not device:
            return
        timer = self.timers.pop(device, None)
        if timer:
            timer.cancel()

        fn = getattr(self, 'value_%s' % value.label.replace(' ', '_'), None)
        if fn:
            fn(logger, node, device, value)

    def value_basic(self, logger, node, device, value):
        state = 'on' if value == 255 else 'off'
        logger.info('Basic sensor update: %s', state)
        if state is not None:
            self.pub_device_state(device, state, 'sensor')

    def value_Alarm_Type(self, logger, node, device, value):
        if 'COMMAND_CLASS_DOOR_LOCK' in node.command_classes_as_string:
            if value.data not in LOCK_ALARM_TYPE:
                logger.warning('Lock update unknown: %s', value.data)
                return
            logger.info('Lock update: %s', LOCK_ALARM_TYPE[value.data])
            state = LOCK_ALARM_STATE.get(value.data)
            if state is not None:
                self.pub_device_state(device, state, 'lock')

    def value_Switch(self, logger, node, device, value):
        state = 'on' if value.data else 'off'
        logger.info('Switch update: %s', state)
        self.pub_device_state(device, state, 'ack')

    def value_Sensor(self, logger, node, device, value):
        # Neo CoolCam Door/Window sensors emit both Sensor and Access Control
        # for events, but use both for reliability.
        state = 'on' if value.data else 'off'
        logger.info('Sensor update: %s', state)
        self.pub_device_state(device, state, 'sensor')

    def value_Access_Control(self, logger, node, device, value):
        # Philio 4 in 1 Multi-Sensor only emits this for open/close.
        state = ACCESS_CONTROL_STATE.get(value.data)
        if state is None:
            logger.warning('Access control unknown: %s', value.data)
            return
        logger.info('Access control update: %s', state)
        self.pub_device_state(device, state, 'sensor')

    def value_Temperature(self, logger, node, device, value):
        if value.units == 'F':
            celsius = (value.data - 32) * 5 / 9
        else:
            celsius = value.data
        logger.debug('Temperature: %.1fC', celsius)
        device = 'temp.' + device.split('.')[-1]
        message = {
            'topic': 'temp',
            'device': device,
            'temp': celsius,
        }
        self.publish(message)

    def value_Luminance(self, logger, node, device, value):
        # label: [Luminance] data: [16.0]
        device = 'lux.' + device.split('.')[-1]
        message = {
            'topic': 'lux',
            'device': device,
            'lux': value.data,
        }
        self.publish(message)

    def value_Battery_Level(self, logger, node, device, value):
        # label: [Battery Level] data: [100]
        message = {
            'topic': 'openzwave',
            'device': device,
            'battery': value.data,
        }
        self.publish(message)

    def value_Burglar(self, logger, node, device, value):
        state = BURGLAR.get(value.data)
        if state is None:
            logger.warning("Burglar unknown: %s", value.data)
            return

        logger.info("motion update: %s", state)
        if state == 'Motion':
            device = 'pir.' + device.split('.')[-1]
            self.pub_device_state(device, 'on', 'sensor')

            # sensors do not send off, so trigger this on a timer delay
            if device in self.timers:
                self.timers[device].cancel()

            def switch_off():
                logger.info("%s motion auto off", device)
                self.pub_device_state(device, 'off', 'sensor')

            timer = self.timers[device] = threading.Timer(60.0, switch_off)
            timer.start()

    def pub_device_state(self, device, command, topic):
        message = {
            'topic': topic,
            'device': device,
            'command': command,
        }
        self.publish(message)

    def publish(self, message):
        topic = 'gohome/%s/%s' % (message['topic'], message['device'])
        message['timestamp'] = datetime.datetime.utcnow().strftime(
            '%Y-%m-%d %H:%M:%S.%f')[:-3]
        message = json.dumps(message)
        self.client.publish(topic, message, retain=True)

    def set_device_state(self, node_id, on):
        node = self.network.nodes.get(node_id)
        logger = self.node_to_logger[node_id]
        if not node:
            logger.warning('No node %d found', node_id)
            return
        by_label = {val.label: val for val in node.values.values()}

        if 'COMMAND_CLASS_DOOR_LOCK' in node.command_classes_as_string:
            logger.info('Unlocking...' if on else 'Locking...')
            by_label['Locked'].data = not on
            logger.info("Locked set to %s", not on)
        elif 'COMMAND_CLASS_SWITCH_BINARY' in node.command_classes_as_string:
            logger.info('Switching on...' if on else 'Switching off...')
            by_label['Switch'].data = on
            logger.info("Switch set to %s", on)
        else:
            logger.info("Node %d not in recognised classes", node_id)

    def ctrl_message(self, state, message, network, controller):
        default_logger.info('controller message: %s', message)

    def lock_node(self):
        def nodes_matching_class(name):
            return filter(lambda n: name in n.command_classes_as_string,
                          self.network.nodes.values())

        return next(nodes_matching_class('COMMAND_CLASS_DOOR_LOCK'), None)

    def on_mqtt_connect(self, client, userdata, flags, rc):
        default_logger.info('Connected to MQTT')
        client.subscribe('gohome/command/#')
        client.subscribe('gohome/config')

    def on_mqtt_message(self, client, userdata, msg):
        if msg.payload.startswith(b'{'):
            message = json.loads(msg.payload)
        else:
            message = yaml.safe_load(msg.payload)
        if 'topic' in message:
            topic = message['topic']
        else:
            topic = msg.topic.split('/')[1]
        if topic == 'config':
            self.config = message
            self.node_to_device = {
                int(device['source'][6:]): _id
                for _id, device in self.config['devices'].items()
                if 'source' in device and device['source'].startswith('zwave.')
            }
            self.device_to_node = {
                device: node_id
                for node_id, device in self.node_to_device.items()
            }
            default_logger.info(str(self.node_to_device))
            self.node_to_logger = collections.defaultdict(
                lambda: default_logger)
            for node_id, device in self.node_to_device.items():
                self.node_to_logger[node_id] = logging.getLogger(device)
            default_logger.info('Configured devices')

        elif topic == 'command':
            if message['device'] not in self.device_to_node:
                return

            default_logger.info('Command received: %s',
                                msg.payload.decode('utf-8'))
            device = message['device']
            node_id = self.device_to_node[device]
            on = message['command'] == 'on'
            self.set_device_state(node_id, on)

            def repeat():
                self.set_device_state(node_id, on)

            timer = self.timers[device] = threading.Timer(5.0, repeat)
            timer.start()

    def setup_mqtt(self):
        self.client = paho.Client()
        self.client.on_connect = self.on_mqtt_connect
        self.client.on_message = self.on_mqtt_message
        url = os.getenv('GOHOME_MQTT')
        if not url:
            default_logger.error("Please set GOHOME_MQTT")
            sys.exit()
        m = re.search(r'^tcp://([^:]+)(?::(\d+))?$', url)
        if not m:
            default_logger.error("Invalid value for GOHOME_MQTT: %s", url)
            sys.exit()
        hostname, port = m.groups()
        port = int(port) if port else 1883
        default_logger.info('Connecting to mqtt server: %s:%d', hostname, port)
        self.client.connect(hostname, port=port)

    def run(self):
        # Connect to mqtt
        self.setup_mqtt()

        # Create a network object
        self.network = ZWaveNetwork(options, autostart=False)

        # Hook Ctrl-C to cleanly shutdown.
        # This ensures openzwave persists its state to the zwcfg xml file.
        def signal_handler(signal, frame):
            default_logger.info("Stopping zwave network")
            self.network.stop()
            default_logger.info("Stopping mqtt client")
            self.client.disconnect()

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        dispatcher.connect(self.network_started,
                           ZWaveNetwork.SIGNAL_NETWORK_STARTED)
        dispatcher.connect(self.network_failed,
                           ZWaveNetwork.SIGNAL_NETWORK_FAILED)
        dispatcher.connect(self.network_ready,
                           ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED)

        self.network.start()

        self.client.loop_forever()
        default_logger.info("Finished")