示例#1
0
    def test_end_to_end_group_write_binary_off(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, switch off light in my kitchen."""
        # Switch off Kitchen-L1
        raw = bytes.fromhex("0610053000112900BCD0FFF90149010080")
        xknx = XKNX()
        knxipframe = KNXIPFrame(xknx)
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.cemi.telegram
        assert telegram == Telegram(
            destination_address=GroupAddress("329"),
            payload=GroupValueWrite(DPTBinary(0)),
            source_address=IndividualAddress("15.15.249"),
        )

        cemi = CEMIFrame(xknx, src_addr=IndividualAddress("15.15.249"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(xknx, cemi=cemi)
        knxipframe2 = KNXIPFrame.init_from_body(routing_indication)

        assert knxipframe2.header.to_knx() == list(raw[0:6])
        assert knxipframe2.body.to_knx() == list(raw[6:])
        assert knxipframe2.to_knx() == list(raw)
示例#2
0
    async def service_send_to_knx_bus(self, call):
        """Service for sending an arbitrary KNX message to the KNX bus."""
        attr_address = call.data.get(KNX_ADDRESS)
        attr_payload = call.data.get(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=GroupAddress(address),
                payload=GroupValueWrite(payload),
            )
            await self.xknx.telegrams.put(telegram)
示例#3
0
    def test_callback_negative_address_filters(self):
        """Test telegram_received_callback after state of switch was changed."""
        xknx = XKNX()
        async_telegram_received_callback = AsyncMock()

        xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_callback,
            address_filters=[
                AddressFilter("2/4-8/*"),
                AddressFilter("1/2/8-")
            ],
        )

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        xknx.telegrams.put_nowait(telegram)
        self.loop.run_until_complete(
            xknx.telegram_queue._process_all_telegrams())

        async_telegram_received_callback.assert_not_called()
示例#4
0
 def test_to_process_error(self):
     """Test process errornous telegram."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValueDpt2ByteUnsigned(
         xknx, group_address=GroupAddress("1/2/3"))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(group_address=GroupAddress("1/2/3"),
                             payload=DPTBinary(1))
         self.loop.run_until_complete(remote_value.process(telegram))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(group_address=GroupAddress("1/2/3"),
                             payload=DPTArray((0x64, )))
         self.loop.run_until_complete(remote_value.process(telegram))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             group_address=GroupAddress("1/2/3"),
             payload=DPTArray((
                 0x64,
                 0x53,
                 0x42,
             )),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
示例#5
0
    def test_maximum_apci(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, testing maximum APCI."""
        telegram = Telegram(
            destination_address=GroupAddress(337),
            payload=GroupValueWrite(DPTBinary(DPTBinary.APCI_MAX_VALUE)),
            source_address=IndividualAddress("1.3.1"),
        )

        cemi = CEMIFrame(src_addr=IndividualAddress("1.3.1"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(cemi=cemi)
        knxipframe = KNXIPFrame.init_from_body(routing_indication)

        raw = bytes.fromhex(
            "06 10 05 30 00 11 29 00 bc d0 13 01 01 51 01 00 bf")

        assert knxipframe.to_knx() == raw

        knxipframe2 = KNXIPFrame()
        knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION)
        knxipframe2.from_knx(knxipframe.to_knx())
        assert knxipframe2.body.cemi.telegram == telegram
示例#6
0
    def test_end_to_end_group_response(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, group response."""
        # Incoming state
        raw = bytes.fromhex(
            "06 10 05 30 00 11 29 00 bc d0 13 01 01 88 01 00 41")
        knxipframe = KNXIPFrame()
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.cemi.telegram
        assert telegram == Telegram(
            destination_address=GroupAddress("392"),
            payload=GroupValueResponse(DPTBinary(1)),
            source_address=IndividualAddress("1.3.1"),
        )

        cemi = CEMIFrame(src_addr=IndividualAddress("1.3.1"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(cemi=cemi)
        knxipframe2 = KNXIPFrame.init_from_body(routing_indication)

        assert knxipframe2.header.to_knx() == raw[0:6]
        assert knxipframe2.body.to_knx() == raw[6:]
        assert knxipframe2.to_knx() == raw
示例#7
0
 async def test_to_process_error(self):
     """Test process errornous telegram."""
     xknx = XKNX()
     remote_value = RemoteValueDpt2ByteUnsigned(
         xknx, group_address=GroupAddress("1/2/3"))
     with pytest.raises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTBinary(1)),
         )
         await remote_value.process(telegram)
     with pytest.raises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTArray((0x64, ))),
         )
         await remote_value.process(telegram)
     with pytest.raises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTArray((0x64, 0x53, 0x42))),
         )
         await remote_value.process(telegram)
示例#8
0
    async def test_process_reset_after(self):
        """Test process / reading telegrams from telegram queue."""
        xknx = XKNX()
        reset_after_sec = 0.001
        async_after_update_callback = AsyncMock()
        binaryinput = BinarySensor(
            xknx,
            "TestInput",
            "1/2/3",
            reset_after=reset_after_sec,
            device_updated_cb=async_after_update_callback,
        )
        telegram_on = Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTBinary(1)),
        )

        await binaryinput.process(telegram_on)
        assert binaryinput.state
        await asyncio.sleep(reset_after_sec * 1.2)
        assert not binaryinput.state
        # once for 'on' and once for 'off'
        assert async_after_update_callback.call_count == 2

        async_after_update_callback.reset_mock()
        # multiple telegrams during reset_after time period shall reset timer
        await binaryinput.process(telegram_on)
        async_after_update_callback.assert_called_once()
        await binaryinput.process(telegram_on)
        await binaryinput.process(telegram_on)
        # second and third telegram resets timer but doesn't run callback
        async_after_update_callback.assert_called_once()
        assert binaryinput.state
        await asyncio.sleep(reset_after_sec * 1.2)
        assert not binaryinput.state
        # once for 'on' and once for 'off'
        assert async_after_update_callback.call_count == 2
示例#9
0
    def test_maximum_apci(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, testing maximum APCI."""
        telegram = Telegram(group_address=GroupAddress(337),
                            payload=DPTBinary(DPTBinary.APCI_MAX_VALUE))
        xknx = XKNX(loop=self.loop)
        knxipframe = KNXIPFrame(xknx)
        knxipframe.init(KNXIPServiceType.ROUTING_INDICATION)
        knxipframe.body.cemi.src_addr = PhysicalAddress("1.3.1")
        knxipframe.body.cemi.telegram = telegram
        knxipframe.body.cemi.set_hops(5)
        knxipframe.normalize()

        raw = (
            0x06,
            0x10,
            0x05,
            0x30,
            0x00,
            0x11,
            0x29,
            0x00,
            0xBC,
            0xD0,
            0x13,
            0x01,
            0x01,
            0x51,
            0x01,
            0x00,
            0xBF,
        )
        self.assertEqual(knxipframe.to_knx(), list(raw))

        knxipframe2 = KNXIPFrame(xknx)
        knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION)
        knxipframe2.from_knx(knxipframe.to_knx())
        self.assertEqual(knxipframe2.body.cemi.telegram, telegram)
示例#10
0
async def main() -> None:
    """Test connection with secure."""

    connection_config = ConnectionConfig(
        connection_type=ConnectionType.TUNNELING_TCP_SECURE,
        gateway_ip="192.168.1.188",
        secure_config=SecureConfig(
            user_id=4,
            knxkeys_file_path="/home/marvin/testcase.knxkeys",
            knxkeys_password="******",
        ),
    )
    xknx = XKNX(connection_config=connection_config)
    await xknx.start()

    await xknx.knxip_interface.send_telegram(
        Telegram(
            GroupAddress("1/0/32"),
            TelegramDirection.OUTGOING,
            GroupValueWrite(DPTBinary(1)),
        ))
    await asyncio.sleep(5)
    print("Tunnel connected")
    await xknx.stop()
示例#11
0
    async def test_process_callback(self):
        """Test after_update_callback after state of switch was changed."""
        xknx = XKNX()
        switch = BinarySensor(xknx,
                              "TestInput",
                              group_address_state="1/2/3",
                              ignore_internal_state=False)
        async_after_update_callback = AsyncMock()

        switch.register_device_updated_cb(async_after_update_callback)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await switch.process(telegram)
        # no _context_task started because ignore_internal_state is False
        assert switch._context_task is None
        async_after_update_callback.assert_called_once_with(switch)

        async_after_update_callback.reset_mock()
        # send same telegram again
        await switch.process(telegram)
        async_after_update_callback.assert_not_called()
示例#12
0
    def test_value_reader_read_success(self, timeout_mock):
        """Test value reader: successfull read."""
        xknx = XKNX()
        test_group_address = GroupAddress("0/0/0")
        response_telegram = Telegram(
            group_address=test_group_address,
            telegramtype=TelegramType.GROUP_RESPONSE,
            direction=TelegramDirection.INCOMING,
            payload=DPTBinary(1),
        )

        value_reader = ValueReader(xknx, test_group_address)
        # Create a task for read() (3.5 compatible)
        read_task = asyncio.ensure_future(value_reader.read())
        # receive the response
        self.loop.run_until_complete(
            value_reader.telegram_received(response_telegram))
        # and yield the result
        successfull_read = self.loop.run_until_complete(
            asyncio.gather(read_task))[0]

        # GroupValueRead telegram is still in the queue because we are not actually processing it
        self.assertEqual(xknx.telegrams.qsize(), 1)
        # Callback was removed again
        self.assertEqual(xknx.telegram_queue.telegram_received_cbs, [])
        # Timeout handle was cancelled (cancelled method requires Python 3.7)
        event_has_cancelled = getattr(value_reader.timeout_handle, "cancelled",
                                      None)
        if callable(event_has_cancelled):
            self.assertTrue(value_reader.timeout_handle.cancelled())
        # timeout() was never called because there was no timeout
        timeout_mock.assert_not_called()
        # Telegram was received
        self.assertEqual(value_reader.received_telegram, response_telegram)
        # Successfull read() returns the telegram
        self.assertEqual(successfull_read, response_telegram)
示例#13
0
    def test_value_reader_read_success(self):
        """Test value reader: successfull read."""
        xknx = XKNX()
        test_group_address = GroupAddress("0/0/0")
        response_telegram = Telegram(
            destination_address=test_group_address,
            direction=TelegramDirection.INCOMING,
            payload=GroupValueResponse(DPTBinary(1)),
        )

        value_reader = ValueReader(xknx, test_group_address)
        # receive the response
        self.loop.run_until_complete(value_reader.telegram_received(response_telegram))
        # and yield the result
        successfull_read = self.loop.run_until_complete(value_reader.read())

        # GroupValueRead telegram is still in the queue because we are not actually processing it
        self.assertEqual(xknx.telegrams.qsize(), 1)
        # Callback was removed again
        self.assertEqual(xknx.telegram_queue.telegram_received_cbs, [])
        # Telegram was received
        self.assertEqual(value_reader.received_telegram, response_telegram)
        # Successfull read() returns the telegram
        self.assertEqual(successfull_read, response_telegram)
示例#14
0
    async def test_value_reader_read_success(self):
        """Test value reader: successfull read."""
        xknx = XKNX()
        test_group_address = GroupAddress("0/0/0")
        response_telegram = Telegram(
            destination_address=test_group_address,
            direction=TelegramDirection.INCOMING,
            payload=GroupValueResponse(DPTBinary(1)),
        )

        value_reader = ValueReader(xknx, test_group_address)
        # receive the response
        await value_reader.telegram_received(response_telegram)
        # and yield the result
        successfull_read = await value_reader.read()

        # GroupValueRead telegram is still in the queue because we are not actually processing it
        assert xknx.telegrams.qsize() == 1
        # Callback was removed again
        assert not xknx.telegram_queue.telegram_received_cbs
        # Telegram was received
        assert value_reader.received_telegram == response_telegram
        # Successfull read() returns the telegram
        assert successfull_read == response_telegram
示例#15
0
文件: cover_test.py 项目: jonppe/xknx
    def test_position_without_position_address_uninitialized_down(self):
        """Test moving uninitialized cover to absolute position - with no absolute positioning supported."""
        xknx = XKNX()
        cover = Cover(
            xknx,
            "TestCover",
            group_address_long="1/2/1",
            group_address_short="1/2/2",
            group_address_position_state="1/2/4",
        )

        with patch("logging.Logger.warning") as mock_warn:
            self.loop.run_until_complete(cover.set_position(50))
            self.assertEqual(xknx.telegrams.qsize(), 0)
            mock_warn.assert_called_with(
                "Current position unknown. Initialize cover by moving to end position."
            )

        self.loop.run_until_complete(cover.set_position(100))
        print(cover.travelcalculator.position_closed)
        self.assertEqual(xknx.telegrams.qsize(), 1)
        telegram = xknx.telegrams.get_nowait()
        self.assertEqual(telegram,
                         Telegram(GroupAddress("1/2/1"), payload=DPTBinary(1)))
示例#16
0
 def test_to_process_error(self):
     """Test process errornous telegram."""
     xknx = XKNX()
     remote_value = RemoteValueColorRGBW(
         xknx, group_address=GroupAddress("1/2/3"))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTBinary(1)),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66))),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(
                 DPTArray((0x00, 0x00, 0x0F, 0x64, 0x65, 0x66, 0x67))),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
示例#17
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."
                ""))
示例#18
0
    def test_no_filters(self):
        """Test telegram_received_callback after state of switch was changed."""
        # pylint: disable=no-self-use
        xknx = XKNX()

        telegram_received_callback = Mock()

        async def async_telegram_received_cb(device):
            """Async callback."""
            telegram_received_callback(device)

        xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_cb)

        telegram = Telegram(
            direction=TelegramDirection.INCOMING,
            payload=DPTBinary(1),
            group_address=GroupAddress("1/2/3"),
        )
        xknx.telegrams.put_nowait(telegram)
        self.loop.run_until_complete(
            xknx.telegram_queue._process_all_telegrams())

        telegram_received_callback.assert_called_with(telegram)
 def test_to_process_error_operation_mode(self):
     """Test process errornous telegram."""
     xknx = XKNX()
     remote_value = RemoteValueOperationMode(
         xknx,
         group_address=GroupAddress("1/2/3"),
         climate_mode_type=RemoteValueOperationMode.ClimateModeType.
         HVAC_MODE,
     )
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTBinary(1)),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
     with self.assertRaises(CouldNotParseTelegram):
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTArray((
                 0x64,
                 0x65,
             ))),
         )
         self.loop.run_until_complete(remote_value.process(telegram))
示例#20
0
    def test_process_to_callback(self, devices_by_ga_mock):
        """Test process_telegram_incoming for returning after processing callback."""
        # pylint: disable=no-self-use
        xknx = XKNX()

        telegram_received_callback = Mock()

        async def async_telegram_received_cb(device):
            """Async callback. Returning 'True'."""
            telegram_received_callback(device)
            return True

        xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_cb)

        telegram = Telegram(
            direction=TelegramDirection.INCOMING,
            payload=DPTBinary(1),
            group_address=GroupAddress("1/2/3"),
        )
        self.loop.run_until_complete(
            xknx.telegram_queue.process_telegram_incoming(telegram))
        telegram_received_callback.assert_called_once_with(telegram)
        devices_by_ga_mock.assert_not_called()
示例#21
0
 def test_dpt_binary(self):
     """Test string representation of DPTBinary."""
     dpt_binary = DPTBinary(7)
     self.assertEqual(str(dpt_binary), '<DPTBinary value="7" />')
示例#22
0
 def calculate_payload(attr_payload):
     """Calculate payload depending on type of attribute."""
     if isinstance(attr_payload, int):
         return DPTBinary(attr_payload)
     return DPTArray(attr_payload)
示例#23
0
 def test_compare_binary(self):
     """Test comparison of DPTBinary objects."""
     self.assertEqual(DPTBinary(0), DPTBinary(0))
     self.assertEqual(DPTBinary(0), DPTBinary(False))
     self.assertEqual(DPTBinary(1), DPTBinary(True))
     self.assertEqual(DPTBinary(2), DPTBinary(2))
     self.assertNotEqual(DPTBinary(1), DPTBinary(4))
     self.assertNotEqual(DPTBinary(2), DPTBinary(0))
     self.assertNotEqual(DPTBinary(0), DPTBinary(2))
示例#24
0
    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)),
        )
示例#25
0
 def _payload_value(payload: int | tuple[int, ...]) -> DPTArray | DPTBinary:
     """Prepare payload value for GroupValueWrite or GroupValueResponse."""
     if isinstance(payload, int):
         return DPTBinary(payload)
     return DPTArray(payload)
示例#26
0
 def test_dpt_binary_assign_limit_exceeded(self):
     """Test initialization of DPTBinary objects with wrong value (value exceeded)."""
     with self.assertRaises(ConversionError):
         DPTBinary(DPTBinary.APCI_MAX_VALUE + 1)
示例#27
0
 def test_dpt_binary_assign(self):
     """Test initialization of DPTBinary objects."""
     self.assertEqual(DPTBinary(8).value, 8)
示例#28
0
文件: dpt_test.py 项目: iligiddi/xknx
 def test_dpt_representation(self):
     """Test representation of DPTBinary and DPTArray."""
     assert DPTBinary(True).__repr__() == "DPTBinary(0x1)"
     assert DPTArray((5, 15)).__repr__() == "DPTArray((0x5, 0xf))"
示例#29
0
 def test_dpt_init_with_string(self):
     """Teest initialization of DPTBinary object with wrong value (wrong type)."""
     with self.assertRaises(TypeError):
         DPTBinary("bla")
示例#30
0
文件: dpt_test.py 项目: iligiddi/xknx
 def test_compare_binary(self):
     """Test comparison of DPTBinary objects."""
     assert DPTBinary(0) == DPTBinary(0)
     assert DPTBinary(0) == DPTBinary(False)
     assert DPTBinary(1) == DPTBinary(True)
     assert DPTBinary(2) == DPTBinary(2)
     assert DPTBinary(1) != DPTBinary(4)
     assert DPTBinary(2) != DPTBinary(0)
     assert DPTBinary(0) != DPTBinary(2)