Skip to content

Commit 9e08690

Browse files
committed
simplification
1 parent c53ab53 commit 9e08690

10 files changed

Lines changed: 103 additions & 273 deletions

File tree

README.md

Lines changed: 3 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Filuvdata%2Fgoogle_nest_fan%2Frefs%2Fheads%2Fmain%2Fcustom_components%2Fgoogle_nest_fan%2Fmanifest.json&query=%24.version&prefix=v&label=dev-version&labelColor=orange)
77

88

9-
A custom HomeAssistant integration that creates an additional entities for each Google Device with a Fan "trait" such as a Nest Thermostat. This entity will track when the fan will shut off "In 2 hours 4 minutes" (rather than the 12 hours hard coded into the core [Google Nest](https://www.home-assistant.io/integrations/nest/) integration.
9+
A custom HomeAssistant integration that creates an additional entity for each Google Device with a Fan "trait" such as a Nest Thermostat. This entity will track when the fan will shut off "In 2 hours 4 minutes" (rather than the 12 hours hard coded into the core [Google Nest](https://www.home-assistant.io/integrations/nest/) integration.
1010

1111
A service `google_nest_fan.run_fan` will also be created as an action to run fans for a custom duration.
1212

13-
A cooresponding number (slider) entity will also be created and will allow you to select the duration you want to start and run your thermostat's fan.
1413

1514
The core Google Nest Integration must be configured and working for this integration to work.
1615

@@ -33,66 +32,6 @@ If the core **Google Nest** integration is configured this integration should be
3332

3433
## Use
3534

36-
Simple use the slider to select the amount of time you want to run the fan. Upon changing the slider, it should send the request to the device to start the fan for the given duration. To stop the fan, simply turn off through the core integration. If you update the slider, it should change the duration to the most recent selected value.
37-
38-
### UI Customization
39-
40-
You can add a custom feature to your thermostat card using the [`Nerwyn/custom-card-features`](https://github.com/Nerwyn/custom-card-features) HACS dashboard integration.
41-
42-
[![My Home Assistant](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?repository=custom-card-features&owner=Nerwyn&category=Plugin)
43-
44-
You can then use a similar configuration to create a custom thermostat card:
45-
46-
<img src="https://raw.githubusercontent.com/iluvdata/google_nest_fan/main/assets/thermostat_card.png" width="600"/>
47-
48-
<details>
49-
<summary style="font-weight: bold;">Config for custom thermostat card</summary>
50-
51-
```yaml
52-
type: thermostat
53-
entity: climate.cottage
54-
show_current_as_primary: false
55-
features:
56-
- type: climate-hvac-modes
57-
- style: icons
58-
type: climate-preset-modes
59-
- type: custom:service-call
60-
entries:
61-
- type: slider
62-
entity_id: number.cottage_fan_run_duration
63-
tap_action:
64-
action: perform-action
65-
target:
66-
entity_id: number.cottage_fan_run_duration
67-
perform_action: number.set_value
68-
data:
69-
value: "{{ value }}"
70-
confirmation: false
71-
range:
72-
- 0
73-
- 15
74-
step: 0.25
75-
value_from_hass_delay: 0
76-
haptics: true
77-
autofill_entity_id: true
78-
label: >-
79-
{{ iif(state_attr("climate.cottage", "fan_mode") === "on" and value >
80-
0, "Running Fan " + (value | round(0, "floor") ) + "h" + ((value %
81-
1)*60) + "m", iif(state_attr("climate.cottage", "fan_mode") === "off"
82-
and value > 0, "Waiting to Start " + (value | round(0, "floor") ) +
83-
"h" + ((value % 1)*60) + "m", iif(state_attr("climate.cottage",
84-
"fan_mode") === "on" and value === 0,"Waiting to Stop", "Start Fan")))
85-
}}
86-
styles: |-
87-
:host{
88-
{{ "--color: rgb(0, 154, 199);" if state_attr("climate.cottage", "fan_mode") === "on" }}
89-
}
90-
icon: >-
91-
{{ iif(state_attr("climate.cottage", "fan_mode") === "on" and value >
92-
0, "mdi:fan", "mdi:fan-off") }}
93-
thumb: default
94-
styles: ""
95-
96-
```
97-
</details>
35+
To activate the fan use the service. To stop the fan, simply turn off through the core integration. The sensor should display the stop time.
36+
9837

assets/thermostat_card.png

-23.4 KB
Binary file not shown.

custom_components/google_nest_fan/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
from typing import cast
77

88
from google_nest_sdm.device import Device
9+
from google_nest_sdm.exceptions import ApiException
910

1011
# pylint: disable=hass-component-root-import
11-
from homeassistant.components.nest import ApiException, NestConfigEntry
12+
from homeassistant.components.nest import NestConfigEntry
1213
from homeassistant.components.nest.climate import FanTrait, ThermostatHvacTrait
1314
from homeassistant.components.nest.const import DOMAIN as NEST_DOMAIN
1415
from homeassistant.config_entries import ConfigEntry
@@ -106,8 +107,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: GoogleNestFan) -> bool:
106107
)
107108
):
108109
raise ConfigEntryError(
109-
translation_domain=DOMAIN, translation_key="nest_not_loaded"
110+
translation_domain=DOMAIN,
111+
translation_key="nest_not_loaded",
110112
)
113+
111114
for nestentry in entries:
112115
for device in nestentry.runtime_data.device_manager.devices.values():
113116
if ThermostatHvacTrait.NAME in device.traits:
@@ -117,7 +120,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: GoogleNestFan) -> bool:
117120
raise ConfigEntryError(
118121
translation_domain=DOMAIN, translation_key="no_thermostats"
119122
)
120-
entry.runtime_data = GoogleNestFanData(devices)
123+
124+
entry.runtime_data = GoogleNestFanData(devices=devices)
121125

122126
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
123127

custom_components/google_nest_fan/config_flow.py

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,72 @@
33
from __future__ import annotations
44

55
import logging
6-
from typing import Any
76

7+
# from typing import Any
88
from google_nest_sdm.device import Device
99

1010
# pylint: disable=hass-component-root-import
1111
from homeassistant.components.nest.climate import ThermostatHvacTrait
1212
from homeassistant.components.nest.const import DOMAIN as NEST_DOMAIN
1313
from homeassistant.components.nest.types import NestConfigEntry
1414

15-
# pylint: enable=hass-component-root-import
16-
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
15+
# from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
16+
from homeassistant.core import HomeAssistant
17+
from homeassistant.helpers import config_entry_flow
1718

1819
from .const import DOMAIN
1920

2021
_LOGGER = logging.getLogger(__name__)
2122

2223

23-
class GoogleNestFanFlow(ConfigFlow, domain=DOMAIN):
24-
"""Google Nest Fan Flow."""
25-
26-
async def async_step_user(
27-
self, user_input: dict[str, Any] | None = None
28-
) -> ConfigFlowResult:
29-
"""Add the integration."""
30-
error: str = ""
31-
entries: list[NestConfigEntry] = self.hass.config_entries.async_loaded_entries(
32-
NEST_DOMAIN
24+
def _async_has_configured_thermostats(hass: HomeAssistant) -> bool:
25+
entries: list[NestConfigEntry] = hass.config_entries.async_loaded_entries(
26+
NEST_DOMAIN
27+
)
28+
if not entries:
29+
return False
30+
devices: list[Device] = []
31+
for entry in entries:
32+
devices.extend(
33+
device
34+
for device in entry.runtime_data.device_manager.devices.values()
35+
if ThermostatHvacTrait.NAME in device.traits
3336
)
34-
if not entries:
35-
error = "nest_not_loaded"
36-
else:
37-
devices: list[Device] = []
38-
for entry in entries:
39-
devices.extend(
40-
device
41-
for device in entry.runtime_data.device_manager.devices.values()
42-
if ThermostatHvacTrait.NAME in device.traits
43-
)
44-
if not devices:
45-
error = "no_thermostats"
46-
if not error:
47-
return self.async_create_entry(
48-
title="Google Nest Fan Customization",
49-
description="Will create entries for all Nest fans",
50-
data={},
51-
)
52-
return self.async_abort(reason=error)
37+
return len(devices) > 0
38+
39+
40+
config_entry_flow.register_discovery_flow(
41+
DOMAIN, "Google Nest Fan", _async_has_configured_thermostats
42+
)
43+
44+
45+
# class GoogleNestFanFlow(ConfigFlow, domain=DOMAIN):
46+
# """Google Nest Fan Flow."""
47+
48+
# async def async_step_user(
49+
# self, user_input: dict[str, Any] | None = None
50+
# ) -> ConfigFlowResult:
51+
# """Add the integration."""
52+
# error: str = ""
53+
# entries: list[NestConfigEntry] = self.hass.config_entries.async_loaded_entries(
54+
# NEST_DOMAIN
55+
# )
56+
# if not entries:
57+
# error = "nest_not_loaded"
58+
# else:
59+
# devices: list[Device] = []
60+
# for entry in entries:
61+
# devices.extend(
62+
# device
63+
# for device in entry.runtime_data.device_manager.devices.values()
64+
# if ThermostatHvacTrait.NAME in device.traits
65+
# )
66+
# if not devices:
67+
# error = "no_thermostats"
68+
# if not error:
69+
# return self.async_create_entry(
70+
# title="Google Nest Fan Customization",
71+
# description="Will create entries for all Nest fans",
72+
# data={},
73+
# )
74+
# return self.async_abort(reason=error)

custom_components/google_nest_fan/const.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@
99
import homeassistant.helpers.config_validation as cv
1010

1111
DOMAIN = "google_nest_fan"
12-
PLATFORMS = {Platform.SENSOR, Platform.NUMBER}
12+
PLATFORMS = {Platform.SENSOR}
1313

14-
SCAN_INTERVAL = timedelta(minutes=1)
14+
# SCAN_INTERVAL = timedelta(minutes=1)
1515

1616
FAN_SERVICE_DURATION = "duration"
1717

1818
FAN_SERVICE = "run_fan"
1919

2020
MAX_RUN_TIME: Final[timedelta] = timedelta(hours=15)
2121

22-
RUN_TIME_DEBOUNCE: Final[timedelta] = timedelta(seconds=2)
22+
# RUN_TIME_DEBOUNCE: Final[timedelta] = timedelta(seconds=2)
2323

2424
FAN_SERVICE_SCHEMA = vol.Schema(
2525
vol.All(

custom_components/google_nest_fan/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"requirements": [],
1313
"ssdp": [],
1414
"zeroconf": [],
15-
"version": "2025.10.2",
16-
"integration_type": "helper",
15+
"version": "2025.10.3",
16+
"integration_type": "service",
1717
"issue_tracker": "https://github.com/iluvdata/google_nest_fan/issues"
1818
}

0 commit comments

Comments
 (0)