diff --git a/homeassistant/components/brother/__init__.py b/homeassistant/components/brother/__init__.py index 8c5cdb2d7ed..d7cf906a87c 100644 --- a/homeassistant/components/brother/__init__.py +++ b/homeassistant/components/brother/__init__.py @@ -6,12 +6,13 @@ import logging from brother import Brother, SnmpError, UnsupportedModel from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_TYPE, EVENT_HOMEASSISTANT_STOP +from homeassistant.const import CONF_HOST, CONF_TYPE from homeassistant.core import Config, HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import DOMAIN +from .const import DATA_CONFIG_ENTRY, DOMAIN, SNMP +from .utils import get_snmp_engine PLATFORMS = ["sensor"] @@ -30,15 +31,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): host = entry.data[CONF_HOST] kind = entry.data[CONF_TYPE] - coordinator = BrotherDataUpdateCoordinator(hass, host=host, kind=kind) + snmp_engine = get_snmp_engine(hass) + + coordinator = BrotherDataUpdateCoordinator( + hass, host=host, kind=kind, snmp_engine=snmp_engine + ) await coordinator.async_refresh() if not coordinator.last_update_success: - coordinator.shutdown() raise ConfigEntryNotReady hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = coordinator + hass.data[DOMAIN].setdefault(DATA_CONFIG_ENTRY, {}) + hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id] = coordinator + hass.data[DOMAIN][SNMP] = snmp_engine for component in PLATFORMS: hass.async_create_task( @@ -59,7 +65,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): ) ) if unload_ok: - hass.data[DOMAIN].pop(entry.entry_id).shutdown() + hass.data[DOMAIN][DATA_CONFIG_ENTRY].pop(entry.entry_id) + if not hass.data[DOMAIN][DATA_CONFIG_ENTRY]: + hass.data[DOMAIN].pop(SNMP) + hass.data[DOMAIN].pop(DATA_CONFIG_ENTRY) return unload_ok @@ -67,12 +76,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): class BrotherDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching Brother data from the printer.""" - def __init__(self, hass, host, kind): + def __init__(self, hass, host, kind, snmp_engine): """Initialize.""" - self.brother = Brother(host, kind=kind) - self._unsub_stop = hass.bus.async_listen( - EVENT_HOMEASSISTANT_STOP, self._handle_ha_stop - ) + self.brother = Brother(host, kind=kind, snmp_engine=snmp_engine) super().__init__( hass, @@ -83,22 +89,8 @@ class BrotherDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): """Update data via library.""" - # Race condition on shutdown. Stop all the fetches. - if self._unsub_stop is None: - return None - try: await self.brother.async_update() except (ConnectionError, SnmpError, UnsupportedModel) as error: raise UpdateFailed(error) from error return self.brother.data - - def shutdown(self): - """Shutdown the Brother coordinator.""" - self._unsub_stop() - self._unsub_stop = None - self.brother.shutdown() - - def _handle_ha_stop(self, _): - """Handle Home Assistant stopping.""" - self.shutdown() diff --git a/homeassistant/components/brother/config_flow.py b/homeassistant/components/brother/config_flow.py index aa9d7ce53a3..6a9d2ca6746 100644 --- a/homeassistant/components/brother/config_flow.py +++ b/homeassistant/components/brother/config_flow.py @@ -9,6 +9,7 @@ from homeassistant import config_entries, exceptions from homeassistant.const import CONF_HOST, CONF_TYPE from .const import DOMAIN, PRINTER_TYPES # pylint:disable=unused-import +from .utils import get_snmp_engine DATA_SCHEMA = vol.Schema( { @@ -48,9 +49,10 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): if not host_valid(user_input[CONF_HOST]): raise InvalidHost() - brother = Brother(user_input[CONF_HOST]) + snmp_engine = get_snmp_engine(self.hass) + + brother = Brother(user_input[CONF_HOST], snmp_engine=snmp_engine) await brother.async_update() - brother.shutdown() await self.async_set_unique_id(brother.serial.lower()) self._abort_if_unique_id_configured() @@ -83,7 +85,9 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # Hostname is format: brother.local. self.host = discovery_info["hostname"].rstrip(".") - self.brother = Brother(self.host) + snmp_engine = get_snmp_engine(self.hass) + + self.brother = Brother(self.host, snmp_engine=snmp_engine) try: await self.brother.async_update() except (ConnectionError, SnmpError, UnsupportedModel): diff --git a/homeassistant/components/brother/const.py b/homeassistant/components/brother/const.py index 5aecde16327..5ae459c79aa 100644 --- a/homeassistant/components/brother/const.py +++ b/homeassistant/components/brother/const.py @@ -41,12 +41,16 @@ ATTR_YELLOW_DRUM_REMAINING_PAGES = "yellow_drum_remaining_pages" ATTR_YELLOW_INK_REMAINING = "yellow_ink_remaining" ATTR_YELLOW_TONER_REMAINING = "yellow_toner_remaining" +DATA_CONFIG_ENTRY = "config_entry" + DOMAIN = "brother" UNIT_PAGES = "p" PRINTER_TYPES = ["laser", "ink"] +SNMP = "snmp" + SENSOR_TYPES = { ATTR_STATUS: { ATTR_ICON: "mdi:printer", diff --git a/homeassistant/components/brother/manifest.json b/homeassistant/components/brother/manifest.json index 52286cd2c68..15828e5f05a 100644 --- a/homeassistant/components/brother/manifest.json +++ b/homeassistant/components/brother/manifest.json @@ -3,7 +3,7 @@ "name": "Brother Printer", "documentation": "https://www.home-assistant.io/integrations/brother", "codeowners": ["@bieniu"], - "requirements": ["brother==0.2.0"], + "requirements": ["brother==0.2.1"], "zeroconf": [{ "type": "_printer._tcp.local.", "name": "brother*" }], "config_flow": true, "quality_scale": "platinum" diff --git a/homeassistant/components/brother/sensor.py b/homeassistant/components/brother/sensor.py index 40e2deae67d..a379d9b4154 100644 --- a/homeassistant/components/brother/sensor.py +++ b/homeassistant/components/brother/sensor.py @@ -24,6 +24,7 @@ from .const import ( ATTR_YELLOW_DRUM_COUNTER, ATTR_YELLOW_DRUM_REMAINING_LIFE, ATTR_YELLOW_DRUM_REMAINING_PAGES, + DATA_CONFIG_ENTRY, DOMAIN, SENSOR_TYPES, ) @@ -37,7 +38,7 @@ ATTR_SERIAL = "serial" async def async_setup_entry(hass, config_entry, async_add_entities): """Add Brother entities from a config_entry.""" - coordinator = hass.data[DOMAIN][config_entry.entry_id] + coordinator = hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id] sensors = [] diff --git a/homeassistant/components/brother/utils.py b/homeassistant/components/brother/utils.py new file mode 100644 index 00000000000..3a53f4c04a2 --- /dev/null +++ b/homeassistant/components/brother/utils.py @@ -0,0 +1,30 @@ +"""Brother helpers functions.""" +import logging + +import pysnmp.hlapi.asyncio as hlapi +from pysnmp.hlapi.asyncio.cmdgen import lcd + +from homeassistant.const import EVENT_HOMEASSISTANT_STOP +from homeassistant.core import callback +from homeassistant.helpers import singleton + +from .const import DOMAIN, SNMP + +_LOGGER = logging.getLogger(__name__) + + +@singleton.singleton("snmp_engine") +def get_snmp_engine(hass): + """Get SNMP engine.""" + _LOGGER.debug("Creating SNMP engine") + snmp_engine = hlapi.SnmpEngine() + + @callback + def shutdown_listener(ev): + if hass.data.get(DOMAIN): + _LOGGER.debug("Unconfiguring SNMP engine") + lcd.unconfigure(hass.data[DOMAIN][SNMP], None) + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, shutdown_listener) + + return snmp_engine diff --git a/requirements_all.txt b/requirements_all.txt index f6716f52511..763d35a8cae 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -380,7 +380,7 @@ bravia-tv==1.0.8 broadlink==0.16.0 # homeassistant.components.brother -brother==0.2.0 +brother==0.2.1 # homeassistant.components.brottsplatskartan brottsplatskartan==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 748fd695137..3d57d3d2302 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -210,7 +210,7 @@ bravia-tv==1.0.8 broadlink==0.16.0 # homeassistant.components.brother -brother==0.2.0 +brother==0.2.1 # homeassistant.components.bsblan bsblan==0.4.0