def __init__(self, hass, name, host, config_entry): self._scan_interval = SCAN_INTERVAL self._hass = hass self._name = name self._hp_data = HPDeviceData(hass, host, name) self._binary_sensors = {} self._sensors = {} self._config_entry = config_entry self._components_hash = None self._remove_async_track_time = None
def __init__(self, hass, name, host, config_entry): self._scan_interval = SCAN_INTERVAL self._hass = hass self._name = name self._hp_data = HPDeviceData(hass, host, name) self._entities = {} self._domain_loaded = {} self._config_entry = config_entry self._components_hash = None self._remove_async_track_time = None self._unload_domain = [] self._load_domain = [] self._should_reload = False self._last_update = None self._is_first_time_online = True
async def async_parse(self, hass): hostname = "192.168.1.30" device_data = HPDeviceData(hass, hostname, "HP7740", self.data_provider) self._data = await device_data.get_data() json_data = json.dumps(self._data) _LOGGER.debug(json_data)
class HPPrinterHomeAssistant: def __init__(self, hass, name, host, config_entry): self._scan_interval = SCAN_INTERVAL self._hass = hass self._name = name self._hp_data = HPDeviceData(hass, host, name) self._binary_sensors = {} self._sensors = {} self._config_entry = config_entry self._components_hash = None self._remove_async_track_time = None @property def name(self): return self._name @property def sensors(self): return self._sensors @property def binary_sensors(self): return self._binary_sensors def get_sensor(self, name): return self._sensors.get(name) def get_binary_sensor(self, name): return self._binary_sensors.get(name) def initialize(self): if self._hp_data is not None: async_call_later(self._hass, 5, self.async_finalize) async def async_finalize(self, event_time): _LOGGER.debug(f"async_finalize called at {event_time}") self._hass.services.async_register(DOMAIN, 'save_debug_data', self.save_debug_data) await self.async_update(None) self._remove_async_track_time = async_track_time_interval( self._hass, self.async_update, SCAN_INTERVAL) async def async_remove(self): _LOGGER.debug(f"async_remove called") self._hass.services.async_remove(DOMAIN, 'save_debug_data') if self._remove_async_track_time is not None: self._remove_async_track_time() def save_debug_data(self, service_data): """Call BlueIris to refresh information.""" _LOGGER.debug(f"Saving debug data {DOMAIN} ({service_data})") self._hp_data.get_data(self.store_data) def store_data(self, file, content): try: path = self._hass.config.path(file) with open(path, 'w+') as out: out.write(content) except Exception as ex: exc_type, exc_obj, tb = sys.exc_info() line_number = tb.tb_lineno _LOGGER.error( f'Failed to log {file} data, Error: {ex}, Line: {line_number}') async def async_update(self, event_time): _LOGGER.info(f"Updating") data = await self._hp_data.get_data() cartridges_data = data.get(HP_DEVICE_CARTRIDGES) is_online = self.create_status_sensor(data) if is_online: self.create_printer_sensor(data) self.create_scanner_sensor(data) if cartridges_data is not None: for key in cartridges_data: cartridge = cartridges_data.get(key) if cartridge is not None: self.create_cartridge_sensor(data, cartridge, key) previous_hash = self._components_hash entities = [] for binary_sensor_name in self._binary_sensors: entities.append(binary_sensor_name) for sensor_name in self._sensors: entities.append(sensor_name) self._components_hash = ', '.join(entities) hash_changed = previous_hash is None or previous_hash != self._components_hash _LOGGER.info( f"Hash: {self._components_hash}, Previous Hash: {previous_hash}, changed: {hash_changed}" ) if hash_changed: entry = self._config_entry if previous_hash is not None: unload = self._hass.config_entries.async_forward_entry_unload self._hass.async_create_task( unload(entry, DOMAIN_BINARY_SENSOR)) self._hass.async_create_task(unload(entry, DOMAIN_SENSOR)) if self._components_hash is not None: setup = self._hass.config_entries.async_forward_entry_setup self._hass.async_create_task(setup(entry, DOMAIN_BINARY_SENSOR)) self._hass.async_create_task(setup(entry, DOMAIN_SENSOR)) else: async_dispatcher_send(self._hass, SIGNAL_UPDATE_HP_PRINTER) def create_status_sensor(self, data): is_online = data.get(HP_DEVICE_IS_ONLINE, False) model = data.get(ENTITY_MODEL) name = data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_STATUS}" icon = "mdi:printer-off" if is_online: icon = "mdi:printer" attributes = { "friendly_name": sensor_name, "device_class": "connectivity" } entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: is_online, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: icon, ENTITY_MODEL: model } self._binary_sensors[sensor_name] = entity return is_online def create_printer_sensor(self, data): printer_data = data.get(HP_DEVICE_PRINTER) model = data.get(ENTITY_MODEL) if printer_data is not None: name = data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_PRINTER}" state = printer_data.get(HP_DEVICE_PRINTER_STATE) attributes = { "unit_of_measurement": "Pages", "friendly_name": sensor_name } for key in printer_data: if key != HP_DEVICE_PRINTER_STATE: attributes[key] = printer_data[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: PAGES_ICON, ENTITY_MODEL: model } self._sensors[sensor_name] = entity def create_scanner_sensor(self, data): scanner_data = data.get(HP_DEVICE_SCANNER) model = data.get(ENTITY_MODEL) if scanner_data is not None: name = data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_SCANNER}" state = scanner_data.get(HP_DEVICE_SCANNER_STATE) attributes = { "unit_of_measurement": "Pages", "friendly_name": sensor_name } for key in scanner_data: if key != HP_DEVICE_SCANNER_STATE: attributes[key] = scanner_data[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: SCANNER_ICON, ENTITY_MODEL: model } self._sensors[sensor_name] = entity def create_cartridge_sensor(self, data, cartridge, key): name = data.get("Name", DEFAULT_NAME) model = data.get(ENTITY_MODEL) sensor_name = f"{name} {key}" state = cartridge.get(HP_DEVICE_CARTRIDGE_STATE, 0) attributes = {"unit_of_measurement": "%", "friendly_name": sensor_name} for key in cartridge: if key != HP_DEVICE_CARTRIDGE_STATE: attributes[key] = cartridge[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: INK_ICON, ENTITY_MODEL: model } self._sensors[sensor_name] = entity
class HPPrinterHomeAssistant: def __init__(self, hass, name, host, config_entry): self._scan_interval = SCAN_INTERVAL self._hass = hass self._name = name self._hp_data = HPDeviceData(hass, host, name) self._entities = {} self._domain_loaded = {} self._config_entry = config_entry self._components_hash = None self._remove_async_track_time = None self._unload_domain = [] self._load_domain = [] self._should_reload = False self._last_update = None self._is_first_time_online = True self._data = {} self._device_info = None @property def name(self): return self._name @property def device_info(self): return self._device_info def initialize(self): if self._hp_data is not None: async_call_later(self._hass, 5, self.async_finalize) async def async_finalize(self, event_time): _LOGGER.debug(f"async_finalize called at {event_time}") self._hass.services.async_register(DOMAIN, 'save_debug_data', self.save_debug_data) self._remove_async_track_time = async_track_time_interval( self._hass, self.async_update, SCAN_INTERVAL) self._hass.async_create_task(self.async_init_entry()) def generate_device_info(self): device_model = self._data.get(ENTITY_MODEL, self.name) device_model_family = self._data.get(ENTITY_MODEL_FAMILY, self.name) device_id = f"{DEFAULT_NAME}-{self._name}-{device_model_family}" self._device_info = { "identifiers": {(DOMAIN, device_id)}, "name": device_model_family, "manufacturer": MANUFACTURER, "model": device_model } async def async_remove(self): _LOGGER.debug(f"async_remove called") self._hass.services.async_remove(DOMAIN, 'save_debug_data') if self._remove_async_track_time is not None: self._remove_async_track_time() unload = self._hass.config_entries.async_forward_entry_unload self._hass.async_create_task( unload(self._config_entry, DOMAIN_BINARY_SENSOR)) self._hass.async_create_task(unload(self._config_entry, DOMAIN_SENSOR)) device_identifiers = self._device_info.get("identifiers") device_connections = self._device_info.get("connections", {}) device_reg = await dr.async_get_registry(self._hass) device = device_reg.async_get_device(device_identifiers, device_connections) if device is not None: device_reg.async_remove_device(device.id) async def async_update_entry(self, entry, clear_all): _LOGGER.info(f"async_update_entry: {entry}") self._config_entry = entry self._last_update = datetime.now() self._load_domain = [] self._unload_domain = [] if clear_all: device_reg = await dr.async_get_registry(self._hass) device_reg.async_clear_config_entry(self._config_entry.entry_id) for domain in [DOMAIN_SENSOR, DOMAIN_BINARY_SENSOR]: has_entities = self._domain_loaded.get(domain, False) if domain not in self._load_domain: self._load_domain.append(domain) if has_entities and domain not in self._unload_domain: self._unload_domain.append(domain) if clear_all: await self.async_update(datetime.now()) async def async_init_entry(self): _LOGGER.debug(f"async_init_entry called") await self.async_update_entry(self._config_entry, True) def set_domain_entities_state(self, domain, has_entities): self._domain_loaded[domain] = has_entities def get_entities(self, domain): return self._entities.get(domain, {}) def get_entity(self, domain, name): entities = self.get_entities(domain) entity = {} if entities is not None: entity = entities.get(name, {}) return entity def set_entity(self, domain, name, data): entities = self._entities.get(domain) if entities is None: self._entities[domain] = {} entities = self._entities.get(domain) entities[name] = data def save_debug_data(self, service_data): """Call BlueIris to refresh information.""" _LOGGER.debug(f"Saving debug data {DOMAIN} ({service_data})") self._hass.async_create_task(self._hp_data.get_data(self.store_data)) def store_data(self, file, content): try: path = self._hass.config.path(file) with open(path, 'w+') as out: out.write(content) except Exception as ex: exc_type, exc_obj, tb = sys.exc_info() line_number = tb.tb_lineno _LOGGER.error( f'Failed to log {file} data, Error: {ex}, Line: {line_number}') async def async_update(self, event_time): _LOGGER.info(f"Updating {event_time}") self._data = await self._hp_data.get_data() cartridges_data = self._data.get(HP_DEVICE_CARTRIDGES) is_online = self.create_status_binary_sensor() self.create_status_sensor() if is_online: self.create_printer_sensor() self.create_scanner_sensor() if cartridges_data is not None: for key in cartridges_data: cartridge = cartridges_data.get(key) if cartridge is not None: self.create_cartridge_sensor(cartridge, key) if self._is_first_time_online: self._is_first_time_online = False await self.async_update_entry(self._config_entry, False) await self.discover_all() async def discover_all(self): self.generate_device_info() for domain in [DOMAIN_SENSOR, DOMAIN_BINARY_SENSOR]: await self.discover(domain) async def discover(self, domain): signal = SIGNALS.get(domain) if signal is None: _LOGGER.error(f"Cannot discover domain {domain}") return unload = self._hass.config_entries.async_forward_entry_unload setup = self._hass.config_entries.async_forward_entry_setup entry = self._config_entry can_unload = domain in self._unload_domain can_load = domain in self._load_domain can_notify = not can_load and not can_unload if can_unload: _LOGGER.info(f"Unloading domain {domain}") self._hass.async_create_task(unload(entry, domain)) self._unload_domain.remove(domain) if can_load: _LOGGER.info(f"Loading domain {domain}") self._hass.async_create_task(setup(entry, domain)) self._load_domain.remove(domain) if can_notify: async_dispatcher_send(self._hass, signal) def create_status_sensor(self): is_online = self._data.get(HP_DEVICE_IS_ONLINE, False) status = self._data.get(PRINTER_CURRENT_STATUS, "Off") name = self._data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_STATUS}" icon = "mdi:printer" if is_online else "mdi:printer-off" attributes = { "friendly_name": sensor_name, "device_class": "connectivity" } entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: status, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: icon } self.set_entity(DOMAIN_SENSOR, sensor_name, entity) def create_status_binary_sensor(self): is_online = self._data.get(HP_DEVICE_IS_ONLINE, False) name = self._data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_STATUS}" icon = "mdi:printer-off" if is_online: icon = "mdi:printer" attributes = { "friendly_name": sensor_name, "device_class": "connectivity" } entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: is_online, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: icon } self.set_entity(DOMAIN_BINARY_SENSOR, sensor_name, entity) return is_online def create_printer_sensor(self): printer_data = self._data.get(HP_DEVICE_PRINTER) if printer_data is not None: name = self._data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_PRINTER}" state = printer_data.get(HP_DEVICE_PRINTER_STATE) attributes = { "unit_of_measurement": "Pages", "friendly_name": sensor_name } for key in printer_data: if key != HP_DEVICE_PRINTER_STATE: attributes[key] = printer_data[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: PAGES_ICON } self.set_entity(DOMAIN_SENSOR, sensor_name, entity) def create_scanner_sensor(self): scanner_data = self._data.get(HP_DEVICE_SCANNER) if scanner_data is not None: name = self._data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {HP_DEVICE_SCANNER}" state = scanner_data.get(HP_DEVICE_SCANNER_STATE) attributes = { "unit_of_measurement": "Pages", "friendly_name": sensor_name } for key in scanner_data: if key != HP_DEVICE_SCANNER_STATE: attributes[key] = scanner_data[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: SCANNER_ICON } self.set_entity(DOMAIN_SENSOR, sensor_name, entity) def create_cartridge_sensor(self, cartridge, key): name = self._data.get("Name", DEFAULT_NAME) sensor_name = f"{name} {key}" state = cartridge.get(HP_DEVICE_CARTRIDGE_STATE, 0) attributes = {"unit_of_measurement": "%", "friendly_name": sensor_name} for key in cartridge: if key != HP_DEVICE_CARTRIDGE_STATE: attributes[key] = cartridge[key] entity = { ENTITY_NAME: sensor_name, ENTITY_STATE: state, ENTITY_ATTRIBUTES: attributes, ENTITY_ICON: INK_ICON } self.set_entity(DOMAIN_SENSOR, sensor_name, entity)