Skip to content

Commit 6153527

Browse files
committed
initial change to support print pages
1 parent c20d2fa commit 6153527

File tree

10 files changed

+131
-36
lines changed

10 files changed

+131
-36
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2.0.5
4+
5+
- New feature: Print pages (according to printer's supported jobs) buttons [#161](https://github.com/elad-bar/ha-hpprinter/issues/161)
6+
37
## 2.0.4
48

59
- Fix update data when printer goes online [#161](https://github.com/elad-bar/ha-hpprinter/issues/161)

custom_components/hpprinter/button.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import logging
2+
3+
from homeassistant.components.button import ButtonEntity
4+
from homeassistant.config_entries import ConfigEntry
5+
from homeassistant.const import Platform
6+
from homeassistant.core import HomeAssistant
7+
8+
from .common.base_entity import BaseEntity, async_setup_base_entry
9+
from .common.entity_descriptions import IntegrationButtonEntityDescription
10+
from .managers.ha_coordinator import HACoordinator
11+
12+
_LOGGER = logging.getLogger(__name__)
13+
14+
15+
async def async_setup_entry(
16+
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
17+
):
18+
await async_setup_base_entry(
19+
hass,
20+
entry,
21+
Platform.BUTTON,
22+
HAButtonEntity,
23+
async_add_entities,
24+
)
25+
26+
27+
class HAButtonEntity(BaseEntity, ButtonEntity):
28+
"""Representation of a sensor."""
29+
30+
def __init__(
31+
self,
32+
entity_description: IntegrationButtonEntityDescription,
33+
coordinator: HACoordinator,
34+
device_key: str,
35+
):
36+
super().__init__(entity_description, coordinator, device_key)
37+
38+
async def async_press(self) -> None:
39+
"""Press the button."""
40+
await self.local_coordinator.async_print_job(self._entity_description.key)

custom_components/hpprinter/common/base_entity.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def _async_handle_device_created(
9494

9595

9696
class BaseEntity(CoordinatorEntity):
97+
_entity_description: IntegrationEntityDescription
9798
_translations: dict
9899

99100
def __init__(
@@ -105,6 +106,7 @@ def __init__(
105106
super().__init__(coordinator)
106107

107108
self.entity_description = entity_description
109+
self._entity_description = entity_description
108110

109111
self._device_key = device_key
110112
self._device_type = entity_description.device_type

custom_components/hpprinter/common/entity_descriptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from dataclasses import dataclass
22

33
from homeassistant.components.binary_sensor import BinarySensorEntityDescription
4+
from homeassistant.components.button import ButtonEntityDescription
45
from homeassistant.components.sensor import SensorEntityDescription
56
from homeassistant.const import Platform
67
from homeassistant.helpers.entity import EntityDescription
@@ -13,6 +14,13 @@ class IntegrationEntityDescription(EntityDescription):
1314
exclude: dict | None = None
1415

1516

17+
@dataclass(frozen=True, kw_only=True)
18+
class IntegrationButtonEntityDescription(
19+
ButtonEntityDescription, IntegrationEntityDescription
20+
):
21+
platform: Platform | None = Platform.BUTTON
22+
23+
1624
@dataclass(frozen=True, kw_only=True)
1725
class IntegrationBinarySensorEntityDescription(
1826
BinarySensorEntityDescription, IntegrationEntityDescription

custom_components/hpprinter/managers/ha_config_manager.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66

77
import aiofiles
88

9+
from homeassistant.components.button import ButtonDeviceClass
910
from homeassistant.config_entries import STORAGE_VERSION, ConfigEntry
1011
from homeassistant.const import Platform
1112
from homeassistant.core import HomeAssistant
1213
from homeassistant.helpers import translation
1314
from homeassistant.helpers.entity import DeviceInfo
1415
from homeassistant.helpers.json import JSONEncoder
1516
from homeassistant.helpers.storage import Store
17+
from homeassistant.util import slugify
1618

1719
from ..common.consts import (
1820
CONFIGURATION_FILE,
@@ -21,9 +23,11 @@
2123
DEFAULT_NAME,
2224
DOMAIN,
2325
DURATION_UNITS,
26+
PRINTER_MAIN_DEVICE,
2427
)
2528
from ..common.entity_descriptions import (
2629
IntegrationBinarySensorEntityDescription,
30+
IntegrationButtonEntityDescription,
2731
IntegrationEntityDescription,
2832
IntegrationSensorEntityDescription,
2933
)
@@ -333,6 +337,20 @@ def _load_entity_descriptions(self):
333337

334338
self._update_platforms()
335339

340+
def load_buttons_entity_descriptions(self, job_types: list[str]):
341+
for job_type in job_types:
342+
entity_description = IntegrationButtonEntityDescription(
343+
key=job_type,
344+
name=job_type,
345+
device_type=PRINTER_MAIN_DEVICE,
346+
device_class=ButtonDeviceClass.IDENTIFY,
347+
translation_key=slugify(job_type),
348+
)
349+
350+
self._entity_descriptions.append(entity_description)
351+
352+
self._update_platforms()
353+
336354
def _update_platforms(self):
337355
for entity_description in self._entity_descriptions:
338356
if (

custom_components/hpprinter/managers/ha_coordinator.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async def initialize(self):
8888

8989
await self._api.initialize()
9090

91-
await self.async_config_entry_first_refresh()
91+
await self.async_request_refresh()
9292

9393
def _load_signal_handlers(self):
9494
loop = self.hass.loop
@@ -105,7 +105,7 @@ def on_device_discovered(
105105

106106
self.config_entry.async_on_unload(
107107
async_dispatcher_connect(
108-
self.hass, SIGNAL_HA_DEVICE_DISCOVERED, self._on_device_discovered
108+
self.hass, SIGNAL_HA_DEVICE_DISCOVERED, on_device_discovered
109109
)
110110
)
111111

@@ -310,6 +310,9 @@ def get_debug_data(self) -> dict:
310310

311311
return data
312312

313+
async def async_print_job(self, job: str):
314+
await self._api.async_print_job(job)
315+
313316
def get_devices(self) -> dict[str, DeviceInfo]:
314317
return self._devices
315318

@@ -343,6 +346,9 @@ async def _on_device_discovered(
343346
else:
344347
self.create_sub_unit_device(device_key, device_data, device_config)
345348

349+
job_types: list[str] = device_data.get("job_types", [])
350+
self.config_manager.load_buttons_entity_descriptions(job_types)
351+
346352
async_dispatcher_send(
347353
self.hass,
348354
SIGNAL_HA_DEVICE_CREATED,

custom_components/hpprinter/managers/rest_api.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -278,22 +278,6 @@ def _extract_data(self, devices: list[dict]):
278278
for device_key in self._data:
279279
self.device_data_changed(device_key)
280280

281-
@staticmethod
282-
def _get_device_from_list(
283-
data: list[dict], identifier_key: str, device_id
284-
) -> dict | None:
285-
data_items = [
286-
data_item
287-
for data_item in data
288-
if data_item.get(identifier_key) == device_id
289-
]
290-
291-
if data_items:
292-
return data_items[0]
293-
294-
else:
295-
return None
296-
297281
def _get_device_config(self, device_type: str) -> dict | None:
298282
data_configs = [
299283
data_point
@@ -358,11 +342,23 @@ def _get_device_data(
358342
for property_key in properties:
359343
property_details = properties.get(property_key)
360344
property_path = property_details.get("path")
345+
property_type = property_details.get("type")
361346
options = property_details.get("options")
362347
validation_warning = property_details.get("validationWarning", False)
363-
value = data_item_flat.get(property_path)
364348

365-
is_valid = True if options is None else str(value).lower() in options
349+
if property_type == "list":
350+
value = [
351+
data_item_flat.get(item)
352+
for item in data_item_flat
353+
if item.startswith(f"{property_path}.")
354+
]
355+
356+
is_valid = True
357+
358+
else:
359+
value = data_item_flat.get(property_path)
360+
361+
is_valid = True if options is None else str(value).lower() in options
366362

367363
if value is not None:
368364
if is_valid:
@@ -497,3 +493,6 @@ def device_data_changed(self, device_key: str):
497493
device_data,
498494
device_config,
499495
)
496+
497+
async def async_print_job(self, job: str):
498+
_LOGGER.debug(f"Start job, Name: {job}")

custom_components/hpprinter/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"iot_class": "local_polling",
1010
"issue_tracker": "https://github.com/elad-bar/ha-hpprinter/issues",
1111
"requirements": ["xmltodict~=0.13.0", "flatten_json", "defusedxml"],
12-
"version": "2.0.4"
12+
"version": "2.0.5"
1313
}

custom_components/hpprinter/parameters/data_points.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@
3131
}
3232
}
3333
},
34+
{
35+
"name": "PrintJobs",
36+
"endpoint": "/DevMgmt/InternalPrintCap.xml",
37+
"path": "InternalPrintCap",
38+
"device_type": "Main",
39+
"interval": "52w",
40+
"properties": {
41+
"job_url": {
42+
"path": "JobUrl"
43+
},
44+
"job_types": {
45+
"path": "JobTypesSupport.JobType",
46+
"type": "list",
47+
"platform": "button"
48+
}
49+
}
50+
},
3451
{
3552
"name": "Consumable",
3653
"endpoint": "/DevMgmt/ConsumableConfigDyn.xml",

utils/api_test.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import json
23
import logging
34
import os
45
import sys
@@ -48,27 +49,26 @@ async def initialize(self):
4849
self._api = RestAPIv2(hass, self._config_manager)
4950
await self._api.initialize()
5051

51-
if self._api.is_online:
52-
53-
await self._api.update([PRODUCT_MAIN_ENDPOINT])
52+
await self._api.update([PRODUCT_MAIN_ENDPOINT])
5453

55-
main_device = self._api.data.get(PRINTER_MAIN_DEVICE)
56-
model = main_device.get(MODEL_PROPERTY)
57-
title = f"{model} ({self._api.config_data.hostname})"
54+
main_device = self._api.data.get(PRINTER_MAIN_DEVICE)
55+
model = main_device.get(MODEL_PROPERTY)
56+
title = f"{model} ({self._api.config_data.hostname})"
5857

59-
print(title)
58+
_LOGGER.info(f"Title: {title}")
6059

61-
for i in range(0, 1):
62-
# self._api.config_data.update({
63-
# key: os.environ.get(key) if i % 2 == 0 or key != "host" else "127.0.0.1"
64-
# for key in self._api.config_data.to_dict()
65-
#})
60+
def _modify_connection(self, index: int):
61+
self._api.config_data.update({
62+
key: os.environ.get(key) if index % 2 == 0 or key != "host" else "127.0.0.1"
63+
for key in self._api.config_data.to_dict()
64+
})
6665

66+
async def update(self, times: int):
67+
if self._api.is_online:
68+
for i in range(0, times):
6769
await self._api.update()
6870

69-
# print(json.dumps(self._api.data_config, indent=4))
70-
# print(json.dumps(self._api.data, indent=4))
71-
# print(json.dumps(self._api.data[PRINTER_MAIN_DEVICE], indent=4))
71+
_LOGGER.debug(json.dumps(self._api.data[PRINTER_MAIN_DEVICE], indent=4))
7272

7373
await asyncio.sleep(10)
7474

@@ -83,6 +83,7 @@ async def initialize(self):
8383

8484
try:
8585
loop.run_until_complete(instance.initialize())
86+
loop.run_until_complete(instance.update(1))
8687

8788
except KeyboardInterrupt:
8889
_LOGGER.info("Aborted")

0 commit comments

Comments
 (0)