def test_value_reader_read_success(self, timeout_mock): """Test value reader: successfull read.""" xknx = XKNX(loop=self.loop) 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)
def test_process_switch(self): """Test process / reading telegrams from telegram queue. Test if switch position is processed correctly.""" xknx = XKNX(loop=self.loop) light = Light(xknx, name="TestLight", group_address_switch='1/2/3', group_address_brightness='1/2/5') self.assertEqual(light.state, False) telegram = Telegram(GroupAddress('1/2/3'), payload=DPTBinary(1)) self.loop.run_until_complete(asyncio.Task(light.process(telegram))) self.assertEqual(light.state, True) telegram = Telegram(GroupAddress('1/2/3'), payload=DPTBinary(0)) self.loop.run_until_complete(asyncio.Task(light.process(telegram))) self.assertEqual(light.state, False)
async def main(): """Connect and read value from KNX bus.""" xknx = XKNX() await xknx.start() value_reader = ValueReader(xknx, GroupAddress('2/0/8')) telegram = await value_reader.read() if telegram is not None: print(telegram) value_reader = ValueReader(xknx, GroupAddress('2/1/8')) telegram = await value_reader.read() if telegram is not None: print(telegram) await xknx.stop()
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 telegram with notification. Test if device was updated.""" xknx = XKNX(loop=self.loop) notification = Notification(xknx, 'Warning', group_address='1/2/3') telegram_set = Telegram(GroupAddress('1/2/3'), payload=DPTArray( DPTString().to_knx("Ein Prosit!"))) self.loop.run_until_complete( asyncio.Task(notification.process(telegram_set))) self.assertEqual(notification.message, "Ein Prosit!") telegram_unset = Telegram(GroupAddress('1/2/3'), payload=DPTArray(DPTString().to_knx(""))) self.loop.run_until_complete( asyncio.Task(notification.process(telegram_unset))) self.assertEqual(notification.message, "")
def __init__(self, xknx, name, group_address_state=None, sync_state=True, device_class=None, significant_bit=1, reset_after=None, actions=None, device_updated_cb=None): """Initialize BinarySensor class.""" # pylint: disable=too-many-arguments super().__init__(xknx, name, device_updated_cb) if isinstance(group_address_state, (str, int)): group_address_state = GroupAddress(group_address_state) if not isinstance(significant_bit, int): raise TypeError() if actions is None: actions = [] self.group_address_state = group_address_state self.sync_state = sync_state self.device_class = device_class self.significant_bit = significant_bit self.reset_after = reset_after self.state = BinarySensorState.OFF self.actions = actions self.last_set = None self.count_set_on = 0 self.count_set_off = 0
def test_start(self): """Test start, run and stop.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) telegram_in = Telegram(direction=TelegramDirection.INCOMING, payload=DPTBinary(1), group_address=GroupAddress("1/2/3")) self.loop.run_until_complete(xknx.telegram_queue.start()) self.assertFalse(xknx.telegram_queue.queue_stopped.is_set()) # queue shall now consume telegrams from xknx.telegrams self.assertEqual(xknx.telegrams.qsize(), 0) xknx.telegrams.put_nowait(telegram_in) xknx.telegrams.put_nowait(telegram_in) self.assertEqual(xknx.telegrams.qsize(), 2) # wait until telegrams are consumed self.loop.run_until_complete(xknx.telegrams.join()) self.assertEqual(xknx.telegrams.qsize(), 0) self.loop.run_until_complete(xknx.telegrams.join()) self.assertEqual(xknx.telegrams.qsize(), 0) # stop run() task with stop() self.loop.run_until_complete(xknx.telegram_queue.stop()) self.assertTrue(xknx.telegram_queue.queue_stopped.is_set())
def test_outgoing(self, logger_warning_mock, if_mock): """Test outgoing telegrams in telegram queue.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) async_if_send_telegram = asyncio.Future() async_if_send_telegram.set_result(None) if_mock.send_telegram.return_value = async_if_send_telegram telegram = Telegram(direction=TelegramDirection.OUTGOING, payload=DPTBinary(1), group_address=GroupAddress("1/2/3")) # log a warning if there is no KNXIP interface instanciated self.loop.run_until_complete( asyncio.Task(xknx.telegram_queue.process_telegram(telegram))) logger_warning_mock.assert_called_once_with( "No KNXIP interface defined") if_mock.send_telegram.assert_not_called() # if we have an interface send the telegram xknx.knxip_interface = if_mock self.loop.run_until_complete( asyncio.Task(xknx.telegram_queue.process_telegram(telegram))) if_mock.send_telegram.assert_called_once_with(telegram)
def test_tunnellilng(self): """Test tunnellilnging from KNX bus.""" # pylint: disable=too-many-locals xknx = XKNX(loop=self.loop) communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray((0x1, 0x2, 0x3))) sequence_counter = 42 src_address = PhysicalAddress('2.2.2') tunnellilng = Tunnelling(xknx, udp_client, telegram, src_address, sequence_counter, communication_channel_id) tunnellilng.timeout_in_seconds = 0 self.assertEqual(tunnellilng.awaited_response_class, TunnellingAck) self.assertEqual(tunnellilng.communication_channel_id, communication_channel_id) # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame(xknx) exp_knxipframe.init(KNXIPServiceType.TUNNELLING_REQUEST) exp_knxipframe.body.cemi.telegram = telegram exp_knxipframe.body.cemi.src_addr = src_address exp_knxipframe.body.communication_channel_id = communication_channel_id exp_knxipframe.body.sequence_counter = sequence_counter exp_knxipframe.normalize() print(exp_knxipframe) 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(asyncio.Task(tunnellilng.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: tunnellilng.response_rec_callback(wrong_knxipframe, None) mock_warning.assert_called_with('Cant 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.warning') as mock_warning: tunnellilng.response_rec_callback(err_knxipframe, None) mock_warning.assert_called_with( 'Error: reading rading group address from KNX bus failed: %s', ErrorCode.E_CONNECTION_ID) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame(xknx) res_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK) with patch('logging.Logger.info') as mock_info: tunnellilng.response_rec_callback(res_knxipframe, None) mock_info.assert_called_with( 'Success: received correct answer from KNX bus: %s', ErrorCode.E_NO_ERROR) self.assertTrue(tunnellilng.success)
def test_process_wrong_payload(self): """Test process wrong telegram (wrong payload type).""" xknx = XKNX(loop=self.loop) notification = Notification(xknx, 'Warning', group_address='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTBinary(1)) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete( asyncio.Task(notification.process(telegram)))
def test_sync_operation_mode(self): """Test sync function / sending group reads to KNX bus for operation mode.""" xknx = XKNX(loop=self.loop) climate = Climate(xknx, 'TestClimate', group_address_operation_mode='1/2/3', group_address_controller_status='1/2/4') self.loop.run_until_complete(asyncio.Task(climate.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 2) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( telegram1, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ)) telegram2 = xknx.telegrams.get_nowait() self.assertEqual( telegram2, Telegram(GroupAddress('1/2/4'), TelegramType.GROUP_READ))
def test_state_addresses(self): """Test expose sensor returns empty list as state addresses.""" xknx = XKNX(loop=self.loop) sensor = Sensor(xknx, 'TestSensor', value_type='temperature', group_address='1/2/3') self.assertEqual(sensor.state_addresses(), [GroupAddress('1/2/3')])
def test_telegram(self): """Test string representation of Telegram.""" telegram = Telegram(group_address=GroupAddress('1/2/3'), payload=DPTBinary(7)) self.assertEqual( str(telegram), '<Telegram group_address="GroupAddress("1/2/3")", payload="<DPTBinary value="7" />" telegramtype="TelegramType.GROUP_WRITE" direction=' '"TelegramDirection.OUTGOING" />')
def __init__(self, xknx, name, group_address=None, group_address_state=None, device_updated_cb=None): """Initialize notification class.""" # pylint: disable=too-many-arguments super().__init__(xknx, name, device_updated_cb) if isinstance(group_address, (str, int)): group_address = GroupAddress(group_address) if isinstance(group_address_state, (str, int)): group_address_state = GroupAddress(group_address_state) self.group_address = group_address self.group_address_state = group_address_state self.message = ""
def test_process_payload_invalid_length(self): """Test process wrong telegram (wrong payload length).""" # pylint: disable=invalid-name xknx = XKNX(loop=self.loop) notification = Notification(xknx, 'Warning', group_address='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray((23, 24))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(asyncio.Task(notification.process(telegram)))
def test_state_addresses(self): """Test state addresses of sensor object.""" xknx = XKNX(loop=self.loop) sensor = Sensor(xknx, 'TestSensor', value_type='temperature', group_address_state='1/2/3') self.assertEqual(sensor.state_addresses(), [GroupAddress('1/2/3')])
def test_process_fan_payload_invalid_length(self): """Test process wrong telegrams. (wrong payload length).""" # pylint: disable=invalid-name xknx = XKNX(loop=self.loop) fan = Fan(xknx, name="TestFan", group_address_speed='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray((23, 24))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(asyncio.Task(fan.process(telegram)))
def test_process_power_status(self): """Test process / reading telegrams from telegram queue. Test if DPT20.105 controller mode is set correctly.""" xknx = XKNX(loop=self.loop) climate = Climate(xknx, 'TestClimate', group_address_on_off='1/2/2') telegram = Telegram(GroupAddress('1/2/2')) telegram.payload = DPTBinary(1) self.loop.run_until_complete(asyncio.Task(climate.process(telegram))) self.assertEqual(climate.is_on, True)
def test_set(self): """Test setting value.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValueSceneNumber( xknx, group_address=GroupAddress("1/2/3")) self.loop.run_until_complete(asyncio.Task(remote_value.set(10))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/3'), payload=DPTArray((0x0A, )))) self.loop.run_until_complete(asyncio.Task(remote_value.set(11))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/3'), payload=DPTArray((0x0B, ))))
def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValueStartStopBlinds( xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTArray((0x01))) self.loop.run_until_complete( asyncio.Task(remote_value.process(telegram))) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(0x10)) self.loop.run_until_complete( asyncio.Task(remote_value.process(telegram))) # pylint: disable=pointless-statement remote_value.value
def test_sync_state(self): """Test sync function / sending group reads to KNX bus.""" xknx = XKNX(loop=self.loop) notification = Notification(xknx, "Warning", group_address='1/2/3') self.loop.run_until_complete(asyncio.Task(notification.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ))
def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValueSceneNumber( 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( asyncio.Task(remote_value.process(telegram))) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTArray(( 0x64, 0x65, ))) self.loop.run_until_complete( asyncio.Task(remote_value.process(telegram)))
def test_sync(self): """Test sync function / sending group reads to KNX bus. Testing with a Light without dimm functionality.""" xknx = XKNX(loop=self.loop) light = Light(xknx, name="TestLight", group_address_switch='1/2/3', group_address_brightness='1/2/5') self.loop.run_until_complete(asyncio.Task(light.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 2) telegram1 = xknx.telegrams.get_nowait() self.assertEqual(telegram1, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ)) telegram2 = xknx.telegrams.get_nowait() self.assertEqual(telegram2, Telegram(GroupAddress('1/2/5'), TelegramType.GROUP_READ))
def test_address(self): """Test string representation of address object.""" address = GroupAddress("1/2/3") self.assertEqual( repr(address), 'GroupAddress("1/2/3")') self.assertEqual( str(address), '1/2/3')
def test_set_off(self): """Test switching off switch.""" xknx = XKNX(loop=self.loop) switch = Switch(xknx, 'TestOutlet', group_address='1/2/3') self.loop.run_until_complete(asyncio.Task(switch.set_off())) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/3'), payload=DPTBinary(0)))
def test_state_addresses(self): """Test expose sensor returns empty list as state addresses.""" xknx = XKNX(loop=self.loop) binary_sensor = BinarySensor(xknx, 'TestInput', group_address='1/2/3', group_address_state='1/2/4') self.assertEqual(binary_sensor.state_addresses(), [GroupAddress('1/2/4')])
async def monitor(address_filters, db): xknx = XKNX() xknx.telegram_queue.register_telegram_received_cb(telegram_received_cb, address_filters) await xknx.start() await xknx.telegram_queue.process_telegram_outgoing( Telegram(GroupAddress('0/0/1'), payload=DPTBinary(1))) while True: conn = sqlite3.connect(db) c = conn.cursor() c.execute('SELECT {id},{coi1},{coi2},{coi3} FROM {tn} WHERE {cn}="knx" AND {cs}="p" ORDER BY {ord} DESC LIMIT 1'.\ format(id='ID',coi1='DEVICE', coi2='FUNCTION', coi3='VALUE', tn='INSTRUCTIONS', cn='CONTROLLER', cs='STATE', ord='ID')) all_rows = c.fetchall() if (str(all_rows) != "[]"): id, device, function, value = split_telegram_ins(all_rows) if (function == "bin"): await xknx.telegram_queue.process_telegram_outgoing( Telegram(GroupAddress(device), payload=DPTBinary(int(value)))) c.execute('UPDATE {tn} SET {cs}="d" WHERE {ide}=id'.\ format(tn='INSTRUCTIONS', cs='STATE', ide='ID')) date_time = str(datetime.datetime.now()) + " " + str( datetime.datetime.today().weekday()) c.execute( "SELECT VALUE FROM DATA WHERE CONTROLLER=? AND DEVICE=? AND FUNCTION=? ORDER BY ID DESC LIMIT 1", ("knx", device, function)) all_rows = c.fetchall() if (str(all_rows) != "[]"): if (str(all_rows)[3:-4] != value): conn.execute( "INSERT INTO DATA (DATE_TIME,CONTROLLER,DEVICE,FUNCTION,VALUE)\ VALUES (?,?,?,?,?)", [date_time, "knx", device, function, value]) else: conn.execute( "INSERT INTO DATA (DATE_TIME,CONTROLLER,DEVICE,FUNCTION,VALUE)\ VALUES (?,?,?,?,?)", [date_time, "knx", device, function, value]) conn.commit() conn.close() await asyncio.sleep(0.1) await xknx.stop()
def test_sync_angle(self): """Test sync function for cover with angle.""" xknx = XKNX(loop=self.loop) cover = Cover(xknx, 'TestCover', group_address_long='1/2/1', group_address_short='1/2/2', group_address_position_state='1/2/3', group_address_angle_state='1/2/4') self.loop.run_until_complete(asyncio.Task(cover.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 2) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( telegram1, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ)) telegram2 = xknx.telegrams.get_nowait() self.assertEqual( telegram2, Telegram(GroupAddress('1/2/4'), TelegramType.GROUP_READ))
def test_process_speed(self): """Test process / reading telegrams from telegram queue. Test if speed is processed.""" xknx = XKNX(loop=self.loop) fan = Fan(xknx, name="TestFan", group_address_speed='1/2/3') self.assertEqual(fan.current_speed, None) # 140 is 55% as byte (0...255) telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray(140)) self.loop.run_until_complete(asyncio.Task(fan.process(telegram))) self.assertEqual(fan.current_speed, 55)
def test_set(self): """Test notificationing off notification.""" xknx = XKNX(loop=self.loop) notification = Notification(xknx, 'Warning', group_address='1/2/3') self.loop.run_until_complete(asyncio.Task(notification.set("Ein Prosit!"))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/3'), payload=DPTArray(DPTString().to_knx("Ein Prosit!"))))