Skip to content

Commit b19edfb

Browse files
authored
Merge pull request #15 from jscruz/fix-issues
Fix issues
2 parents 68d8d23 + 8e05eca commit b19edfb

6 files changed

Lines changed: 133 additions & 32 deletions

File tree

custom_components/carbon_intensity_uk/__init__.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,22 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
4141
_LOGGER.info(STARTUP_MESSAGE)
4242

4343
postcode = entry.data.get(CONF_POSTCODE)
44-
_LOGGER.debug("Postcode setup: %s" % postcode)
44+
_LOGGER.debug("Setting up Carbon Intensity UK for postcode: %s", postcode)
4545

4646
coordinator = CarbonIntensityDataUpdateCoordinator(hass, postcode=postcode)
47-
_LOGGER.debug("Coordinator refresh triggered")
47+
_LOGGER.debug("Performing initial data fetch for postcode: %s", postcode)
4848
await coordinator.async_refresh()
49-
_LOGGER.debug("Coordinator refresh completed")
5049

5150
if not coordinator.last_update_success:
51+
_LOGGER.warning(
52+
"Initial data fetch failed for postcode %s — will retry on next poll", postcode
53+
)
5254
raise ConfigEntryNotReady
5355

5456
hass.data[DOMAIN][entry.entry_id] = coordinator
5557

5658
platforms = [p for p in PLATFORMS if entry.options.get(p, True)]
59+
_LOGGER.debug("Forwarding entry setup to platforms: %s", platforms)
5760
coordinator.platforms.extend(platforms)
5861
await hass.config_entries.async_forward_entry_setups(entry, platforms)
5962

@@ -76,16 +79,24 @@ def __init__(self, hass, postcode):
7679
async def _async_update_data(self):
7780
"""Update data via library."""
7881
try:
79-
_LOGGER.debug("Coordinator update data async")
82+
_LOGGER.debug("Fetching data from Carbon Intensity API")
8083
data = await self.api.async_get_data()
81-
_LOGGER.debug("Coordinator update done")
82-
return data.get("data", {})
84+
result = data.get("data", {})
85+
_LOGGER.debug(
86+
"Data fetch succeeded: index=%s, forecast=%s gCO2/kWh",
87+
result.get("current_period_index"),
88+
result.get("current_period_forecast"),
89+
)
90+
return result
8391
except Exception as exception:
92+
_LOGGER.warning("Failed to fetch data from Carbon Intensity API: %s", exception)
8493
raise UpdateFailed(exception)
8594

8695

8796
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
8897
"""Handle removal of an entry."""
98+
postcode = entry.data.get(CONF_POSTCODE)
99+
_LOGGER.debug("Unloading Carbon Intensity UK entry for postcode: %s", postcode)
89100
coordinator = hass.data[DOMAIN][entry.entry_id]
90101
unloaded = all(
91102
await asyncio.gather(
@@ -98,11 +109,15 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
98109
)
99110
if unloaded:
100111
hass.data[DOMAIN].pop(entry.entry_id)
112+
_LOGGER.debug("Successfully unloaded Carbon Intensity UK entry for postcode: %s", postcode)
113+
else:
114+
_LOGGER.warning("Failed to unload one or more platforms for postcode: %s", postcode)
101115

102116
return unloaded
103117

104118

105119
async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry):
106120
"""Reload config entry."""
121+
_LOGGER.debug("Reloading Carbon Intensity UK entry for postcode: %s", entry.data.get(CONF_POSTCODE))
107122
await async_unload_entry(hass, entry)
108-
await async_setup_entry(hass, entry)
123+
await async_setup_entry(hass, entry)

custom_components/carbon_intensity_uk/config_flow.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ async def async_step_user(
3737
if user_input is not None:
3838
valid = await self._test_credentials(user_input[CONF_POSTCODE])
3939
if valid:
40-
_LOGGER.debug("Input is valid")
40+
_LOGGER.debug("Postcode %s validated, creating config entry", user_input[CONF_POSTCODE])
4141
return self.async_create_entry(
4242
title=user_input[CONF_POSTCODE], data=user_input
4343
)
4444
else:
45-
_LOGGER.debug("Input not valid")
45+
_LOGGER.warning("Postcode %s failed validation — check it is a valid UK postcode area", user_input[CONF_POSTCODE])
4646
self._errors["base"] = "auth"
4747

4848
return await self._show_config_form(user_input)
@@ -67,11 +67,10 @@ async def _test_credentials(self, postcode):
6767
try:
6868
client = CarbonIntentisityApi(postcode)
6969
await client.async_get_data()
70-
_LOGGER.debug("Input successfully")
70+
_LOGGER.debug("API connectivity test for postcode %s succeeded", postcode)
7171
return True
7272
except Exception as exception: # pylint: disable=broad-except
73-
_LOGGER.debug(exception)
74-
_LOGGER.debug("Oops! Input failed!")
73+
_LOGGER.warning("API connectivity test for postcode %s failed: %s", postcode, exception)
7574
return False
7675

7776

custom_components/carbon_intensity_uk/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
NAME = "Carbon Intensity UK"
44
DOMAIN = "carbon_intensity_uk"
55
DOMAIN_DATA = f"{DOMAIN}_data"
6-
VERSION = "0.0.3"
6+
VERSION = "1.0.1"
77

88
ISSUE_URL = "https://github.com/jscruz/sensor.carbon_intensity_uk/issues"
99

custom_components/carbon_intensity_uk/entity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ def unique_id(self):
2727
@property
2828
def device_info(self):
2929
return {
30-
"identifiers": {(DOMAIN, self.unique_id)},
30+
"identifiers": {(DOMAIN, self.config_entry.entry_id)},
3131
"name": NAME,
3232
"model": VERSION,
3333
"manufacturer": NAME,
3434
}
3535

3636
@property
37-
def device_state_attributes(self):
37+
def extra_state_attributes(self):
3838
"""Return the state attributes."""
3939
return self.coordinator.data
4040

custom_components/carbon_intensity_uk/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"iot_class": "cloud_polling",
99
"issue_tracker": "https://github.com/jscruz/sensor.carbon_intensity_uk/issues",
1010
"requirements": ["aiohttp", "numpy", "carbon_intensity_uk"],
11-
"version": "1.0.0"
11+
"version": "1.0.1"
1212
}
Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,131 @@
11
"""Sensor platform for carbon intensity UK."""
2+
import logging
3+
24
from custom_components.carbon_intensity_uk.const import (
35
DEFAULT_NAME,
46
DOMAIN,
57
ICON,
68
HIGH_ICON,
79
LOW_ICON,
810
MODERATE_ICON,
9-
SENSOR,
1011
)
1112
from custom_components.carbon_intensity_uk.entity import CarbonIntensityEntity
1213

14+
_LOGGER = logging.getLogger(__name__)
15+
16+
SENSOR_TYPES = [
17+
{
18+
"key": "current_period_index",
19+
"name": f"{DEFAULT_NAME} Current Index",
20+
"unit": None,
21+
"icon": ICON,
22+
"dynamic_icon": True,
23+
},
24+
{
25+
"key": "current_period_forecast",
26+
"name": f"{DEFAULT_NAME} Current Intensity",
27+
"unit": "gCO2/kWh",
28+
"icon": "mdi:molecule-co2",
29+
"dynamic_icon": False,
30+
},
31+
{
32+
"key": "current_period_national_index",
33+
"name": f"{DEFAULT_NAME} National Index",
34+
"unit": None,
35+
"icon": ICON,
36+
"dynamic_icon": False,
37+
},
38+
{
39+
"key": "current_period_national_forecast",
40+
"name": f"{DEFAULT_NAME} National Intensity",
41+
"unit": "gCO2/kWh",
42+
"icon": "mdi:molecule-co2",
43+
"dynamic_icon": False,
44+
},
45+
{
46+
"key": "current_low_carbon_percentage",
47+
"name": f"{DEFAULT_NAME} Low Carbon Percentage",
48+
"unit": "%",
49+
"icon": "mdi:wind-turbine",
50+
"dynamic_icon": False,
51+
},
52+
{
53+
"key": "current_fossil_fuel_percentage",
54+
"name": f"{DEFAULT_NAME} Fossil Fuel Percentage",
55+
"unit": "%",
56+
"icon": "mdi:fire",
57+
"dynamic_icon": False,
58+
},
59+
{
60+
"key": "lowest_period_index",
61+
"name": f"{DEFAULT_NAME} Lowest Period Index",
62+
"unit": None,
63+
"icon": "mdi:leaf",
64+
"dynamic_icon": False,
65+
},
66+
{
67+
"key": "lowest_period_forecast",
68+
"name": f"{DEFAULT_NAME} Lowest Period Intensity",
69+
"unit": "gCO2/kWh",
70+
"icon": "mdi:molecule-co2",
71+
"dynamic_icon": False,
72+
},
73+
{
74+
"key": "optimal_window_index",
75+
"name": f"{DEFAULT_NAME} Optimal Window Index",
76+
"unit": None,
77+
"icon": "mdi:clock-check",
78+
"dynamic_icon": False,
79+
},
80+
{
81+
"key": "optimal_window_forecast",
82+
"name": f"{DEFAULT_NAME} Optimal Window Intensity",
83+
"unit": "gCO2/kWh",
84+
"icon": "mdi:molecule-co2",
85+
"dynamic_icon": False,
86+
},
87+
]
88+
1389

1490
async def async_setup_entry(hass, entry, async_add_devices):
1591
"""Setup sensor platform."""
1692
coordinator = hass.data[DOMAIN][entry.entry_id]
17-
async_add_devices([CarbonIntensitySensor(coordinator, entry)])
93+
sensors = [CarbonIntensitySensor(coordinator, entry, sensor) for sensor in SENSOR_TYPES]
94+
_LOGGER.debug("Registering %d Carbon Intensity UK sensors", len(sensors))
95+
async_add_devices(sensors)
1896

1997

2098
class CarbonIntensitySensor(CarbonIntensityEntity):
2199
"""Carbon Intensity Sensor class."""
22100

101+
def __init__(self, coordinator, config_entry, sensor_type):
102+
super().__init__(coordinator, config_entry)
103+
self._sensor_type = sensor_type
104+
23105
@property
24106
def name(self):
25-
"""Return the name of the sensor."""
26-
return f"{DEFAULT_NAME}"
107+
return self._sensor_type["name"]
108+
109+
@property
110+
def unique_id(self):
111+
return f"{self.config_entry.entry_id}_{self._sensor_type['key']}"
27112

28113
@property
29114
def state(self):
30-
"""Return the state of the sensor."""
31-
return self.coordinator.data.get("current_period_index")
115+
return self.coordinator.data.get(self._sensor_type["key"]) if self.coordinator.data else None
116+
117+
@property
118+
def unit_of_measurement(self):
119+
return self._sensor_type.get("unit")
32120

33121
@property
34122
def icon(self):
35-
"""Return the icon of the sensor."""
36-
index = self.coordinator.data.get("current_period_index")
37-
if index == "high":
38-
return HIGH_ICON
39-
elif index == "moderate":
40-
return MODERATE_ICON
41-
elif index == "low":
42-
return LOW_ICON
43-
else:
44-
return ICON
123+
if self._sensor_type["dynamic_icon"]:
124+
index = self.coordinator.data.get("current_period_index") if self.coordinator.data else None
125+
if index == "high":
126+
return HIGH_ICON
127+
elif index == "moderate":
128+
return MODERATE_ICON
129+
elif index == "low":
130+
return LOW_ICON
131+
return self._sensor_type["icon"]

0 commit comments

Comments
 (0)