Skip to content

Commit fd58996

Browse files
committed
initial
0 parents  commit fd58996

14 files changed

Lines changed: 339 additions & 0 deletions

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Google Nest Fan
2+
3+
4+
[![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg?style=flat-square&logo=homeassistantcommunitystore)](https://hacs.xyz/)
5+
![GitHub Release](https://img.shields.io/github/v/release/iluvdata/google_nest_fan)
6+
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Filuvdata%2Fgoogle_nest_fan%2Frefs%2Ftags%2F2025.7.1%2Fcustom_components%2Ftplink_cloud%2Fmanifest.json&query=%24.version&prefix=v&label=dev-version)
7+
8+
9+
A custom HomeAssistant integration that creates two additional entities for each Google Device with a Fan "trait" such as a Nest Thermostat. These entities will allow you to set the fan to run for a customized amount of time (rather than the 12 hours hard coded into the core [Google Nest](https://www.home-assistant.io/integrations/nest/) integration. The core Google Nest Integration must be configured and working for this integration to work.
10+
11+
## Installation with HACS
12+
13+
The recommended way to install this is via HACS:
14+
15+
16+
17+
[![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/?category=custom_respository&owner=iluvdata&repository=google_nest_fan)
18+
19+
#### Semi-manual install
20+
21+
1. Click on HACS in the Homeassistant side bar
22+
2. Click on the three dots in the upper right-hand corner and select "Custom repositories."
23+
3. In the form enter:
24+
25+
1. Respository: `iluvdata/google_nest_fan`
26+
2. Select "Integration" as "Type"
27+
28+
## Manual Installation
29+
30+
Copy the `google_nest_fan` directory to the `custom_components` directory of your Homeassistant Instance.
31+
32+
## Configuration
33+
34+
35+
Add the intergration to Home Assistant:
36+
37+
[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=google_nest_fan)
38+
39+
If the core **Google Nest** integration is configured this integration should be able to discover your devices with fan and add the additional controls.
40+
41+
## Use
42+
43+
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.
44+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Setup Google Nest Fan Integration."""
2+
3+
from dataclasses import dataclass
4+
5+
from google_nest_sdm.device import Device
6+
7+
# pylint: disable=hass-component-root-import
8+
from homeassistant.components.nest.climate import ThermostatHvacTrait
9+
from homeassistant.components.nest.const import DOMAIN as NEST_DOMAIN
10+
from homeassistant.components.nest.types import NestConfigEntry
11+
12+
# pylint: enable=hass-component-root-import
13+
from homeassistant.config_entries import ConfigEntry
14+
from homeassistant.core import HomeAssistant
15+
from homeassistant.exceptions import ConfigEntryError
16+
17+
from .const import DOMAIN, PLATFORMS
18+
19+
20+
@dataclass
21+
class GoogleNestFanData:
22+
"""Class to hold integration data."""
23+
24+
devices: list[Device]
25+
26+
27+
type GoogleNestFan = ConfigEntry[GoogleNestFanData]
28+
29+
30+
async def async_setup_entry(hass: HomeAssistant, entry: GoogleNestFan) -> bool:
31+
"""Setup this config."""
32+
entries: list[NestConfigEntry] = hass.config_entries.async_loaded_entries(
33+
NEST_DOMAIN
34+
)
35+
if not entries:
36+
raise ConfigEntryError(
37+
translation_domain=DOMAIN, translation_key="nest_not_loaded"
38+
)
39+
devices: list[Device] = []
40+
for nestentry in entries:
41+
devices.extend(
42+
device
43+
for device in nestentry.runtime_data.device_manager.devices.values()
44+
if ThermostatHvacTrait.NAME in device.traits
45+
)
46+
if not devices:
47+
raise ConfigEntryError(
48+
translation_domain=DOMAIN, translation_key="no_thermostats"
49+
)
50+
entry.runtime_data = GoogleNestFanData(devices)
51+
52+
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
53+
54+
return True
Binary file not shown.
Binary file not shown.
391 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""Config flow for the TPLink Cloud integration."""
2+
3+
from __future__ import annotations
4+
5+
import logging
6+
from typing import Any
7+
8+
from google_nest_sdm.device import Device
9+
10+
# pylint: disable=hass-component-root-import
11+
from homeassistant.components.nest.climate import ThermostatHvacTrait
12+
from homeassistant.components.nest.const import DOMAIN as NEST_DOMAIN
13+
from homeassistant.components.nest.types import NestConfigEntry
14+
15+
# pylint: enable=hass-component-root-import
16+
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
17+
18+
from .const import DOMAIN
19+
20+
_LOGGER = logging.getLogger(__name__)
21+
22+
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
33+
)
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)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""Google Nest Fan Constants."""
2+
3+
from homeassistant.const import Platform
4+
5+
DOMAIN = "google_nest_fan"
6+
PLATFORMS = {Platform.NUMBER, Platform.SENSOR}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"domain": "google_nest_fan",
3+
"name": "Google Nest Fan Customization",
4+
"codeowners": ["@iluvdata"],
5+
"config_flow": true,
6+
"single_config_entry": true,
7+
"dependencies": ["nest"],
8+
"documentation": "https://github.com/iluvdata/google_nest_fan",
9+
"homekit": {},
10+
"iot_class": "cloud_push",
11+
"quality_scale": "bronze",
12+
"requirements": [],
13+
"ssdp": [],
14+
"zeroconf": [],
15+
"version": "2025.8.1",
16+
"integration_type": "service",
17+
"issue_tracker": "https://github.com/iluvdata/google_nest_fan/issues"
18+
}

0 commit comments

Comments
 (0)