Add Brother Printer integration (#30359)
* Init entities as unavailable when offline * Initial commit * Fix CODEOWNERS * CODEOWNERS * Run script.hassfest * Add initial test * Bump library * More tests * Tests * Add new sensors and fix KeyError * Fix unique_id and device_info * Fix check for configured device * More tests * Bump library version * Add uptime sensor * Use config entry unique ID * Run python3 -m script.gen_requirements_all * Fix pylint error * Remove pysnmp dependency * Raise ConfigEntryNotReady when device offline at HA start * Remove period from logging message * Generator simplification * Change raise_on_progress * Rename data to printer * Move update state to async_update * Remove unused _unit_of_measurement * Remove update of device_info * Suggested change for tests * Remove unnecessary argument * Suggested changepull/30524/head
parent
8257ea30c0
commit
21029b1d7b
|
@ -95,6 +95,9 @@ omit =
|
|||
homeassistant/components/broadlink/remote.py
|
||||
homeassistant/components/broadlink/sensor.py
|
||||
homeassistant/components/broadlink/switch.py
|
||||
homeassistant/components/brother/__init__.py
|
||||
homeassistant/components/brother/sensor.py
|
||||
homeassistant/components/brother/const.py
|
||||
homeassistant/components/brottsplatskartan/sensor.py
|
||||
homeassistant/components/browser/*
|
||||
homeassistant/components/brunt/cover.py
|
||||
|
|
|
@ -51,6 +51,7 @@ homeassistant/components/blink/* @fronzbot
|
|||
homeassistant/components/bmw_connected_drive/* @gerard33
|
||||
homeassistant/components/braviatv/* @robbiet480
|
||||
homeassistant/components/broadlink/* @danielhiversen @felipediel
|
||||
homeassistant/components/brother/* @bieniu
|
||||
homeassistant/components/brunt/* @eavanvalkenburg
|
||||
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
||||
homeassistant/components/buienradar/* @mjj4791 @ties
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
"""The Brother component."""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from brother import Brother, SnmpError, UnsupportedModel
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_TYPE
|
||||
from homeassistant.core import Config, HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
PLATFORMS = ["sensor"]
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = timedelta(seconds=30)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: Config):
|
||||
"""Set up the Brother component."""
|
||||
hass.data[DOMAIN] = {}
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
"""Set up Brother from a config entry."""
|
||||
host = entry.data[CONF_HOST]
|
||||
kind = entry.data[CONF_TYPE]
|
||||
|
||||
brother = BrotherPrinterData(host, kind)
|
||||
|
||||
await brother.async_update()
|
||||
|
||||
if not brother.available:
|
||||
raise ConfigEntryNotReady()
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = brother
|
||||
|
||||
for component in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
"""Unload a config entry."""
|
||||
unload_ok = all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(entry, component)
|
||||
for component in PLATFORMS
|
||||
]
|
||||
)
|
||||
)
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
class BrotherPrinterData:
|
||||
"""Define an object to hold sensor data."""
|
||||
|
||||
def __init__(self, host, kind):
|
||||
"""Initialize."""
|
||||
self._brother = Brother(host, kind=kind)
|
||||
self.host = host
|
||||
self.model = None
|
||||
self.serial = None
|
||||
self.firmware = None
|
||||
self.available = False
|
||||
self.data = {}
|
||||
self.unavailable_logged = False
|
||||
|
||||
@Throttle(DEFAULT_SCAN_INTERVAL)
|
||||
async def async_update(self):
|
||||
"""Update data via library."""
|
||||
try:
|
||||
await self._brother.async_update()
|
||||
except (ConnectionError, SnmpError, UnsupportedModel) as error:
|
||||
if not self.unavailable_logged:
|
||||
_LOGGER.error(
|
||||
"Could not fetch data from %s, error: %s", self.host, error
|
||||
)
|
||||
self.unavailable_logged = True
|
||||
self.available = self._brother.available
|
||||
return
|
||||
|
||||
self.model = self._brother.model
|
||||
self.serial = self._brother.serial
|
||||
self.firmware = self._brother.firmware
|
||||
self.available = self._brother.available
|
||||
self.data = self._brother.data
|
||||
if self.available and self.unavailable_logged:
|
||||
_LOGGER.info("Printer %s is available again", self.host)
|
||||
self.unavailable_logged = False
|
|
@ -0,0 +1,69 @@
|
|||
"""Adds config flow for Brother Printer."""
|
||||
import ipaddress
|
||||
import re
|
||||
|
||||
from brother import Brother, SnmpError, UnsupportedModel
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries, exceptions
|
||||
from homeassistant.const import CONF_HOST, CONF_TYPE
|
||||
|
||||
from .const import DOMAIN, PRINTER_TYPES # pylint:disable=unused-import
|
||||
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST, default=""): str,
|
||||
vol.Optional(CONF_TYPE, default="laser"): vol.In(PRINTER_TYPES),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def host_valid(host):
|
||||
"""Return True if hostname or IP address is valid."""
|
||||
try:
|
||||
if ipaddress.ip_address(host).version == (4 or 6):
|
||||
return True
|
||||
except ValueError:
|
||||
disallowed = re.compile(r"[^a-zA-Z\d\-]")
|
||||
return all(x and not disallowed.search(x) for x in host.split("."))
|
||||
|
||||
|
||||
class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Brother Printer."""
|
||||
|
||||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the initial step."""
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
try:
|
||||
if not host_valid(user_input[CONF_HOST]):
|
||||
raise InvalidHost()
|
||||
|
||||
brother = Brother(user_input[CONF_HOST])
|
||||
await brother.async_update()
|
||||
|
||||
await self.async_set_unique_id(brother.serial.lower())
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
title = f"{brother.model} {brother.serial}"
|
||||
return self.async_create_entry(title=title, data=user_input)
|
||||
except InvalidHost:
|
||||
errors[CONF_HOST] = "wrong_host"
|
||||
except ConnectionError:
|
||||
errors["base"] = "connection_error"
|
||||
except SnmpError:
|
||||
errors["base"] = "snmp_error"
|
||||
except UnsupportedModel:
|
||||
return self.async_abort(reason="unsupported_model")
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||
)
|
||||
|
||||
|
||||
class InvalidHost(exceptions.HomeAssistantError):
|
||||
"""Error to indicate that hostname/IP address is invalid."""
|
|
@ -0,0 +1,132 @@
|
|||
"""Constants for Brother integration."""
|
||||
ATTR_BELT_UNIT_REMAINING_LIFE = "belt_unit_remaining_life"
|
||||
ATTR_BLACK_INK_REMAINING = "black_ink_remaining"
|
||||
ATTR_BLACK_TONER_REMAINING = "black_toner_remaining"
|
||||
ATTR_BW_COUNTER = "b/w_counter"
|
||||
ATTR_COLOR_COUNTER = "color_counter"
|
||||
ATTR_CYAN_INK_REMAINING = "cyan_ink_remaining"
|
||||
ATTR_CYAN_TONER_REMAINING = "cyan_toner_remaining"
|
||||
ATTR_DRUM_COUNTER = "drum_counter"
|
||||
ATTR_DRUM_REMAINING_LIFE = "drum_remaining_life"
|
||||
ATTR_DRUM_REMAINING_PAGES = "drum_remaining_pages"
|
||||
ATTR_FUSER_REMAINING_LIFE = "fuser_remaining_life"
|
||||
ATTR_ICON = "icon"
|
||||
ATTR_LABEL = "label"
|
||||
ATTR_LASER_REMAINING_LIFE = "laser_remaining_life"
|
||||
ATTR_MAGENTA_INK_REMAINING = "magenta_ink_remaining"
|
||||
ATTR_MAGENTA_TONER_REMAINING = "magenta_toner_remaining"
|
||||
ATTR_MANUFACTURER = "Brother"
|
||||
ATTR_PAGE_COUNTER = "page_counter"
|
||||
ATTR_PF_KIT_1_REMAINING_LIFE = "pf_kit_1_remaining_life"
|
||||
ATTR_PF_KIT_MP_REMAINING_LIFE = "pf_kit_mp_remaining_life"
|
||||
ATTR_STATUS = "status"
|
||||
ATTR_UNIT = "unit"
|
||||
ATTR_UPTIME = "uptime"
|
||||
ATTR_YELLOW_INK_REMAINING = "yellow_ink_remaining"
|
||||
ATTR_YELLOW_TONER_REMAINING = "yellow_toner_remaining"
|
||||
|
||||
DOMAIN = "brother"
|
||||
|
||||
UNIT_PAGES = "p"
|
||||
UNIT_DAYS = "days"
|
||||
UNIT_PERCENT = "%"
|
||||
|
||||
PRINTER_TYPES = ["laser", "ink"]
|
||||
|
||||
SENSOR_TYPES = {
|
||||
ATTR_STATUS: {
|
||||
ATTR_ICON: "icon:mdi:printer",
|
||||
ATTR_LABEL: ATTR_STATUS.title(),
|
||||
ATTR_UNIT: None,
|
||||
},
|
||||
ATTR_PAGE_COUNTER: {
|
||||
ATTR_ICON: "mdi:file-document-outline",
|
||||
ATTR_LABEL: ATTR_PAGE_COUNTER.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PAGES,
|
||||
},
|
||||
ATTR_BW_COUNTER: {
|
||||
ATTR_ICON: "mdi:file-document-outline",
|
||||
ATTR_LABEL: ATTR_BW_COUNTER.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PAGES,
|
||||
},
|
||||
ATTR_COLOR_COUNTER: {
|
||||
ATTR_ICON: "mdi:file-document-outline",
|
||||
ATTR_LABEL: ATTR_COLOR_COUNTER.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PAGES,
|
||||
},
|
||||
ATTR_DRUM_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:chart-donut",
|
||||
ATTR_LABEL: ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_BELT_UNIT_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:current-ac",
|
||||
ATTR_LABEL: ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_FUSER_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:water-outline",
|
||||
ATTR_LABEL: ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_LASER_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:spotlight-beam",
|
||||
ATTR_LABEL: ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_PF_KIT_1_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:printer-3d",
|
||||
ATTR_LABEL: ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_PF_KIT_MP_REMAINING_LIFE: {
|
||||
ATTR_ICON: "mdi:printer-3d",
|
||||
ATTR_LABEL: ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_BLACK_TONER_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_CYAN_TONER_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_MAGENTA_TONER_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_YELLOW_TONER_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_BLACK_INK_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_BLACK_INK_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_CYAN_INK_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_CYAN_INK_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_MAGENTA_INK_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_YELLOW_INK_REMAINING: {
|
||||
ATTR_ICON: "mdi:printer-3d-nozzle",
|
||||
ATTR_LABEL: ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(),
|
||||
ATTR_UNIT: UNIT_PERCENT,
|
||||
},
|
||||
ATTR_UPTIME: {
|
||||
ATTR_ICON: "mdi:timer",
|
||||
ATTR_LABEL: ATTR_UPTIME.title(),
|
||||
ATTR_UNIT: UNIT_DAYS,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"domain": "brother",
|
||||
"name": "Brother Printer",
|
||||
"documentation": "https://www.home-assistant.io/integrations/brother",
|
||||
"dependencies": [],
|
||||
"codeowners": ["@bieniu"],
|
||||
"requirements": ["brother==0.1.4"],
|
||||
"config_flow": true
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
"""Support for the Brother service."""
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import (
|
||||
ATTR_DRUM_COUNTER,
|
||||
ATTR_DRUM_REMAINING_LIFE,
|
||||
ATTR_DRUM_REMAINING_PAGES,
|
||||
ATTR_ICON,
|
||||
ATTR_LABEL,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_UNIT,
|
||||
DOMAIN,
|
||||
SENSOR_TYPES,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Add Brother entities from a config_entry."""
|
||||
brother = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
sensors = []
|
||||
|
||||
name = brother.model
|
||||
device_info = {
|
||||
"identifiers": {(DOMAIN, brother.serial)},
|
||||
"name": brother.model,
|
||||
"manufacturer": ATTR_MANUFACTURER,
|
||||
"model": brother.model,
|
||||
"sw_version": brother.firmware,
|
||||
}
|
||||
|
||||
for sensor in SENSOR_TYPES:
|
||||
if sensor in brother.data:
|
||||
sensors.append(BrotherPrinterSensor(brother, name, sensor, device_info))
|
||||
async_add_entities(sensors, True)
|
||||
|
||||
|
||||
class BrotherPrinterSensor(Entity):
|
||||
"""Define an Brother Printer sensor."""
|
||||
|
||||
def __init__(self, printer, name, kind, device_info):
|
||||
"""Initialize."""
|
||||
self.printer = printer
|
||||
self._name = name
|
||||
self._device_info = device_info
|
||||
self._unique_id = f"{self.printer.serial.lower()}_{kind}"
|
||||
self.kind = kind
|
||||
self._state = None
|
||||
self._attrs = {}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return f"{self._name} {SENSOR_TYPES[self.kind][ATTR_LABEL]}"
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
if self.kind == ATTR_DRUM_REMAINING_LIFE:
|
||||
self._attrs["remaining_pages"] = self.printer.data.get(
|
||||
ATTR_DRUM_REMAINING_PAGES
|
||||
)
|
||||
self._attrs["counter"] = self.printer.data.get(ATTR_DRUM_COUNTER)
|
||||
return self._attrs
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon."""
|
||||
return SENSOR_TYPES[self.kind][ATTR_ICON]
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique_id for this entity."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit the value is expressed in."""
|
||||
return SENSOR_TYPES[self.kind][ATTR_UNIT]
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return True if entity is available."""
|
||||
return self.printer.available
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return self._device_info
|
||||
|
||||
async def async_update(self):
|
||||
"""Update the data from printer."""
|
||||
await self.printer.async_update()
|
||||
|
||||
self._state = self.printer.data.get(self.kind)
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"config": {
|
||||
"title": "Brother Printer",
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Brother Printer",
|
||||
"description": "Set up Brother printer integration. If you have problems with configuration go to: https://www.home-assistant.io/integrations/brother",
|
||||
"data": {
|
||||
"host": "Printer hostname or IP address",
|
||||
"type": "Type of the printer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"wrong_host": "Invalid hostname or IP address.",
|
||||
"connection_error": "Connection error.",
|
||||
"snmp_error": "SNMP server turned off or printer not supported."
|
||||
},
|
||||
"abort": {
|
||||
"unsupported_model": "This printer model is not supported."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ FLOWS = [
|
|||
"ambiclimate",
|
||||
"ambient_station",
|
||||
"axis",
|
||||
"brother",
|
||||
"cast",
|
||||
"cert_expiry",
|
||||
"coolmaster",
|
||||
|
|
|
@ -339,6 +339,9 @@ braviarc-homeassistant==0.3.7.dev0
|
|||
# homeassistant.components.broadlink
|
||||
broadlink==0.12.0
|
||||
|
||||
# homeassistant.components.brother
|
||||
brother==0.1.4
|
||||
|
||||
# homeassistant.components.brottsplatskartan
|
||||
brottsplatskartan==0.0.1
|
||||
|
||||
|
|
|
@ -120,6 +120,9 @@ bomradarloop==0.1.3
|
|||
# homeassistant.components.broadlink
|
||||
broadlink==0.12.0
|
||||
|
||||
# homeassistant.components.brother
|
||||
brother==0.1.4
|
||||
|
||||
# homeassistant.components.buienradar
|
||||
buienradar==1.0.1
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
"""Tests for Brother Printer."""
|
|
@ -0,0 +1,127 @@
|
|||
"""Define tests for the Brother Printer config flow."""
|
||||
import json
|
||||
|
||||
from asynctest import patch
|
||||
from brother import SnmpError, UnsupportedModel
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.brother import config_flow
|
||||
from homeassistant.components.brother.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TYPE
|
||||
|
||||
from tests.common import load_fixture
|
||||
|
||||
CONFIG = {
|
||||
CONF_HOST: "localhost",
|
||||
CONF_NAME: "Printer",
|
||||
CONF_TYPE: "laser",
|
||||
}
|
||||
|
||||
|
||||
async def test_show_form(hass):
|
||||
"""Test that the form is served with no input."""
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
|
||||
async def test_create_entry_with_hostname(hass):
|
||||
"""Test that the user step works with printer hostname."""
|
||||
with patch(
|
||||
"brother.Brother._get_data",
|
||||
return_value=json.loads(load_fixture("brother_printer_data.json")),
|
||||
):
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
flow.context = {}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "user"}, data=CONFIG
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "HL-L2340DW 0123456789"
|
||||
assert result["data"][CONF_HOST] == CONFIG[CONF_HOST]
|
||||
assert result["data"][CONF_NAME] == CONFIG[CONF_NAME]
|
||||
|
||||
|
||||
async def test_create_entry_with_ip_address(hass):
|
||||
"""Test that the user step works with printer IP address."""
|
||||
with patch(
|
||||
"brother.Brother._get_data",
|
||||
return_value=json.loads(load_fixture("brother_printer_data.json")),
|
||||
):
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
flow.context = {}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": "user"},
|
||||
data={CONF_NAME: "Name", CONF_HOST: "127.0.0.1", CONF_TYPE: "laser"},
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "HL-L2340DW 0123456789"
|
||||
assert result["data"][CONF_HOST] == "127.0.0.1"
|
||||
assert result["data"][CONF_NAME] == "Name"
|
||||
|
||||
|
||||
async def test_invalid_hostname(hass):
|
||||
"""Test invalid hostname in user_input."""
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": "user"},
|
||||
data={CONF_NAME: "Name", CONF_HOST: "invalid/hostname", CONF_TYPE: "laser"},
|
||||
)
|
||||
|
||||
assert result["errors"] == {CONF_HOST: "wrong_host"}
|
||||
|
||||
|
||||
async def test_connection_error(hass):
|
||||
"""Test connection to host error."""
|
||||
with patch("brother.Brother._get_data", side_effect=ConnectionError()):
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "user"}, data=CONFIG
|
||||
)
|
||||
|
||||
assert result["errors"] == {"base": "connection_error"}
|
||||
|
||||
|
||||
async def test_snmp_error(hass):
|
||||
"""Test SNMP error."""
|
||||
with patch("brother.Brother._get_data", side_effect=SnmpError("error")):
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "user"}, data=CONFIG
|
||||
)
|
||||
|
||||
assert result["errors"] == {"base": "snmp_error"}
|
||||
|
||||
|
||||
async def test_unsupported_model_error(hass):
|
||||
"""Test unsupported printer model error."""
|
||||
with patch("brother.Brother._get_data", side_effect=UnsupportedModel("error")):
|
||||
flow = config_flow.BrotherConfigFlow()
|
||||
flow.hass = hass
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "user"}, data=CONFIG
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "unsupported_model"
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.10.0": ["000104000003da"],
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.17.0": "1.17",
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.8.0": [
|
||||
"63010400000001",
|
||||
"110104000003da",
|
||||
"410104000023f0",
|
||||
"31010400000001",
|
||||
"6f010400001d4c",
|
||||
"81010400000050",
|
||||
"8601040000000a"
|
||||
],
|
||||
"1.3.6.1.4.1.2435.2.4.3.2435.5.13.3.0": "Brother HL-L2340DW",
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.11.0": ["82010400002b06"],
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.1.0": "0123456789",
|
||||
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.4.5.2.0": "WAITING "
|
||||
}
|
Loading…
Reference in New Issue