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(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.loop.run_until_complete(binaryinput.process(telegram_on)) self.assertTrue(binaryinput.state) self.loop.run_until_complete(asyncio.sleep(reset_after_sec * 1.1)) self.assertFalse(binaryinput.state) # once for 'on' and once for 'off' self.assertEqual(async_after_update_callback.call_count, 2) async_after_update_callback.reset_mock() # multiple telegrams during reset_after time period shall reset timer self.loop.run_until_complete(binaryinput.process(telegram_on)) async_after_update_callback.assert_called_once() self.loop.run_until_complete(binaryinput.process(telegram_on)) self.loop.run_until_complete(binaryinput.process(telegram_on)) # second and third telegram resets timer but doesn't run callback async_after_update_callback.assert_called_once() self.assertTrue(binaryinput.state) self.loop.run_until_complete(asyncio.sleep(reset_after_sec * 1.1)) self.assertFalse(binaryinput.state) # once for 'on' and once for 'off' self.assertEqual(async_after_update_callback.call_count, 2)
def test_process_callback_ignore_internal_state_no_counter(self): """Test after_update_callback after state of switch was changed.""" # pylint: disable=protected-access xknx = XKNX() switch = BinarySensor( xknx, "TestInput", group_address_state="1/2/3", ignore_internal_state=True, context_timeout=0, ) 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)), ) self.loop.run_until_complete(switch.process(telegram)) # no _context_task started because context_timeout is False self.assertIsNone(switch._context_task) async_after_update_callback.assert_called_once_with(switch) async_after_update_callback.reset_mock() # send same telegram again self.loop.run_until_complete(switch.process(telegram)) async_after_update_callback.assert_called_once_with(switch)
def test_process_callback(self): """Test after_update_callback after state of switch was changed.""" # pylint: disable=protected-access xknx = XKNX() switch = BinarySensor(xknx, "TestInput", group_address_state="1/2/3", ignore_internal_state=False) after_update_callback = Mock() async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.loop.run_until_complete(switch.process(telegram)) # no _context_task started because ignore_internal_state is False self.assertIsNone(switch._context_task) after_update_callback.assert_called_once_with(switch) after_update_callback.reset_mock() # send same telegram again self.loop.run_until_complete(switch.process(telegram)) after_update_callback.assert_not_called()
def test_process_group_value_response(self): """Test precess of GroupValueResponse telegrams.""" # pylint: disable=protected-access xknx = XKNX() switch = BinarySensor( xknx, "TestInput", group_address_state="1/2/3", ignore_internal_state=True, ) async_after_update_callback = AsyncMock() switch.register_device_updated_cb(async_after_update_callback) write_telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) response_telegram = Telegram( group_address=GroupAddress("1/2/3"), payload=DPTBinary(1), telegramtype=TelegramType.GROUP_RESPONSE, ) self.assertIsNone(switch.state) # initial GroupValueResponse changes state and runs callback self.loop.run_until_complete(switch.process(response_telegram)) self.assertTrue(switch.state) async_after_update_callback.assert_called_once_with(switch) # GroupValueWrite with same payload runs callback because of `ignore_internal_state` async_after_update_callback.reset_mock() self.loop.run_until_complete(switch.process(write_telegram)) self.assertTrue(switch.state) async_after_update_callback.assert_called_once_with(switch) # GroupValueResponse should not run callback when state has not changed async_after_update_callback.reset_mock() self.loop.run_until_complete(switch.process(response_telegram)) async_after_update_callback.assert_not_called()
def test_process(self): """Test process / reading telegrams from telegram queue.""" xknx = XKNX() binaryinput = BinarySensor(xknx, "TestInput", "1/2/3") self.assertEqual(binaryinput.state, None) telegram_on = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(binaryinput.process(telegram_on)) self.assertEqual(binaryinput.state, True) telegram_off = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binaryinput.process(telegram_off)) self.assertEqual(binaryinput.state, False) binaryinput2 = BinarySensor(xknx, "TestInput", "1/2/4") self.assertEqual(binaryinput2.state, None) telegram_off2 = Telegram( destination_address=GroupAddress("1/2/4"), payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binaryinput2.process(telegram_off2)) self.assertEqual(binaryinput2.state, False)
def test_process_significant_bit(self): """Test process / reading telegrams from telegram queue with specific significant bit set.""" xknx = XKNX(loop=self.loop) binaryinput = BinarySensor(xknx, 'TestInput', '1/2/3', significant_bit=3) self.assertEqual(binaryinput.state, BinarySensorState.OFF) # Wrong significant bit: 0000 1011 = 11 telegram_on = Telegram() telegram_on.payload = DPTBinary(11) self.loop.run_until_complete( asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, BinarySensorState.OFF) # Correct significant bit: 0000 1101 = 13 telegram_on = Telegram() telegram_on.payload = DPTBinary(13) self.loop.run_until_complete( asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, BinarySensorState.ON) # Resetting, significant bit: 0000 0011 = 3 telegram_off = Telegram() telegram_off.payload = DPTBinary(3) self.loop.run_until_complete( asyncio.Task(binaryinput.process(telegram_off))) self.assertEqual(binaryinput.state, BinarySensorState.OFF)
def test_process_action_ignore_internal_state(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/5', ignore_internal_state=True) action_on = Action( xknx, hook='on', target='TestOutlet', method='on') binary_sensor.actions.append(action_on) 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) self.loop.run_until_complete(asyncio.Task(switch.set_off())) self.assertEqual( xknx.devices['TestOutlet'].state, False) self.assertEqual( xknx.devices['TestInput'].state, BinarySensorState.ON) self.loop.run_until_complete(asyncio.sleep(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)
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)
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, False) self.assertEqual( xknx.devices['TestOutlet'].state, False) telegram_on = Telegram(group_address=GroupAddress('1/2/3')) telegram_on.payload = DPTBinary(1) self.loop.run_until_complete(asyncio.Task(binary_sensor.process(telegram_on))) self.assertEqual( xknx.devices['TestInput'].state, True) self.assertEqual( xknx.devices['TestOutlet'].state, True) telegram_off = Telegram(group_address=GroupAddress('1/2/3')) telegram_off.payload = DPTBinary(0) self.loop.run_until_complete(asyncio.Task(binary_sensor.process(telegram_off))) self.assertEqual( xknx.devices['TestInput'].state, False) self.assertEqual( xknx.devices['TestOutlet'].state, False)
def test_process_reset_after(self): """Test process / reading telegrams from telegram queue.""" xknx = XKNX(loop=self.loop) binaryinput = BinarySensor(xknx, 'TestInput', '1/2/3', reset_after=0.01) telegram_on = Telegram(payload=DPTBinary(1)) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, BinarySensorState.OFF)
def test_process_wrong_payload(self): """Test process wrong telegram (wrong payload type).""" xknx = XKNX(loop=self.loop) binary_sensor = BinarySensor(xknx, 'Warning', group_address_state='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray((0x1, 0x2, 0x3))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(asyncio.Task(binary_sensor.process(telegram)))
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, False) telegram_on = Telegram(group_address=GroupAddress('1/2/3')) telegram_on.payload = DPTBinary(1) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, True) telegram_off = Telegram(group_address=GroupAddress('1/2/3')) telegram_off.payload = DPTBinary(0) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_off))) self.assertEqual(binaryinput.state, False)
def test_process_invert(self): """Test process / reading telegrams from telegram queue.""" xknx = XKNX() bs_invert = BinarySensor(xknx, "TestInput", "1/2/3", invert=True) self.assertEqual(bs_invert.state, None) telegram_on = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(0)) self.loop.run_until_complete(bs_invert.process(telegram_on)) self.assertEqual(bs_invert.state, True) telegram_off = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.loop.run_until_complete(bs_invert.process(telegram_off)) self.assertEqual(bs_invert.state, False)
def test_process_callback_ignore_internal_state(self): """Test after_update_callback after state of switch was changed.""" # pylint: disable=protected-access xknx = XKNX() switch = BinarySensor( xknx, "TestInput", group_address_state="1/2/3", ignore_internal_state=True, context_timeout=0.001, ) after_update_callback = Mock() async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.assertEqual(switch.counter, 0) self.loop.run_until_complete(switch.process(telegram)) after_update_callback.assert_not_called() self.assertEqual(switch.counter, 1) self.loop.run_until_complete(switch._context_task) after_update_callback.assert_called_with(switch) # once with counter 1 and once with counter 0 self.assertEqual(after_update_callback.call_count, 2) after_update_callback.reset_mock() # send same telegram again self.loop.run_until_complete(switch.process(telegram)) self.assertEqual(switch.counter, 1) self.loop.run_until_complete(switch.process(telegram)) self.assertEqual(switch.counter, 2) after_update_callback.assert_not_called() self.loop.run_until_complete(switch._context_task) after_update_callback.assert_called_with(switch) # once with counter 2 and once with counter 0 self.assertEqual(after_update_callback.call_count, 2) self.assertEqual(switch.counter, 0)
def test_process_action_ignore_internal_state(self): """Test process / reading telegrams from telegram queue. Test if action is executed.""" xknx = XKNX(loop=self.loop) switch = Switch(xknx, "TestOutlet", group_address="5/5/5") binary_sensor = BinarySensor(xknx, "TestInput", group_address_state="1/2/3", ignore_internal_state=True) action_on = Action(xknx, hook="on", target="TestOutlet", method="on") binary_sensor.actions.append(action_on) self.assertEqual(binary_sensor.state, None) self.assertEqual(switch.state, False) telegram_on = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) with patch("time.time") as mock_time, patch( "asyncio.sleep", new_callable=AsyncMock) as mock_sleep: mock_time.return_value = 1599076123.0 self.loop.run_until_complete(binary_sensor.process(telegram_on)) self.loop.run_until_complete( xknx.devices.process(xknx.telegrams.get_nowait())) self.assertEqual(binary_sensor.state, True) self.assertEqual(switch.state, True) self.loop.run_until_complete(switch.set_off()) self.loop.run_until_complete( xknx.devices.process(xknx.telegrams.get_nowait())) self.assertEqual(switch.state, False) self.assertEqual(binary_sensor.state, True) # add a second to the time to avoid double tap behaviour here mock_time.return_value += BinarySensor.DEFAULT_CONTEXT_TIMEOUT self.loop.run_until_complete(binary_sensor.process(telegram_on)) self.loop.run_until_complete( xknx.devices.process(xknx.telegrams.get_nowait())) self.assertEqual(binary_sensor.state, True) self.assertEqual(switch.state, True)
def test_process_reset_after(self): """Test process / reading telegrams from telegram queue.""" xknx = XKNX(loop=self.loop) reset_after_ms = 0.01 binaryinput = BinarySensor(xknx, 'TestInput', '1/2/3', reset_after=reset_after_ms) telegram_on = Telegram(group_address=GroupAddress('1/2/3')) telegram_on.payload = DPTBinary(1) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_on))) self.loop.run_until_complete(asyncio.sleep(reset_after_ms*2/1000)) self.assertEqual(binaryinput.state, False)
def test_process_action(self): """Test process / reading telegrams from telegram queue. Test if action is executed.""" xknx = XKNX() switch = Switch(xknx, "TestOutlet", group_address="1/2/3") 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) self.assertEqual(binary_sensor.state, None) self.assertEqual(switch.state, None) telegram_on = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(binary_sensor.process(telegram_on)) # process outgoing telegram from queue self.loop.run_until_complete( switch.process(xknx.telegrams.get_nowait())) self.assertEqual(binary_sensor.state, True) self.assertEqual(switch.state, True) telegram_off = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binary_sensor.process(telegram_off)) self.loop.run_until_complete( switch.process(xknx.telegrams.get_nowait())) self.assertEqual(binary_sensor.state, False) self.assertEqual(switch.state, False)
def test_process_wrong_payload(self): """Test process wrong telegram (wrong payload type).""" xknx = XKNX() binary_sensor = BinarySensor(xknx, "Warning", group_address_state="1/2/3") telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(binary_sensor.process(telegram))
def test_process_reset_after(self): """Test process / reading telegrams from telegram queue.""" xknx = XKNX() reset_after_sec = 0.001 binaryinput = BinarySensor(xknx, "TestInput", "1/2/3", reset_after=reset_after_sec) telegram_on = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.loop.run_until_complete(binaryinput.process(telegram_on)) self.loop.run_until_complete(asyncio.sleep(reset_after_sec * 2)) self.assertEqual(binaryinput.state, False)
def test_process_significant_bit(self): """Test process / reading telegrams from telegram queue with specific significant bit set.""" xknx = XKNX(loop=self.loop) binaryinput = BinarySensor(xknx, 'TestInput', '1/2/3', significant_bit=3) self.assertEqual(binaryinput.state, BinarySensorState.OFF) # Wrong significant bit: 0000 1011 = 11 telegram_on = Telegram() telegram_on.payload = DPTBinary(11) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, BinarySensorState.OFF) # Correct significant bit: 0000 1101 = 13 telegram_on = Telegram() telegram_on.payload = DPTBinary(13) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_on))) self.assertEqual(binaryinput.state, BinarySensorState.ON) # Resetting, significant bit: 0000 0011 = 3 telegram_off = Telegram() telegram_off.payload = DPTBinary(3) self.loop.run_until_complete(asyncio.Task(binaryinput.process(telegram_off))) self.assertEqual(binaryinput.state, BinarySensorState.OFF)
def test_process_callback(self): """Test after_update_callback after state of switch was changed.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) switch = BinarySensor(xknx, 'TestInput', group_address_state='1/2/3') after_update_callback = Mock() async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram() telegram.payload = DPTBinary(1) self.loop.run_until_complete(asyncio.Task(switch.process(telegram))) after_update_callback.assert_called_with(switch)
def test_binary_sensor_loop(self): """Test binary_sensor and expose_sensor with binary values.""" test_cases = [ ("binary", DPTBinary(0), False), ("binary", DPTBinary(1), True), ] for value_type, test_payload, test_value in test_cases: with self.subTest(value_type=value_type): xknx = XKNX(loop=self.loop) sensor = BinarySensor( xknx, "TestSensor_%s" % value_type, group_address_state="1/1/1" ) 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(sensor.process(incoming_telegram)) incoming_value = sensor.is_on() self.assertEqual(incoming_value, test_value) self.loop.run_until_complete(expose.set(test_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, ), )
def test_binary_sensor_loop(self): """Test binary_sensor and expose_sensor with binary values.""" test_cases = [ ('binary', DPTBinary(0), False), ('binary', DPTBinary(1), True), ] for value_type, test_payload, test_value in test_cases: with self.subTest(value_type=value_type): xknx = XKNX(loop=self.loop) sensor = BinarySensor( xknx, 'TestSensor_%s' % value_type, group_address_state='1/1/1' ) 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.is_on() self.assertEqual(incoming_value, test_value) self.loop.run_until_complete(asyncio.Task(expose.set(test_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))