Skip to content

Commit 877ffca

Browse files
LorbusChrisfrenck
authored andcommitted
ipp: Make IPP protocol version configurable
Adds a checkbox to optionally configure a printer with legacy IPP v1.1 instead of the default v2.0. Fixes: #93211
1 parent 3eab72b commit 877ffca

File tree

10 files changed

+86
-9
lines changed

10 files changed

+86
-9
lines changed

homeassistant/components/ipp/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
)
1313
from homeassistant.core import HomeAssistant
1414

15-
from .const import CONF_BASE_PATH
15+
from .const import CONF_BASE_PATH, CONF_PROTO_LEGACY
1616
from .coordinator import IPPDataUpdateCoordinator
1717

1818
PLATFORMS = [Platform.SENSOR]
@@ -31,6 +31,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: IPPConfigEntry) -> bool:
3131
host=entry.data[CONF_HOST],
3232
port=entry.data[CONF_PORT],
3333
base_path=entry.data[CONF_BASE_PATH],
34+
proto_legacy=entry.data[CONF_PROTO_LEGACY],
3435
tls=entry.data[CONF_SSL],
3536
verify_ssl=entry.data[CONF_VERIFY_SSL],
3637
device_id=device_id,

homeassistant/components/ipp/config_flow.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@
2929
from homeassistant.core import HomeAssistant
3030
from homeassistant.helpers.aiohttp_client import async_get_clientsession
3131

32-
from .const import CONF_BASE_PATH, CONF_SERIAL, DOMAIN
32+
from .const import (
33+
CONF_BASE_PATH,
34+
CONF_PROTO_LEGACY,
35+
CONF_SERIAL,
36+
DOMAIN,
37+
IPP_PROTO_VERSION_DEFAULT,
38+
IPP_PROTO_VERSION_LEGACY,
39+
)
3340

3441
_LOGGER = logging.getLogger(__name__)
3542

@@ -47,6 +54,9 @@ async def validate_input(hass: HomeAssistant, data: dict) -> dict[str, Any]:
4754
tls=data[CONF_SSL],
4855
verify_ssl=data[CONF_VERIFY_SSL],
4956
session=session,
57+
ipp_version=IPP_PROTO_VERSION_LEGACY
58+
if data[CONF_PROTO_LEGACY]
59+
else IPP_PROTO_VERSION_DEFAULT,
5060
)
5161

5262
printer = await ipp.printer()
@@ -57,8 +67,6 @@ async def validate_input(hass: HomeAssistant, data: dict) -> dict[str, Any]:
5767
class IPPFlowHandler(ConfigFlow, domain=DOMAIN):
5868
"""Handle an IPP config flow."""
5969

60-
VERSION = 1
61-
6270
def __init__(self) -> None:
6371
"""Set up the instance."""
6472
self.discovery_info: dict[str, Any] = {}
@@ -127,6 +135,7 @@ async def async_step_zeroconf(
127135
CONF_BASE_PATH: f"/{base_path}",
128136
CONF_NAME: name,
129137
CONF_UUID: unique_id,
138+
CONF_PROTO_LEGACY: False,
130139
}
131140
)
132141

@@ -215,6 +224,7 @@ def _show_setup_form(self, errors: dict | None = None) -> ConfigFlowResult:
215224
vol.Required(CONF_BASE_PATH, default="/ipp/print"): str,
216225
vol.Required(CONF_SSL, default=False): bool,
217226
vol.Required(CONF_VERIFY_SSL, default=False): bool,
227+
vol.Required(CONF_PROTO_LEGACY, default=False): bool,
218228
}
219229
),
220230
errors=errors or {},

homeassistant/components/ipp/const.py

+4
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@
1616

1717
# Config Keys
1818
CONF_BASE_PATH = "base_path"
19+
CONF_PROTO_LEGACY = "proto_legacy"
1920
CONF_SERIAL = "serial"
2021
CONF_TLS = "tls"
22+
23+
IPP_PROTO_VERSION_LEGACY = (1, 1)
24+
IPP_PROTO_VERSION_DEFAULT = (2, 0)

homeassistant/components/ipp/coordinator.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from homeassistant.helpers.aiohttp_client import async_get_clientsession
1212
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
1313

14-
from .const import DOMAIN
14+
from .const import DOMAIN, IPP_PROTO_VERSION_DEFAULT, IPP_PROTO_VERSION_LEGACY
1515

1616
SCAN_INTERVAL = timedelta(seconds=60)
1717

@@ -30,6 +30,7 @@ def __init__(
3030
base_path: str,
3131
tls: bool,
3232
verify_ssl: bool,
33+
proto_legacy: bool,
3334
device_id: str,
3435
) -> None:
3536
"""Initialize global IPP data updater."""
@@ -41,6 +42,9 @@ def __init__(
4142
tls=tls,
4243
verify_ssl=verify_ssl,
4344
session=async_get_clientsession(hass, verify_ssl),
45+
ipp_version=IPP_PROTO_VERSION_LEGACY
46+
if proto_legacy
47+
else IPP_PROTO_VERSION_DEFAULT,
4448
)
4549

4650
super().__init__(

homeassistant/components/ipp/strings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"port": "[%key:common::config_flow::data::port%]",
1111
"base_path": "Relative path to the printer",
1212
"ssl": "[%key:common::config_flow::data::ssl%]",
13-
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
13+
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]",
14+
"proto_legacy": "Use IPP v1.1 for compatibility with older printers"
1415
}
1516
},
1617
"zeroconf_confirm": {

tests/components/ipp/__init__.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from ipaddress import ip_address
44

55
from homeassistant.components import zeroconf
6-
from homeassistant.components.ipp.const import CONF_BASE_PATH
6+
from homeassistant.components.ipp.const import CONF_BASE_PATH, CONF_PROTO_LEGACY
77
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SSL, CONF_VERIFY_SSL
88

99
ATTR_HOSTNAME = "hostname"
@@ -28,6 +28,16 @@
2828
CONF_SSL: False,
2929
CONF_VERIFY_SSL: False,
3030
CONF_BASE_PATH: BASE_PATH,
31+
CONF_PROTO_LEGACY: False,
32+
}
33+
34+
MOCK_USER_INPUT_PROTO_LEGACY = {
35+
CONF_HOST: "192.168.1.32",
36+
CONF_PORT: PORT,
37+
CONF_SSL: False,
38+
CONF_VERIFY_SSL: False,
39+
CONF_BASE_PATH: "/ipp",
40+
CONF_PROTO_LEGACY: True,
3141
}
3242

3343
MOCK_ZEROCONF_IPP_SERVICE_INFO = zeroconf.ZeroconfServiceInfo(

tests/components/ipp/conftest.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pyipp import Printer
88
import pytest
99

10-
from homeassistant.components.ipp.const import CONF_BASE_PATH, DOMAIN
10+
from homeassistant.components.ipp.const import CONF_BASE_PATH, CONF_PROTO_LEGACY, DOMAIN
1111
from homeassistant.const import (
1212
CONF_HOST,
1313
CONF_PORT,
@@ -33,6 +33,7 @@ def mock_config_entry() -> MockConfigEntry:
3333
CONF_VERIFY_SSL: True,
3434
CONF_BASE_PATH: "/ipp/print",
3535
CONF_UUID: "cfe92100-67c4-11d4-a45f-f8d027761251",
36+
CONF_PROTO_LEGACY: False,
3637
},
3738
unique_id="cfe92100-67c4-11d4-a45f-f8d027761251",
3839
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"printer-state": "idle",
3+
"printer-name": "Test Legacy Printer",
4+
"printer-location": null,
5+
"printer-make-and-model": "Test C822 Series",
6+
"printer-uri-supported": [
7+
"http://192.168.1.32/ipp",
8+
"http://192.168.1.32:631/ipp",
9+
"http://192.168.1.32/ipp/lp",
10+
"http://192.168.1.32:631/ipp/lp",
11+
"ipp://192.168.1.32/ipp",
12+
"ipp://192.168.1.32:631/ipp",
13+
"ipp://192.168.1.32/ipp/lp",
14+
"ipp://192.168.1.32:631/ipp/lp"
15+
],
16+
"printer-info": "PCL,XPS,IBMPPR,EPSONFX",
17+
"printer-more-info": null
18+
}

tests/components/ipp/snapshots/test_diagnostics.ambr

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
'base_path': '/ipp/print',
9292
'host': '192.168.1.31',
9393
'port': 631,
94+
'proto_legacy': False,
9495
'ssl': False,
9596
'uuid': 'cfe92100-67c4-11d4-a45f-f8d027761251',
9697
'verify_ssl': True,

tests/components/ipp/test_config_flow.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
)
1616
import pytest
1717

18-
from homeassistant.components.ipp.const import CONF_BASE_PATH, DOMAIN
18+
from homeassistant.components.ipp.const import CONF_BASE_PATH, CONF_PROTO_LEGACY, DOMAIN
1919
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
2020
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_SSL, CONF_UUID
2121
from homeassistant.core import HomeAssistant
2222
from homeassistant.data_entry_flow import FlowResultType
2323

2424
from . import (
2525
MOCK_USER_INPUT,
26+
MOCK_USER_INPUT_PROTO_LEGACY,
2627
MOCK_ZEROCONF_IPP_SERVICE_INFO,
2728
MOCK_ZEROCONF_IPPS_SERVICE_INFO,
2829
)
@@ -132,6 +133,32 @@ async def test_user_connection_upgrade_required(
132133
assert result["errors"] == {"base": "connection_upgrade"}
133134

134135

136+
async def test_user_legacy_printer(hass: HomeAssistant) -> None:
137+
"""Test that a legacy printer can be added."""
138+
fixture = await hass.async_add_executor_job(
139+
load_fixture, "ipp/printer_proto_legacy.json"
140+
)
141+
mock_legacy_printer = Printer.from_dict(json.loads(fixture))
142+
user_input = MOCK_USER_INPUT_PROTO_LEGACY.copy()
143+
with patch(
144+
"homeassistant.components.ipp.config_flow.IPP", autospec=True
145+
) as ipp_mock:
146+
client = ipp_mock.return_value
147+
client.printer.return_value = mock_legacy_printer
148+
result = await hass.config_entries.flow.async_init(
149+
DOMAIN,
150+
context={"source": SOURCE_USER},
151+
data=user_input,
152+
)
153+
154+
assert result["type"] is FlowResultType.CREATE_ENTRY
155+
assert result["title"] == "192.168.1.32"
156+
157+
assert result["data"]
158+
assert result["data"][CONF_HOST] == "192.168.1.32"
159+
assert result["data"][CONF_PROTO_LEGACY] is True
160+
161+
135162
async def test_zeroconf_connection_upgrade_required(
136163
hass: HomeAssistant,
137164
mock_ipp_config_flow: MagicMock,

0 commit comments

Comments
 (0)