Compare commits
	
		
			10 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0afbfe997d | |||
| 6828f3e9a8 | |||
| a56d3e5f88 | |||
| 240dc85ff3 | |||
| 44794c35ca | |||
| a5c7b99569 | |||
| 6935f5f07f | |||
| 74f5887bb2 | |||
| 155b1ff91a | |||
| 7b80acb6b9 | 
							
								
								
									
										157
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								README.md
									
									
									
									
									
								
							| @ -30,6 +30,40 @@ _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._ | ||||
|  | ||||
|  | ||||
| ## Supported Models | ||||
| Support was confirmed for these models. If a supported model is missing, please [add it with this form](https://forms.gle/bTSD8qFotdZFytbf8). | ||||
| - Haier WD90-B14TEAM5 | ||||
| - Haier HD80-A3959 | ||||
| - Haier HWO60SM2F3XH | ||||
| - Hoover H-WASH 500 | ||||
| - Candy CIS633SCTTWIFI | ||||
| - Haier XIB 3B2SFS-80 | ||||
| - Haier XIB 6B2D3FB | ||||
| - Hoover HSOT3161WG | ||||
|  | ||||
| ## Supported Languages | ||||
| Translation of internal names like programs are available for all languages which are official supported by the hOn app: | ||||
| * 🇨🇳 Chinese | ||||
| * 🇭🇷 Croatian | ||||
| * 🇨🇿 Czech | ||||
| * 🇳🇱 Dutch | ||||
| * 🇬🇧 English | ||||
| * 🇫🇷 French | ||||
| * 🇩🇪 German | ||||
| * 🇬🇷 Greek | ||||
| * 🇮🇱 Hebrew | ||||
| * 🇮🇹 Italian | ||||
| * 🇵🇱 Polish | ||||
| * 🇵🇹 Portuguese | ||||
| * 🇷🇴 Romanian | ||||
| * 🇷🇺 Russian | ||||
| * 🇷🇸 Serbian | ||||
| * 🇸🇰 Slovak | ||||
| * 🇸🇮 Slovenian | ||||
| * 🇪🇸 Spanish | ||||
| * 🇹🇷 Turkish | ||||
|  | ||||
| ## Contribute | ||||
| Any kind of contribution is welcome! | ||||
| ### Read out device data | ||||
| @ -94,38 +128,6 @@ For every device exists a hidden button which can be used to log all info of you | ||||
| - 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's translate command](https://github.com/Andre0512/pyhOn#translation) to read out the official translations | ||||
|  | ||||
| ## Tested Devices | ||||
| - Haier WD90-B14TEAM5 | ||||
| - Haier HD80-A3959 | ||||
| - Haier HWO60SM2F3XH | ||||
| - Hoover H-WASH 500 | ||||
| - Candy CIS633SCTTWIFI | ||||
| - Haier XIB 3B2SFS-80 | ||||
| - Haier XIB 6B2D3FB | ||||
|  | ||||
| ## Supported Languages | ||||
| Translation of internal names like programs are available for all languages which are official supported by the hOn app: | ||||
| * 🇨🇳 Chinese | ||||
| * 🇭🇷 Croatian | ||||
| * 🇨🇿 Czech | ||||
| * 🇳🇱 Dutch | ||||
| * 🇬🇧 English | ||||
| * 🇫🇷 French | ||||
| * 🇩🇪 German | ||||
| * 🇬🇷 Greek | ||||
| * 🇮🇱 Hebrew | ||||
| * 🇮🇹 Italian | ||||
| * 🇵🇱 Polish | ||||
| * 🇵🇹 Portuguese | ||||
| * 🇷🇴 Romanian | ||||
| * 🇷🇺 Russian | ||||
| * 🇷🇸 Serbian | ||||
| * 🇸🇰 Slovak | ||||
| * 🇸🇮 Slovenian | ||||
| * 🇪🇸 Spanish | ||||
| * 🇹🇷 Turkish | ||||
|  | ||||
|  | ||||
| ## About this Repo | ||||
| The existing integrations missed some features from the app I liked to have in HomeAssistant. | ||||
| I tried to create a pull request, but in the structures of these existing repos, I find it hard to fit in my needs, so I basically rewrote everything.  | ||||
| @ -137,19 +139,19 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| #### Configs | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | 10° Heating |  | `switch` | `startProgram.10degreeHeatingStatus` | | ||||
| | Echo |  | `switch` | `startProgram.echoStatus` | | ||||
| | Eco Mode |  | `switch` | `startProgram.ecoMode` | | ||||
| | Eco Pilot |  | `select` | `startProgram.humanSensingStatus` | | ||||
| | Health Mode |  | `switch` | `startProgram.healthMode` | | ||||
| | Mute |  | `switch` | `startProgram.muteStatus` | | ||||
| | 10° Heating | `heat-wave` | `switch` | `settings.10degreeHeatingStatus` | | ||||
| | Echo | `account-voice` | `switch` | `settings.echoStatus` | | ||||
| | Eco Mode |  | `switch` | `settings.ecoMode` | | ||||
| | Eco Pilot | `run` | `select` | `settings.humanSensingStatus` | | ||||
| | Health Mode | `medication-outline` | `switch` | `settings.healthMode` | | ||||
| | Mute | `volume-off` | `switch` | `settings.muteStatus` | | ||||
| | Program |  | `select` | `startProgram.program` | | ||||
| | Rapid Mode |  | `switch` | `startProgram.rapidMode` | | ||||
| | Screen Display |  | `switch` | `startProgram.screenDisplayStatus` | | ||||
| | Self Cleaning |  | `switch` | `startProgram.selfCleaningStatus` | | ||||
| | Self Cleaning 56 |  | `switch` | `startProgram.selfCleaning56Status` | | ||||
| | Silent Sleep |  | `switch` | `startProgram.silentSleepStatus` | | ||||
| | Target Temperature | `thermometer` | `number` | `startProgram.tempSel` | | ||||
| | Rapid Mode | `run-fast` | `switch` | `settings.rapidMode` | | ||||
| | Screen Display | `monitor-small` | `switch` | `settings.screenDisplayStatus` | | ||||
| | Self Cleaning | `air-filter` | `switch` | `settings.selfCleaningStatus` | | ||||
| | Self Cleaning 56 | `air-filter` | `switch` | `settings.selfCleaning56Status` | | ||||
| | Silent Sleep | `bed` | `switch` | `settings.silentSleepStatus` | | ||||
| | Target Temperature | `thermometer` | `number` | `settings.tempSel` | | ||||
|  | ||||
| ### Dish washer | ||||
| #### Controls | ||||
| @ -208,7 +210,6 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| | Pan Status | `pot-mix` | `binary_sensor` | `panStatus` | | ||||
| | Power | `lightning-bolt` | `sensor` | `power` | | ||||
| | Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | ||||
| | Remote Control | `remote` | `binary_sensor` | `attributes.parameters.remoteCtrValid` | | ||||
| | Temperature | `thermometer` | `sensor` | `temp` | | ||||
|  | ||||
| ### Oven | ||||
| @ -230,7 +231,6 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| | Connection | `wifi` | `binary_sensor` | `attributes.lastConnEvent.category` | | ||||
| | On | `power-cycle` | `binary_sensor` | `attributes.parameters.onOffStatus` | | ||||
| | Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | ||||
| | Remote Control | `remote` | `binary_sensor` | `attributes.parameters.remoteCtrValid` | | ||||
| | Start Time | `clock-start` | `sensor` | `delayTime` | | ||||
| | Temperature | `thermometer` | `sensor` | `temp` | | ||||
| | Temperature Selected | `thermometer` | `sensor` | `tempSel` | | ||||
| @ -253,58 +253,96 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| | Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` | | ||||
| | Program |  | `select` | `startProgram.program` | | ||||
| | Steam Type | `weather-dust` | `sensor` | `steamType` | | ||||
| | Steam level | `smoke` | `sensor` | `steamLevel` | | ||||
| | Steam level | `smoke` | `sensor` | `startProgram.steamLevel` | | ||||
| | Sterilization | `clock-start` | `switch` | `startProgram.sterilizationStatus` | | ||||
| | Suggested Load | `weight-kilogram` | `sensor` | `startProgram.suggestedLoadD` | | ||||
| | Temperature level | `thermometer` | `number` | `startProgram.tempLevel` | | ||||
| #### Sensors | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | Anti-Crease |  | `binary_sensor` | `anticrease` | | ||||
| | Connection |  | `binary_sensor` | `attributes.lastConnEvent.category` | | ||||
| | Door |  | `binary_sensor` | `doorStatus` | | ||||
| | Dry level | `hair-dryer` | `sensor` | `dryLevel` | | ||||
| | Error | `math-log` | `sensor` | `errors` | | ||||
| | Machine Status | `information` | `sensor` | `machMode` | | ||||
| | Program | `tumble-dryer` | `sensor` | `prCode` | | ||||
| | Program | `tumble-dryer` | `sensor` | `programName` | | ||||
| | Program Phase | `washing-machine` | `sensor` | `prPhase` | | ||||
| | Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | ||||
| | Start Time | `clock-start` | `sensor` | `delayTime` | | ||||
| | Steam level | `smoke` | `sensor` | `steamLevel` | | ||||
| | Temperature level | `thermometer` | `sensor` | `tempLevel` | | ||||
|  | ||||
| ### Washer dryer | ||||
| #### Controls | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | Pause Washing Machine | `pause` | `switch` | `pauseProgram` / `resumeProgram` | | ||||
| | Washing Machine | `washing-machine` | `switch` | `startProgram` / `stopProgram` | | ||||
| | Pause Washer Dryer | `pause` | `switch` | `pauseProgram` / `resumeProgram` | | ||||
| | Washer Dryer | `washing-machine` | `switch` | `startProgram` / `stopProgram` | | ||||
| #### Configs | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | Acqua Plus | `water-plus` | `switch` | `startProgram.acquaplus` | | ||||
| | Anti-Crease | `timer` | `switch` | `startProgram.antiCreaseTime` | | ||||
| | Anti-Crease | `timer` | `switch` | `startProgram.anticrease` | | ||||
| | Auto Dose | `cup` | `switch` | `startProgram.autoDetergentStatus` | | ||||
| | Delay Status | `timer-check` | `switch` | `startProgram.delayStatus` | | ||||
| | Delay Time | `timer-plus` | `number` | `startProgram.delayTime` | | ||||
| | Dry Time |  | `number` | `startProgram.dryTime` | | ||||
| | Dry Time | `timer` | `select` | `startProgram.dryTimeMM` | | ||||
| | Dry level | `hair-dryer` | `select` | `startProgram.dryLevel` | | ||||
| | Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` | | ||||
| | Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `startProgram.extraRinse1` | | ||||
| | Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `startProgram.extraRinse2` | | ||||
| | Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `startProgram.extraRinse3` | | ||||
| | Good Night | `weather-night` | `switch` | `startProgram.goodNight` | | ||||
| | Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` | | ||||
| | Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` | | ||||
| | Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` | | ||||
| | Powder Detergent Dose | `cup` | `sensor` | `startProgram.powderDetergentDose` | | ||||
| | Program |  | `select` | `startProgram.program` | | ||||
| | Remaining Time | `timer` | `sensor` | `startProgram.remainingTime` | | ||||
| | Rinse Iterations | `rotate-right` | `number` | `startProgram.rinseIterations` | | ||||
| | Soak Prewash Selection | `tshirt-crew` | `switch` | `startProgram.haier_SoakPrewashSelection` | | ||||
| | Spin speed | `numeric` | `select` | `startProgram.spinSpeed` | | ||||
| | Steam Level | `weather-dust` | `number` | `startProgram.steamLevel` | | ||||
| | Steam Type | `weather-dust` | `sensor` | `steamType` | | ||||
| | Steam level | `smoke` | `sensor` | `startProgram.steamLevel` | | ||||
| | Sterilization | `clock-start` | `switch` | `startProgram.sterilizationStatus` | | ||||
| | Suggested Load | `weight-kilogram` | `sensor` | `startProgram.suggestedLoadW` | | ||||
| | Suggested Load | `weight-kilogram` | `sensor` | `startProgram.suggestedLoadD` | | ||||
| | Suggested weight | `weight-kilogram` | `sensor` | `startProgram.weight` | | ||||
| | Temperature | `thermometer` | `select` | `startProgram.temp` | | ||||
| | Temperature level | `thermometer` | `number` | `startProgram.tempLevel` | | ||||
| | Water hard | `water` | `number` | `startProgram.waterHard` | | ||||
| | lang |  | `number` | `startProgram.lang` | | ||||
| #### Sensors | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | Acqua Plus |  | `binary_sensor` | `acquaplus` | | ||||
| | Anti-Crease |  | `binary_sensor` | `anticrease` | | ||||
| | Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` | | ||||
| | Current Program | `tumble-dryer` | `sensor` | `prCode` | | ||||
| | Current Temperature | `thermometer` | `sensor` | `temp` | | ||||
| | Current Water Used | `water` | `sensor` | `currentWaterUsed` | | ||||
| | Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` | | ||||
| | Door |  | `binary_sensor` | `doorStatus` | | ||||
| | Door Lock |  | `binary_sensor` | `doorLockStatus` | | ||||
| | Dry level | `hair-dryer` | `sensor` | `dryLevel` | | ||||
| | Error | `math-log` | `sensor` | `errors` | | ||||
| | Extra Rinse 1 |  | `binary_sensor` | `extraRinse1` | | ||||
| | Extra Rinse 2 |  | `binary_sensor` | `extraRinse2` | | ||||
| | Extra Rinse 3 |  | `binary_sensor` | `extraRinse3` | | ||||
| | Good Night Mode |  | `binary_sensor` | `goodNight` | | ||||
| | Machine Status | `information` | `sensor` | `machMode` | | ||||
| | Pre Wash |  | `binary_sensor` | `startProgram.prewash` | | ||||
| | Program | `tumble-dryer` | `sensor` | `programName` | | ||||
| | Program Phase | `washing-machine` | `sensor` | `prPhase` | | ||||
| | Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | ||||
| | Remote Control | `remote` | `binary_sensor` | `attributes.lastConnEvent.category` | | ||||
| | Spin Speed | `fast-forward-outline` | `sensor` | `spinSpeed` | | ||||
| | Spin Speed | `speedometer` | `sensor` | `spinSpeed` | | ||||
| | Start Time | `clock-start` | `sensor` | `delayTime` | | ||||
| | Steam level | `smoke` | `sensor` | `steamLevel` | | ||||
| | Temperature level | `thermometer` | `sensor` | `tempLevel` | | ||||
| | Total Power |  | `sensor` | `totalElectricityUsed` | | ||||
| | Total Wash Cycle | `counter` | `sensor` | `totalWashCycle` | | ||||
| | Total Water |  | `sensor` | `totalWaterUsed` | | ||||
| @ -323,10 +361,10 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| | Delay Status | `timer-check` | `switch` | `startProgram.delayStatus` | | ||||
| | Delay Time | `timer-plus` | `number` | `startProgram.delayTime` | | ||||
| | Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` | | ||||
| | Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `extraRinse1` | | ||||
| | Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `extraRinse2` | | ||||
| | Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `extraRinse3` | | ||||
| | Good Night | `weather-night` | `switch` | `goodNight` | | ||||
| | Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `startProgram.extraRinse1` | | ||||
| | Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `startProgram.extraRinse2` | | ||||
| | Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `startProgram.extraRinse3` | | ||||
| | Good Night | `weather-night` | `switch` | `startProgram.goodNight` | | ||||
| | Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` | | ||||
| | Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` | | ||||
| | Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` | | ||||
| @ -345,13 +383,20 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0 | ||||
| #### Sensors | ||||
| | Name | Icon | Entity | Key | | ||||
| | --- | --- | --- | --- | | ||||
| | Acqua Plus |  | `binary_sensor` | `acquaplus` | | ||||
| | Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` | | ||||
| | Current Temperature | `thermometer` | `sensor` | `temp` | | ||||
| | Current Water Used | `water` | `sensor` | `currentWaterUsed` | | ||||
| | Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` | | ||||
| | Door |  | `binary_sensor` | `doorStatus` | | ||||
| | Door Lock |  | `binary_sensor` | `doorLockStatus` | | ||||
| | Error | `math-log` | `sensor` | `errors` | | ||||
| | Extra Rinse 1 |  | `binary_sensor` | `extraRinse1` | | ||||
| | Extra Rinse 2 |  | `binary_sensor` | `extraRinse2` | | ||||
| | Extra Rinse 3 |  | `binary_sensor` | `extraRinse3` | | ||||
| | Good Night Mode |  | `binary_sensor` | `goodNight` | | ||||
| | Machine Status | `information` | `sensor` | `machMode` | | ||||
| | Pre Wash |  | `binary_sensor` | `startProgram.prewash` | | ||||
| | Program Phase | `washing-machine` | `sensor` | `prPhase` | | ||||
| | Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | ||||
| | Remote Control | `remote` | `binary_sensor` | `attributes.lastConnEvent.category` | | ||||
|  | ||||
| @ -11,7 +11,7 @@ from homeassistant.components.binary_sensor import ( | ||||
| from homeassistant.config_entries import ConfigEntry | ||||
| from homeassistant.core import callback | ||||
| from .const import DOMAIN | ||||
| from .hon import HonCoordinator, HonEntity | ||||
| from .hon import HonCoordinator, HonEntity, unique_entities | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| @ -52,32 +52,6 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = { | ||||
|             on_value="1", | ||||
|             translation_key="door_open", | ||||
|         ), | ||||
|     ), | ||||
|     "TD": ( | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.lastConnEvent.category", | ||||
|             name="Connection", | ||||
|             device_class=BinarySensorDeviceClass.CONNECTIVITY, | ||||
|             on_value="CONNECTED", | ||||
|             translation_key="connection", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="doorStatus", | ||||
|             name="Door", | ||||
|             device_class=BinarySensorDeviceClass.DOOR, | ||||
|             on_value="1", | ||||
|             translation_key="door_open", | ||||
|         ), | ||||
|     ), | ||||
|     "WD": ( | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.lastConnEvent.category", | ||||
|             name="Remote Control", | ||||
|             device_class=BinarySensorDeviceClass.CONNECTIVITY, | ||||
|             on_value="CONNECTED", | ||||
|             icon="mdi:remote", | ||||
|             translation_key="remote_control", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="startProgram.prewash", name="Pre Wash", translation_key="prewash" | ||||
|         ), | ||||
| @ -96,6 +70,22 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = { | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="acquaplus", name="Acqua Plus", translation_key="acqua_plus" | ||||
|         ), | ||||
|     ), | ||||
|     "TD": ( | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.lastConnEvent.category", | ||||
|             name="Connection", | ||||
|             device_class=BinarySensorDeviceClass.CONNECTIVITY, | ||||
|             on_value="CONNECTED", | ||||
|             translation_key="connection", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="doorStatus", | ||||
|             name="Door", | ||||
|             device_class=BinarySensorDeviceClass.DOOR, | ||||
|             on_value="1", | ||||
|             translation_key="door_open", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="anticrease", name="Anti-Crease", translation_key="anti_crease" | ||||
|         ), | ||||
| @ -109,14 +99,6 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = { | ||||
|             icon="mdi:wifi", | ||||
|             translation_key="connection", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.parameters.remoteCtrValid", | ||||
|             name="Remote Control", | ||||
|             device_class=BinarySensorDeviceClass.CONNECTIVITY, | ||||
|             on_value="1", | ||||
|             icon="mdi:remote", | ||||
|             translation_key="remote_control", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.parameters.onOffStatus", | ||||
|             name="On", | ||||
| @ -135,14 +117,6 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = { | ||||
|             icon="mdi:wifi", | ||||
|             translation_key="connection", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.parameters.remoteCtrValid", | ||||
|             name="Remote Control", | ||||
|             device_class=BinarySensorDeviceClass.CONNECTIVITY, | ||||
|             on_value="1", | ||||
|             icon="mdi:remote", | ||||
|             translation_key="remote_control", | ||||
|         ), | ||||
|         HonBinarySensorEntityDescription( | ||||
|             key="attributes.parameters.onOffStatus", | ||||
|             name="On", | ||||
| @ -208,6 +182,9 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = { | ||||
| } | ||||
|  | ||||
|  | ||||
| BINARY_SENSORS["WD"] = unique_entities(BINARY_SENSORS["WM"], BINARY_SENSORS["TD"]) | ||||
|  | ||||
|  | ||||
| async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None: | ||||
|     hon: Hon = hass.data[DOMAIN][entry.unique_id] | ||||
|     coordinators = hass.data[DOMAIN]["coordinators"] | ||||
| @ -224,12 +201,8 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non | ||||
|             for description in descriptions: | ||||
|                 if not device.get(description.key): | ||||
|                     continue | ||||
|                 appliances.extend( | ||||
|                     [ | ||||
|                         HonBinarySensorEntity( | ||||
|                             hass, coordinator, entry, device, description | ||||
|                         ) | ||||
|                     ] | ||||
|                 appliances.append( | ||||
|                     HonBinarySensorEntity(hass, coordinator, entry, device, description) | ||||
|                 ) | ||||
|  | ||||
|     async_add_entities(appliances) | ||||
|  | ||||
| @ -64,6 +64,11 @@ class HonButtonEntity(HonEntity, ButtonEntity): | ||||
|     async def async_press(self) -> None: | ||||
|         await self._device.commands[self.entity_description.key].send() | ||||
|  | ||||
|     @property | ||||
|     def available(self) -> bool: | ||||
|         """Return True if entity is available.""" | ||||
|         return super().available and self._device.get("remoteCtrValid") == "1" | ||||
|  | ||||
|  | ||||
| class HonFeatureRequestButton(HonEntity, ButtonEntity): | ||||
|     def __init__(self, hass, coordinator, entry, device: HonAppliance) -> None: | ||||
| @ -78,5 +83,5 @@ class HonFeatureRequestButton(HonEntity, ButtonEntity): | ||||
|  | ||||
|     async def async_press(self) -> None: | ||||
|         pyhon_version = pkg_resources.get_distribution("pyhon").version | ||||
|         info = f"Device Info:\n{self._device.diagnose}pyhOnVersion: {pyhon_version}" | ||||
|         info = f"Device Info:\n{self._device.diagnose()}pyhOnVersion: {pyhon_version}" | ||||
|         _LOGGER.error(info) | ||||
|  | ||||
| @ -29,7 +29,7 @@ from .hon import HonEntity, HonCoordinator | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| CLIMATES = { | ||||
|     "AC": (ClimateEntityDescription(key="startProgram"),), | ||||
|     "AC": (ClimateEntityDescription(key="startProgram", icon="mdi:air-conditioner"),), | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -47,7 +47,7 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non | ||||
|  | ||||
|         if descriptions := CLIMATES.get(device.appliance_type): | ||||
|             for description in descriptions: | ||||
|                 if description.key not in device.available_settings: | ||||
|                 if description.key not in list(device.commands): | ||||
|                     continue | ||||
|                 appliances.extend( | ||||
|                     [HonClimateEntity(hass, coordinator, entry, device, description)] | ||||
| @ -61,21 +61,21 @@ class HonClimateEntity(HonEntity, ClimateEntity): | ||||
|     ) -> None: | ||||
|         super().__init__(hass, entry, coordinator, device) | ||||
|         self._coordinator = coordinator | ||||
|         self._device = coordinator.device | ||||
|         self._device = device | ||||
|         self.entity_description = description | ||||
|         self._hass = hass | ||||
|         self._attr_unique_id = f"{super().unique_id}climate" | ||||
|  | ||||
|         self._attr_temperature_unit = TEMP_CELSIUS | ||||
|         self._attr_target_temperature_step = PRECISION_WHOLE | ||||
|         self._attr_max_temp = device.settings["tempSel"].max | ||||
|         self._attr_min_temp = device.settings["tempSel"].min | ||||
|         self._attr_max_temp = device.settings["settings.tempSel"].max | ||||
|         self._attr_min_temp = device.settings["settings.tempSel"].min | ||||
|  | ||||
|         self._attr_hvac_modes = [HVACMode.OFF] + [ | ||||
|             HON_HVAC_MODE[mode] for mode in device.settings["machMode"].values | ||||
|             HON_HVAC_MODE[mode] for mode in device.settings["settings.machMode"].values | ||||
|         ] | ||||
|         self._attr_fan_modes = [FAN_OFF] + [ | ||||
|             HON_FAN[mode] for mode in device.settings["windSpeed"].values | ||||
|             HON_FAN[mode] for mode in device.settings["settings.windSpeed"].values | ||||
|         ] | ||||
|         self._attr_swing_modes = [ | ||||
|             SWING_OFF, | ||||
| @ -89,22 +89,28 @@ class HonClimateEntity(HonEntity, ClimateEntity): | ||||
|             | ClimateEntityFeature.SWING_MODE | ||||
|         ) | ||||
|  | ||||
|         self._handle_coordinator_update() | ||||
|  | ||||
|     async def async_set_hvac_mode(self, hvac_mode): | ||||
|         if hvac_mode == HVACMode.OFF: | ||||
|             self._device.commands["stopProgram"].send() | ||||
|             await self._device.commands["stopProgram"].send() | ||||
|         else: | ||||
|             self._device.settings["program"].value = HON_HVAC_PROGRAM[hvac_mode] | ||||
|             self._device.commands["startProgram"].send() | ||||
|             self._device.settings["startProgram.program"].value = HON_HVAC_PROGRAM[ | ||||
|                 hvac_mode | ||||
|             ] | ||||
|             await self._device.commands["startProgram"].send() | ||||
|         self._attr_hvac_mode = hvac_mode | ||||
|  | ||||
|     async def async_set_fan_mode(self, fan_mode): | ||||
|         mode_number = list(HON_FAN.values()).index(fan_mode) | ||||
|         self._device.settings["windSpeed"].value = list(HON_FAN.keys())[mode_number] | ||||
|         self._device.commands["startProgram"].send() | ||||
|         self._device.settings["settings.windSpeed"].value = list(HON_FAN.keys())[ | ||||
|             mode_number | ||||
|         ] | ||||
|         await self._device.commands["settings"].send() | ||||
|  | ||||
|     async def async_set_swing_mode(self, swing_mode): | ||||
|         horizontal = self._device.settings["windDirectionHorizontal"] | ||||
|         vertical = self._device.settings["windDirectionVertical"] | ||||
|         horizontal = self._device.settings["settings.windDirectionHorizontal"] | ||||
|         vertical = self._device.settings["settings.windDirectionVertical"] | ||||
|         if swing_mode in [SWING_BOTH, SWING_HORIZONTAL]: | ||||
|             horizontal.value = "7" | ||||
|         if swing_mode in [SWING_BOTH, SWING_VERTICAL]: | ||||
| @ -114,30 +120,30 @@ class HonClimateEntity(HonEntity, ClimateEntity): | ||||
|         if swing_mode in [SWING_OFF, SWING_VERTICAL] and horizontal.value == "7": | ||||
|             horizontal.value = "0" | ||||
|         self._attr_swing_mode = swing_mode | ||||
|         self._device.commands["startProgram"].send() | ||||
|         await self._device.commands["settings"].send() | ||||
|  | ||||
|     async def async_set_temperature(self, **kwargs): | ||||
|         if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None: | ||||
|             return False | ||||
|         self._device.settings["selTemp"].value = temperature | ||||
|         self._device.commands["startProgram"].send() | ||||
|         self._device.settings["settings.selTemp"].value = temperature | ||||
|         await self._device.commands["settings"].send() | ||||
|  | ||||
|     @callback | ||||
|     def _handle_coordinator_update(self, update=True) -> None: | ||||
|         self._attr_target_temperature = int(float(self._device.get("tempSel"))) | ||||
|         self._attr_current_temperature = float(self._device.get("tempIndoor")) | ||||
|         self._attr_max_temp = self._device.settings["tempSel"].max | ||||
|         self._attr_min_temp = self._device.settings["tempSel"].min | ||||
|         self._attr_max_temp = self._device.settings["settings.tempSel"].max | ||||
|         self._attr_min_temp = self._device.settings["settings.tempSel"].min | ||||
|  | ||||
|         if self._device.get("onOffStatus") == "0": | ||||
|             self._attr_hvac_mode = HVACMode.OFF | ||||
|         else: | ||||
|             self._attr_hvac_mode = HON_HVAC_MODE[self._device.get("machMode")] | ||||
|             self._attr_hvac_mode = HON_HVAC_MODE[self._device.get("machMode") or "0"] | ||||
|  | ||||
|         self._attr_fan_mode = HON_FAN[self._device.settings["windSpeed"].value] | ||||
|         self._attr_fan_mode = HON_FAN[self._device.settings["settings.windSpeed"].value] | ||||
|  | ||||
|         horizontal = self._device.settings["windDirectionHorizontal"] | ||||
|         vertical = self._device.settings["windDirectionVertical"] | ||||
|         horizontal = self._device.settings["settings.windDirectionHorizontal"] | ||||
|         vertical = self._device.settings["settings.windDirectionVertical"] | ||||
|         if horizontal == "7" and vertical == "8": | ||||
|             self._attr_swing_mode = SWING_BOTH | ||||
|         elif horizontal == "7": | ||||
|  | ||||
| @ -120,6 +120,19 @@ TUMBLE_DRYER_PR_PHASE = { | ||||
|     "19": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE", | ||||
|     "20": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE", | ||||
| } | ||||
| DIRTY_LEVEL = { | ||||
|     "1": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.LITTLE", | ||||
|     "2": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.NORMAL", | ||||
|     "3": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.VERY", | ||||
| } | ||||
|  | ||||
| STEAM_LEVEL = { | ||||
|     "0": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.NO_STEAM", | ||||
|     "1": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.COTTON_TITLE", | ||||
|     "2": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.DELICATE_TITLE", | ||||
|     "3": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.SYNTHETIC_TITLE", | ||||
| } | ||||
|  | ||||
| DISHWASHER_PR_PHASE = { | ||||
|     "0": "WASHING_CMD&CTRL.PHASE_READY.TITLE", | ||||
|     "1": "WASHING_CMD&CTRL.PHASE_PREWASH.TITLE", | ||||
|  | ||||
| @ -50,3 +50,12 @@ class HonCoordinator(DataUpdateCoordinator): | ||||
|  | ||||
|     async def _async_update_data(self): | ||||
|         await self._device.update() | ||||
|  | ||||
|  | ||||
| def unique_entities(base_entities, new_entities): | ||||
|     result = list(base_entities) | ||||
|     existing_entities = [entity.key for entity in base_entities] | ||||
|     for entity in new_entities: | ||||
|         if entity.key not in existing_entities: | ||||
|             result.append(entity) | ||||
|     return tuple(result) | ||||
|  | ||||
| @ -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.10.3"], | ||||
|   "version": "0.7.0" | ||||
|  "requirements": ["pyhOn==0.10.6"], | ||||
|   "version": "0.7.3" | ||||
| } | ||||
|  | ||||
| @ -15,7 +15,7 @@ from homeassistant.core import callback | ||||
| from homeassistant.helpers.entity import EntityCategory | ||||
|  | ||||
| from .const import DOMAIN | ||||
| from .hon import HonEntity, HonCoordinator | ||||
| from .hon import HonEntity, HonCoordinator, unique_entities | ||||
|  | ||||
| NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = { | ||||
|     "WM": ( | ||||
| @ -85,16 +85,6 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = { | ||||
|             translation_key="dry_time", | ||||
|         ), | ||||
|     ), | ||||
|     "WD": ( | ||||
|         NumberEntityDescription( | ||||
|             key="startProgram.delayTime", | ||||
|             name="Delay Time", | ||||
|             icon="mdi:timer-plus", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             native_unit_of_measurement=UnitOfTime.MINUTES, | ||||
|             translation_key="delay_time", | ||||
|         ), | ||||
|     ), | ||||
|     "OV": ( | ||||
|         NumberEntityDescription( | ||||
|             key="startProgram.delayTime", | ||||
| @ -156,7 +146,7 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = { | ||||
|     ), | ||||
|     "AC": ( | ||||
|         NumberEntityDescription( | ||||
|             key="startProgram.tempSel", | ||||
|             key="settings.tempSel", | ||||
|             name="Target Temperature", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             icon="mdi:thermometer", | ||||
| @ -166,6 +156,8 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = { | ||||
|     ), | ||||
| } | ||||
|  | ||||
| NUMBERS["WD"] = unique_entities(NUMBERS["WM"], NUMBERS["TD"]) | ||||
|  | ||||
|  | ||||
| async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None: | ||||
|     hon: Hon = hass.data[DOMAIN][entry.unique_id] | ||||
|  | ||||
| @ -14,7 +14,7 @@ from homeassistant.core import callback | ||||
| from homeassistant.helpers.entity import EntityCategory | ||||
|  | ||||
| from .const import DOMAIN | ||||
| from .hon import HonEntity, HonCoordinator | ||||
| from .hon import HonEntity, HonCoordinator, unique_entities | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| @ -66,14 +66,6 @@ SELECTS = { | ||||
|             translation_key="dry_levels", | ||||
|         ), | ||||
|     ), | ||||
|     "WD": ( | ||||
|         SelectEntityDescription( | ||||
|             key="startProgram.program", | ||||
|             name="Program", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="programs_wm", | ||||
|         ), | ||||
|     ), | ||||
|     "OV": ( | ||||
|         SelectEntityDescription( | ||||
|             key="startProgram.program", | ||||
| @ -106,14 +98,17 @@ SELECTS = { | ||||
|             translation_key="programs_ac", | ||||
|         ), | ||||
|         SelectEntityDescription( | ||||
|             key="startProgram.humanSensingStatus", | ||||
|             key="settings.humanSensingStatus", | ||||
|             name="Eco Pilot", | ||||
|             icon="mdi:run", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="eco_pilot", | ||||
|         ), | ||||
|     ), | ||||
| } | ||||
|  | ||||
| SELECTS["WD"] = unique_entities(SELECTS["WM"], SELECTS["TD"]) | ||||
|  | ||||
|  | ||||
| async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None: | ||||
|     hon: Hon = hass.data[DOMAIN][entry.unique_id] | ||||
|  | ||||
| @ -25,7 +25,7 @@ from homeassistant.const import PERCENTAGE | ||||
|  | ||||
| from . import const | ||||
| from .const import DOMAIN | ||||
| from .hon import HonCoordinator, HonEntity | ||||
| from .hon import HonCoordinator, HonEntity, unique_entities | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| @ -112,7 +112,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { | ||||
|             name="Spin Speed", | ||||
|             icon="mdi:speedometer", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             native_unit_of_measurement=UnitOfTime.MINUTES, | ||||
|             native_unit_of_measurement=REVOLUTIONS_PER_MINUTE, | ||||
|             translation_key="spin_speed", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
| @ -161,6 +161,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { | ||||
|             native_unit_of_measurement=UnitOfMass.KILOGRAMS, | ||||
|             translation_key="suggested_load", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="temp", | ||||
|             name="Current Temperature", | ||||
|             icon="mdi:thermometer", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             native_unit_of_measurement=UnitOfTemperature.CELSIUS, | ||||
|             translation_key="temperature", | ||||
|         ), | ||||
|     ), | ||||
|     "TD": ( | ||||
|         SensorEntityDescription( | ||||
| @ -238,12 +246,18 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { | ||||
|             translation_key="energy_label", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="steamLevel", | ||||
|             key="startProgram.steamLevel", | ||||
|             name="Steam level", | ||||
|             icon="mdi:smoke", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="steam_level", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="steamLevel", | ||||
|             name="Steam level", | ||||
|             icon="mdi:smoke", | ||||
|             translation_key="steam_level", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="steamType", | ||||
|             name="Steam Type", | ||||
| @ -251,120 +265,6 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|         ), | ||||
|     ), | ||||
|     "WD": ( | ||||
|         SensorEntityDescription( | ||||
|             key="totalElectricityUsed", | ||||
|             name="Total Power", | ||||
|             device_class=SensorDeviceClass.ENERGY, | ||||
|             state_class=SensorStateClass.TOTAL_INCREASING, | ||||
|             native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, | ||||
|             translation_key="energy_total", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="totalWaterUsed", | ||||
|             name="Total Water", | ||||
|             device_class=SensorDeviceClass.WATER, | ||||
|             state_class=SensorStateClass.TOTAL_INCREASING, | ||||
|             native_unit_of_measurement=UnitOfVolume.LITERS, | ||||
|             translation_key="water_total", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="totalWashCycle", | ||||
|             name="Total Wash Cycle", | ||||
|             state_class=SensorStateClass.TOTAL_INCREASING, | ||||
|             icon="mdi:counter", | ||||
|             translation_key="cycles_total", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="currentElectricityUsed", | ||||
|             name="Current Electricity Used", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             device_class=SensorDeviceClass.POWER, | ||||
|             native_unit_of_measurement=UnitOfPower.KILO_WATT, | ||||
|             icon="mdi:lightning-bolt", | ||||
|             translation_key="energy_current", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="currentWaterUsed", | ||||
|             name="Current Water Used", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             icon="mdi:water", | ||||
|             translation_key="water_current", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="startProgram.weight", | ||||
|             name="Suggested weight", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             native_unit_of_measurement=UnitOfMass.KILOGRAMS, | ||||
|             icon="mdi:weight-kilogram", | ||||
|             translation_key="suggested_load", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="machMode", | ||||
|             name="Machine Status", | ||||
|             icon="mdi:information", | ||||
|             device_class=SensorDeviceClass.ENUM, | ||||
|             translation_key="washing_modes", | ||||
|             options=list(const.MACH_MODE), | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="spinSpeed", | ||||
|             name="Spin Speed", | ||||
|             icon="mdi:fast-forward-outline", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             native_unit_of_measurement=REVOLUTIONS_PER_MINUTE, | ||||
|             translation_key="spin_speed", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="remainingTimeMM", | ||||
|             name="Remaining Time", | ||||
|             icon="mdi:timer", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             native_unit_of_measurement=UnitOfTime.MINUTES, | ||||
|             translation_key="remaining_time", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="prCode", | ||||
|             name="Current Program", | ||||
|             icon="mdi:tumble-dryer", | ||||
|             translation_key="programs", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="prPhase", | ||||
|             name="Program Phase", | ||||
|             icon="mdi:washing-machine", | ||||
|             device_class=SensorDeviceClass.ENUM, | ||||
|             translation_key="program_phases_wm", | ||||
|             options=list(const.WASHING_PR_PHASE), | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="dryLevel", | ||||
|             name="Dry level", | ||||
|             icon="mdi:hair-dryer", | ||||
|             translation_key="dry_levels", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="dirtyLevel", | ||||
|             name="Dirt level", | ||||
|             icon="mdi:liquid-spot", | ||||
|             translation_key="dirt_level", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="steamLevel", | ||||
|             name="Steam level", | ||||
|             icon="mdi:smoke", | ||||
|             translation_key="steam_level", | ||||
|         ), | ||||
|         SensorEntityDescription( | ||||
|             key="temp", | ||||
|             name="Current Temperature", | ||||
|             icon="mdi:thermometer", | ||||
|             state_class=SensorStateClass.MEASUREMENT, | ||||
|             native_unit_of_measurement=UnitOfTemperature.CELSIUS, | ||||
|             translation_key="temperature", | ||||
|         ), | ||||
|     ), | ||||
|     "OV": ( | ||||
|         SensorEntityDescription( | ||||
|             key="remainingTimeMM", | ||||
| @ -501,6 +401,7 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { | ||||
|         ), | ||||
|     ), | ||||
| } | ||||
| SENSORS["WD"] = unique_entities(SENSORS["WM"], SENSORS["TD"]) | ||||
|  | ||||
|  | ||||
| async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None: | ||||
|  | ||||
| @ -10,7 +10,7 @@ from pyhon.appliance import HonAppliance | ||||
| from pyhon.parameter.range import HonParameterRange | ||||
|  | ||||
| from .const import DOMAIN | ||||
| from .hon import HonCoordinator, HonEntity | ||||
| from .hon import HonCoordinator, HonEntity, unique_entities | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| @ -82,28 +82,28 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = { | ||||
|             translation_key="acqua_plus", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="extraRinse1", | ||||
|             key="startProgram.extraRinse1", | ||||
|             name="Extra Rinse 1", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             icon="mdi:numeric-1-box-multiple-outline", | ||||
|             translation_key="extra_rinse_1", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="extraRinse2", | ||||
|             key="startProgram.extraRinse2", | ||||
|             name="Extra Rinse 2", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             icon="mdi:numeric-2-box-multiple-outline", | ||||
|             translation_key="extra_rinse_2", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="extraRinse3", | ||||
|             key="startProgram.extraRinse3", | ||||
|             name="Extra Rinse 3", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             icon="mdi:numeric-3-box-multiple-outline", | ||||
|             translation_key="extra_rinse_3", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="goodNight", | ||||
|             key="startProgram.goodNight", | ||||
|             name="Good Night", | ||||
|             icon="mdi:weather-night", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
| @ -168,7 +168,7 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = { | ||||
|     "WD": ( | ||||
|         HonSwitchEntityDescription( | ||||
|             key="active", | ||||
|             name="Washing Machine", | ||||
|             name="Washer Dryer", | ||||
|             icon="mdi:washing-machine", | ||||
|             turn_on_key="startProgram", | ||||
|             turn_off_key="stopProgram", | ||||
| @ -176,7 +176,7 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = { | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="pause", | ||||
|             name="Pause Washing Machine", | ||||
|             name="Pause Washer Dryer", | ||||
|             icon="mdi:pause", | ||||
|             turn_on_key="pauseProgram", | ||||
|             turn_off_key="resumeProgram", | ||||
| @ -237,65 +237,77 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = { | ||||
|     ), | ||||
|     "AC": ( | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.10degreeHeatingStatus", | ||||
|             key="settings.10degreeHeatingStatus", | ||||
|             name="10° Heating", | ||||
|             icon="mdi:heat-wave", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="10_degree_heating", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.echoStatus", | ||||
|             key="settings.echoStatus", | ||||
|             name="Echo", | ||||
|             icon="mdi:account-voice", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.ecoMode", | ||||
|             key="settings.ecoMode", | ||||
|             name="Eco Mode", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="eco_mode", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.healthMode", | ||||
|             key="settings.healthMode", | ||||
|             name="Health Mode", | ||||
|             icon="mdi:medication-outline", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.muteStatus", | ||||
|             key="settings.muteStatus", | ||||
|             name="Mute", | ||||
|             icon="mdi:volume-off", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="mute_mode", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.rapidMode", | ||||
|             key="settings.rapidMode", | ||||
|             name="Rapid Mode", | ||||
|             icon="mdi:run-fast", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="rapid_mode", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.screenDisplayStatus", | ||||
|             key="settings.screenDisplayStatus", | ||||
|             name="Screen Display", | ||||
|             icon="mdi:monitor-small", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.selfCleaning56Status", | ||||
|             key="settings.selfCleaning56Status", | ||||
|             name="Self Cleaning 56", | ||||
|             icon="mdi:air-filter", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="self_clean_56", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.selfCleaningStatus", | ||||
|             key="settings.selfCleaningStatus", | ||||
|             name="Self Cleaning", | ||||
|             icon="mdi:air-filter", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="self_clean", | ||||
|         ), | ||||
|         HonSwitchEntityDescription( | ||||
|             key="startProgram.silentSleepStatus", | ||||
|             key="settings.silentSleepStatus", | ||||
|             name="Silent Sleep", | ||||
|             icon="mdi:bed", | ||||
|             entity_category=EntityCategory.CONFIG, | ||||
|             translation_key="silent_mode", | ||||
|         ), | ||||
|     ), | ||||
| } | ||||
|  | ||||
| SWITCHES["WD"] = unique_entities(SWITCHES["WD"], SWITCHES["WM"]) | ||||
| SWITCHES["WD"] = unique_entities(SWITCHES["WD"], SWITCHES["TD"]) | ||||
|  | ||||
|  | ||||
| async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None: | ||||
|     hon: Hon = hass.data[DOMAIN][entry.unique_id] | ||||
| @ -311,10 +323,18 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non | ||||
|  | ||||
|         if descriptions := SWITCHES.get(device.appliance_type): | ||||
|             for description in descriptions: | ||||
|                 if ( | ||||
|                     device.get(description.key) is not None | ||||
|                     or description.key in device.available_settings | ||||
|                 if description.entity_category == EntityCategory.CONFIG: | ||||
|                     if description.key not in device.available_settings: | ||||
|                         continue | ||||
|                 else: | ||||
|                     if not any( | ||||
|                         [ | ||||
|                             device.get(description.key) is not None, | ||||
|                             description.turn_on_key in list(device.commands), | ||||
|                             description.turn_off_key in list(device.commands), | ||||
|                         ] | ||||
|                     ): | ||||
|                         continue | ||||
|                 appliances.extend( | ||||
|                     [HonSwitchEntity(hass, coordinator, entry, device, description)] | ||||
|                 ) | ||||
| @ -376,3 +396,11 @@ class HonSwitchEntity(HonEntity, SwitchEntity): | ||||
|             await self.coordinator.async_refresh() | ||||
|         else: | ||||
|             await self._device.commands[self.entity_description.turn_off_key].send() | ||||
|  | ||||
|     @property | ||||
|     def available(self) -> bool: | ||||
|         """Return True if entity is available.""" | ||||
|         if self.entity_category == EntityCategory.CONFIG: | ||||
|             return super().available | ||||
|         else: | ||||
|             return super().available and self._device.get("remoteCtrValid") == "1" | ||||
|  | ||||
							
								
								
									
										24
									
								
								info.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								info.md
									
									
									
									
									
								
							| @ -13,12 +13,6 @@ Support for home appliances of Haier's mobile app hOn. | ||||
| - [Dish Washer](https://github.com/Andre0512/hon#dish-washer) | ||||
| - [Air conditioner](https://github.com/Andre0512/hon#air-conditioner) [BETA] | ||||
|  | ||||
| ## Tested Appliances | ||||
| - Haier WD90-B14TEAM5 | ||||
| - Haier HD80-A3959 | ||||
| - Haier HWO60SM2F3XH | ||||
| - Hoover H-WASH 500 | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
| **Method 1**: [](https://my.home-assistant.io/redirect/config_flow_start/?domain=hon) | ||||
| @ -26,9 +20,16 @@ Support for home appliances of Haier's mobile app hOn. | ||||
| **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 | ||||
| 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! | ||||
| ## Supported Models | ||||
| Support was confirmed for these models. If a supported model is missing, please [add it with this form](https://forms.gle/bTSD8qFotdZFytbf8). | ||||
| - Haier WD90-B14TEAM5 | ||||
| - Haier HD80-A3959 | ||||
| - Haier HWO60SM2F3XH | ||||
| - Hoover H-WASH 500 | ||||
| - Candy CIS633SCTTWIFI | ||||
| - Haier XIB 3B2SFS-80 | ||||
| - Haier XIB 6B2D3FB | ||||
| - Hoover HSOT3161WG | ||||
|  | ||||
| ## Supported Languages | ||||
| Translation of internal names like programs are available for all languages which are official supported by the hOn app: | ||||
| @ -52,10 +53,13 @@ Translation of internal names like programs are available for all languages whic | ||||
| * 🇪🇸 Spanish | ||||
| * 🇹🇷 Turkish | ||||
|  | ||||
| ## Contribute | ||||
| 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) | ||||
|  | ||||
|  | ||||
| @ -3,10 +3,14 @@ | ||||
| import asyncio | ||||
| import json | ||||
| import re | ||||
| import sys | ||||
| from pathlib import Path | ||||
|  | ||||
| from pyhon import HonAPI | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     sys.path.insert(0, str(Path(__file__).parent.parent)) | ||||
|  | ||||
| from custom_components.hon import const | ||||
|  | ||||
| SENSOR = { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	