Compare commits

..

9 Commits

Author SHA1 Message Date
d91b3edb40 Use unique_id instead of mac address for #22 2023-04-15 22:05:02 +02:00
83c5e3479e Add hob support #22 2023-04-15 04:34:12 +02:00
b0cd020941 Bump versions 2023-04-15 00:32:47 +02:00
593842144a Add zip release for download count 2023-04-12 23:59:09 +02:00
9a6e1155f9 Add useful links 2023-04-12 23:58:10 +02:00
365a3af171 Clean up sessions correct, fixes #19 2023-04-12 19:28:04 +02:00
6de6ff375c Bump version to v0.5.0 2023-04-12 02:11:41 +02:00
89d2fd4af1 Read out device data via ui 2023-04-11 22:08:47 +02:00
92add01a59 Bump pyhon version 2023-04-11 01:03:54 +02:00
13 changed files with 248 additions and 35 deletions

25
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Release
on:
release:
types: [published]
jobs:
release-zip:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: ZIP Component Dir
run: |
cd ${{ github.workspace }}/custom_components/hon
zip -r haier_hon.zip ./
- name: Upload zip to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ github.workspace }}/custom_components/hon/haier_hon.zip
asset_name: haier_hon.zip
tag: ${{ github.ref }}
overwrite: true

View File

@ -9,6 +9,7 @@ Home Assistant integration for Haier hOn: support for Haier/Candy/Hoover home ap
- Washer Dryer
- Washing Machine
- Oven
- Hob
## Installation
**Method 1:** [![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=Andre0512&repository=hon&category=integration)
@ -26,14 +27,34 @@ _Restart Home Assistant_
**Method 2**: Settings > Devices & Services > Add Integration > **Haier hOn**
_If the integration is not in the list, you need to clear the browser cache._
## Contribute
Any kind of contribution is welcome!
#### Add appliances or additional attributes
### Read out device data
If you want to make a request for adding new appliances or additional attributes and don't want to use the command line, here is how you can read out your device data.
For every device exists a hidden button which can be used to log all info of your appliance.
1. Enable the "Log Device Info" button
_This button can be found in the diagnostic section of your device or in the entity overview if "show disabled entities" is enabled._
2. Press the button
3. Go to Settings > System > Logs, click _load full logs_ and scroll down
_The formatting is messy if you not load full logs_
4. Here you can find all data which can be read out via the api
```yaml
data:
appliance:
applianceId: 12-34-56-78-90-ab#2022-10-25T19:47:11Z
applianceModelId: 1569
...
```
5. Copy this data and create a [new issue](https://github.com/Andre0512/hon/issues/new) with your request
### Add appliances or additional attributes
1. Install [pyhOn](https://github.com/Andre0512/pyhOn)
```commandline
$ pip install pyhOn
```
2. Use the commandline tool to read out all appliance data from your account
2. Use the command line tool to read out all appliance data from your account
```commandline
$ pyhOn
User for hOn account: user.name@example.com
@ -70,7 +91,7 @@ Any kind of contribution is welcome!
#### Tips and Tricks
- If you want to have some states humanreadable, have a look at the `translation_key` parameter of the `EntityDescription`.
- If you need to implement some more logic, create a pull request to the underlying library. There we collect special requirements in the `appliances` directory.
- Use [pyhOn](https://github.com/Andre0512/pyhOn)s translate command to read out the official translations
- Use [pyhOn's translate command](https://github.com/Andre0512/pyhOn#translation) to read out the official translations
## Tested Devices
- Haier WD90-B14TEAM5

View File

@ -104,14 +104,14 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
"OV": (
HonBinarySensorEntityDescription(
key="attributes.lastConnEvent.category",
name="Online",
name="Connection",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="CONNECTED",
icon="mdi:wifi",
),
HonBinarySensorEntityDescription(
key="attributes.parameters.remoteCtrValid",
name="On",
name="Remote Control",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="1",
icon="mdi:remote",
@ -124,6 +124,41 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
icon="mdi:power-cycle",
),
),
"IV": (
HonBinarySensorEntityDescription(
key="attributes.lastConnEvent.category",
name="Connection",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="CONNECTED",
icon="mdi:wifi",
),
HonBinarySensorEntityDescription(
key="attributes.parameters.remoteCtrValid",
name="Remote Control",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="1",
icon="mdi:remote",
),
HonBinarySensorEntityDescription(
key="attributes.parameters.onOffStatus",
name="On",
device_class=BinarySensorDeviceClass.RUNNING,
on_value="1",
icon="mdi:power-cycle",
),
HonBinarySensorEntityDescription(
key="hotStatus",
name="Hot Status",
device_class=BinarySensorDeviceClass.HEAT,
on_value="1",
),
HonBinarySensorEntityDescription(
key="hobLockStatus",
name="Hob Lock",
device_class=BinarySensorDeviceClass.LOCK,
on_value="0",
),
),
}
@ -132,11 +167,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := BINARY_SENSORS.get(device.appliance_type):

View File

@ -1,11 +1,18 @@
import logging
import urllib
from urllib.parse import quote
from homeassistant.components.button import ButtonEntityDescription, ButtonEntity
from homeassistant.config_entries import ConfigEntry
from pyhon import Hon
from pyhon.appliance import HonAppliance
from homeassistant.const import EntityCategory
from .const import DOMAIN
from .hon import HonCoordinator, HonEntity
_LOGGER = logging.getLogger(__name__)
BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = {
"OV": (
ButtonEntityDescription(
@ -18,7 +25,14 @@ BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = {
name="Stop Program",
icon="mdi:power-off",
),
)
),
"IV": (
ButtonEntityDescription(
key="startProgram",
name="Start Program",
icon="mdi:pot-steam",
),
),
}
@ -27,11 +41,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := BUTTONS.get(device.appliance_type):
@ -41,6 +55,7 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
appliances.extend(
[HonButtonEntity(hass, coordinator, entry, device, description)]
)
appliances.extend([HonFeatureRequestButton(hass, coordinator, entry, device)])
async_add_entities(appliances)
@ -58,3 +73,18 @@ class HonButtonEntity(HonEntity, ButtonEntity):
async def async_press(self) -> None:
await self._device.commands[self.entity_description.key].send()
class HonFeatureRequestButton(HonEntity, ButtonEntity):
def __init__(self, hass, coordinator, entry, device: HonAppliance) -> None:
super().__init__(hass, entry, coordinator, device)
self._device = device
self._attr_unique_id = f"{super().unique_id}_log_device_info"
self._attr_icon = "mdi:information"
self._attr_name = "Log Device Info"
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_entity_registry_enabled_default = False
async def async_press(self) -> None:
_LOGGER.error("Device Info:\n" + self._device.diagnose)

View File

@ -22,12 +22,12 @@ class HonEntity(CoordinatorEntity):
self._hass = hass
self._device = device
self._attr_unique_id = self._device.mac_address
self._attr_unique_id = self._device.unique_id
@property
def device_info(self):
return DeviceInfo(
identifiers={(DOMAIN, self._device.mac_address)},
identifiers={(DOMAIN, self._device.unique_id)},
manufacturer=self._device.get("brand", ""),
name=self._device.nick_name
if self._device.nick_name
@ -43,7 +43,7 @@ class HonCoordinator(DataUpdateCoordinator):
super().__init__(
hass,
_LOGGER,
name=device.mac_address,
name=device.unique_id,
update_interval=timedelta(seconds=30),
)
self._device = device

View File

@ -6,6 +6,6 @@
"documentation": "https://github.com/Andre0512/hon/",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/Andre0512/hon/issues",
"requirements": ["pyhOn==0.6.3"],
"version": "0.5.0-beta.4"
"requirements": ["pyhOn==0.8.0b3"],
"version": "0.6.0-beta.2"
}

View File

@ -106,6 +106,20 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
native_unit_of_measurement=UnitOfTime.MINUTES,
),
),
"IV": (
NumberEntityDescription(
key="startProgram.temp",
name="Temperature",
entity_category=EntityCategory.CONFIG,
icon="mdi:thermometer",
),
NumberEntityDescription(
key="startProgram.powerManagement",
name="Power Management",
entity_category=EntityCategory.CONFIG,
icon="mdi:timelapse",
),
),
}
@ -114,11 +128,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := NUMBERS.get(device.appliance_type):

View File

@ -68,6 +68,7 @@ SELECTS = {
key="startProgram.program",
name="Program",
entity_category=EntityCategory.CONFIG,
translation_key="programs",
),
SelectEntityDescription(
key="startProgram.preheatStatus",
@ -75,6 +76,14 @@ SELECTS = {
entity_category=EntityCategory.CONFIG,
),
),
"IV": (
SelectEntityDescription(
key="startProgram.program",
name="Program",
entity_category=EntityCategory.CONFIG,
translation_key="programs",
),
),
}
@ -83,11 +92,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := SELECTS.get(device.appliance_type):

View File

@ -221,6 +221,22 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
icon="mdi:thermometer",
),
),
"IV": (
SensorEntityDescription(
key="remainingTimeMM",
name="Remaining Time",
icon="mdi:timer",
native_unit_of_measurement=UnitOfTime.MINUTES,
),
SensorEntityDescription(
key="temp",
name="Temperature",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(key="errors", name="Error", icon="mdi:math-log"),
),
}
@ -229,11 +245,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := SENSORS.get(device.appliance_type):

View File

@ -97,11 +97,11 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
coordinators = hass.data[DOMAIN]["coordinators"]
appliances = []
for device in hon.appliances:
if device.mac_address in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
if device.unique_id in coordinators:
coordinator = hass.data[DOMAIN]["coordinators"][device.unique_id]
else:
coordinator = HonCoordinator(hass, device)
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
hass.data[DOMAIN]["coordinators"][device.unique_id] = coordinator
await coordinator.async_config_entry_first_refresh()
if descriptions := SWITCHES.get(device.appliance_type):

View File

@ -402,7 +402,64 @@
"wool": "Wool",
"wool_and_delicates_49": "Wool and Delicates 49'",
"wool_dry": "Wool Dry",
"wool_soft_care": "Wool and Soft Car"
"wool_soft_care": "Wool and Soft Car",
"bakery": "Pasta and Pastries",
"bakery_steam": "Steam-baked bread",
"bottom_heating": "Bottom Heating",
"bottom_heating_fan": "Bottom Heating + Fan",
"bread": "Bread",
"bread_steam": "Steam-baked pastries",
"combi": "Combi",
"convection_fan": "Convection + Fan",
"convection_fan_turnspit": "Convection + Fan + Turnspit",
"conventional": "Conventional",
"conventional_turnspit": "Convection + Turnspit",
"defrost": "Defrost",
"descaling": "Descaling",
"fish": "Fish",
"fish_steam": "Steam-cooked fish",
"grill_cata": "Grill",
"grill_fan_cata": "Grill fan",
"grill_fan_pyro": "Grill + Fan",
"grill_pyro": "Grill",
"h20_clean": "H2O-Clean",
"iot_bread": "Bread",
"iot_h20_clean": "h2O clean",
"leavening": "Leavening",
"light_fan": "Light Fan",
"low_temp_cooking": "Low Temperature Cooking",
"low_temp_cooking_fish": "Low Temperature Cooking - Fish",
"low_temp_cooking_fish_steam": "Low Temperature Steam Cooking - Fish",
"low_temp_cooking_meat": "Low Temperature Cooking - Meat",
"low_temp_cooking_meat_steam": "Low Temperature Steam Cooking - Meat",
"low_temp_cooking_steam": "Low Temperature Steam Cooking",
"meat": "Meat",
"meat_steam": "Steam-cooked meat",
"multi_level": "Multi-Level",
"paella": "Paella",
"pasta_and_bakery": "Pasta and Bakery",
"pizza": "Pizza",
"pyrolysis": "Pyrolysis",
"pyrolysis_plus": "Pyrolysis +",
"red_meat": "Red Meat",
"red_meat_steam": "Steam-cooked red meat",
"regenerate": "Regeneration",
"soft_plus": "Soft+",
"super_grill": "Super Grill",
"tailor_bake": "Tailor bake",
"tailor_bake_cata": "Tailor Bake",
"tailor_bake_pyro": "Tailor Bake",
"vegetables": "Vegetables",
"vegetables_cata": "Vegetables",
"vegetables_pyro": "Vegetables",
"water_discharge": "Water Drain",
"white_meat": "White Meat",
"white_meat_steam": "Steam-cooked white meat",
"iot_standard_boiling": "Boiling",
"iot_standard_frying": "Frying",
"iot_standard_keep_warm": "Keep Warm",
"iot_standard_melting": "Melting",
"iot_standard_simmering": "Simmering"
}
}
}

View File

@ -1,4 +1,6 @@
{
"name": "Haier hOn",
"homeassistant": "2023.2.0"
"homeassistant": "2023.2.0",
"zip_release": true,
"filename": "haier_hon.zip"
}

12
info.md
View File

@ -9,6 +9,7 @@ Support for home appliances of Haier's mobile app hOn.
- Washer Dryer
- Washing Machine
- Oven
- Hob
## Tested Appliances
- Haier WD90-B14TEAM5
@ -26,11 +27,14 @@ _If the integration is not in the list, you need to clear the browser cache._
## Contribute
Want to help us to support more appliances?
Or add more sensors?
Or help with translating?
Or beautify some icons or captions?
Want to help us to support more appliances? Or add more sensors? Or help with translating? Or beautify some icons or captions?
Check out the [project on GitHub](https://github.com/Andre0512/hon), every contribution is welcome!
## Useful Links
* [GitHub repository](https://github.com/Andre0512/hon) (please add a star if you like this integration!)
* [pyhOn library](https://github.com/Andre0512/pyhOn)
* [Release notes](https://github.com/Andre0512/hon/releases)
* [Discussion and help](https://github.com/Andre0512/hon/discussions)
* [Issues](https://github.com/Andre0512/hon/issues)