def create_std_ext_msg(address, flags, cmd1, cmd2, user_data=None, target=None, ack=0): """Create a standard or extended message.""" from pyinsteon.protocol.messages.user_data import UserData address = Address(address) data = bytearray() data.append(0x02) if target: target = Address(target) msg_type = 0x51 if user_data else 0x50 else: msg_type = 0x62 data.append(msg_type) data.append(address.high) data.append(address.middle) data.append(address.low) if target: data.append(target.high) data.append(target.middle) data.append(target.low) data.append(flags) data.append(cmd1) data.append(cmd2) if user_data: user_data = UserData(user_data) for byte in user_data: data.append(user_data[byte]) if ack: data.append(ack) return bytes(data)
def setUp(self): """Set up the test.""" self._id_mgr = DeviceIdManager() self._test_response = None self._modem_address = Address("4d5e6f") self._cat = 0x01 self._subcat = 0x02 self._firmware = 0x03 self._target = Address(bytearray([self._cat, self._subcat, self._firmware]))
def cmd_kwargs(cmd1, cmd2, user_data, target=None, address=None, hops_left=3): """Return a kwargs dict for a standard messsage command.""" kwargs = {"cmd1": cmd1, "cmd2": cmd2, "user_data": user_data} if target: kwargs["target"] = Address(target) kwargs["hops_left"] = hops_left if address: kwargs["address"] = Address(address) return kwargs
def setUp(self): """Set up the tests.""" self.hex = "010203" self.address = Address(self.hex) self.address_bytes = Address(bytearray(unhexlify(self.hex))) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
async def async_load(self, *args, **kwargs): """Load the mock devices.""" if self._connected: addr0 = Address("AA.AA.AA") addr1 = Address("11.11.11") addr2 = Address("22.22.22") addr3 = Address("33.33.33") self._devices[addr0] = Hub(addr0, 0x03, 0x00, 0x00, "Hub AA.AA.AA", "0") self._devices[addr1] = MockSwitchLinc(addr1, 0x02, 0x00, 0x00, "Device 11.11.11", "1") self._devices[addr2] = GeneralController(addr2, 0x00, 0x00, 0x00, "Device 22.22.22", "2") self._devices[addr3] = DimmableLightingControl_KeypadLinc_8( addr3, 0x02, 0x00, 0x00, "Device 33.33.33", "3") for device in [ self._devices[addr] for addr in [addr1, addr2, addr3] ]: device.async_read_config = AsyncMock() device.aldb.async_write = AsyncMock() device.aldb.async_load = AsyncMock() device.async_add_default_links = AsyncMock() device.async_read_op_flags = AsyncMock( return_value=ResponseStatus.SUCCESS) device.async_read_ext_properties = AsyncMock( return_value=ResponseStatus.SUCCESS) device.async_write_op_flags = AsyncMock( return_value=ResponseStatus.SUCCESS) device.async_write_ext_properties = AsyncMock( return_value=ResponseStatus.SUCCESS) for device in [self._devices[addr] for addr in [addr2, addr3]]: device.async_status = AsyncMock() self._devices[addr1].async_status = AsyncMock( side_effect=AttributeError) self._devices[addr0].aldb.async_load = AsyncMock() self._devices[addr2].async_read_op_flags = AsyncMock( return_value=ResponseStatus.FAILURE) self._devices[addr2].async_read_ext_properties = AsyncMock( return_value=ResponseStatus.FAILURE) self._devices[addr2].async_write_op_flags = AsyncMock( return_value=ResponseStatus.FAILURE) self._devices[addr2].async_write_ext_properties = AsyncMock( return_value=ResponseStatus.FAILURE) self.modem = self._devices[addr0]
async def test_append(self): """Test appending an address to the list of devices to ID.""" self._id_mgr = DeviceIdManager() address = Address("020202") self._id_mgr.append(address) assert self._id_mgr[address] is not None assert self._id_mgr[address].cat is None
async def test_receive_on_msg(self): """Test receiving an ON message.""" async with async_protocol_manager() as protocol: last_topic = None def topic_received(cmd1, cmd2, target, user_data, hops_left, topic=pub.AUTO_TOPIC): """Receive the OFF topic for a device.""" nonlocal last_topic last_topic = topic.name address = random_address() byte_data = create_std_ext_msg(address, 0x80, 0x11, 0xFF, target=Address("000001")) expected_topic = "{}.{}.on.broadcast".format(address.id, 1) pub.subscribe(topic_received, expected_topic) on_cmd = DataItem(byte_data, 0) data = [on_cmd] send_data(data, protocol.read_queue) await asyncio.sleep(0.05) assert last_topic == expected_topic
async def async_validate_values(self, topic=pub.AUTO_TOPIC, **kwargs): """Validate what should be returned from the handler.""" if not topic.name.startswith("handler"): return self._call_count += 1 for test in self._assert_tests: if kwargs.get(test) is None: continue try: if test == "address" or test == "target": self._assert_tests[test] = Address(self._assert_tests[test]) elif str(self._assert_tests[test]).startswith("0x"): self._assert_tests[test] = int.from_bytes( unhexlify(self._assert_tests[test]), "big" ) if type(self._assert_tests[test]) == "float": self._assert_tests[test] = round(self._assert_tests[test], 1) if test == "data": for k, v in self._assert_tests[test].items(): assert kwargs[test][k] == v else: assert kwargs.get(test) == self._assert_tests[test] except (AssertionError, KeyError): self._assert_result = False raise AssertionError( "Failed test '{}' with argument '{}' value {} vs expected value {}".format( self._current_test, test, kwargs.get(test), self._assert_tests[test], ) )
def setUp(self): """Test set up.""" self.hex = "0262010203140506a1a2a3a4a5a6a7a8a9aaabacadae" self.message_id = MessageId.SEND_EXTENDED self.address = Address("010203") self.flags = MessageFlags(0x14) self.cmd1 = int(0x05) self.cmd2 = int(0x06) self.user_data = UserData(unhexlify(self.hex)[8:]) kwargs = { "address": self.address, "flags": self.flags, "cmd1": self.cmd1, "cmd2": self.cmd2, "user_data": self.user_data, } super(TestSendExtended, self).base_setup(MessageId.SEND_EXTENDED, unhexlify(self.hex), **kwargs) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
async def async_remove_device_override(address): """Remove an Insten device and associated entities.""" address = Address(address) await async_remove_device(address) devices.set_id(address, None, None, None) await devices.async_identify_device(address) await async_srv_save_devices()
async def test_send_on_all_link_broadcast_topic(self): """Test sending the broadcast ON command.""" from pyinsteon.handlers.to_device.on_level_all_link_broadcast import ( OnLevelAllLinkBroadcastCommand, ) topic_lock = asyncio.Lock() async with async_protocol_manager(): last_topic = None def topic_received(cmd1, cmd2, user_data, topic=pub.AUTO_TOPIC): """Receive the OFF topic for a device.""" nonlocal last_topic last_topic = topic.name if topic_lock.locked(): topic_lock.release() group = 3 target = Address(bytearray([0x00, 0x00, group])) ack_topic = "ack.{}.on.all_link_broadcast".format(target.id) pub.subscribe(topic_received, ack_topic) cmd = OnLevelAllLinkBroadcastCommand(group=group) await topic_lock.acquire() await cmd.async_send() # Mock transport auto sends ACK/NAK try: await asyncio.wait_for(topic_lock.acquire(), 2) assert last_topic == ack_topic except asyncio.TimeoutError: assert ack_topic is None if topic_lock.locked(): topic_lock.release()
def test_set_device_id(self): """Test setting the device ID.""" address = Address("030303") self._id_mgr.set_device_id(address, self._cat, self._subcat, self._firmware) assert self._id_mgr[address].cat == self._cat assert self._id_mgr[address].subcat == self._subcat assert self._id_mgr[address].firmware == self._firmware
def setUp(self): """Test set up.""" self.hex = "026F400405060708090a0b" self.action = ManageAllLinkRecordAction(0x40) self.flags = AllLinkRecordFlags(0x04) self.group = int(0x05) self.target = Address("060708") self.data1 = int(0x09) self.data2 = int(0x0A) self.data3 = int(0x0B) kwargs = { "action": self.action, "flags": self.flags, "group": self.group, "target": self.target, "data1": self.data1, "data2": self.data2, "data3": self.data3, } super(TestManageAllLinkRecord, self).base_setup(MessageId.MANAGE_ALL_LINK_RECORD, unhexlify(self.hex), **kwargs) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
def add_device_override(config_data, new_override): """Add a new device override.""" try: address = str(Address(new_override[CONF_ADDRESS])) cat = normalize_byte_entry_to_int(new_override[CONF_CAT]) subcat = normalize_byte_entry_to_int(new_override[CONF_SUBCAT]) except ValueError as err: raise ValueError("Incorrect values") from err overrides = config_data.get(CONF_OVERRIDE, []) curr_override = {} # If this address has an override defined, remove it for override in overrides: if override[CONF_ADDRESS] == address: curr_override = override break if curr_override: overrides.remove(curr_override) curr_override[CONF_ADDRESS] = address curr_override[CONF_CAT] = cat curr_override[CONF_SUBCAT] = subcat overrides.append(curr_override) config_data[CONF_OVERRIDE] = overrides return config_data
def convert_yaml_to_config_flow(yaml_config): """Convert the YAML based configuration to a config flow configuration.""" config = {} if yaml_config.get(CONF_HOST): hub_version = yaml_config.get(CONF_HUB_VERSION, 2) default_port = PORT_HUB_V2 if hub_version == 2 else PORT_HUB_V1 config[CONF_HOST] = yaml_config.get(CONF_HOST) config[CONF_PORT] = yaml_config.get(CONF_PORT, default_port) config[CONF_HUB_VERSION] = hub_version if hub_version == 2: config[CONF_USERNAME] = yaml_config[CONF_USERNAME] config[CONF_PASSWORD] = yaml_config[CONF_PASSWORD] else: config[CONF_DEVICE] = yaml_config[CONF_PORT] options = {} for old_override in yaml_config.get(CONF_OVERRIDE, []): override = {} override[CONF_ADDRESS] = str(Address(old_override[CONF_ADDRESS])) override[CONF_CAT] = normalize_byte_entry_to_int( old_override[CONF_CAT]) override[CONF_SUBCAT] = normalize_byte_entry_to_int( old_override[CONF_SUBCAT]) options = add_device_override(options, override) for x10_device in yaml_config.get(CONF_X10, []): options = add_x10_device(options, x10_device) return config, options
def add_device_override(config_data, new_override): """Add a new device override.""" try: address = str(Address(new_override[CONF_ADDRESS])) cat = normalize_byte_entry_to_int(new_override[CONF_CAT]) subcat = normalize_byte_entry_to_int(new_override[CONF_SUBCAT]) except ValueError as err: raise ValueError("Incorrect values") from err overrides = [] for override in config_data.get(CONF_OVERRIDE, []): if override[CONF_ADDRESS] != address: overrides.append(override) curr_override = {} curr_override[CONF_ADDRESS] = address curr_override[CONF_CAT] = cat curr_override[CONF_SUBCAT] = subcat overrides.append(curr_override) new_config = {} if config_data.get(CONF_X10): new_config[CONF_X10] = config_data[CONF_X10] new_config[CONF_OVERRIDE] = overrides return new_config
async def test_import_options(opp: OpenPeerPower): """Test setting up the entry from YAML including options.""" config = {} config[DOMAIN] = MOCK_IMPORT_FULL_CONFIG_PLM with patch.object( insteon, "async_connect", new=mock_successful_connection ), patch.object(insteon, "close_insteon_connection"), patch.object( insteon, "devices", new=MockDevices() ), patch( PATCH_CONNECTION, new=mock_successful_connection ): assert await async_setup_component( opp, insteon.DOMAIN, config, ) await opp.async_block_till_done() await asyncio.sleep(0.01) # Need to yield to async processes # pylint: disable=no-member assert insteon.devices.add_x10_device.call_count == 2 assert insteon.devices.set_id.call_count == 1 options = opp.config_entries.async_entries(DOMAIN)[0].options assert len(options[CONF_OVERRIDE]) == 1 assert options[CONF_OVERRIDE][0][CONF_ADDRESS] == str(Address(MOCK_ADDRESS)) assert options[CONF_OVERRIDE][0][CONF_CAT] == MOCK_CAT assert options[CONF_OVERRIDE][0][CONF_SUBCAT] == MOCK_SUBCAT assert len(options[CONF_X10]) == 2 assert options[CONF_X10][0] == MOCK_IMPORT_FULL_CONFIG_PLM[CONF_X10][0] assert options[CONF_X10][1] == MOCK_IMPORT_FULL_CONFIG_PLM[CONF_X10][1]
def setUp(self): """Test set up.""" self.hex_data = "0250010203040506070809" self.bytes_data = bytearray(unhexlify(self.hex_data)) self.message_id = 0x50 self.address = Address("010203") self.target = Address("040506") self.flags = MessageFlags(0x07) self.cmd1 = int(0x08) self.cmd2 = int(0x09) self.msg, self.msg_bytes = hex_to_inbound_message(self.hex_data) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
def random_address(): """Generate a random address.""" address = "" for _ in range(0, 3): rand_int = randint(1, 255) if address: address = f"{address}." address = f"{address}{rand_int:02x}" return Address(address)
def _compare_records(aldb_rec, dict_rec): """Compare a record in the ALDB to the dictionary record.""" assert aldb_rec.is_in_use == dict_rec["in_use"] assert aldb_rec.is_controller == (dict_rec["is_controller"]) assert not aldb_rec.is_high_water_mark assert aldb_rec.group == dict_rec["group"] assert aldb_rec.target == Address(dict_rec["target"]) assert aldb_rec.data1 == dict_rec["data1"] assert aldb_rec.data2 == dict_rec["data2"] assert aldb_rec.data3 == dict_rec["data3"]
def setUp(self): """Set up the test.""" self.hex_data = "0251112233445566778899a1a2a3a4a5a6a7a8a9aaabacadae" self.message_id = 0x51 self.bytes_data = bytearray(unhexlify(self.hex_data)) self.address = Address("112233") self.target = Address("445566") self.flags = MessageFlags(0x77) self.cmd1 = int(0x88) self.cmd2 = int(0x99) self.user_data = UserData(unhexlify("a1a2a3a4a5a6a7a8a9aaabacadae")) self.msg, self.msg_bytes = hex_to_inbound_message(self.hex_data) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
def setUp(self): """Set up the test.""" self._address = Address("010203") self._properties = {} set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=False, )
async def test_notify_on_aldb_record_added(hass, hass_ws_client, aldb_data): """Test getting an Insteon device's All-Link Database.""" ws_client, devices = await _setup(hass, hass_ws_client, aldb_data) with patch.object(insteon.api.aldb, "devices", devices): await ws_client.send_json({ ID: 2, TYPE: "insteon/aldb/notify", DEVICE_ADDRESS: "33.33.33", }) msg = await ws_client.receive_json() assert msg["success"] pub.sendMessage( f"{DEVICE_LINK_CONTROLLER_CREATED}.333333", controller=Address("11.11.11"), responder=Address("33.33.33"), group=100, ) msg = await ws_client.receive_json() assert msg["event"]["type"] == "record_loaded"
def make_command_response_messages( address, topic, cmd1, cmd2, target="000000", user_data=None ): """Return a colleciton of ACK and Direct ACK responses to commands.""" address = Address(address) ack = "ack.{}.{}".format(address.id, topic) direct_ack = "{}.{}.direct_ack".format(address.id, topic) return [ TopicItem(ack, cmd_kwargs(cmd1, cmd2, user_data), 0.25), TopicItem(direct_ack, cmd_kwargs(cmd1, cmd2, user_data, target), 0.25), ]
async def async_setup(self): """Set up the test.""" self.state_value = None self.address = Address("1a2b3c") self.device = DimmableLightingControl(self.address, 0x01, 0x02, 0x03, "Test", "Modem 1") self.device.groups[1].subscribe(self.state_updated) set_log_levels( logger="info", logger_pyinsteon="info", logger_messages="info", logger_topics=True, )
async def async_load(self, *args, **kwargs): """Load the mock devices.""" if self._connected: addr0 = Address("AA.AA.AA") addr1 = Address("11.11.11") addr2 = Address("22.22.22") addr3 = Address("33.33.33") self._devices[addr0] = Hub(addr0) self._devices[addr1] = MockSwitchLinc(addr1, 0x02, 0x00) self._devices[addr2] = GeneralController_MiniRemote_4( addr2, 0x00, 0x00) self._devices[addr3] = SwitchedLightingControl_SwitchLinc( addr3, 0x02, 0x00) for device in [ self._devices[addr] for addr in [addr1, addr2, addr3] ]: device.async_read_config = AsyncMock() for device in [self._devices[addr] for addr in [addr2, addr3]]: device.async_status = AsyncMock() self._devices[addr1].async_status = AsyncMock( side_effect=AttributeError) self.modem = self._devices[addr0]
def setUp(self): """Set up the TestCancelAllLinking tests.""" self.hex = "02620102030011ff" self.address = Address("010203") self.cmd1 = 0x11 self.cmd2 = 0xFF kwargs = { "address": self.address, "cmd1": self.cmd1, "cmd2": self.cmd2 } super(TestSendStandard, self).base_setup(MessageId.SEND_STANDARD, unhexlify(self.hex), **kwargs)
def fill_rec(flags, group, target, data1, data2, data3): """Fill an All-Link Record.""" from pyinsteon.data_types.all_link_record_flags import AllLinkRecordFlags kwargs = { "flags": AllLinkRecordFlags(flags), "group": group, "target": Address(target), "data1": data1, "data2": data2, "data3": data3, } return kwargs
async def test_id_awake_device(self): """Test an awake device is recognized.""" self._id_mgr = DeviceIdManager() address = Address("010101") off, ack, dir_ack, response = self._set_topics(address) topic_item_1 = TopicItem( off, cmd_kwargs(0x10, 0x00, None, Address("000001")), 1) topic_item_2 = TopicItem(ack, cmd_kwargs(0x10, 0x00, None, None), 0.5) topic_item_3 = TopicItem( dir_ack, cmd_kwargs(0x10, 0x00, None, self._modem_address, None, 3), 0.5) topic_item_4 = TopicItem( response, cmd_kwargs(0x10, 0x12, None, self._target, None, 3), 0.5) topic_data = [topic_item_1, topic_item_2, topic_item_3, topic_item_4] self._id_mgr.start() self._id_mgr.append(address) send_topics(topic_data) await asyncio.sleep(3.5) device_id = self._id_mgr[address] assert device_id.cat == self._cat self._id_mgr.close() await asyncio.sleep(0.1)
def fill_properties(self, address, props_dict): """Fill the operating flags and extended properties of a device.""" device = self._devices[Address(address)] operating_flags = props_dict.get("operating_flags", {}) properties = props_dict.get("properties", {}) for flag in operating_flags: value = operating_flags[flag] if device.operating_flags.get(flag): device.operating_flags[flag].load(value) for flag in properties: value = properties[flag] if device.properties.get(flag): device.properties[flag].load(value)