コード例 #1
0
    def test_EndTOEnd_group_write_2bytes(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, setting value of thermostat."""
        # Incoming Temperature from thermostat
        raw = ((0x06, 0x10, 0x05, 0x30, 0x00, 0x13, 0x29, 0x00, 0xbc, 0xd0,
                0x14, 0x02, 0x08, 0x01, 0x03, 0x00, 0x80, 0x07, 0xc1))
        xknx = XKNX(loop=self.loop)
        knxipframe = KNXIPFrame(xknx)
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.telegram
        self.assertEqual(
            telegram,
            Telegram(GroupAddress("2049"),
                     payload=DPTArray(DPTTemperature().to_knx(19.85))))

        knxipframe2 = KNXIPFrame(xknx)
        knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION)
        knxipframe2.body.src_addr = PhysicalAddress("1.4.2")
        knxipframe2.body.telegram = telegram
        knxipframe2.body.set_hops(5)
        knxipframe2.normalize()

        self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6]))
        self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:]))
        self.assertEqual(knxipframe2.to_knx(), list(raw))
コード例 #2
0
    async def test_process_callback(self):
        """Test process / reading telegrams from telegram queue. Test if callback is called."""

        xknx = XKNX()
        sensor = RawValue(
            xknx,
            "TestSensor",
            2,
            group_address="1/2/3",
        )
        after_update_callback = AsyncMock()
        sensor.register_device_updated_cb(after_update_callback)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray((0x01, 0x02))),
        )
        await sensor.process(telegram)
        after_update_callback.assert_called_with(sensor)
        assert sensor.last_telegram == telegram
        # consecutive telegrams with same payload shall only trigger one callback
        after_update_callback.reset_mock()
        await sensor.process(telegram)
        after_update_callback.assert_not_called()
コード例 #3
0
ファイル: __init__.py プロジェクト: antsar/home-assistant
    async def service_send_to_knx_bus(self, call: ServiceCall) -> None:
        """Service for sending an arbitrary KNX message to the KNX bus."""
        attr_address = call.data[KNX_ADDRESS]
        attr_payload = call.data[SERVICE_KNX_ATTR_PAYLOAD]
        attr_type = call.data.get(SERVICE_KNX_ATTR_TYPE)

        payload: DPTBinary | DPTArray
        if attr_type is not None:
            transcoder = DPTBase.parse_transcoder(attr_type)
            if transcoder is None:
                raise ValueError(
                    f"Invalid type for knx.send service: {attr_type}")
            payload = DPTArray(transcoder.to_knx(attr_payload))
        elif isinstance(attr_payload, int):
            payload = DPTBinary(attr_payload)
        else:
            payload = DPTArray(attr_payload)

        for address in attr_address:
            telegram = Telegram(
                destination_address=parse_device_group_address(address),
                payload=GroupValueWrite(payload),
            )
            await self.xknx.telegrams.put(telegram)
コード例 #4
0
    def test_process_exception(self, process_tg_in_mock, logging_error_mock):
        """Test process_telegram exception handling."""
        # pylint: disable=no-self-use
        xknx = XKNX(loop=self.loop)

        async def process_exception():
            raise CouldNotParseTelegram(
                "Something went wrong when receiving the telegram."
                "")

        process_tg_in_mock.return_value = asyncio.ensure_future(
            process_exception())

        telegram = Telegram(direction=TelegramDirection.INCOMING,
                            payload=DPTBinary(1),
                            group_address=GroupAddress("1/2/3"))

        self.loop.run_until_complete(
            asyncio.Task(xknx.telegram_queue.process_telegram(telegram)))
        logging_error_mock.assert_called_once_with(
            "Error while processing telegram %s",
            CouldNotParseTelegram(
                "Something went wrong when receiving the telegram."
                ""))
コード例 #5
0
    def test_process(self):
        """Test process / reading telegrams from telegram queue."""
        xknx = XKNX(loop=self.loop)
        binaryinput = BinarySensor(xknx, 'TestInput', '1/2/3')

        self.assertEqual(binaryinput.state, BinarySensorState.OFF)

        telegram_on = Telegram()
        telegram_on.payload = DPTBinary(1)
        self.loop.run_until_complete(
            asyncio.Task(binaryinput.process(telegram_on)))

        self.assertEqual(binaryinput.state, BinarySensorState.ON)

        telegram_off = Telegram()
        telegram_off.payload = DPTBinary(0)
        self.loop.run_until_complete(
            asyncio.Task(binaryinput.process(telegram_off)))
        self.assertEqual(binaryinput.state, BinarySensorState.OFF)
コード例 #6
0
ファイル: telegram_test.py プロジェクト: spacegaier/xknx
 def test_telegram_not_equal(self):
     """Test not equals operator."""
     self.assertNotEqual(
         Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()),
         Telegram(GroupAddress("1/2/4"), payload=GroupValueRead()),
     )
     self.assertNotEqual(
         Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()),
         Telegram(GroupAddress("1/2/3"),
                  payload=GroupValueWrite(DPTBinary(1))),
     )
     self.assertNotEqual(
         Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()),
         Telegram(
             GroupAddress("1/2/3"),
             TelegramDirection.INCOMING,
             payload=GroupValueRead(),
         ),
     )
コード例 #7
0
ファイル: climate_test.py プロジェクト: vosc/xknx
 def test_process_operation_mode(self):
     """Test process / reading telegrams from telegram queue. Test if setpoint is processed correctly."""
     xknx = XKNX(loop=self.loop)
     climate_mode = ClimateMode(xknx,
                                'TestClimate',
                                group_address_operation_mode='1/2/5',
                                group_address_controller_status='1/2/3')
     for operation_mode in DPT_20102_MODES:
         telegram = Telegram(GroupAddress('1/2/5'))
         telegram.payload = DPTArray(DPTHVACMode.to_knx(operation_mode))
         self.loop.run_until_complete(
             asyncio.Task(climate_mode.process(telegram)))
         self.assertEqual(climate_mode.operation_mode, operation_mode)
     for operation_mode in DPT_20102_MODES:
         if operation_mode == HVACOperationMode.AUTO:
             continue
         telegram = Telegram(GroupAddress('1/2/3'))
         telegram.payload = DPTArray(
             DPTControllerStatus.to_knx(operation_mode))
         self.loop.run_until_complete(
             asyncio.Task(climate_mode.process(telegram)))
         self.assertEqual(climate_mode.operation_mode, operation_mode)
コード例 #8
0
ファイル: light_test.py プロジェクト: mielune/xknx
    def test_sync_state_address(self):
        """Test sync function / sending group reads to KNX bus. Testing with a Light with dimm functionality."""
        xknx = XKNX()
        light = Light(
            xknx,
            name="TestLight",
            group_address_switch="1/2/3",
            group_address_switch_state="1/2/4",
            group_address_brightness="1/2/5",
            group_address_brightness_state="1/2/6",
            group_address_color="1/2/7",
            group_address_color_state="1/2/8",
            group_address_tunable_white="1/2/9",
            group_address_tunable_white_state="1/2/10",
            group_address_color_temperature="1/2/11",
            group_address_color_temperature_state="1/2/12",
            group_address_rgbw="1/2/13",
            group_address_rgbw_state="1/2/14",
        )
        self.loop.run_until_complete(light.sync())

        self.assertEqual(xknx.telegrams.qsize(), 6)

        telegrams = []
        for _ in range(6):
            telegrams.append(xknx.telegrams.get_nowait())

        test_telegrams = [
            Telegram(GroupAddress("1/2/4"), TelegramType.GROUP_READ),
            Telegram(GroupAddress("1/2/6"), TelegramType.GROUP_READ),
            Telegram(GroupAddress("1/2/8"), TelegramType.GROUP_READ),
            Telegram(GroupAddress("1/2/10"), TelegramType.GROUP_READ),
            Telegram(GroupAddress("1/2/12"), TelegramType.GROUP_READ),
            Telegram(GroupAddress("1/2/14"), TelegramType.GROUP_READ),
        ]

        self.assertEqual(len(set(telegrams)), 6)
        self.assertEqual(set(telegrams), set(test_telegrams))
コード例 #9
0
    def test_process_action(self):
        """Test process / reading telegrams from telegram queue. Test if action is executed."""
        xknx = XKNX(loop=self.loop)
        switch = Switch(xknx, 'TestOutlet', group_address='1/2/3')
        xknx.devices.add(switch)

        binary_sensor = BinarySensor(xknx,
                                     'TestInput',
                                     group_address_state='1/2/3')
        action_on = Action(xknx, hook='on', target='TestOutlet', method='on')
        binary_sensor.actions.append(action_on)
        action_off = Action(xknx,
                            hook='off',
                            target='TestOutlet',
                            method='off')
        binary_sensor.actions.append(action_off)
        xknx.devices.add(binary_sensor)

        self.assertEqual(xknx.devices['TestInput'].state,
                         BinarySensorState.OFF)
        self.assertEqual(xknx.devices['TestOutlet'].state, False)

        telegram_on = Telegram()
        telegram_on.payload = DPTBinary(1)
        self.loop.run_until_complete(
            asyncio.Task(binary_sensor.process(telegram_on)))

        self.assertEqual(xknx.devices['TestInput'].state, BinarySensorState.ON)
        self.assertEqual(xknx.devices['TestOutlet'].state, True)

        telegram_off = Telegram()
        telegram_off.payload = DPTBinary(0)
        self.loop.run_until_complete(
            asyncio.Task(binary_sensor.process(telegram_off)))

        self.assertEqual(xknx.devices['TestInput'].state,
                         BinarySensorState.OFF)
        self.assertEqual(xknx.devices['TestOutlet'].state, False)
コード例 #10
0
    def test_sync_state_address(self):
        """Test sync function / sending group reads to KNX bus. Testing with a Light with dimm functionality."""
        xknx = XKNX(loop=self.loop)
        light = Light(xknx,
                      name="TestLight",
                      group_address_switch='1/2/3',
                      group_address_switch_state='1/2/4',
                      group_address_brightness='1/2/5',
                      group_address_brightness_state='1/2/6',
                      group_address_color='1/2/7',
                      group_address_color_state='1/2/8',
                      group_address_tunable_white='1/2/9',
                      group_address_tunable_white_state='1/2/10',
                      group_address_color_temperature='1/2/11',
                      group_address_color_temperature_state='1/2/12',
                      group_address_rgbw='1/2/13',
                      group_address_rgbw_state='1/2/14')
        self.loop.run_until_complete(asyncio.Task(light.sync()))

        self.assertEqual(xknx.telegrams.qsize(), 6)

        telegrams = []
        for _ in range(6):
            telegrams.append(xknx.telegrams.get_nowait())

        test_telegrams = [
            Telegram(GroupAddress('1/2/4'), TelegramType.GROUP_READ),
            Telegram(GroupAddress('1/2/6'), TelegramType.GROUP_READ),
            Telegram(GroupAddress('1/2/8'), TelegramType.GROUP_READ),
            Telegram(GroupAddress('1/2/10'), TelegramType.GROUP_READ),
            Telegram(GroupAddress('1/2/12'), TelegramType.GROUP_READ),
            Telegram(GroupAddress('1/2/14'), TelegramType.GROUP_READ)
        ]

        self.assertEqual(len(set(telegrams)), 6)
        self.assertEqual(set(telegrams), set(test_telegrams))
コード例 #11
0
    async def test_tunnelling(self):
        """Test tunnelling from KNX bus."""
        communication_channel_id = 23
        data_endpoint = ("192.168.1.2", 4567)
        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
        cemi = CEMIFrame.init_from_telegram(
            Telegram(
                destination_address=GroupAddress("1/2/3"),
                payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))),
            )
        )
        sequence_counter = 42
        tunnelling = Tunnelling(
            udp_transport,
            data_endpoint,
            cemi,
            sequence_counter,
            communication_channel_id,
        )
        tunnelling.timeout_in_seconds = 0

        assert tunnelling.awaited_response_class == TunnellingAck
        assert tunnelling.communication_channel_id == communication_channel_id

        # Expected KNX/IP-Frame:
        tunnelling_request = TunnellingRequest(
            communication_channel_id=communication_channel_id,
            sequence_counter=sequence_counter,
        )
        tunnelling_request.cemi = cemi
        exp_knxipframe = KNXIPFrame.init_from_body(tunnelling_request)
        with patch("xknx.io.transport.UDPTransport.send") as mock_udp_send, patch(
            "xknx.io.transport.UDPTransport.getsockname"
        ) as mock_udp_getsockname:
            mock_udp_getsockname.return_value = ("192.168.1.3", 4321)
            await tunnelling.start()
            mock_udp_send.assert_called_with(exp_knxipframe, addr=data_endpoint)

        # Response KNX/IP-Frame with wrong type
        wrong_knxipframe = KNXIPFrame()
        wrong_knxipframe.init(KNXIPServiceType.CONNECTIONSTATE_REQUEST)
        with patch("logging.Logger.warning") as mock_warning:
            tunnelling.response_rec_callback(wrong_knxipframe, HPAI(), None)
            mock_warning.assert_called_with("Could not understand knxipframe")

        # Response KNX/IP-Frame with error:
        err_knxipframe = KNXIPFrame()
        err_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK)
        err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID
        with patch("logging.Logger.debug") as mock_warning:
            tunnelling.response_rec_callback(err_knxipframe, HPAI(), None)
            mock_warning.assert_called_with(
                "Error: KNX bus responded to request of type '%s' with error in '%s': %s",
                type(tunnelling).__name__,
                type(err_knxipframe.body).__name__,
                ErrorCode.E_CONNECTION_ID,
            )

        # Correct Response KNX/IP-Frame:
        res_knxipframe = KNXIPFrame()
        res_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK)
        tunnelling.response_rec_callback(res_knxipframe, HPAI(), None)
        assert tunnelling.success
コード例 #12
0
ファイル: cover_test.py プロジェクト: magenbrot/xknx
    async def test_stop(self):
        """Test stopping cover."""
        xknx = XKNX()
        cover_short_stop = Cover(
            xknx,
            "TestCover",
            group_address_long="1/2/1",
            group_address_short="1/2/2",
            group_address_position="1/2/3",
            group_address_position_state="1/2/4",
        )
        # Attempt stopping while not actually moving
        await cover_short_stop.stop()
        assert xknx.telegrams.qsize() == 0

        # Attempt stopping while moving down
        cover_short_stop.travelcalculator.set_position(0)
        await cover_short_stop.set_down()
        await cover_short_stop.stop()
        assert xknx.telegrams.qsize() == 2
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/1"),
            payload=GroupValueWrite(DPTBinary(1)),
        )
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/2"),
            payload=GroupValueWrite(DPTBinary(1)),
        )

        # Attempt stopping while moving up
        cover_short_stop.travelcalculator.set_position(100)
        await cover_short_stop.set_up()
        await cover_short_stop.stop()
        assert xknx.telegrams.qsize() == 2
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/1"),
            payload=GroupValueWrite(DPTBinary(0)),
        )
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/2"),
            payload=GroupValueWrite(DPTBinary(0)),
        )

        cover_manual_stop = Cover(
            xknx,
            "TestCover",
            group_address_long="1/2/1",
            group_address_short="1/2/2",
            group_address_stop="1/2/0",
            group_address_position="1/2/3",
            group_address_position_state="1/2/4",
        )
        await cover_manual_stop.stop()
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/0"),
            payload=GroupValueWrite(DPTBinary(1)),
        )
コード例 #13
0
ファイル: sensor_expose_loop_test.py プロジェクト: vosc/xknx
    def test_array_sensor_loop(self):
        """Test sensor and expose_sensor with different values."""
        test_cases = [
            ('angle', DPTArray((0x0B)), 16),
            ('brightness', DPTArray((0x27, 0x10)), 10000),
            ('color_temperature', DPTArray((0x0D, 0x48)), 3400),
            ('counter_pulses', DPTArray((0x9F)), -97),
            ('current', DPTArray((0x00, 0x03)), 3),
            ('delta_time_hrs', DPTArray((0x04, 0xD2)), 1234),
            ('delta_time_min', DPTArray((0xFB, 0x2E)), -1234),
            ('delta_time_ms', DPTArray((0x7D, 0x00)), 32000),
            ('delta_time_sec', DPTArray((0x83, 0x00)), -32000),
            ('electric_current', DPTArray((0x3D, 0xCC, 0xCC, 0xCD)), 0.1),
            ('electric_potential', DPTArray((0x43, 0xF0, 0xDE, 0xB8)), 481.74),
            ('energy', DPTArray((0x43, 0xE4, 0x00, 0x00)), 456),
            ('enthalpy', DPTArray((0xC1, 0x4E)), -4387.84),
            ('frequency', DPTArray((0x42, 0x46, 0xCC, 0xCD)), 49.7),
            ('heatflowrate', DPTArray((0x42, 0xAE, 0x00, 0x00)), 87),
            ('humidity', DPTArray((0x6C, 0xB6)), 98795.52),
            ('illuminance', DPTArray((0x2F, 0xE9)), 648),
            ('luminous_flux', DPTArray((0x43, 0x87, 0x40, 0x00)), 270.5),
            ('percent', DPTArray((0x26)), 15),
            ('percentU8', DPTArray((0xCD)), 205),
            ('percentV8', DPTArray((0x9A)), -102),
            ('percentV16', DPTArray((0xFF, 0xFF)), -1),
            ('phaseanglerad', DPTArray((0xC1, 0x10, 0x00, 0x00)), -9),
            ('phaseangledeg', DPTArray((0x43, 0x87, 0x40, 0x00)), 270.5),
            ('power', DPTArray((0x42, 0xA9, 0xBD, 0x71)), 84.87),
            ('powerfactor', DPTArray((0x42, 0xA9, 0x6B, 0x85)), 84.71),
            ('ppm', DPTArray((0x00, 0x03)), 0.03),
            ('pressure', DPTArray((0x42, 0xA9, 0x6B, 0x85)), 84.71),
            ('pressure_2byte', DPTArray((0x2E, 0xA9)), 545.6),
            ('pulse', DPTArray((0x11)), 17),
            ('rotation_angle', DPTArray((0xAE, 0xC0)), -20800),
            ('scene_number', DPTArray((0x00)), 1),
            ('speed', DPTArray((0x00, 0x00, 0x00, 0x00)), 0),
            ('speed_ms', DPTArray((0x0E, 0xA4)), 34),
            ('string',
             DPTArray((0x4B, 0x4E, 0x58, 0x20, 0x69, 0x73, 0x20, 0x4F, 0x4B,
                       0x00, 0x00, 0x00, 0x00, 0x00)), "KNX is OK"),
            ('temperature', DPTArray((0x03, 0x12)), 7.86),
            ('voltage', DPTArray((0x07, 0x9A)), 19.46),
            # Generic DPT Without Min/Max and Unit.
            ('DPT-5', DPTArray((0x1F)), 31),
            ('1byte_unsigned', DPTArray((0x08)), 8),
            ('DPT-7', DPTArray((0xD4, 0x31)), 54321),
            ('2byte_unsigned', DPTArray((0x30, 0x39)), 12345),
            ('DPT-8', DPTArray((0x80, 0x44)), -32700),
            ('2byte_signed', DPTArray((0x00, 0x01)), 1),
            ('DPT-9', DPTArray((0x2E, 0xA9)), 545.6),
            ('DPT-12', DPTArray((0x07, 0x5B, 0xCD, 0x15)), 123456789),
            ('4byte_unsigned', DPTArray((0x00, 0x00, 0x00, 0x00)), 0),
            ('DPT-13', DPTArray((0x02, 0xE5, 0x5E, 0xF7)), 48586487),
            ('4byte_signed', DPTArray((0xFD, 0x1A, 0xA1, 0x09)), -48586487),
            ('DPT-14', DPTArray((0x47, 0xC0, 0xF7, 0x20)), 98798.25),
            ('4byte_float', DPTArray((0xC2, 0x09, 0xEE, 0xCC)), -34.4832),
        ]

        for value_type, test_payload, test_value in test_cases:
            with self.subTest(value_type=value_type):
                xknx = XKNX(loop=self.loop)
                sensor = Sensor(xknx,
                                'TestSensor_%s' % value_type,
                                group_address_state='1/1/1',
                                value_type=value_type)
                expose = ExposeSensor(xknx,
                                      'TestExpose_%s' % value_type,
                                      group_address='2/2/2',
                                      value_type=value_type)

                incoming_telegram = Telegram(
                    GroupAddress('1/1/1'),
                    TelegramType.GROUP_WRITE,
                    direction=TelegramDirection.INCOMING,
                    payload=test_payload)
                self.loop.run_until_complete(
                    asyncio.Task(sensor.process(incoming_telegram)))
                incoming_value = sensor.resolve_state()
                if isinstance(test_value, float):
                    self.assertEqual(round(incoming_value, 4), test_value)
                else:
                    self.assertEqual(incoming_value, test_value)

                # HA sends strings for new values
                stringified_value = str(test_value)
                self.loop.run_until_complete(
                    asyncio.Task(expose.set(stringified_value)))
                self.assertEqual(xknx.telegrams.qsize(), 1)
                outgoing_telegram = xknx.telegrams.get_nowait()
                self.assertEqual(
                    outgoing_telegram,
                    Telegram(GroupAddress('2/2/2'),
                             TelegramType.GROUP_WRITE,
                             direction=TelegramDirection.OUTGOING,
                             payload=test_payload))
コード例 #14
0
 def test_process_group_read(self):
     """Test if process_group_read. Nothing really to test here."""
     xknx = XKNX()
     device = Device(xknx, "TestDevice")
     self.loop.run_until_complete(device.process_group_read(Telegram()))
コード例 #15
0
 async def send_group_read(self):
     """Send group read."""
     telegram = Telegram(self.group_address, TelegramType.GROUP_READ)
     await self.xknx.telegrams.put(telegram)
コード例 #16
0
ファイル: telegram_test.py プロジェクト: spacegaier/xknx
 def test_telegram_equal(self):
     """Test equals operator."""
     self.assertEqual(
         Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()),
         Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()),
     )
コード例 #17
0
ファイル: payload_reader.py プロジェクト: spacegaier/xknx
 async def send_telegram(self, payload: APCI) -> None:
     """Send the telegram."""
     await self.xknx.telegrams.put(
         Telegram(destination_address=self.address, payload=payload))
コード例 #18
0
ファイル: cemi_frame_test.py プロジェクト: mielune/xknx
def test_set_invalid_telegram(frame):
    """Test for setting invalid telegram type"""
    tg = Telegram(telegramtype=None)
    with raises(TypeError):
        frame.telegram = tg
コード例 #19
0
    async def test_tunnel_connect_send_disconnect(
        self, time_travel, route_back, data_endpoint_addr, local_endpoint
    ):
        """Test initiating a tunnelling connection."""
        local_addr = ("192.168.1.1", 12345)
        remote_addr = ("192.168.1.2", 3671)
        self.tunnel.route_back = route_back
        gateway_data_endpoint = (
            HPAI(*data_endpoint_addr) if data_endpoint_addr else HPAI()
        )
        self.tunnel.transport.connect = AsyncMock()
        self.tunnel.transport.getsockname = Mock(return_value=local_addr)
        self.tunnel.transport.send = Mock()
        self.tunnel.transport.stop = Mock()

        # Connect
        connect_request = ConnectRequest(
            control_endpoint=local_endpoint,
            data_endpoint=local_endpoint,
        )
        connect_frame = KNXIPFrame.init_from_body(connect_request)

        connection_task = asyncio.create_task(self.tunnel.connect())
        await time_travel(0)
        self.tunnel.transport.connect.assert_called_once()
        self.tunnel.transport.send.assert_called_once_with(connect_frame)

        connect_response_frame = KNXIPFrame.init_from_body(
            ConnectResponse(
                communication_channel=23,
                data_endpoint=gateway_data_endpoint,
                identifier=7,
            )
        )
        self.tunnel.transport.handle_knxipframe(connect_response_frame, remote_addr)
        await connection_task
        assert self.tunnel._data_endpoint_addr == data_endpoint_addr
        assert self.tunnel._src_address == IndividualAddress(7)

        # Send - use data endpoint
        self.tunnel.transport.send.reset_mock()
        test_telegram = Telegram(payload=GroupValueWrite(DPTArray((1,))))
        test_telegram_frame = KNXIPFrame.init_from_body(
            TunnellingRequest(
                communication_channel_id=23,
                sequence_counter=0,
                cemi=CEMIFrame.init_from_telegram(
                    test_telegram,
                    code=CEMIMessageCode.L_DATA_REQ,
                    src_addr=IndividualAddress(7),
                ),
            )
        )
        asyncio.create_task(self.tunnel.send_telegram(test_telegram))
        await time_travel(0)
        self.tunnel.transport.send.assert_called_once_with(
            test_telegram_frame, addr=data_endpoint_addr
        )
        # skip ack and confirmation

        # Disconnect
        self.tunnel.transport.send.reset_mock()
        disconnect_request = DisconnectRequest(
            communication_channel_id=23,
            control_endpoint=local_endpoint,
        )
        disconnect_frame = KNXIPFrame.init_from_body(disconnect_request)

        disconnection_task = asyncio.create_task(self.tunnel.disconnect())
        await time_travel(0)
        self.tunnel.transport.send.assert_called_once_with(disconnect_frame)

        disconnect_response_frame = KNXIPFrame.init_from_body(
            DisconnectResponse(communication_channel_id=23)
        )
        self.tunnel.transport.handle_knxipframe(disconnect_response_frame, remote_addr)
        await disconnection_task
        assert self.tunnel._data_endpoint_addr is None
        self.tunnel.transport.stop.assert_called_once()
コード例 #20
0
    async def test_switch_on_off(self):
        """Test switching on/off of a Fan."""
        xknx = XKNX()
        fan = Fan(xknx, name="TestFan", group_address_speed="1/2/3")

        # Turn the fan on via speed GA. First try without providing a speed,
        # which will set it to the default 50% percentage.
        await fan.turn_on()
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        # 128 is 50% as byte (0...255)
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray(128)),
        )

        # Try again, but this time with a speed provided
        await fan.turn_on(55)
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        # 140 is 55% as byte (0...255)
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray(140)),
        )

        # Turn the fan off via the speed GA
        await fan.turn_off()
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray(0)),
        )

        fan_with_switch = Fan(
            xknx,
            name="TestFanSwitch",
            group_address_speed="1/2/3",
            group_address_switch="4/5/6",
        )

        # Turn the fan on via the switch GA, which should not adjust the speed
        await fan_with_switch.turn_on()
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("4/5/6"),
            payload=GroupValueWrite(DPTBinary(1)),
        )

        # Turn the fan off via the switch GA
        await fan_with_switch.turn_off()
        assert xknx.telegrams.qsize() == 1
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("4/5/6"),
            payload=GroupValueWrite(DPTBinary(0)),
        )

        # Turn the fan on again this time with a provided speed, which for a switch GA fan
        # should result in separate telegrams to switch on the fan and then set the speed.
        await fan_with_switch.turn_on(55)
        assert xknx.telegrams.qsize() == 2
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("4/5/6"),
            payload=GroupValueWrite(DPTBinary(1)),
        )
        telegram = xknx.telegrams.get_nowait()
        assert telegram == Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray(140)),
        )
コード例 #21
0
 def test_process_group_read(self):
     """Test if process_group_read. Nothing really to test here."""
     xknx = XKNX(loop=self.loop)
     device = Device(xknx, 'TestDevice')
     self.loop.run_until_complete(
         asyncio.Task(device.process_group_read(Telegram())))
コード例 #22
0
def test_telegram_unsupported_address(frame):
    """Test telegram conversion flags with an unsupported address"""
    with raises(TypeError):
        frame.telegram = Telegram(destination_address=object())
コード例 #23
0
def test_telegram_individual_address(frame):
    """Test telegram conversion flags with a individual address"""
    frame.telegram = Telegram(destination_address=IndividualAddress(0))

    assert (frame.flags & CEMIFlags.DESTINATION_INDIVIDUAL_ADDRESS
            ) == CEMIFlags.DESTINATION_INDIVIDUAL_ADDRESS
コード例 #24
0
def test_telegram_group_address(frame):
    """Test telegram conversion flags with a group address"""
    frame.telegram = Telegram(destination_address=GroupAddress(0))

    assert (frame.flags & CEMIFlags.DESTINATION_GROUP_ADDRESS
            ) == CEMIFlags.DESTINATION_GROUP_ADDRESS
コード例 #25
0
ファイル: climate_test.py プロジェクト: vosc/xknx
    def test_target_temperature_down(self):
        """Test decrease target temperature."""
        # pylint: disable=no-self-use
        xknx = XKNX(loop=self.loop)
        climate = Climate(xknx,
                          'TestClimate',
                          group_address_target_temperature='1/2/2',
                          group_address_setpoint_shift='1/2/3')

        self.loop.run_until_complete(
            asyncio.Task(climate.set_setpoint_shift(1)))
        self.assertEqual(xknx.telegrams.qsize(), 1)
        self.assertEqual(
            xknx.telegrams.get_nowait(),
            # DEFAULT_SETPOINT_SHIFT_STEP is 0.5 -> payload = setpoint_shift * 2
            Telegram(GroupAddress('1/2/3'), payload=DPTArray(2)))

        self.loop.run_until_complete(
            asyncio.Task(climate.target_temperature.set(23.00)))
        self.assertEqual(xknx.telegrams.qsize(), 1)
        self.assertEqual(
            xknx.telegrams.get_nowait(),
            Telegram(GroupAddress('1/2/2'),
                     payload=DPTArray(DPT2ByteFloat().to_knx(23.00))))
        self.assertEqual(climate.base_temperature, 22.0)

        # First change
        self.loop.run_until_complete(
            asyncio.Task(climate.set_target_temperature(20.50)))
        self.assertEqual(xknx.telegrams.qsize(), 2)
        self.assertEqual(xknx.telegrams.get_nowait(),
                         Telegram(GroupAddress('1/2/3'),
                                  payload=DPTArray(0xFD)))  # -3
        self.assertEqual(
            xknx.telegrams.get_nowait(),
            Telegram(GroupAddress('1/2/2'),
                     payload=DPTArray(DPT2ByteFloat().to_knx(20.50))))
        self.assertEqual(climate.target_temperature.value, 20.50)

        # Second change
        self.loop.run_until_complete(
            asyncio.Task(climate.set_target_temperature(19.00)))
        self.assertEqual(xknx.telegrams.qsize(), 2)
        self.assertEqual(xknx.telegrams.get_nowait(),
                         Telegram(GroupAddress('1/2/3'),
                                  payload=DPTArray(0xFA)))  # -6
        self.assertEqual(
            xknx.telegrams.get_nowait(),
            Telegram(GroupAddress('1/2/2'),
                     payload=DPTArray(DPT2ByteFloat().to_knx(19.00))))
        self.assertEqual(climate.target_temperature.value, 19.00)

        # Test min target temperature
        # Base (22) - setpoint_shift_min (6)
        self.assertEqual(climate.target_temperature_min, 16.00)

        # third change - limit exceeded, setting to min
        self.loop.run_until_complete(
            asyncio.Task(climate.set_target_temperature(15.50)))
        self.assertEqual(climate.target_temperature_min, 16.00)
        self.assertEqual(climate.setpoint_shift, -6)
コード例 #26
0
def test_telegram_unsupported_address():
    """Test telegram conversion flags with an unsupported address."""
    frame = CEMIFrame()
    with pytest.raises(TypeError):
        frame.telegram = Telegram(destination_address=object())
コード例 #27
0
 async def test_process_group_read(self):
     """Test if process_group_read. Nothing really to test here."""
     xknx = XKNX()
     device = Device(xknx, "TestDevice")
     await device.process_group_read(Telegram())
コード例 #28
0
    async def test_binary_sensor_loop(self, value_type, test_payload, test_value):
        """Test binary_sensor and expose_sensor with binary values."""
        xknx = XKNX()
        xknx.knxip_interface = AsyncMock()
        xknx.rate_limit = False

        telegram_callback = AsyncMock()
        xknx.telegram_queue.register_telegram_received_cb(
            telegram_callback,
            address_filters=[AddressFilter("i-test")],
            match_for_outgoing=True,
        )
        await xknx.telegram_queue.start()

        expose = ExposeSensor(
            xknx,
            "TestExpose",
            group_address="i-test",
            value_type=value_type,
        )
        assert expose.resolve_state() is None

        await expose.set(test_value)
        await xknx.telegrams.join()
        outgoing_telegram = Telegram(
            destination_address=InternalGroupAddress("i-test"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(test_payload),
        )
        # InternalGroupAddress isn't passed to knxip_interface
        xknx.knxip_interface.send_telegram.assert_not_called()
        telegram_callback.assert_called_with(outgoing_telegram)
        assert expose.resolve_state() == test_value

        bin_sensor = BinarySensor(xknx, "TestSensor", group_address_state="i-test")
        assert bin_sensor.state is None

        # read sensor state (from expose as it has the same GA)
        # wait_for_result so we don't have to await self.xknx.telegrams.join()
        await bin_sensor.sync(wait_for_result=True)
        read_telegram = Telegram(
            destination_address=InternalGroupAddress("i-test"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueRead(),
        )
        response_telegram = Telegram(
            destination_address=InternalGroupAddress("i-test"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueResponse(test_payload),
        )
        xknx.knxip_interface.send_telegram.assert_not_called()
        telegram_callback.assert_has_calls(
            [
                call(read_telegram),
                call(response_telegram),
            ]
        )
        # test if Sensor has successfully read from ExposeSensor
        assert bin_sensor.state == test_value
        assert expose.resolve_state() == bin_sensor.state
        await xknx.telegram_queue.stop()
コード例 #29
0
ファイル: telegram_test.py プロジェクト: mielune/xknx
 def test_telegram_equal(self):
     """Test equals operator."""
     self.assertEqual(
         Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ),
         Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ),
     )
コード例 #30
0
    def test_tunnelling(self):
        """Test tunnelling from KNX bus."""
        # pylint: disable=too-many-locals
        xknx = XKNX()
        communication_channel_id = 23
        udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))),
        )
        sequence_counter = 42
        src_address = IndividualAddress("2.2.2")
        tunnelling = Tunnelling(
            xknx,
            udp_client,
            telegram,
            src_address,
            sequence_counter,
            communication_channel_id,
        )
        tunnelling.timeout_in_seconds = 0

        self.assertEqual(tunnelling.awaited_response_class, TunnellingAck)
        self.assertEqual(tunnelling.communication_channel_id,
                         communication_channel_id)

        # Expected KNX/IP-Frame:
        tunnelling_request = TunnellingRequest(
            xknx,
            communication_channel_id=communication_channel_id,
            sequence_counter=sequence_counter,
        )
        tunnelling_request.cemi.telegram = telegram
        tunnelling_request.cemi.src_addr = src_address
        exp_knxipframe = KNXIPFrame.init_from_body(tunnelling_request)
        with patch("xknx.io.UDPClient.send") as mock_udp_send, patch(
                "xknx.io.UDPClient.getsockname") as mock_udp_getsockname:
            mock_udp_getsockname.return_value = ("192.168.1.3", 4321)
            self.loop.run_until_complete(tunnelling.start())
            mock_udp_send.assert_called_with(exp_knxipframe)

        # Response KNX/IP-Frame with wrong type
        wrong_knxipframe = KNXIPFrame(xknx)
        wrong_knxipframe.init(KNXIPServiceType.CONNECTIONSTATE_REQUEST)
        with patch("logging.Logger.warning") as mock_warning:
            tunnelling.response_rec_callback(wrong_knxipframe, None)
            mock_warning.assert_called_with("Could not understand knxipframe")

        # Response KNX/IP-Frame with error:
        err_knxipframe = KNXIPFrame(xknx)
        err_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK)
        err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID
        with patch("logging.Logger.debug") as mock_warning:
            tunnelling.response_rec_callback(err_knxipframe, None)
            mock_warning.assert_called_with(
                "Error: KNX bus responded to request of type '%s' with error in '%s': %s",
                type(tunnelling).__name__,
                type(err_knxipframe.body).__name__,
                ErrorCode.E_CONNECTION_ID,
            )

        # Correct Response KNX/IP-Frame:
        res_knxipframe = KNXIPFrame(xknx)
        res_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK)
        tunnelling.response_rec_callback(res_knxipframe, None)
        self.assertTrue(tunnelling.success)