Esempio n. 1
0
    def test_len(self):
        """Test len() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()
        self.assertEqual(len(devices), 0)

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)
        self.assertEqual(len(devices), 1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)
        self.assertEqual(len(devices), 2)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)
        self.assertEqual(len(devices), 3)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)
        self.assertEqual(len(devices), 4)
Esempio n. 2
0
    def test_iter(self):
        """Test __iter__() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')

        devices.add(light2)

        self.assertEqual(
            tuple(devices.__iter__()),
            (light1, sensor1, sensor2, light2))
Esempio n. 3
0
    def __init__(self,
                 config=None,
                 loop=None,
                 own_address=Address(DEFAULT_ADDRESS),
                 address_format=AddressFormat.LEVEL3,
                 telegram_received_cb=None,
                 device_updated_cb=None):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = None
        self.knxip_interface = None
        self.started = False
        self.address_format = address_format
        self.own_address = own_address
        self.logger = logging.getLogger('xknx.log')
        self.knx_logger = logging.getLogger('xknx.knx')
        self.telegram_logger = logging.getLogger('xknx.telegram')

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)
Esempio n. 4
0
    def test_len(self):
        """Test len() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()
        self.assertEqual(len(devices), 0)

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)
        self.assertEqual(len(devices), 1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)
        self.assertEqual(len(devices), 2)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)
        self.assertEqual(len(devices), 3)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)
        self.assertEqual(len(devices), 4)
Esempio n. 5
0
File: xknx.py Progetto: XKNX/xknx
    def __init__(
            self,
            own_address: str | IndividualAddress = DEFAULT_ADDRESS,
            address_format: GroupAddressType = GroupAddressType.LONG,
            telegram_received_cb: Callable[[Telegram], Awaitable[None]]
        | None = None,
            device_updated_cb: Callable[[Device], Awaitable[None]]
        | None = None,
            connection_state_changed_cb: Callable[[XknxConnectionState],
                                                  Awaitable[None]]
        | None = None,
            rate_limit: int = DEFAULT_RATE_LIMIT,
            multicast_group: str = DEFAULT_MCAST_GRP,
            multicast_port: int = DEFAULT_MCAST_PORT,
            log_directory: str | None = None,
            state_updater: TrackerOptionType = False,
            daemon_mode: bool = False,
            connection_config: ConnectionConfig = ConnectionConfig(),
    ) -> None:
        """Initialize XKNX class."""
        self.connection_manager = ConnectionManager()
        self.devices = Devices()
        self.knxip_interface = knx_interface_factory(
            self, connection_config=connection_config)
        self.management = Management(self)
        self.telegrams: asyncio.Queue[Telegram | None] = asyncio.Queue()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self,
                                          default_tracker_option=state_updater)
        self.task_registry = TaskRegistry(self)

        self.current_address = IndividualAddress(0)
        self.daemon_mode = daemon_mode
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.own_address = IndividualAddress(own_address)
        self.rate_limit = rate_limit
        self.sigint_received = asyncio.Event()
        self.started = asyncio.Event()
        self.version = VERSION

        GroupAddress.address_format = address_format  # for global string representation
        if log_directory is not None:
            self.setup_logging(log_directory)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

        if connection_state_changed_cb is not None:
            self.connection_manager.register_connection_state_changed_cb(
                connection_state_changed_cb)
Esempio n. 6
0
File: xknx.py Progetto: phbaer/xknx
    def __init__(self,
                 config=None,
                 loop=None,
                 own_address=PhysicalAddress(DEFAULT_ADDRESS),
                 address_format=GroupAddressType.LONG,
                 telegram_received_cb=None,
                 device_updated_cb=None,
                 rate_limit=DEFAULT_RATE_LIMIT):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = None
        self.knxip_interface = None
        self.started = False
        self.address_format = address_format
        self.own_address = own_address
        self.rate_limit = rate_limit
        self.logger = logging.getLogger('xknx.log')
        self.knx_logger = logging.getLogger('xknx.knx')
        self.telegram_logger = logging.getLogger('xknx.telegram')
        self.connection_config = None

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)
Esempio n. 7
0
    def test_contains(self):
        """Test __contains__() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)
        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)
        self.assertTrue('Living-Room.Light_1' in devices)
        self.assertTrue('Living-Room.Light_2' in devices)
        self.assertFalse('Living-Room.Light_3' in devices)
Esempio n. 8
0
File: xknx.py Progetto: mielune/xknx
    def __init__(
            self,
            config=None,
            own_address=DEFAULT_ADDRESS,
            address_format=GroupAddressType.LONG,
            telegram_received_cb=None,
            device_updated_cb=None,
            rate_limit=DEFAULT_RATE_LIMIT,
            multicast_group=DEFAULT_MCAST_GRP,
            multicast_port=DEFAULT_MCAST_PORT,
            log_directory=None,
            state_updater=False,
            daemon_mode=False,
            connection_config=ConnectionConfig(),
    ):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self)
        self.knxip_interface = None
        self.started = asyncio.Event()
        self.address_format = address_format
        self.own_address = PhysicalAddress(own_address)
        self.rate_limit = rate_limit
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.connection_config = connection_config
        self.start_state_updater = state_updater
        self.daemon_mode = daemon_mode
        self.version = VERSION

        if log_directory is not None:
            self.setup_logging(log_directory)

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)
Esempio n. 9
0
    def __init__(
        self,
        config: Optional[str] = None,
        own_address: Union[str, IndividualAddress] = DEFAULT_ADDRESS,
        address_format: GroupAddressType = GroupAddressType.LONG,
        telegram_received_cb: Optional[Callable[[Telegram], Awaitable[None]]] = None,
        device_updated_cb: Optional[Callable[[Device], Awaitable[None]]] = None,
        rate_limit: int = DEFAULT_RATE_LIMIT,
        multicast_group: str = DEFAULT_MCAST_GRP,
        multicast_port: int = DEFAULT_MCAST_PORT,
        log_directory: Optional[str] = None,
        state_updater: bool = False,
        daemon_mode: bool = False,
        connection_config: ConnectionConfig = ConnectionConfig(),
    ) -> None:
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams: asyncio.Queue[Optional[Telegram]] = asyncio.Queue()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self)
        self.knxip_interface: Optional[KNXIPInterface] = None
        self.started = asyncio.Event()
        self.connected = asyncio.Event()
        self.address_format = address_format
        self.own_address = IndividualAddress(own_address)
        self.rate_limit = rate_limit
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.connection_config = connection_config
        self.start_state_updater = state_updater
        self.daemon_mode = daemon_mode
        self.version = VERSION

        if log_directory is not None:
            self.setup_logging(log_directory)

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)
Esempio n. 10
0
 def test_modification_of_device(self):
     """Test if devices object does store references and not copies of objects."""
     xknx = XKNX(loop=self.loop)
     devices = Devices()
     light1 = Light(xknx,
                    'Living-Room.Light_1',
                    group_address_switch='1/6/7')
     devices.add(light1)
     for device in devices:
         self.loop.run_until_complete(asyncio.Task(device.set_on()))
     self.assertTrue(light1.state)
     device2 = devices["Living-Room.Light_1"]
     self.loop.run_until_complete(asyncio.Task(device2.set_off()))
     self.assertFalse(light1.state)
     for device in devices.devices_by_group_address(GroupAddress('1/6/7')):
         self.loop.run_until_complete(asyncio.Task(device.set_on()))
     self.assertTrue(light1.state)
Esempio n. 11
0
 def test_modification_of_device(self):
     """Test if devices object does store references and not copies of objects."""
     xknx = XKNX(loop=self.loop)
     devices = Devices()
     light1 = Light(xknx,
                    'Living-Room.Light_1',
                    group_address_switch='1/6/7')
     devices.add(light1)
     for device in devices:
         self.loop.run_until_complete(asyncio.Task(device.set_on()))
     self.assertTrue(light1.state)
     device2 = devices["Living-Room.Light_1"]
     self.loop.run_until_complete(asyncio.Task(device2.set_off()))
     self.assertFalse(light1.state)
     for device in devices.devices_by_group_address(GroupAddress('1/6/7')):
         self.loop.run_until_complete(asyncio.Task(device.set_on()))
     self.assertTrue(light1.state)
Esempio n. 12
0
    def test_iter(self):
        """Test __iter__() function."""
        xknx = XKNX()
        devices = Devices()

        light1 = Light(xknx, "Livingroom", group_address_switch="1/6/7")
        sensor1 = BinarySensor(xknx, "Diningroom", group_address_state="3/0/1")
        sensor2 = BinarySensor(xknx, "Diningroom", group_address_state="3/0/1")
        light2 = Light(xknx, "Livingroom", group_address_switch="1/6/8")
        devices.add(light1)
        devices.add(sensor1)
        devices.add(sensor2)
        devices.add(light2)

        assert tuple(devices.__iter__()) == (light1, sensor1, sensor2, light2)
Esempio n. 13
0
File: xknx.py Progetto: cian/xknx
    def __init__(
        self,
        config=None,
        loop=None,
        own_address=DEFAULT_ADDRESS,
        address_format=GroupAddressType.LONG,
        telegram_received_cb=None,
        device_updated_cb=None,
        rate_limit=DEFAULT_RATE_LIMIT,
        multicast_group=DEFAULT_MCAST_GRP,
        multicast_port=DEFAULT_MCAST_PORT,
    ):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self)
        self.knxip_interface = None
        self.started = asyncio.Event()
        self.address_format = address_format
        self.own_address = PhysicalAddress(own_address)
        self.rate_limit = rate_limit
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.logger = logging.getLogger("xknx.log")
        self.knx_logger = logging.getLogger("xknx.knx")
        self.telegram_logger = logging.getLogger("xknx.telegram")
        self.raw_socket_logger = logging.getLogger("xknx.raw_socket")
        self.connection_config = None
        self.version = VERSION

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)
Esempio n. 14
0
    def test_get_item(self):
        """Test get item by name or by index."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        switch1 = Switch(xknx,
                         "TestOutlet_1",
                         group_address='1/2/3')
        devices.add(switch1)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)

        switch2 = Switch(xknx,
                         "TestOutlet_2",
                         group_address='1/2/4')
        devices.add(switch2)

        self.assertEqual(devices["Living-Room.Light_1"], light1)
        self.assertEqual(devices["TestOutlet_1"], switch1)
        self.assertEqual(devices["Living-Room.Light_2"], light2)
        self.assertEqual(devices["TestOutlet_2"], switch2)
        with self.assertRaises(KeyError):
            # pylint: disable=pointless-statement
            devices["TestOutlet_X"]

        self.assertEqual(devices[0], light1)
        self.assertEqual(devices[1], switch1)
        self.assertEqual(devices[2], light2)
        self.assertEqual(devices[3], switch2)
        with self.assertRaises(IndexError):
            # pylint: disable=pointless-statement
            devices[4]
Esempio n. 15
0
    def test_get_item(self):
        """Test get item by name or by index."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        switch1 = Switch(xknx,
                         "TestOutlet_1",
                         group_address='1/2/3')
        devices.add(switch1)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)

        switch2 = Switch(xknx,
                         "TestOutlet_2",
                         group_address='1/2/4')
        devices.add(switch2)

        self.assertEqual(devices["Living-Room.Light_1"], light1)
        self.assertEqual(devices["TestOutlet_1"], switch1)
        self.assertEqual(devices["Living-Room.Light_2"], light2)
        self.assertEqual(devices["TestOutlet_2"], switch2)
        with self.assertRaises(KeyError):
            # pylint: disable=pointless-statement
            devices["TestOutlet_X"]

        self.assertEqual(devices[0], light1)
        self.assertEqual(devices[1], switch1)
        self.assertEqual(devices[2], light2)
        self.assertEqual(devices[3], switch2)
        with self.assertRaises(IndexError):
            # pylint: disable=pointless-statement
            devices[4]
Esempio n. 16
0
    def test_contains(self):
        """Test __contains__() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)
        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)
        self.assertTrue('Living-Room.Light_1' in devices)
        self.assertTrue('Living-Room.Light_2' in devices)
        self.assertFalse('Living-Room.Light_3' in devices)
Esempio n. 17
0
    def test_device_by_group_address(self):
        """Test get devices by group address."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)

        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('1/6/7'))),
            (light1,))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('1/6/8'))),
            (light2,))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('3/0/1'))),
            (sensor1, sensor2))
Esempio n. 18
0
File: xknx.py Progetto: XKNX/xknx
class XKNX:
    """Class for reading and writing KNX/IP packets."""

    DEFAULT_ADDRESS = "15.15.250"
    DEFAULT_RATE_LIMIT = 20

    def __init__(
            self,
            own_address: str | IndividualAddress = DEFAULT_ADDRESS,
            address_format: GroupAddressType = GroupAddressType.LONG,
            telegram_received_cb: Callable[[Telegram], Awaitable[None]]
        | None = None,
            device_updated_cb: Callable[[Device], Awaitable[None]]
        | None = None,
            connection_state_changed_cb: Callable[[XknxConnectionState],
                                                  Awaitable[None]]
        | None = None,
            rate_limit: int = DEFAULT_RATE_LIMIT,
            multicast_group: str = DEFAULT_MCAST_GRP,
            multicast_port: int = DEFAULT_MCAST_PORT,
            log_directory: str | None = None,
            state_updater: TrackerOptionType = False,
            daemon_mode: bool = False,
            connection_config: ConnectionConfig = ConnectionConfig(),
    ) -> None:
        """Initialize XKNX class."""
        self.connection_manager = ConnectionManager()
        self.devices = Devices()
        self.knxip_interface = knx_interface_factory(
            self, connection_config=connection_config)
        self.management = Management(self)
        self.telegrams: asyncio.Queue[Telegram | None] = asyncio.Queue()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self,
                                          default_tracker_option=state_updater)
        self.task_registry = TaskRegistry(self)

        self.current_address = IndividualAddress(0)
        self.daemon_mode = daemon_mode
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.own_address = IndividualAddress(own_address)
        self.rate_limit = rate_limit
        self.sigint_received = asyncio.Event()
        self.started = asyncio.Event()
        self.version = VERSION

        GroupAddress.address_format = address_format  # for global string representation
        if log_directory is not None:
            self.setup_logging(log_directory)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

        if connection_state_changed_cb is not None:
            self.connection_manager.register_connection_state_changed_cb(
                connection_state_changed_cb)

    def __del__(self) -> None:
        """Destructor. Cleaning up if this was not done before."""
        if self.started.is_set():
            try:
                loop = asyncio.get_event_loop()
                loop.run_until_complete(self.stop())
            except RuntimeError as exp:
                logger.warning("Could not close loop, reason: %s", exp)

    async def __aenter__(self) -> "XKNX":
        """Start XKNX from context manager."""
        await self.start()
        return self

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc: BaseException | None,
        traceback: TracebackType | None,
    ) -> None:
        """Stop XKNX from context manager."""
        await self.stop()

    async def start(self) -> None:
        """Start XKNX module. Connect to KNX/IP devices and start state updater."""
        if self.knxip_interface.connection_config.threaded:
            await self.connection_manager.register_loop()
        self.task_registry.start()
        logger.info(
            "XKNX v%s starting %s connection to KNX bus.",
            VERSION,
            self.knxip_interface.connection_config.connection_type.name.lower(
            ),
        )
        await self.knxip_interface.start()
        await self.telegram_queue.start()
        self.state_updater.start()
        self.started.set()
        if self.daemon_mode:
            await self.loop_until_sigint()

    async def join(self) -> None:
        """Wait until all telegrams were processed."""
        await self.telegrams.join()

    async def stop(self) -> None:
        """Stop XKNX module."""
        self.task_registry.stop()
        self.state_updater.stop()
        await self.join()
        await self.telegram_queue.stop()
        await self.knxip_interface.stop()
        self.started.clear()

    async def loop_until_sigint(self) -> None:
        """Loop until Crtl-C was pressed."""
        def sigint_handler() -> None:
            """End loop."""
            self.sigint_received.set()

        if platform == "win32":
            logger.warning("Windows does not support signals")
        else:
            loop = asyncio.get_running_loop()
            loop.add_signal_handler(signal.SIGINT, sigint_handler)
        logger.warning("Press Ctrl+C to stop")
        await self.sigint_received.wait()

    @staticmethod
    def setup_logging(log_directory: str) -> None:
        """Configure logging to file."""
        if not os.path.isdir(log_directory):
            logger.warning("The provided log directory does not exist.")
            return

        _handler = TimedRotatingFileHandler(
            filename=f"{log_directory}{os.sep}xknx.log",
            when="midnight",
            backupCount=7,
            encoding="utf-8",
        )
        _formatter = logging.Formatter(
            "%(asctime)s | %(name)s | %(levelname)s | %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
        _handler.setFormatter(_formatter)
        _handler.setLevel(logging.DEBUG)

        for log_namespace in [
                "xknx.log",
                "xknx.knx",
                "xknx.raw_socket",
                "xknx.telegram",
                "xknx.state_updater",
        ]:
            _logger = logging.getLogger(log_namespace)
            _logger.addHandler(_handler)
Esempio n. 19
0
File: xknx.py Progetto: phbaer/xknx
class XKNX:
    """Class for reading and writing KNX/IP packets."""

    # pylint: disable=too-many-instance-attributes

    DEFAULT_ADDRESS = '15.15.250'
    DEFAULT_RATE_LIMIT = 20

    def __init__(self,
                 config=None,
                 loop=None,
                 own_address=PhysicalAddress(DEFAULT_ADDRESS),
                 address_format=GroupAddressType.LONG,
                 telegram_received_cb=None,
                 device_updated_cb=None,
                 rate_limit=DEFAULT_RATE_LIMIT):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = None
        self.knxip_interface = None
        self.started = False
        self.address_format = address_format
        self.own_address = own_address
        self.rate_limit = rate_limit
        self.logger = logging.getLogger('xknx.log')
        self.knx_logger = logging.getLogger('xknx.knx')
        self.telegram_logger = logging.getLogger('xknx.telegram')
        self.connection_config = None

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

    def __del__(self):
        """Destructor. Cleaning up if this was not done before."""
        if self.started:
            try:
                task = self.loop.create_task(self.stop())
                self.loop.run_until_complete(task)
            except RuntimeError as exp:
                self.logger.warning("Could not close loop, reason: %s", exp)

    async def start(self,
                    state_updater=False,
                    daemon_mode=False,
                    connection_config=None):
        """Start XKNX module. Connect to KNX/IP devices and start state updater."""
        if connection_config is None:
            if self.connection_config is None:
                connection_config = ConnectionConfig()
            else:
                connection_config = self.connection_config
        self.knxip_interface = KNXIPInterface(self, connection_config=connection_config)
        await self.knxip_interface.start()
        await self.telegram_queue.start()

        if state_updater:
            from xknx.core import StateUpdater
            self.state_updater = StateUpdater(self)
            await self.state_updater.start()

        if daemon_mode:
            await self.loop_until_sigint()

        self.started = True

    async def join(self):
        """Wait until all telegrams were processed."""
        await self.telegrams.join()

    async def _stop_knxip_interface_if_exists(self):
        """Stop KNXIPInterface if initialized."""
        if self.knxip_interface is not None:
            await self.knxip_interface.stop()
            self.knxip_interface = None

    async def stop(self):
        """Stop XKNX module."""
        await self.join()
        await self.telegram_queue.stop()
        await self._stop_knxip_interface_if_exists()
        self.started = False

    async def loop_until_sigint(self):
        """Loop until Crtl-C was pressed."""
        def sigint_handler():
            """End loop."""
            self.sigint_received.set()
        if platform == "win32":
            self.logger.warning('Windows does not support signals')
        else:
            self.loop.add_signal_handler(signal.SIGINT, sigint_handler)
        self.logger.warning('Press Ctrl+C to stop')
        await self.sigint_received.wait()
Esempio n. 20
0
    def test_iter(self):
        """Test __iter__() function."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')

        devices.add(light2)

        self.assertEqual(
            tuple(devices.__iter__()),
            (light1, sensor1, sensor2, light2))
Esempio n. 21
0
    def test_device_by_group_address(self):
        """Test get devices by group address."""
        xknx = XKNX()
        devices = Devices()

        light1 = Light(xknx,
                       "Living-Room.Light_1",
                       group_address_switch="1/6/7")
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               "DiningRoom.Motion.Sensor",
                               group_address_state="3/0/1")
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               "DiningRoom.Motion.Sensor",
                               group_address_state="3/0/1")
        devices.add(sensor2)

        light2 = Light(xknx,
                       "Living-Room.Light_2",
                       group_address_switch="1/6/8")
        devices.add(light2)

        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress("1/6/7"))),
            (light1, ))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress("1/6/8"))),
            (light2, ))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress("3/0/1"))),
            (sensor1, sensor2),
        )
Esempio n. 22
0
class XKNX:
    """Class for reading and writing KNX/IP packets."""

    # pylint: disable=too-many-instance-attributes

    DEFAULT_ADDRESS = '15.15.250'

    def __init__(self,
                 config=None,
                 loop=None,
                 own_address=Address(DEFAULT_ADDRESS),
                 address_format=AddressFormat.LEVEL3,
                 telegram_received_cb=None,
                 device_updated_cb=None):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = None
        self.knxip_interface = None
        self.started = False
        self.address_format = address_format
        self.own_address = own_address
        self.logger = logging.getLogger('xknx.log')
        self.knx_logger = logging.getLogger('xknx.knx')
        self.telegram_logger = logging.getLogger('xknx.telegram')

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

    def __del__(self):
        """Destructor. Cleaning up if this was not done before."""
        if self.started:
            try:
                task = self.loop.create_task(self.stop())
                self.loop.run_until_complete(task)
            except RuntimeError as exp:
                self.logger.warning("Could not close loop, reason: %s", exp)

    @asyncio.coroutine
    def start(self,
              state_updater=False,
              daemon_mode=False,
              connection_config=ConnectionConfig()):
        """Start XKNX module. Connect to KNX/IP devices and start state updater."""
        self.knxip_interface = KNXIPInterface(
            self, connection_config=connection_config)
        yield from self.knxip_interface.start()
        yield from self.telegram_queue.start()

        if state_updater:
            from xknx.core import StateUpdater
            self.state_updater = StateUpdater(self)
            yield from self.state_updater.start()

        if daemon_mode:
            yield from self.loop_until_sigint()

        self.started = True

    @asyncio.coroutine
    def join(self):
        """Wait until all telegrams were processed."""
        yield from self.telegrams.join()

    def _stop_knxip_interface_if_exists(self):
        """Stop KNXIPInterface if initialized."""
        if self.knxip_interface is not None:
            yield from self.knxip_interface.stop()
            self.knxip_interface = None

    @asyncio.coroutine
    def stop(self):
        """Stop XKNX module."""
        yield from self.join()
        yield from self.telegram_queue.stop()
        yield from self._stop_knxip_interface_if_exists()
        self.started = False

    @asyncio.coroutine
    def loop_until_sigint(self):
        """Loop until Crtl-C was pressed."""
        def sigint_handler():
            """End loop."""
            self.sigint_received.set()

        self.loop.add_signal_handler(signal.SIGINT, sigint_handler)
        self.logger.warning('Press Ctrl+C to stop')
        yield from self.sigint_received.wait()
Esempio n. 23
0
class XKNX:
    """Class for reading and writing KNX/IP packets."""

    # pylint: disable=too-many-instance-attributes

    DEFAULT_ADDRESS = '15.15.250'
    DEFAULT_RATE_LIMIT = 20

    def __init__(self,
                 config=None,
                 loop=None,
                 own_address=PhysicalAddress(DEFAULT_ADDRESS),
                 address_format=GroupAddressType.LONG,
                 telegram_received_cb=None,
                 device_updated_cb=None,
                 rate_limit=DEFAULT_RATE_LIMIT,
                 multicast_group=DEFAULT_MCAST_GRP,
                 multicast_port=DEFAULT_MCAST_PORT):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.loop = loop or asyncio.get_event_loop()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self)
        self.knxip_interface = None
        self.started = asyncio.Event()
        self.address_format = address_format
        self.own_address = own_address
        self.rate_limit = rate_limit
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.logger = logging.getLogger('xknx.log')
        self.knx_logger = logging.getLogger('xknx.knx')
        self.telegram_logger = logging.getLogger('xknx.telegram')
        self.raw_socket_logger = logging.getLogger('xknx.raw_socket')
        self.connection_config = None
        self.version = VERSION

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

    def __del__(self):
        """Destructor. Cleaning up if this was not done before."""
        if self.started.is_set():
            try:
                task = self.loop.create_task(self.stop())
                self.loop.run_until_complete(task)
            except RuntimeError as exp:
                self.logger.warning("Could not close loop, reason: %s", exp)

    async def start(self,
                    state_updater=False,
                    daemon_mode=False,
                    connection_config=None):
        """Start XKNX module. Connect to KNX/IP devices and start state updater."""
        if connection_config is None:
            if self.connection_config is None:
                connection_config = ConnectionConfig()
            else:
                connection_config = self.connection_config
        self.knxip_interface = KNXIPInterface(self, connection_config=connection_config)
        self.logger.info('XKNX v%s starting %s connection to KNX bus.',
                         VERSION, connection_config.connection_type.name.lower())
        await self.knxip_interface.start()
        await self.telegram_queue.start()
        if state_updater:
            self.state_updater.start()
        self.started.set()
        if daemon_mode:
            await self.loop_until_sigint()

    async def join(self):
        """Wait until all telegrams were processed."""
        await self.telegrams.join()

    async def _stop_knxip_interface_if_exists(self):
        """Stop KNXIPInterface if initialized."""
        if self.knxip_interface is not None:
            await self.knxip_interface.stop()
            self.knxip_interface = None

    async def stop(self):
        """Stop XKNX module."""
        self.state_updater.stop()
        await self.join()
        await self.telegram_queue.stop()
        await self._stop_knxip_interface_if_exists()
        self.started.clear()

    async def loop_until_sigint(self):
        """Loop until Crtl-C was pressed."""
        def sigint_handler():
            """End loop."""
            self.sigint_received.set()
        if platform == "win32":
            self.logger.warning('Windows does not support signals')
        else:
            self.loop.add_signal_handler(signal.SIGINT, sigint_handler)
        self.logger.warning('Press Ctrl+C to stop')
        await self.sigint_received.wait()
Esempio n. 24
0
    def test_iter(self):
        """Test __iter__() function."""
        xknx = XKNX()
        devices = Devices()

        light1 = Light(xknx,
                       "Living-Room.Light_1",
                       group_address_switch="1/6/7")
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               "DiningRoom.Motion.Sensor",
                               group_address_state="3/0/1")
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               "DiningRoom.Motion.Sensor",
                               group_address_state="3/0/1")
        devices.add(sensor2)

        light2 = Light(xknx,
                       "Living-Room.Light_2",
                       group_address_switch="1/6/8")

        devices.add(light2)

        self.assertEqual(tuple(devices.__iter__()),
                         (light1, sensor1, sensor2, light2))
Esempio n. 25
0
File: xknx.py Progetto: mielune/xknx
class XKNX:
    """Class for reading and writing KNX/IP packets."""

    # pylint: disable=too-many-instance-attributes

    DEFAULT_ADDRESS = "15.15.250"
    DEFAULT_RATE_LIMIT = 20

    def __init__(
            self,
            config=None,
            own_address=DEFAULT_ADDRESS,
            address_format=GroupAddressType.LONG,
            telegram_received_cb=None,
            device_updated_cb=None,
            rate_limit=DEFAULT_RATE_LIMIT,
            multicast_group=DEFAULT_MCAST_GRP,
            multicast_port=DEFAULT_MCAST_PORT,
            log_directory=None,
            state_updater=False,
            daemon_mode=False,
            connection_config=ConnectionConfig(),
    ):
        """Initialize XKNX class."""
        # pylint: disable=too-many-arguments
        self.devices = Devices()
        self.telegrams = asyncio.Queue()
        self.sigint_received = asyncio.Event()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self)
        self.knxip_interface = None
        self.started = asyncio.Event()
        self.address_format = address_format
        self.own_address = PhysicalAddress(own_address)
        self.rate_limit = rate_limit
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.connection_config = connection_config
        self.start_state_updater = state_updater
        self.daemon_mode = daemon_mode
        self.version = VERSION

        if log_directory is not None:
            self.setup_logging(log_directory)

        if config is not None:
            Config(self).read(config)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

    def __del__(self):
        """Destructor. Cleaning up if this was not done before."""
        if self.started.is_set():
            try:
                loop = asyncio.get_event_loop()
                loop.run_until_complete(self.stop())
            except RuntimeError as exp:
                logger.warning("Could not close loop, reason: %s", exp)

    async def __aenter__(self):
        """Start XKNX from context manager."""
        await self.start()
        return self

    async def __aexit__(self, exc_type, exc, traceback):
        """Stop XKNX from context manager."""
        await self.stop()

    async def start(self):
        """Start XKNX module. Connect to KNX/IP devices and start state updater."""
        self.knxip_interface = KNXIPInterface(
            self, connection_config=self.connection_config)
        logger.info(
            "XKNX v%s starting %s connection to KNX bus.",
            VERSION,
            self.connection_config.connection_type.name.lower(),
        )
        await self.knxip_interface.start()
        await self.telegram_queue.start()
        if self.start_state_updater:
            self.state_updater.start()
        self.started.set()
        if self.daemon_mode:
            await self.loop_until_sigint()

    async def join(self):
        """Wait until all telegrams were processed."""
        await self.telegrams.join()

    async def _stop_knxip_interface_if_exists(self):
        """Stop KNXIPInterface if initialized."""
        if self.knxip_interface is not None:
            await self.knxip_interface.stop()
            self.knxip_interface = None

    async def stop(self):
        """Stop XKNX module."""
        self.state_updater.stop()
        await self.join()
        await self.telegram_queue.stop()
        await self._stop_knxip_interface_if_exists()
        self.started.clear()

    async def loop_until_sigint(self):
        """Loop until Crtl-C was pressed."""
        def sigint_handler():
            """End loop."""
            self.sigint_received.set()

        if platform == "win32":
            logger.warning("Windows does not support signals")
        else:
            loop = asyncio.get_running_loop()
            loop.add_signal_handler(signal.SIGINT, sigint_handler)
        logger.warning("Press Ctrl+C to stop")
        await self.sigint_received.wait()

    @staticmethod
    def setup_logging(log_directory: str):
        """Configure logging to file."""
        if not os.path.isdir(log_directory):
            logger.warning("The provided log directory does not exist.")
            return

        _handler = TimedRotatingFileHandler(
            filename=f"{log_directory}{os.sep}xknx.log",
            when="midnight",
            backupCount=7,
            encoding="utf-8",
        )
        _formatter = logging.Formatter(
            "%(asctime)s | %(name)s | %(levelname)s | %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
        _handler.setFormatter(_formatter)
        _handler.setLevel(logging.DEBUG)

        for log_namespace in [
                "xknx.log",
                "xknx.knx",
                "xknx.raw_socket",
                "xknx.telegram",
                "xknx.state_updater",
        ]:
            _logger = logging.getLogger(log_namespace)
            _logger.addHandler(_handler)
Esempio n. 26
0
    def test_device_by_group_address(self):
        """Test get devices by group address."""
        xknx = XKNX(loop=self.loop)
        devices = Devices()

        light1 = Light(xknx,
                       'Living-Room.Light_1',
                       group_address_switch='1/6/7')
        devices.add(light1)

        sensor1 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=2)
        devices.add(sensor1)

        sensor2 = BinarySensor(xknx,
                               'DiningRoom.Motion.Sensor',
                               group_address_state='3/0/1',
                               significant_bit=3)
        devices.add(sensor2)

        light2 = Light(xknx,
                       'Living-Room.Light_2',
                       group_address_switch='1/6/8')
        devices.add(light2)

        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('1/6/7'))),
            (light1,))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('1/6/8'))),
            (light2,))
        self.assertEqual(
            tuple(devices.devices_by_group_address(GroupAddress('3/0/1'))),
            (sensor1, sensor2))
Esempio n. 27
0
    def test_device_by_group_address(self):
        """Test get devices by group address."""
        xknx = XKNX()
        devices = Devices()

        light1 = Light(xknx, "Livingroom", group_address_switch="1/6/7")
        sensor1 = BinarySensor(xknx, "Diningroom", group_address_state="3/0/1")
        sensor2 = BinarySensor(xknx, "Diningroom", group_address_state="3/0/1")
        light2 = Light(xknx, "Livingroom", group_address_switch="1/6/8")
        devices.add(light1)
        devices.add(sensor1)
        devices.add(sensor2)
        devices.add(light2)

        assert tuple(devices.devices_by_group_address(
            GroupAddress("1/6/7"))) == (light1, )
        assert tuple(devices.devices_by_group_address(
            GroupAddress("1/6/8"))) == (light2, )
        assert tuple(devices.devices_by_group_address(
            GroupAddress("3/0/1"))) == (
                sensor1,
                sensor2,
            )