예제 #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
class TestApi(TestPyZWave):
    """
    Parent test class for api
    """

    @classmethod
    def setUpClass(self):
        super(TestApi, self).setUpClass()
        self.options = ZWaveOption(device=self.device, user_path=self.userpath)
        self.options.set_log_file("OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(False)
        self.options.set_save_log_level("Debug")
        self.options.set_logging(True)
        self.options.lock()
        self.ctrl_command_result = None
        dispatcher.connect(self.ctrl_message, ZWaveController.SIGNAL_CONTROLLER)
        self.node_result = None
        dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)
        self.network = ZWaveNetwork(self.options)
        time.sleep(1.0)

    @classmethod
    def tearDownClass(self):
        self.network.stop()
        time.sleep(2.0)
        super(TestApi, self).tearDownClass()
        self.network=None

    def setUp(self):
        self.wait_for_network_state(self.network.STATE_AWAKED, 1)

    def wait_for_queue(self):
        for i in range(0,60):
            if self.network.controller.send_queue_count <= 0:
                break
            else:
                time.sleep(0.5)

    def wait_for_network_state(self, state, multiply=1):
        for i in range(0,SLEEP*multiply):
            if self.network.state>=state:
                break
            else:
                #sys.stdout.write(".")
                #sys.stdout.flush()
                time.sleep(1.0)

    def ctrl_message(self, state, message, network, controller):
        self.ctrl_command_result = state

    def node_update(self, network, node):
        self.node_result = node
예제 #3
0
class TestApi(TestPyZWave):
    """
    Parent test class for api
    """
    @classmethod
    def setUpClass(self):
        super(TestApi, self).setUpClass()
        self.options = ZWaveOption(device=self.device, user_path=self.userpath)
        self.options.set_log_file("OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(False)
        self.options.set_save_log_level("Debug")
        self.options.set_logging(True)
        self.options.lock()
        self.network = ZWaveNetwork(self.options)
        self.ctrl_command_result = None
        dispatcher.connect(self.ctrl_message,
                           ZWaveController.SIGNAL_CONTROLLER)
        self.node_result = None
        dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)

    @classmethod
    def tearDownClass(self):
        self.network.stop()
        super(TestApi, self).tearDownClass()

    def setUp(self):
        self.wait_for_network_state(self.network.STATE_AWAKED, 1)

    def wait_for_queue(self):
        for i in range(0, 60):
            if self.network.controller.send_queue_count <= 0:
                break
            else:
                time.sleep(0.5)

    def wait_for_network_state(self, state, multiply=1):
        for i in range(0, SLEEP * multiply):
            if self.network.state >= state:
                break
            else:
                #sys.stdout.write(".")
                #sys.stdout.flush()
                time.sleep(1.0)

    def ctrl_message(self, state, message, network, controller):
        self.ctrl_command_result = state

    def node_update(self, network, node):
        self.node_result = node
예제 #4
0
class TestNetworkStartStop(TestPyZWave):

    @classmethod
    def setUpClass(self):
        super(TestNetworkStartStop, self).setUpClass()
        self.options = None
        self.network = None

    @classmethod
    def tearDownClass(self):
        if self.network is not None:
            self.network.stop()
        super(TestNetworkStartStop, self).tearDownClass()

    def test_000_network_start_stop(self):
        self.driver_ready = False
        self.driver_removed = False
        self.options = ZWaveOption(device=self.device, user_path=self.userpath)
        self.options.set_log_file("OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(False)
        self.options.set_save_log_level("Debug")
        self.options.set_logging(True)
        self.options.lock()
        dispatcher.connect(self.driver_ready_message, ZWaveNetwork.SIGNAL_DRIVER_READY)
        dispatcher.connect(self.driver_removed_message, ZWaveNetwork.SIGNAL_DRIVER_REMOVED)
        self.network = ZWaveNetwork(self.options)
        for i in range(0, SLEEP):
            if self.network.state>=self.network.STATE_AWAKED:
                break
            else:
                time.sleep(1.0)
        self.assertTrue(self.driver_ready)
        self.network.stop()
        for i in range(0, SLEEP):
            if self.network.state==self.network.STATE_STOPPED:
                break
            else:
                time.sleep(1.0)
        self.assertEqual(self.network.state, self.network.STATE_STOPPED)
        #self.assertTrue(self.driver_removed)
        self.network = None

    def driver_ready_message(self, network, controller):
        self.driver_ready = True

    def driver_removed_message(self, network):
        self.driver_removed = True
예제 #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
파일: 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()
예제 #7
0
class ZWaveManager():

	def	__init__( self ):
		device="/dev/ttyUSB0"
	
		options = ZWaveOption( "/dev/ttyUSB0", \
			config_path=os.path.expanduser("~/.zwave/config/"), \
			#user_path='.', \
			user_path=os.path.expanduser("~/.zwave/"), \
			cmd_line="")

		options.set_append_log_file(False)
		options.set_console_output(False)
		options.set_save_log_level('Info')

		options.set_logging(True)
		options.lock()

		print "Initialize Z-Wave network"
		self.network = ZWaveNetwork(options, log=None)

		print "Wait for driver"
		# Waiting for driver
		for i in range(0,20):
			if self.network.state>=self.network.STATE_INITIALISED: break
			else: time.sleep(1.0)

		if self.network.state<self.network.STATE_INITIALISED:
			print "Can't initialise driver! Look at the logs in OZW_Log.log"
			quit(1)
	
		print "Wait for network ready"
		# Waiting for network ready
		for i in range(0,90):
			if self.network.state>=self.network.STATE_READY: break
			else: time.sleep(1.0)
		if not self.network.is_ready:
			print "Can't start network! Look at the logs in OZW_Log.log"
			quit(2)

	def f7(self, seq):
		seen = set()
		seen_add = seen.add
		return [ x for x in seq if x not in seen and not seen_add(x)]
		

	def print_nodes(self):
		for node in self.network.nodes:
			print
			print "------------------------------------------------------------"
			print "%s - Name : %s" % (self.network.nodes[node].node_id,self.network.nodes[node].name)
			print "%s - Location : %s" % (self.network.nodes[node].node_id,self.network.nodes[node].location)
			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 - Neigbors : %s" % (self.network.nodes[node].node_id,self.network.nodes[node].neighbors)
			groups = {}
			for grp in self.network.nodes[node].groups :
				groups[self.network.nodes[node].groups[grp].index] = {'label':self.network.nodes[node].groups[grp].label, 'associations':self.network.nodes[node].groups[grp].associations}
			print "%s - Groups : %s" % (self.network.nodes[node].node_id, groups)
			values = {}
			for val in self.network.nodes[node].values :
				values[self.network.nodes[node].values[val].object_id] = {
					'label':self.network.nodes[node].values[val].label,
					'help':self.network.nodes[node].values[val].help,
					'command_class':self.network.nodes[node].values[val].command_class,
					'max':self.network.nodes[node].values[val].max,
					'min':self.network.nodes[node].values[val].min,
					'units':self.network.nodes[node].values[val].units,
					'data':self.network.nodes[node].values[val].data_as_string,
					'ispolled':self.network.nodes[node].values[val].is_polled
					}
			#print "%s - Values : %s" % (self.network.nodes[node].node_id, values)
			#print "------------------------------------------------------------"
			for cmd in self.network.nodes[node].command_classes:
				print "   ---------   "
				#print "cmd = ",cmd
				values = {}
				for val in self.network.nodes[node].get_values_for_command_class(cmd) :
					values[self.network.nodes[node].values[val].object_id] = {
						'label':self.network.nodes[node].values[val].label,
						'help':self.network.nodes[node].values[val].help,
						'max':self.network.nodes[node].values[val].max,
						'min':self.network.nodes[node].values[val].min,
						'units':self.network.nodes[node].values[val].units,
						'data':self.network.nodes[node].values[val].data,
						'data_str':self.network.nodes[node].values[val].data_as_string,
						'genre':self.network.nodes[node].values[val].genre,
						'type':self.network.nodes[node].values[val].type,
						'ispolled':self.network.nodes[node].values[val].is_polled,
						'readonly':self.network.nodes[node].values[val].is_read_only,
						'writeonly':self.network.nodes[node].values[val].is_write_only,
						}
				print "%s - Values for command class : %s : %s" % (self.network.nodes[node].node_id,
											self.network.nodes[node].get_command_class_as_string(cmd),
											values)
			print "------------------------------------------------------------"
		print
	
	def print_all_lights(self):
		values = {}
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() :
				print("node/name/location/version/index/instance : %s/%s/%s/%s/%s/%s" % (node, \
					self.network.nodes[node].name,
					self.network.nodes[node].location,
					self.network.nodes[node].version,
					self.network.nodes[node].values[val].index,
					self.network.nodes[node].values[val].instance))
				print("  label/help : %s/%s" % (self.network.nodes[node].values[val].label,self.network.nodes[node].values[val].help))
				print("  id on the network : %s" % (self.network.nodes[node].values[val].id_on_network))
				print("  state: %s" % (self.network.nodes[node].get_switch_state(val)))

	def print_all_dimmers(self):
		values = {}
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_dimmers() :
				print("node/name/location/version/index/instance : %s/%s/%s/%s/%s/%s" % (node, \
				self.network.nodes[node].name,
				self.network.nodes[node].location,
				self.network.nodes[node].version,
				self.network.nodes[node].values[val].index,
				self.network.nodes[node].values[val].instance))
				print("  label/help : %s/%s" % ( \
				self.network.nodes[node].values[val].label,
				self.network.nodes[node].values[val].help))
				print("  level: %s" % (self.network.nodes[node].get_dimmer_level(val)))

	def get_switches_dimmers(self):
		values = {} ; locations = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() : 
				loc={}
				loc['node']=node
				loc['name']=self.network.nodes[node].name
				loc['location']=self.network.nodes[node].location
				loc['version']=self.network.nodes[node].version
				loc['index']=self.network.nodes[node].values[val].index
				loc['instance']=self.network.nodes[node].values[val].instance
				loc['label']=self.network.nodes[node].values[val].label
				loc['help']=self.network.nodes[node].values[val].help
				loc['id']=self.network.nodes[node].values[val].id_on_network
				loc['level']=self.network.nodes[node].get_dimmer_level(val)
				loc['state']=self.network.nodes[node].get_switch_state(val)
				locations.append(loc)
			for val in self.network.nodes[node].get_dimmers() : 
				loc={}
				loc['node']=node
				loc['name']=self.network.nodes[node].name
				loc['location']=self.network.nodes[node].location
				loc['version']=self.network.nodes[node].version
				loc['index']=self.network.nodes[node].values[val].index
				loc['instance']=self.network.nodes[node].values[val].instance
				loc['label']=self.network.nodes[node].values[val].label
				loc['help']=self.network.nodes[node].values[val].help
				loc['id']=self.network.nodes[node].values[val].id_on_network
				loc['level']=self.network.nodes[node].get_dimmer_level(val)
				loc['state']=self.network.nodes[node].get_switch_state(val)
				locations.append(loc)

		return locations

	def get_switches_dimmers_locations(self):
		values = {} ; locations = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() : locations.append(self.network.nodes[node].location)
			for val in self.network.nodes[node].get_dimmers() : locations.append(self.network.nodes[node].location)
		return sorted( self.f7(locations) )

	def get_switches_locations(self):
		values = {} ; locations = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() : locations.append(self.network.nodes[node].location)
		return locations

	def get_dimmers_locations(self):
		values = {} ; locations = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_dimmers() : locations.append(self.network.nodes[node].location)
		return locations

	def get_lights_locations(self):
		locations=[]
		for location in self.get_switches_locations(): locations.append(location)
		for location in self.get_dimmers_locations(): locations.append(location)
		return sorted( self.f7(locations) )


			
	def get_switches_from_location(self, location):
		values = {}
		switches = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() :
				if self.network.nodes[node].location == location:
					switch = {}
					switch['name']=self.network.nodes[node].name
					switch['node']=node
					switch['type']='switch'
					switch['state']=self.network.nodes[node].get_switch_state(val)
					switches.append( switch  )
		return switches

	def get_dimmers_from_location(self, location):
		values = {}
		dimmers = []
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_dimmers() :
				if self.network.nodes[node].location == location:
					dimmer = {}
					dimmer['name']=self.network.nodes[node].name
					dimmer['type']='dimmer'
					dimmer['node']=node
					dimmer['level']=self.network.nodes[node].get_dimmer_level(val)
					dimmer['state']=dimmer['level']>0
					dimmers.append( dimmer)
		return dimmers

	def get_lights_from_location(self, location):
		lights = []
		for switch in self.get_switches_from_location( location ):
			lights.append(switch)
		for dimmer in self.get_dimmers_from_location( location ):
			lights.append(dimmer)
		return lights

	def get_switch_state( self, node ):
		node=int(node)
		for val in self.network.nodes[node].get_switches():
			return self.network.nodes[node].get_switch_state(val)
	
	def get_dimmer_level( self, node ):
		node=int(node)
		for val in self.network.nodes[node].get_dimmers():
			return self.network.nodes[node].get_dimmer_level(val)

	def light_on(self,node):
		node=int(node)
		for val in self.network.nodes[node].get_switches() : self.network.nodes[node].set_switch(val,True)
		print "Node %s, Switch on" % (str(node))

	def light_off(self,node):
		node=int(node)
		for val in self.network.nodes[node].get_switches() : self.network.nodes[node].set_switch(val,False)
		print "Node %s, Switch off" % (str(node))

	def set_dimmer(self,node,level):
		#  level : a value between 0-99 or 255. 255 set the level to the last value. 0 turn the dimmer off
		node=int(node)
		level=int(level)
		for val in self.network.nodes[node].get_dimmers() : 
			self.network.nodes[node].set_dimmer(val,level)
			self.network.nodes[node].set_dimmer(val,level)
			self.network.nodes[node].set_dimmer(val,level)
		print "Node %s, Dimmer set to %s" % (str(node), str(level))


	def all_lights_on(self):
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() : self.network.nodes[node].set_switch(val,True)

	def all_lights_off(self):
		for node in self.network.nodes:
			for val in self.network.nodes[node].get_switches() : self.network.nodes[node].set_switch(val,False)

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

	def test(self):
		return "life"


	def ozw_library_version(self):
		return self.network.controller.ozw_library_version

	def python_ozw_library_version(self):
		return self.network.controller.python_library_version

	def zw_library_version(self):
		return self.network.controller.library_description

	def home_id(self):
		return self.network.home_id_str

	def controller_node_id(self):
		return self.network.controller.node.node_id

	def controller_node_version(self):
		return self.network.controller.node.version

	def nodes(self):
		return self.network.nodes_count

	def controller_capabilities(self):
		return self.network.controller.capabilities

	def controller_node_capabilities(self):
		return self.network.controller.node.capabilities

	def controller_stats(self):
		return self.network.controller.stats
예제 #8
0
            set_time = str(h1) + str(h0) + ":" + str(m1) + str(m0)

        elif (alarm_state == 2):
            things[things_index].check(s, x, y)


####################################
# Main Loop
####################################

while True:

    # check event
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            network.stop()
            GPIO.cleanup()
            pygame.quit()
            sys.exit()

        if (event.type is pygame.MOUSEBUTTONDOWN):
            pos = pygame.mouse.get_pos()
            x, y = pos
            if (state == 2 and alarm_state == 0):
                check_other(state, x, y)
            else:
                if left_rect.collidepoint(x, y):
                    left_button_action(state)
                elif right_rect.collidepoint(x, y):
                    right_button_action(state)
                else:
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
예제 #10
0
class ZwaveBackend(Backend):
    """
    Start and manage a Z-Wave network.

    If you are using a USB adapter and want a consistent naming for the device paths, you can use udev.

    .. code-block:: shell

        # Get the vendorID and productID of your device through lsusb.
        # Then add a udev rule for it to link it e.g. to /dev/zwave.

        cat <<EOF > /etc/udev/rules.d/92-zwave.rules
        SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="zwave"
        EOF

        # Restart the udev service
        systemctl restart systemd-udevd.service

    Triggers:

        * :class:`platypush.message.event.zwave.ZwaveNetworkReadyEvent` when the network is up and running.
        * :class:`platypush.message.event.zwave.ZwaveNetworkStoppedEvent` when the network goes down.
        * :class:`platypush.message.event.zwave.ZwaveNetworkResetEvent` when the network is reset.
        * :class:`platypush.message.event.zwave.ZwaveNetworkErrorEvent` when an error occurs on the network.
        * :class:`platypush.message.event.zwave.ZwaveNodeQueryCompletedEvent` when all the nodes on the network
          have been queried.
        * :class:`platypush.message.event.zwave.ZwaveNodeEvent` when a node attribute changes.
        * :class:`platypush.message.event.zwave.ZwaveNodeAddedEvent` when a node is added to the network.
        * :class:`platypush.message.event.zwave.ZwaveNodeRemovedEvent` when a node is removed from the network.
        * :class:`platypush.message.event.zwave.ZwaveNodeRenamedEvent` when a node is renamed.
        * :class:`platypush.message.event.zwave.ZwaveNodeReadyEvent` when a node is ready.
        * :class:`platypush.message.event.zwave.ZwaveNodeGroupEvent` when a node is associated/de-associated to a
          group.
        * :class:`platypush.message.event.zwave.ZwaveNodeSceneEvent` when a scene is set on a node.
        * :class:`platypush.message.event.zwave.ZwaveNodePollingEnabledEvent` when the polling is successfully turned
          on a node.
        * :class:`platypush.message.event.zwave.ZwaveNodePollingDisabledEvent` when the polling is successfully turned
          off a node.
        * :class:`platypush.message.event.zwave.ZwaveButtonCreatedEvent` when a button is added to the network.
        * :class:`platypush.message.event.zwave.ZwaveButtonRemovedEvent` when a button is removed from the network.
        * :class:`platypush.message.event.zwave.ZwaveButtonOnEvent` when a button is pressed.
        * :class:`platypush.message.event.zwave.ZwaveButtonOffEvent` when a button is released.
        * :class:`platypush.message.event.zwave.ZwaveValueAddedEvent` when a value is added to a node on the network.
        * :class:`platypush.message.event.zwave.ZwaveValueChangedEvent` when the value of a node on the network
          changes.
        * :class:`platypush.message.event.zwave.ZwaveValueRefreshedEvent` when the value of a node on the network
          is refreshed.
        * :class:`platypush.message.event.zwave.ZwaveValueRemovedEvent` when the value of a node on the network
          is removed.
        * :class:`platypush.message.event.zwave.ZwaveCommandEvent` when a command is received on the network.
        * :class:`platypush.message.event.zwave.ZwaveCommandWaitingEvent` when a command is waiting for a message
          to complete.

    Requires:

        * **python-openzwave** (``pip install python-openzwave``)

    """
    def __init__(self,
                 device: str,
                 config_path: Optional[str] = None,
                 user_path: Optional[str] = None,
                 ready_timeout: float = 10.0,
                 *args,
                 **kwargs):
        """
        :param device: Path to the Z-Wave adapter (e.g. /dev/ttyUSB0 or /dev/ttyACM0).
        :param config_path: Z-Wave configuration path (default: ``<OPENZWAVE_PATH>/ozw_config``).
        :param user_path: Z-Wave user path where runtime and configuration files will be stored
            (default: ``<PLATYPUSH_WORKDIR>/zwave``).
        :param ready_timeout: Network ready timeout in seconds (default: 60).
        """
        import python_openzwave
        from openzwave.network import ZWaveNetwork

        super().__init__(*args, **kwargs)
        self.device = device

        if not config_path:
            config_path = os.path.join(
                os.path.dirname(inspect.getfile(python_openzwave)),
                'ozw_config')
        if not user_path:
            user_path = os.path.join(Config.get('workdir'), 'zwave')
            os.makedirs(user_path, mode=0o770, exist_ok=True)

        self.config_path = config_path
        self.user_path = user_path
        self.ready_timeout = ready_timeout
        self.network: Optional[ZWaveNetwork] = None

    def start_network(self):
        if self.network and self.network.state >= self.network.STATE_AWAKED:
            self.logger.info('Z-Wave network already started')
            return

        from openzwave.network import ZWaveNetwork, dispatcher
        from openzwave.option import ZWaveOption

        network_ready.clear()
        logging.getLogger('openzwave').addHandler(self.logger)
        opts = ZWaveOption(self.device,
                           config_path=self.config_path,
                           user_path=self.user_path)
        opts.set_console_output(False)
        opts.lock()

        self.network = ZWaveNetwork(opts, log=None)
        dispatcher.connect(_zwcallback)
        ready = network_ready.wait(self.ready_timeout)

        if not ready:
            self.logger.warning(
                'Driver not ready after {} seconds: continuing anyway'.format(
                    self.ready_timeout))

    def stop_network(self):
        if self.network:
            self.network.stop()
            network_ready.clear()
            self.network = None

    def _process_event(self, event: _ZWEvent):
        from platypush.plugins.zwave import ZwavePlugin
        network = event.network or self.network

        if event.signal == network.SIGNAL_NETWORK_STOPPED or \
                event.signal == network.SIGNAL_DRIVER_REMOVED:
            event_queue.put(ZwaveNetworkStoppedEvent(device=self.device))
        elif event.signal == network.SIGNAL_ALL_NODES_QUERIED or \
                event.signal == network.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD:
            event = ZwaveNodeQueryCompletedEvent(device=self.device)
        elif event.signal == network.SIGNAL_NETWORK_FAILED:
            event = ZwaveNetworkErrorEvent(device=self.device)
            self.logger.warning('Z-Wave network error')
        elif event.signal == network.SIGNAL_NETWORK_RESETTED or \
                event.signal == network.SIGNAL_DRIVER_RESET:
            event = ZwaveNetworkResetEvent(device=self.device)
        elif event.signal == network.SIGNAL_BUTTON_ON:
            event = ZwaveButtonOnEvent(device=self.device,
                                       node=ZwavePlugin.node_to_dict(
                                           event.args['node']))
        elif event.signal == network.SIGNAL_BUTTON_OFF:
            event = ZwaveButtonOffEvent(device=self.device,
                                        node=ZwavePlugin.node_to_dict(
                                            event.args['node']))
        elif event.signal == network.SIGNAL_CONTROLLER_COMMAND:
            event = ZwaveCommandEvent(
                device=self.device,
                state=event.args['state'],
                state_description=event.args['state_full'],
                error=event.args['error'] if event.args['error_int'] else None,
                error_description=event.args['error_full']
                if event.args['error_int'] else None,
                node=ZwavePlugin.node_to_dict(event.args['node'])
                if event.args['node'] else None)
        elif event.signal == network.SIGNAL_CONTROLLER_WAITING:
            event = ZwaveCommandWaitingEvent(
                device=self.device,
                state=event.args['state'],
                state_description=event.args['state_full'])
        elif event.signal == network.SIGNAL_CREATE_BUTTON:
            event = ZwaveButtonCreatedEvent(device=self.device,
                                            node=ZwavePlugin.node_to_dict(
                                                event.args['node']))
        elif event.signal == network.SIGNAL_DELETE_BUTTON:
            event = ZwaveButtonRemovedEvent(device=self.device,
                                            node=ZwavePlugin.node_to_dict(
                                                event.args['node']))
        elif event.signal == network.SIGNAL_GROUP:
            event = ZwaveNodeGroupEvent(device=self.device,
                                        node=ZwavePlugin.node_to_dict(
                                            event.args['node']),
                                        group_index=event.args['groupidx'])
        elif event.signal == network.SIGNAL_NETWORK_AWAKED:
            event = ZwaveNetworkReadyEvent(
                device=self.device,
                ozw_library_version=self.network.controller.
                ozw_library_version,
                python_library_version=self.network.controller.
                python_library_version,
                zwave_library=self.network.controller.library_description,
                home_id=self.network.controller.home_id,
                node_id=self.network.controller.node_id,
                node_version=self.network.controller.node.version,
                nodes_count=self.network.nodes_count,
            )
        elif event.signal == network.SIGNAL_NODE_EVENT:
            event = ZwaveNodeEvent(device=self.device,
                                   node=ZwavePlugin.node_to_dict(
                                       event.args['node']))
        elif event.signal == network.SIGNAL_NODE_ADDED:
            event = ZwaveNodeAddedEvent(device=self.device,
                                        node=ZwavePlugin.node_to_dict(
                                            event.args['node']))
        elif event.signal == network.SIGNAL_NODE_NAMING:
            event = ZwaveNodeRenamedEvent(device=self.device,
                                          node=ZwavePlugin.node_to_dict(
                                              event.args['node']))
        elif event.signal == network.SIGNAL_NODE_READY:
            event = ZwaveNodeReadyEvent(device=self.device,
                                        node=ZwavePlugin.node_to_dict(
                                            event.args['node']))
        elif event.signal == network.SIGNAL_NODE_REMOVED:
            event = ZwaveNodeRemovedEvent(device=self.device,
                                          node=ZwavePlugin.node_to_dict(
                                              event.args['node']))
        elif event.signal == network.SIGNAL_POLLING_DISABLED:
            event = ZwaveNodePollingEnabledEvent(device=self.device,
                                                 node=ZwavePlugin.node_to_dict(
                                                     event.args['node']))
        elif event.signal == network.SIGNAL_POLLING_ENABLED:
            event = ZwaveNodePollingDisabledEvent(
                device=self.device,
                node=ZwavePlugin.node_to_dict(event.args['node']))
        elif event.signal == network.SIGNAL_SCENE_EVENT:
            event = ZwaveNodeSceneEvent(device=self.device,
                                        scene_id=event.args['scene_id'],
                                        node=ZwavePlugin.node_to_dict(
                                            event.args['node']))
        elif event.signal == network.SIGNAL_VALUE_ADDED:
            event = ZwaveValueAddedEvent(
                device=self.device,
                node=ZwavePlugin.node_to_dict(event.args['node']),
                value=ZwavePlugin.value_to_dict(event.args['value']))
        elif event.signal == network.SIGNAL_VALUE_CHANGED:
            event = ZwaveValueChangedEvent(
                device=self.device,
                node=ZwavePlugin.node_to_dict(event.args['node']),
                value=ZwavePlugin.value_to_dict(event.args['value']))
        elif event.signal == network.SIGNAL_VALUE_REFRESHED:
            event = ZwaveValueRefreshedEvent(
                device=self.device,
                node=ZwavePlugin.node_to_dict(event.args['node']),
                value=ZwavePlugin.value_to_dict(event.args['value']))
        elif event.signal == network.SIGNAL_VALUE_REMOVED:
            event = ZwaveValueRemovedEvent(
                device=self.device,
                node=ZwavePlugin.node_to_dict(event.args['node']),
                value=ZwavePlugin.value_to_dict(event.args['value']))

        if isinstance(event, ZwaveEvent):
            self.bus.post(event)

    def __enter__(self):
        self.start_network()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop_network()

    def loop(self):
        try:
            event = event_queue.get(block=True, timeout=1.0)
            self._process_event(event)
        except queue.Empty:
            pass
예제 #11
0
class TestApi(TestPyZWave):
    """
    Parent test class for api
    """

    @classmethod
    def setUpClass(self):
        super(TestApi, self).setUpClass()
        self.options = ZWaveOption(device=self.device, user_path=self.userpath)
        self.options.set_log_file("OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(self.ozwout)
        self.options.set_save_log_level(self.ozwlog)
        self.options.set_logging(True)
        self.options.lock()
        self.node_result = None
        dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)
        self.network = ZWaveNetwork(self.options)
        self.ctrl_command_result = None
        self.ctrl_command_signal = None
        #dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND)
        time.sleep(1.0)

    @classmethod
    def tearDownClass(self):
        self.network.stop()
        time.sleep(2.0)
        self.network.destroy()
        time.sleep(1.0)
        super(TestApi, self).tearDownClass()
        self.network = None

    def setUp(self):
        self.wait_for_network_state(self.network.STATE_AWAKED, 1)

    def wait_for_queue(self):
        for i in range(0,60):
            if self.network.controller.send_queue_count <= 0:
                break
            else:
                time.sleep(0.5)

    def wait_for_network_state(self, state, multiply=1):
        for i in range(0,SLEEP*multiply):
            if self.network.state>=state:
                break
            else:
                time.sleep(1.0)

    def ctrl_message(self, network, controller, node, node_id,
            state_int, state, state_full,
            error_int, error, error_full,):
        self.ctrl_state_result = state
        self.ctrl_command_signal = {
            'network':network,
            'controller':controller,
            'node':node,
            'node_id':node_id,
            'state_int':state_int,
            'state':state,
            'state_full':state_full,
            'error_int':error_int,
            'error':error,
            'error_full':error_full,
        }

    def ctrl_waiting(self, network, controller,
            state_int, state, state_full):
        self.ctrl_state_result = state

    def node_update(self, network, node):
        self.node_result = node
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
예제 #13
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
예제 #14
0
class AlidronOZW(object):

    def __init__(self, device, isac_node):
        self.isac_node = isac_node

        self.signals = {}

        self._ozw_notif_queue = Queue()
        self._running = True
        green.spawn(self._notif_reader)

        self.options = ZWaveOption(
            device,
            config_path='/usr/share/openzwave/config',
            user_path='./user-dir',
            cmd_line=''
        )
        self.options.set_log_file("./user-dir/OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(False)
        self.options.set_save_log_level('Info')
        self.options.set_logging(False)
        self.options.lock()

        self.network = ZWaveNetwork(self.options, log=None)

        notif_to_func = [
            (ZWaveNetwork.SIGNAL_NETWORK_STARTED,    self.notif_network_started),
            (ZWaveNetwork.SIGNAL_NETWORK_RESETTED,   self.notif_network_resetted),
            (ZWaveNetwork.SIGNAL_NETWORK_READY,      self.notif_network_ready),
            (ZWaveNetwork.SIGNAL_NODE_ADDED,         self.notif_node_added),
            (ZWaveNetwork.SIGNAL_NODE_NAMING,        self.notif_node_named),
            (ZWaveNetwork.SIGNAL_NODE_REMOVED,       self.notif_node_removed),
            (ZWaveNetwork.SIGNAL_VALUE_ADDED,        self.notif_value_added),
            (ZWaveNetwork.SIGNAL_VALUE_CHANGED,      self.notif_value_update),
            (ZWaveNetwork.SIGNAL_VALUE_REMOVED,      self.notif_value_removed),
            (ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND, self.notif_ctrl_message),
            (ZWaveNetwork.SIGNAL_CONTROLLER_WAITING, self.notif_ctrl_message),
        ]
        for notif, func in notif_to_func:
            dispatcher.connect(self._notif_wrapper(func), notif, weak=False)

        # dispatcher.connect(self._notif_wrapper_all, All)

        self.isac_node.add_rpc(self.network_heal)
        self.isac_node.add_rpc(self.controller_add_node, name='add_node')
        self.isac_node.add_rpc(self.controller_remove_node, name='remove_node')
        self.isac_node.add_rpc(self.controller_cancel_command, name='cancel_command')

    # Plumbing

    def _notif_wrapper(self, f):
        def _notif(*args, **kwargs):
            logger.debug('Received notification for %s with args %s and kwargs %s', f.__name__, args, kwargs)
            del kwargs['signal']
            del kwargs['sender']
            self._ozw_notif_queue.put((f, args, kwargs))

        return _notif

    def _notif_wrapper_all(self, *args, **kwargs):
        del kwargs['sender']
        self._ozw_notif_queue.put((self.all_notif, args, kwargs))

    def _notif_reader(self):
        while self._running:
            notif = self._ozw_notif_queue.get()
            if notif is None:
                continue

            f, args, kwargs = notif
            logger.debug('Reading notification for %s with args %s and kwargs %s', f.__name__, args, kwargs)
            f(*args, **kwargs)

    def all_notif(self, *args, **kwargs):
        import time
        from pprint import pformat as pf
        extra = []
        if 'value' in kwargs and kwargs['value']:
            extra.append('value: %s' % self._make_uri(kwargs['node'], kwargs['value']))
        elif 'node' in kwargs and kwargs['node']:
            extra.append('node: %s' % (kwargs['node'].name if kwargs['node'].name else kwargs['node'].node_id))
        extra = ' ; '.join(extra)

        if args:
            logger.warning('>~>~># %f: %s ; %s ; %s', time.time(), pf(args), pf(kwargs), extra)
        else:
            logger.warning('>~>~># %f: %s ; %s', time.time(), pf(kwargs), extra)

    # Notifications from PYOZW

    def notif_network_started(self, network):
        logger.info('//////////// ZWave network is started ////////////')
        logger.debug(
            'OpenZWave network is started: \
            homeid %0.8x - %d nodes were found.',
            network.home_id, network.nodes_count
        )

    def notif_network_resetted(self, network):
        logger.warning('OpenZWave network is resetted.')

    def notif_network_ready(self, network):
        logger.info('//////////// ZWave network is ready ////////////')
        logger.debug(
            'ZWave network is ready: %d nodes were found.',
            network.nodes_count
        )

    def notif_node_added(self, network, node):
        node_name = self._node_name(node)
        logger.info('Node added: %s.', node_name)
        self.isac_node.add_rpc(partial(self.node_heal, node), '%s/heal' % node_name)
        self.isac_node.add_rpc(partial(self.node_is_failed, node), '%s/is_failed' % node_name)

    def notif_node_named(self, network, node):
        logger.info('Node named: %s.', self._node_name(node))
        # TODO: renaming of RPC enpoints as well as all IsacValue attached to the node, if the name really changed

    def notif_node_removed(self, network, node):
        logger.info('Node removed: %s.', self._node_name(node))
        # TODO: Remove RPC endpoint (values should be removed by receiving VALUE_REMOVED notif)

    def notif_value_added(self, network, node, value):
        uri = self._make_uri(node, value)

        if uri in self.signals:
            logger.info('%s already registered', uri)
            return
        else:
            logger.info('Registering signal %s', uri)

        self.signals[uri] = {
            'metadata': {
                'uri': uri,
                'label': value.label,
                'help': value.help,
                'max': value.max,
                'min': value.min,
                'units': value.units,
                'genre': value.genre,
                'type': value.type,
                'is_read_only': value.is_read_only,
                'is_write_only': value.is_write_only,
                'instance': value.instance,
                'index': value.index,
                'value_id': value.value_id,
                'node_id': node.node_id,
                'node_name': node.name,
                'location': node.location,
                'home_id': node._network.home_id,
                'command_class': node.get_command_class_as_string(value.command_class),
                'data_items':
                    list(value.data_items)
                    if type(value.data_items) is set
                    else value.data_items,
            },
            'static_tags': {
                'home_id': node._network.home_id,
                'location': node.location,
                'node_id': node.node_id,
                'command_class': node.get_command_class_as_string(value.command_class),
                'index': value.index,
                'instance': value.instance,
            },
            'node_value': (node, value),
        }

        data = self._value_data(value)

        #print '>>>> Creating IV', uri, data
        self.signals[uri]['isac_value'] = IsacValue(
            self.isac_node, uri, data,
            static_tags=self.signals[uri]['static_tags'],
            metadata=self.signals[uri]['metadata'],
            survey_last_value=False,
            survey_static_tags=False
        )
        self.signals[uri]['isac_value'].observers += self._update_data_from_isac

        uri_poll = uri + '/poll'
        self.signals[uri_poll] = {
            'isac_value': IsacValue(
                self.isac_node, uri_poll, value.is_polled,
                survey_last_value=False, survey_static_tags=False
            ),
            'node_value': self.signals[uri]['node_value'],
        }
        self.signals[uri_poll]['isac_value'].observers += self._set_poll_from_isac

    def notif_value_update(self, network, node, value):
        uri = self._make_uri(node, value)

        logger.info('Value update for %s : %s.', uri, value.data)

        if uri not in self.signals:
            logger.info('%s not yet registered, skipping', uri)
            return

        signal = self.signals[uri]

        signal['isac_value'].value = self._value_data(value)

    def notif_value_removed(self, network, node, value):
        pass
        # TODO: Remove IsacValue

    def notif_ctrl_message(self, network, controller, **kwargs):
        # from pprint import pformat as pf
        # logger.warning('Controller message : %s', pf(kwargs))
        pass

    # Update from ISAC

    def _update_data_from_isac(self, isac_value, value, ts, tags):
        uri = isac_value.uri
        signal = self.signals.get(uri, None)
        if signal is None:
            logger.error(
                'Received an update from isac \
                for a signal we don\'t know?! %s',
                uri
            )
            return

        if signal['node_value'][1].is_read_only:
            logger.error(
                'Signal %s is read only but we received an update \
                from isac to write a value, %s, to it',
                uri,
                value
            )
            return

        logger.info('Updating value %s with %s', uri, value)
        signal['node_value'][1].data = value

    def _set_poll_from_isac(self, isac_value, value, ts, tags):
        uri = isac_value.uri
        signal = self.signals.get(uri, None)
        if signal is None:
            logger.error('Signal %s is unknown?!', uri)
            return

        if uri.endswith('/poll'):
            if bool(value):
                try:
                    intensity = int(value)
                except ValueError:
                    intensity = 1

                signal['node_value'][1].enable_poll(intensity)
            else:
                signal['node_value'][1].disable_poll()

    # RPC methods

    # controller: (hard_reset) has_node_failed(nodeid) name remove_failed_node(nodeid) replace_failed_node(nodeid) (soft_reset)
    # node: location name

    # def has_node_failed(self, node_name):
    #     from pprint import pprint as pp
    #     nodes_by_name = {node.name: node for node in self.network.nodes.values()}
    #     pp(nodes_by_name)
    #     node_id = nodes_by_name[node_name].node_id
    #
    #     print nodes_by_name[node_name].is_failed
    #     return self.network.controller.has_node_failed(node_id)

    def network_heal(self, upNodeRoute=False):
        logger.info('Healing network')
        self.network.heal(upNodeRoute)

    def controller_add_node(self, doSecurity=False):
        logger.info('Set controller into inclusion mode')
        return self.network.controller.add_node(doSecurity)

    def controller_remove_node(self):
        logger.info('Set controller into exclusion mode')
        return self.network.controller.remove_node()

    def controller_cancel_command(self):
        logger.info('Cancelling controller command')
        return self.network.controller.cancel_command()

    def node_heal(self, node, upNodeRoute=False):
        logger.info('Healing node %s', self._node_name(node))
        return node.heal(upNodeRoute)

    def node_is_failed(self, node):
        logger.info('Asking if node %s is failed (%s)', self._node_name(node), node.is_failed)
        return node.is_failed

    # Tooling

    @staticmethod
    def _replace_all(s, olds, new):
        return reduce(lambda s, old: s.replace(old, new), list(olds), s)

    def _node_name(self, node):
        return node.name if node.name else str(node.node_id)

    def _value_data(self, value):
        data = value.data
        logger.debug('data type is %s', type(data))
        if type(data) is str:
            try:
                data.decode()
            except UnicodeDecodeError:
                data = binascii.b2a_base64(data)

        return data

    def _make_uri(self, node, value):

        def _values_by_index(values):
            per_idx = {}
            for value in values:
                idx = value.index
                if idx not in per_idx:
                    per_idx[idx] = []
                per_idx[idx].append(value)
            return per_idx

        ok = False
        while not ok:
            try:
                values_by_idx = _values_by_index(node.get_values(class_id=value.command_class).values())
                ok = True
            except RuntimeError as ex:
                if ex.message == 'dictionary changed size during iteration':
                    continue
                else:
                    raise

        is_multi_instance = len(values_by_idx[value.index]) > 1

        cmd_class = node.get_command_class_as_string(value.command_class)
        cmd_class = cmd_class.replace('COMMAND_CLASS_', '').lower()

        node_name = self._node_name(node)
        label = self._replace_all(value.label.lower(), ' /()%:', '_').strip('_')

        if is_multi_instance:
            uri = 'zwave://%s.%s/%s/%d/%s' % (
                node._network.home_id_str, node_name, cmd_class, value.instance, label)
        else:
            uri = 'zwave://%s.%s/%s/%s' % (
                node._network.home_id_str, node_name, cmd_class, label)

        return str(uri)

    # Lifecycle

    def shutdown(self):
        # Stopping internal notification reader greenlet
        self._running = False
        self._ozw_notif_queue.put(None)

        self.network.stop()
        logger.info('Stopped network')
        self.network.destroy()
        logger.info('Destroyed network')
        self.isac_node.shutdown()
        logger.info('Stopped ISAC node')
예제 #15
0
class ZWaveControlPlugin(Plugin):
    @staticmethod
    def get_dependencies():
        return []

    def __init__(self, object_group, config):
        Plugin.__init__(self,
                        config=config,
                        object_group=object_group,
                        plugin_name=PLUGIN_NAME)

        # Get parameters from the config file

        if not self.is_enabled():
            return

        # Initialize zwave library
        # Options
        try:
            opts = ZWaveOption(
                device="/dev/ttyUSB0",
                config_path=
                "/home/mlamonta/git/python-openzwave/openzwave/config/",
                user_path="logs")
            opts.set_log_file("./logs/zwave.log")
            opts.set_save_log_level("Alert")
            opts.set_append_log_file(False)
            opts.set_console_output(False)
            opts.set_logging(True)
            opts.lock()
        except ZWaveException as e:
            self.logger.error(str(e))
            return

        # Network
        self.net = ZWaveNetwork(opts)

        self.logger.info(
            "------------------------------------------------------------")
        self.logger.info("Waiting for network awake : ")
        self.logger.info(
            "------------------------------------------------------------")
        for i in range(0, 300):
            if self.net.state >= self.net.STATE_AWAKED:
                self.logger.info("done")
                break
            else:
                time.sleep(1.0)

        if self.net.state < self.net.STATE_AWAKED:
            self.logger.warning("Network is not awake")
            return

        self.logger.info(
            "------------------------------------------------------------")

        for node in self.net.nodes:
            self.logger.info("%s - %s / %s" %
                             (self.net.nodes[node].node_id,
                              self.net.nodes[node].manufacturer_name,
                              self.net.nodes[node].product_name))

        self._initialized = True

    @staticmethod
    def get_template_config(config):
        config.add_section(PLUGIN_NAME)
        config.set(PLUGIN_NAME, "enabled", "true")

    def stop(self):
        if self.is_initialized():
            self.net.stop()

    @staticmethod
    def get_dimmer_code(uid, name, current_value):
        dimmer_html = """

         <div class="col-md-5">
             <h2>Dimmer</h2>
             <div class="input-group input-group-lg">
                 <input type="text" class="form-control" name="%s" value="%s">  <!-- DIMMER NAME, VALUE -->
                 <div class="input-group-btn">
                     <button name="%s"
                             type="button"
                             class="btn btn-primary"
                             onclick="updateZWave('%s')">Submit</button>
                 </div>
             </div>
             <script>
                 $("input[name='%s']").TouchSpin({
                     min: 0,
                     max: 100,
                     step: 1,
                     decimals: 0,
                     boostat: 5,
                     maxboostedstep: 10,
                     prefix: "Set:",
                     postfix: '%%'
                 });
             </script>
         </div>

         """ % (str(uid), current_value, str(uid) + "_btn", str(uid), str(uid))

        return dimmer_html

    def get_html(self):
        html = ""

        if self.is_initialized():

            html = '<div id="zwave" class="jumbotron">'
            for node in self.net.nodes:

                node_html = ""

                switches = self.net.nodes[node].get_switches()
                for switch in switches:
                    node_html += "<h3>" + str(
                        switches[switch].label) + "  " + str(
                            switches[switch].data) + "</h3>"

                dimmers = self.net.nodes[node].get_dimmers()
                for dimmer in dimmers:
                    node_html += ZWaveControlPlugin.get_dimmer_code(
                        dimmer, "Dimmer: " + str(dimmer),
                        str(dimmers[dimmer].data))

                html += """
                    <div class="row">
                        <div class="col-md-12">
                            <h2>%d: %s - %s</h2>
                            %s
                        </div>
                    </div>
                """ % (self.net.nodes[node].node_id,
                       self.net.nodes[node].manufacturer_name,
                       self.net.nodes[node].product_name, node_html)

            html += "</div>"

        return html

    def parse_zwave_command_message(self, msg):
        try:
            if not self.is_initialized():
                self.logger.warning("Error zwave message while uninitialized")
                return

            if len(msg.split(',')) != 3:
                self.logger.warning("Error parsing zwave message")
                return

            self.logger.debug("Got message: " + msg)

            dev = msg.split(',')[1]
            val = int(msg.split(',')[2])

            # Find the right device and set its value
            for node in self.net.nodes:
                switches = self.net.nodes[node].get_switches()
                for switch in switches:
                    self.logger.debug("checking switch: " + str(switch))
                    if str(switch) == dev:
                        switches[switch].data = switches[switch].check_data(
                            val)
                        self.logger.debug("match")
                        return

                dimmers = self.net.nodes[node].get_dimmers()
                for dimmer in dimmers:
                    self.logger.debug("checking dimmer: " + str(dimmer))
                    if str(dimmer) == dev:
                        dimmers[dimmer].data = dimmers[dimmer].check_data(val)
                        self.logger.debug("match")
                        return

            self.logger.warning("device: " + dev + " not found")

        except Exception as e:
            self.logger.error("Exception in parse_zwave_command_message: " +
                              e.message)

    def get_javascript(self):
        jscript = ""

        if self.is_initialized():
            jscript = """

                function updateZWave(device)
                {
                    var new_value = $("input[name='"+device+"']").val()

                    $.get("cgi-bin/web_control.py?set_zwave="+new_value+"&device="+device, function (result)
                    {
                        if (result.trim() == "OK")
                        {
                            $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            $("button[name='"+device+"_btn']").toggleClass('btn-success');
                            setTimeout(function()
                            {
                                $("button[name='"+device+"_btn']").toggleClass('btn-success');
                                $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            }, 5000);
                        }
                        else
                        {
                            $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            $("button[name='"+device+"_btn']").toggleClass('btn-danger');
                            alert(result);
                            setTimeout(function()
                            {
                                $("button[name='"+device+"_btn']").toggleClass('btn-danger');
                                $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            }, 5000);
                        }
                    });
                }

                """

        return jscript
예제 #16
0
파일: check.py 프로젝트: chenchenece/zwave
class ZwaveNetworkDebug:
    """
        Class of zwavenetwork:
        In the context of the instance of ZwaveNetwork the instance of zwave 
        sensor and zwave actuator is able to proceeded.
    """
    def __init__(self):
        """
            Initialize using zwave.json config file defined in CONFIG variable
        """
        multisensor_cred = Setting(CONFIG)
        self.device = str(multisensor_cred.setting["device"])
        self.log = str(multisensor_cred.setting["log"])
        self.log_file = str(multisensor_cred.setting["log_file"])
        self.write_file = bool(multisensor_cred.setting["write_log_file"])
        self.output_console = bool(multisensor_cred.setting["write_console"])
        # format config dict

    def network_init(self):
        """
            Zwave network initialization.
            Terminate program if initialization failed.
        """
        logging.basicConfig(level=logging.INFO)
        logger = logging.getLogger('openzwave')

        # option initialization, abort if initialization failed
        try:
            options = ZWaveOption(self.device, \
             config_path="../openzwave/config", \
             user_path=".", cmd_line="")
            options.set_log_file(self.log_file)
            options.set_append_log_file(self.write_file)
            options.set_console_output(self.output_console)
            options.set_save_log_level(self.log)
            options.set_logging(False)
            options.lock()
        except Exception as e:
            print("Zwave initialization failed!")
            print("Please check the USB port of Zwave Stick")
            print(e)
            sys.exit(-1)

        # create a network instance
        self.network = ZWaveNetwork(options, log=None)

    def network_awake(self):
        """
            Awake zwave network.
            Terminated program if awake failed! 
        """
        print("INFO: Waiting for network awaked :")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_AWAKED:
                break
            else:
                sys.stdout.write('.')
                sys.stdout.flush()
                time.sleep(1.0)

        if self.network.state < self.network.STATE_AWAKED:
            sys.exit("Network is not awake, program abort!")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_READY:
                break
            else:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1.0)

        if not self.network.is_ready:
            sys.exit("Network is not ready, program abort!")
        print("\nINFO: Network [{}] awaked!".format(self.network.home_id_str))
        print("INFO: Number of nodes: [{}]".format(self.network.nodes_count))

    def network_stop(self):
        """
            Stop network.
        """
        self.network.stop()
        print("INFO: Network stopped")

    def check_node_connection(self, node_id):
        """ 
            This function aims to check whether the node (specified by 
            node_id) is connected in network. If not, the value, which is old 
            historical data, will be abandoned.

            Args: node id of specified nodes in network
            Return: ture if node is still connected in the network, or 
            otherwise 

            Note: this function is used for debugging purpose
        """
        if self.network.manager.isNodeFailed(self.network.home_id, node_id):
            return False
        return True

    def check_all_nodes_connection(self):
        for node in self.network.nodes:
            if not self.check_node_connection(node):
                return False
        return True

    def print_network(self):
        """
            Print network info.
            The module is modified based on example demo program in openzwave 
            library.

            Args: instance of network
            Return: None
        """
        print("Network home id : {}".format(self.network.home_id_str))
        print("Controller node id : {}" \
            .format(self.network.controller.node.node_id))
        print("Nodes in network : {}".format(self.network.nodes_count))
        print("Controller capabilities : {}" \
            .format(self.network.controller.capabilities))
        print("Controller node capabilities : {}" \
            .format(self.network.controller.node.capabilities))
        print("Nodes in network : {}".format(self.network.nodes_count))
        print("-" * SEPARATOR_LENGTH)

    def print_nodes(self):
        """
            Print ALL nodes info.
            The module is modified based on example demo program in openzwave 
            library.

            Args: instance of network
            Return: None
        """
        for node in self.network.nodes:
            print("-" * SEPARATOR_LENGTH)
            print("{} - Name : {}" \
                .format(self.network.nodes[node].node_id, \
                    self.network.nodes[node].name))
            print("{} - Manufacturer name / id : {} / {}" \
                .format(self.network.nodes[node].node_id, \
                    self.network.nodes[node].manufacturer_name, \
                    self.network.nodes[node].manufacturer_id))
            print("{} - Product name / id / type : {} / {} / {}" \
                .format(self.network.nodes[node].node_id, \
                    self.network.nodes[node].product_name, \
                    self.network.nodes[node].product_id, \
                    self.network.nodes[node].product_type))
            # work through each nodes
            for val in self.network.nodes[node].values:
                print("{} - value id: {}".format(node, val))
                print("{} - value label: {}" \
                    .format(node, self.network.nodes[node].values[val].label))
                print("{} - value max: {}" \
                    .format(node, self.network.nodes[node].values[val].max))
                print("{} - value min: {}" \
                    .format(node, self.network.nodes[node].values[val].min))
                print("{} - units: {}" \
                    .format(node, self.network.nodes[node].values[val].units))
                print("-" * int(SEPARATOR_LENGTH / 2))
            print("-" * SEPARATOR_LENGTH)
예제 #17
0
class ZwaveNetwork:
    """
        Class of zwavenetwork:
        In the context of the instance of ZwaveNetwork the instance of zwave 
        sensor and zwave actuator is able to proceeded.
    """
    def __init__(self):
        """
            Initialize using zwave.json config file defined in CONFIG variable
        """
        global MAX_THREAD
        global listen
        multisensor_cred = Setting(CONFIG)
        self.device = str(multisensor_cred.setting["device"])
        self.log = str(multisensor_cred.setting["log"])
        self.log_file = str(multisensor_cred.setting["log_file"])
        self.write_file = bool(multisensor_cred.setting["write_log_file"])
        self.output_console = bool(multisensor_cred.setting["write_console"])
        # format config dict
        self.config = {}
        for config_k, config_v in multisensor_cred.setting["config"].items():
            item = {}
            for k, v in config_v.iteritems():
                item[int(k)] = int(v)   
            self.config[int(config_k)] = item

        for k, v in multisensor_cred.setting["listen"].items():
            item = []
            for node in v:
                item.append(str(node))
            listen[int(k)] = item

        self.mapping  = {int(k): str(v) \
            for k, v in multisensor_cred.setting["mapping"].iteritems()}
        MAX_THREAD = int(multisensor_cred.setting["MAX_THREAD"])

    def network_init(self):
        """
            Zwave network initialization.
            Terminate program if initialization failed.
        """
        logging.basicConfig(level=logging.INFO)
        logger = logging.getLogger('openzwave')

        # option initialization, abort if initialization failed
        try:
            options = ZWaveOption(self.device, \
             config_path="../openzwave/config", \
             user_path=".", cmd_line="")
            options.set_log_file(self.log_file)
            options.set_append_log_file(self.write_file)
            options.set_console_output(self.output_console)
            options.set_save_log_level(self.log)
            options.set_logging(False)
            options.lock()
        except Exception as e:
            print("Zwave initialization failed!")
            print("Please check the USB port of Zwave Stick")
            print(e)
            sys.exit(-1)

        # create a network instance
        self.network = ZWaveNetwork(options, log=None)

    def network_awake(self):
        """
            Awake zwave network.
            Terminated program if awake failed! 
        """
        print("INFO: Waiting for network awaked :")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_AWAKED:
                break
            else:
                sys.stdout.write('.')
                sys.stdout.flush()
                time.sleep(1.0)

        if self.network.state < self.network.STATE_AWAKED:
            sys.exit("Network is not awake, program abort!")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_READY:
                break
            else:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1.0)

        if not self.network.is_ready:
            sys.exit("Network is not ready, program abort!")
        print("\nINFO: Network [{}] awaked!" .format(self.network.home_id_str))
        print("INFO: Number of nodes: [{}]" .format(self.network.nodes_count))

    def config_node(self, node_id):
        """
            config a node specified by node id.

            Args: node id of specific node
            Return: None
        """
        if node_id in self.config:
            for k, v in self.config[node_id].iteritems():
                self.network.nodes[node_id].set_config_param(k, v)

    def config_all_nodes(self):
        """
            set all nodes using parameter and value specified in zwave.json.
            And update node name according to zwave.json file.

            Args: None
            Return: None
        """
        for node_id in self.network.nodes:
            self.config_node(node_id)
            self.update_node_name(node_id)

    def update_node_name(self, node_id):
        """
            update the nodes' name according to zwave.json config file

            Args: node_id the id of node (a positive integer)
            Return: None
        """
        if node_id in self.mapping:
            self.network.nodes[node_id].name = self.mapping[node_id]

    def network_stop(self):
        """
            Stop network.
        """
        self.network.stop()
        print("INFO: Network stopped")

    @staticmethod
    def check_node_connection(network, node_id):
        """ 
            This function aims to check whether the node (specified by 
            node_id) is connected in network. If not, the value, which is old 
            historical data, will be abandoned.

            Args: node id of specified nodes in network
            Return: ture if node is still connected in the network, or 
            otherwise 

            Note: this function is used for debugging purpose
        """
        if network.manager.isNodeFailed(network.home_id, node_id):
            return False
        return True
예제 #18
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)
예제 #19
0
def list_nodes(args):
    global home_id
    if args.timeout is None:
        args.timeout = 60 * 60 * 4 + 1
    import openzwave
    from openzwave.node import ZWaveNode
    from openzwave.value import ZWaveValue
    from openzwave.scene import ZWaveScene
    from openzwave.controller import ZWaveController
    from openzwave.network import ZWaveNetwork
    from openzwave.option import ZWaveOption

    #Define some manager options
    print(
        "-------------------------------------------------------------------------------"
    )
    print("Define options for device {0}".format(args.device))
    options = ZWaveOption(device=args.device,
                          config_path=args.config_path,
                          user_path=args.user_path)
    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()

    print("Start network")
    network = ZWaveNetwork(options, log=None)

    delta = 0.5
    for i in range(0, int(args.timeout / delta)):
        time.sleep(delta)
        if network.state >= network.STATE_AWAKED:
            break

    print(
        "-------------------------------------------------------------------------------"
    )
    print("Network is awaked. Talk to controller.")
    print("Get python_openzwave version : {}".format(
        network.controller.python_library_version))
    print("Get python_openzwave config version : {}".format(
        network.controller.python_library_config_version))
    print("Get python_openzwave flavor : {}".format(
        network.controller.python_library_flavor))
    print("Get openzwave version : {}".format(
        network.controller.ozw_library_version))
    print("Get config path : {}".format(
        network.controller.library_config_path))
    print("Controller capabilities : {}".format(
        network.controller.capabilities))
    print("Controller node capabilities : {}".format(
        network.controller.node.capabilities))
    print("Nodes in network : {}".format(network.nodes_count))

    print(
        "-------------------------------------------------------------------------------"
    )
    if args.timeout > 1800:
        print(
            "You defined a really long timneout. Please use --help to change this feature."
        )
    print("Wait for network ready ({0}s)".format(args.timeout))
    for i in range(0, int(args.timeout / delta)):
        time.sleep(delta)
        if network.state == network.STATE_READY:
            break
    print(
        "-------------------------------------------------------------------------------"
    )
    if network.state == network.STATE_READY:
        print("Network is ready. Get nodes")
    elif network.state == network.STATE_AWAKED:
        print(
            "Network is awake. Some sleeping devices may miss. You can increase timeout to get them. But will continue."
        )
    else:
        print(
            "Network is still starting. You MUST increase timeout. But will continue."
        )

    for node in network.nodes:

        print("------------------------------------------------------------")
        print("{} - Name : {} ( Location : {} )".format(
            network.nodes[node].node_id, network.nodes[node].name,
            network.nodes[node].location))
        print(" {} - Ready : {} / Awake : {} / Failed : {}".format(
            network.nodes[node].node_id, network.nodes[node].is_ready,
            network.nodes[node].is_awake, network.nodes[node].is_failed))
        print(" {} - Manufacturer : {}  ( id : {} )".format(
            network.nodes[node].node_id, network.nodes[node].manufacturer_name,
            network.nodes[node].manufacturer_id))
        print(
            " {} - Product : {} ( id  : {} / type : {} / Version : {})".format(
                network.nodes[node].node_id, network.nodes[node].product_name,
                network.nodes[node].product_id,
                network.nodes[node].product_type, network.nodes[node].version))
        print(" {} - Command classes : {}".format(
            network.nodes[node].node_id,
            network.nodes[node].command_classes_as_string))
        print(" {} - Capabilities : {}".format(
            network.nodes[node].node_id, network.nodes[node].capabilities))
        print(" {} - Neighbors : {} / Power level : {}".format(
            network.nodes[node].node_id, network.nodes[node].neighbors,
            network.nodes[node].get_power_level()))
        print(" {} - Is sleeping : {} / Can wake-up : {} / Battery level : {}".
              format(network.nodes[node].node_id,
                     network.nodes[node].is_sleeping,
                     network.nodes[node].can_wake_up(),
                     network.nodes[node].get_battery_level()))

    print("------------------------------------------------------------")
    print("Driver statistics : {}".format(network.controller.stats))
    print("------------------------------------------------------------")
    print("Stop network")
    network.stop()
    print("Exit")
예제 #20
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'])
예제 #21
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"
예제 #22
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)
예제 #23
0
class ZwaveNetwork:
    def __init__(self):
        """
            Initialize using zwave.json config file defined in CONFIG variable
        """
        # check will not be changed once it is initialized
        global listen
        global MAX_THREAD
        multisensor_cred = Setting(CONFIG)
        self.device = str(multisensor_cred.setting["device"])
        self.log = str(multisensor_cred.setting["log"])
        self.log_file = str(multisensor_cred.setting["log_file"])
        self.write_file = bool(multisensor_cred.setting["write_log_file"])
        self.output_console = bool(multisensor_cred.setting["write_console"])

        self.config = {}
        # format config dict
        for config_k, config_v in multisensor_cred.setting["config"].items():
            item = {}
            for k, v in config_v.iteritems():
                item[int(k)] = int(v)
            self.config[int(config_k)] = item
        # format listen item
        for k, v in multisensor_cred.setting["listen"].items():
            item = []
            for node in v:
                item.append(str(node))
            listen[int(k)] = item
        MAX_THREAD = int(multisensor_cred.setting["MAX_THREAD"])

    def network_init(self):
        """
            Zwave network initialization.
            Terminate program if initialization failed.
        """
        logging.basicConfig(level=logging.INFO)
        logger = logging.getLogger('openzwave')

        # option initialization, abort if initialization failed
        try:
            options = ZWaveOption(self.device, \
             config_path="../openzwave/config", \
             user_path=".", cmd_line="")
            options.set_log_file(self.log_file)
            options.set_append_log_file(self.write_file)
            options.set_console_output(self.output_console)
            options.set_save_log_level(self.log)
            options.set_logging(False)
            options.lock()
        except Exception as e:
            print(
                "Zwave initialization failed! \nPlease listen the USB port of zwave stick!"
            )
            print(e)
            sys.exit(-1)

        # create a network instance
        self.network = ZWaveNetwork(options, log=None)

    def network_awake(self):
        """
            Awake zwave network.
            Terminated program if awake failed! """
        print("INFO: Waiting for network awaked : ")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_AWAKED:
                break
            else:
                sys.stdout.write('.')
                sys.stdout.flush()
                time.sleep(1.0)

        if self.network.state < self.network.STATE_AWAKED:
            sys.exit("Network is not awake, program abort!")

        for i in range(0, 300):
            if self.network.state >= self.network.STATE_READY:
                break
            else:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1.0)

        if not self.network.is_ready:
            sys.exit("Network is not ready, program abort!")
        print("\nINFO: Network [{}] awaked!".format(self.network.home_id_str))
        print("INFO: Number of nodes: [{}]".format(self.network.nodes_count))

    def config_node(self, node_id):
        """
            config a node specified by node id.

            Args: node id of specific node
            Return: None
        """
        if node_id in self.config:
            for k, v in self.config[node_id]:
                print("key = " + str(k) + " value = " + str(v))
                self.networks.nodes[node_id].set_config_param(k, v)

    def config_all_nodes(self):
        """
            config all nodes using parameter and value specified in zwave.json

            Args: None
            Return: None
        """
        for ndoe_id in self.network.nodes:
            config_node(node_id)

    def network_stop(self):
        """
            Stop network.
        """
        self.network.stop()
        print("INFO: Network stopped")

    def check_node_connection(self, node_id):
        """ 
            This function aims to check whether the node (specified by node_id) is connected in network. If not, the value, which is old historical data, will be abandoned.

            Args: node id of specified nodes in network
            Return: ture if node is still connected in the network, or otherwise 

            Note: this function is used for debugging purpose
        """
        if self.network.manager.isNodeFailed(self.network.home_id, node_id):
            print("WARN: Node [{}] is failed!".format(node_id))
            return False
        return True

    def check_all_nodes_connection(self):
        """ 
            This function aims to check whether ALL nodes is connected in network. If any 'dead' node is detected, the function will return false.

            Args: None
            Return: ture if all node is still connected in the network, or otherwise

            Note: this function is used for debugging purpose
        """
        for node in self.network.nodes:
            if not self.check_node_connection(node):
                return False
        return True

    @staticmethod
    def get_mac_id(node):
        """
            Assemble manufacturer id, product type and product id to standard mac assress format.

            Args: instance of a node
            Return: String of standard mac address format
        """
        mac_str= node.manufacturer_id[2:] + \
            node.product_type[2:] + \
            node.product_id[2:]
        return ':'.join(mac_str[i:i + 2] for i in range(0, len(mac_str), 2))

    @staticmethod
    def get_source_name(network, node, value):
        """
            build src name for each sensor points
        """
        src = []
        src.append(hex(network.home_id))
        src.append(node.name)
        src.append(value.label)
        if not value.units == '':
            src.append(value.units)
        return '_'.join(src)
예제 #24
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"
예제 #25
0
class ZStickInterface(object):
    def __init__(self):
        self.sensor_events = []
        self.device = "/dev/ttyACM0"
        config_path = "plugins/python-openzwave/openzwave/config"
        user_path = "plugins/python-openzwave/config"
        # If using older Z-sticks, use the below device:
        # self.device = "/dev/ttyUSB0"
        # Change config paths where appropriate
        self.options = ZWaveOption(self.device, config_path=config_path,
                                   user_path=user_path, cmd_line="")
        # Turn off ozw console output
        self.options.set_console_output(False)
        self.options.set_save_log_level("Info")
        self.options.set_logging(False)
        self.options.lock()

        self.manager = libopenzwave.PyManager()
        self.manager.create()
        self.manager.addWatcher(self.event_callback)
        self.manager.addDriver(self.device)

        print("Starting Z-Wave Network...")
        self.network = ZWaveNetwork(self.options, log=None)
        # Wait for network to start
        while not self.network.state >= self.network.STATE_AWAKED:
            time.sleep(1)
        print("Z-Wave Network Started")

    def toggle_switch(self, node_id):
        try:
            in_work_node = self.network.nodes[node_id]
            switch_val = in_work_node.get_switches().keys()[0]
            if in_work_node.get_switch_state(switch_val):
                in_work_node.set_switch(switch_val, False)
            else:
                in_work_node.set_switch(switch_val, True)
        except:
            print("Invalid node id")

    def switch(self, node_id, state, function):
        try:
            in_work_node = self.network.nodes[node_id]
            if function == "dimmer":
                switch_val = in_work_node.get_dimmers().keys()[0]
                if state == "False":
                    in_work_node.set_dimmer(switch_val, 0)
                elif state == "True":
                    in_work_node.set_dimmer(switch_val, 99)
                else:
                    in_work_node.set_dimmer(switch_val, int(state))
            elif function == "switch":
                switch_val = in_work_node.get_switches().keys()[0]
                if state == "False":
                    in_work_node.set_switch(switch_val, False)
                else:
                    in_work_node.set_switch(switch_val, True)
        except:
            print("Invalid node id")

    def event_callback(self, args):
        if args["notificationType"] in ("ValueAdded", "ValueChanged"):
            cmd_class = args["valueId"]["commandClass"]
            if cmd_class == "COMMAND_CLASS_SENSOR_BINARY":
                node_id = args["valueId"]["nodeId"]
                state = args["valueId"]["value"]
                data = {"node_id": node_id, "state": state}
                self.sensor_events.append(data)

    def get_sensor_events(self):
        last_events = self.sensor_events
        self.sensor_events = []
        return last_events

    def stop_network(self):
        self.network.stop()
예제 #26
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()
예제 #27
0
class ZWaveControlPlugin(Plugin):

    @staticmethod
    def get_dependencies():
        return []

    def __init__(self, object_group, config):
        Plugin.__init__(self, config=config, object_group=object_group, plugin_name=PLUGIN_NAME)

        # Get parameters from the config file

        if not self.is_enabled():
            return

        # Initialize zwave library
        # Options
        try:
            opts = ZWaveOption(device="/dev/ttyUSB0",
                               config_path="/home/mlamonta/git/python-openzwave/openzwave/config/",
                               user_path="logs")
            opts.set_log_file("./logs/zwave.log")
            opts.set_save_log_level("Alert")
            opts.set_append_log_file(False)
            opts.set_console_output(False)
            opts.set_logging(True)
            opts.lock()
        except ZWaveException as e:
            self.logger.error(str(e))
            return

        # Network
        self.net = ZWaveNetwork(opts)

        self.logger.info("------------------------------------------------------------")
        self.logger.info("Waiting for network awake : ")
        self.logger.info("------------------------------------------------------------")
        for i in range(0, 300):
            if self.net.state >= self.net.STATE_AWAKED:
                self.logger.info("done")
                break
            else:
                time.sleep(1.0)

        if self.net.state < self.net.STATE_AWAKED:
            self.logger.warning("Network is not awake")
            return

        self.logger.info("------------------------------------------------------------")

        for node in self.net.nodes:
            self.logger.info("%s - %s / %s" % (self.net.nodes[node].node_id,
                                               self.net.nodes[node].manufacturer_name,
                                               self.net.nodes[node].product_name) )

        self._initialized = True

    @staticmethod
    def get_template_config(config):
        config.add_section(PLUGIN_NAME)
        config.set(PLUGIN_NAME, "enabled", "true")
        
    def stop(self):
        if self.is_initialized():
            self.net.stop()

    @staticmethod
    def get_dimmer_code(uid, name, current_value):
        dimmer_html = """

         <div class="col-md-5">
             <h2>Dimmer</h2>
             <div class="input-group input-group-lg">
                 <input type="text" class="form-control" name="%s" value="%s">  <!-- DIMMER NAME, VALUE -->
                 <div class="input-group-btn">
                     <button name="%s"
                             type="button"
                             class="btn btn-primary"
                             onclick="updateZWave('%s')">Submit</button>
                 </div>
             </div>
             <script>
                 $("input[name='%s']").TouchSpin({
                     min: 0,
                     max: 100,
                     step: 1,
                     decimals: 0,
                     boostat: 5,
                     maxboostedstep: 10,
                     prefix: "Set:",
                     postfix: '%%'
                 });
             </script>
         </div>

         """ % (str(uid),
                current_value,
                str(uid) + "_btn",
                str(uid),
                str(uid) )

        return dimmer_html

    def get_html(self):
        html = ""
        
        if self.is_initialized():

            html = '<div id="zwave" class="jumbotron">'
            for node in self.net.nodes:

                node_html = ""

                switches = self.net.nodes[node].get_switches()
                for switch in switches:
                    node_html += "<h3>" + str(switches[switch].label) + "  " + str(switches[switch].data) + "</h3>"

                dimmers = self.net.nodes[node].get_dimmers()
                for dimmer in dimmers:
                    node_html += ZWaveControlPlugin.get_dimmer_code(dimmer,
                                                                    "Dimmer: " + str(dimmer),
                                                                    str(dimmers[dimmer].data))

                html += """
                    <div class="row">
                        <div class="col-md-12">
                            <h2>%d: %s - %s</h2>
                            %s
                        </div>
                    </div>
                """ % ( self.net.nodes[node].node_id,
                        self.net.nodes[node].manufacturer_name,
                        self.net.nodes[node].product_name,
                        node_html )

            html += "</div>"

        return html

    def parse_zwave_command_message(self, msg):
        try:
            if not self.is_initialized():
                self.logger.warning("Error zwave message while uninitialized")
                return

            if len(msg.split(',')) != 3:
                self.logger.warning("Error parsing zwave message")
                return

            self.logger.debug("Got message: " + msg)

            dev = msg.split(',')[1]
            val = int(msg.split(',')[2])

            # Find the right device and set its value
            for node in self.net.nodes:
                switches = self.net.nodes[node].get_switches()
                for switch in switches:
                    self.logger.debug("checking switch: " + str(switch))
                    if str(switch) == dev:
                        switches[switch].data = switches[switch].check_data(val)
                        self.logger.debug("match")
                        return

                dimmers = self.net.nodes[node].get_dimmers()
                for dimmer in dimmers:
                    self.logger.debug("checking dimmer: " + str(dimmer) )
                    if str(dimmer) == dev:
                        dimmers[dimmer].data = dimmers[dimmer].check_data(val)
                        self.logger.debug("match")
                        return

            self.logger.warning("device: " + dev + " not found")

        except Exception as e:
            self.logger.error("Exception in parse_zwave_command_message: " + e.message)

    def get_javascript(self):
        jscript = ""

        if self.is_initialized():
            jscript = """

                function updateZWave(device)
                {
                    var new_value = $("input[name='"+device+"']").val()

                    $.get("cgi-bin/web_control.py?set_zwave="+new_value+"&device="+device, function (result)
                    {
                        if (result.trim() == "OK")
                        {
                            $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            $("button[name='"+device+"_btn']").toggleClass('btn-success');
                            setTimeout(function()
                            {
                                $("button[name='"+device+"_btn']").toggleClass('btn-success');
                                $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            }, 5000);
                        }
                        else
                        {
                            $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            $("button[name='"+device+"_btn']").toggleClass('btn-danger');
                            alert(result);
                            setTimeout(function()
                            {
                                $("button[name='"+device+"_btn']").toggleClass('btn-danger');
                                $("button[name='"+device+"_btn']").toggleClass('btn-primary');
                            }, 5000);
                        }
                    });
                }

                """
        
        return jscript
예제 #28
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
예제 #29
0
class TestApi(TestPyZWave):
    """
    Parent test class for api
    """
    @classmethod
    def setUpClass(self):
        super(TestApi, self).setUpClass()
        self.options = ZWaveOption(device=self.device, user_path=self.userpath)
        self.options.set_log_file("OZW_Log.log")
        self.options.set_append_log_file(False)
        self.options.set_console_output(self.ozwout)
        self.options.set_save_log_level(self.ozwlog)
        self.options.set_logging(True)
        self.options.lock()
        dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE)
        self.network = ZWaveNetwork(self.options)
        self.node_result = None
        self.ctrl_command_result = None
        self.ctrl_command_signal = None
        #dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND)
        time.sleep(1.0)

    @classmethod
    def tearDownClass(self):
        self.network.stop()
        time.sleep(2.0)
        self.network.destroy()
        time.sleep(1.0)
        super(TestApi, self).tearDownClass()
        self.network = None

    def setUp(self):
        self.node_result = None
        self.ctrl_command_result = None
        self.ctrl_command_signal = None
        self.wait_for_network_state(self.network.STATE_AWAKED, 1)
        time.sleep(1.0)
        self.wait_for_queue()
        self.active_nodes = {}
        for node in self.network.nodes:
            if self.network.nodes[node].is_info_received:
                self.active_nodes[node] = self.network.nodes[node]
        print('active nodes : %s' % self.active_nodes)

    def wait_for_queue(self):
        for i in range(0, 60):
            if self.network.controller.send_queue_count <= 0:
                break
            else:
                time.sleep(0.5)

    def wait_for_network_state(self, state, multiply=1):
        for i in range(0, SLEEP * multiply):
            if self.network.state >= state:
                break
            else:
                time.sleep(1.0)

    def ctrl_message(
        self,
        network,
        controller,
        node,
        node_id,
        state_int,
        state,
        state_full,
        error_int,
        error,
        error_full,
    ):
        self.ctrl_state_result = state
        self.ctrl_command_signal = {
            'network': network,
            'controller': controller,
            'node': node,
            'node_id': node_id,
            'state_int': state_int,
            'state': state,
            'state_full': state_full,
            'error_int': error_int,
            'error': error,
            'error_full': error_full,
        }

    def ctrl_waiting(self, network, controller, state_int, state, state_full):
        self.ctrl_state_result = state

    def node_update(self, network, node):
        self.node_result = node
예제 #30
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
예제 #31
0
print "------------------------------------------------------------"

#print
#print "------------------------------------------------------------"
#print "Activate the switches on the network"
#print "Nodes in network : %s" % network.nodes_count
#print "------------------------------------------------------------"
#for node in network.nodes:
#    for val in network.nodes[node].get_switches() :
#        print("Activate switch %s on node %s" % \
#                (network.nodes[node].values[val].label,node))
#        network.nodes[node].set_switch(val,True)
#        print("Sleep 10 seconds")
#        time.sleep(10.0)
#        print("Dectivate switch %s on node %s" % \
#                (network.nodes[node].values[val].label,node))
#        network.nodes[node].set_switch(val,False)
#print "%s" % ('Done')
#print "------------------------------------------------------------"

print
print "------------------------------------------------------------"
print "Driver statistics : %s" % network.controller.stats
print "------------------------------------------------------------"

print
print "------------------------------------------------------------"
print "Stop network"
print "------------------------------------------------------------"
network.stop()
예제 #32
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')
예제 #33
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
예제 #34
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")