Building a Sensor Entity
A sensor is one of the simplest entity kinds in WoowTech: it exposes a single read-only reading, optionally tagged with a unit. To create one, subclass SensorEntity from homeassistant.components.sensor and fill in the relevant properties below.
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.const import UnitOfTemperature
class GreenhouseTempSensor(SensorEntity):
"""A sensor reporting the greenhouse air temperature."""
_attr_name = "Greenhouse temperature"
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_state_class = SensorStateClass.MEASUREMENT
@property
def native_value(self) -> float:
return self._probe.read_celsius()
Properties
Below are the attributes a sensor platform can define. As with every WoowTech entity, properties must return data already cached in memory — never reach out to a device or the network from inside a property getter. Put any I/O in update() / async_update() instead.
| Property | Default | Purpose |
|---|---|---|
native_value |
required | The current reading expressed in the sensor's own (native) unit. Accepts str, int, float, date, datetime, or Decimal. Picking a device_class may narrow which of those types are valid. |
native_unit_of_measurement |
None |
The unit the native_value is given in, such as °C or W. |
device_class |
None |
Declares the semantic kind of measurement so the UI can format and convert it sensibly. |
state_class |
None |
Marks how the value behaves over time, which in turn drives long-term statistics. |
last_reset |
None |
For a TOTAL accumulator, the timestamp when the running figure last started over. Surfaced in attributes as ISO 8601. |
suggested_display_precision |
None |
How many decimal places the frontend should round to when showing the value. |
suggested_unit_of_measurement |
None |
A preferred display unit applied automatically the first time the entity (which needs a unique_id) is seen. |
options |
None |
For an ENUM sensor, the closed list of allowed text states. Cannot be combined with state_class or a unit. |
A note on units and conversion
When the framework knows both the device_class and a convertible native_unit_of_measurement (temperature being the classic case), it will translate the stored native reading into whatever unit the user has chosen in their profile. Your code keeps reporting in the native unit; WoowTech handles the rest.
Device Classes
Setting device_class lets WoowTech apply the right icon, default precision, and unit-conversion rules. Every class accepts only certain units, and the value you publish has to be in one of them. The catalog is large; the table below groups the most common ones. The full enumeration lives in homeassistant.components.sensor.SensorDeviceClass.
| Device class | Typical units | What it represents |
|---|---|---|
TEMPERATURE |
°C, °F, K | Ambient or object temperature |
HUMIDITY |
% | Relative humidity |
PRESSURE / ATMOSPHERIC_PRESSURE |
Pa, hPa, bar, psi, mmHg, inHg | Generic or barometric pressure |
POWER |
W, kW, MW, mW | Instantaneous power draw or output |
ENERGY |
Wh, kWh, MWh, GJ | Consumed or produced energy |
VOLTAGE |
V, mV | Electrical potential |
CURRENT |
A, mA | Electrical current |
FREQUENCY |
Hz, kHz, MHz, GHz | Cycle rate |
BATTERY |
% | Remaining battery charge |
ILLUMINANCE |
lx | Ambient light level |
IRRADIANCE |
W/m², BTU/(h·ft²) | Radiant flux per area |
CO2 |
ppm | Carbon-dioxide concentration |
CO |
ppm | Carbon-monoxide concentration |
OZONE |
µg/m³ | Ozone concentration |
PM1 / PM25 / PM10 |
µg/m³ | Particulate matter by size |
AQI |
(unitless) | Air-quality index |
DISTANCE |
mm, cm, m, km, in, ft, mi | Generic length |
SPEED |
m/s, km/h, mph, kn, ft/s | Rate of travel |
WEIGHT |
g, kg, mg, oz, lb, st | Mass |
VOLUME |
L, mL, m³, ft³, gal | Quantity of liquid or gas |
AREA |
m², km², ft², ac, ha | Surface extent |
SIGNAL_STRENGTH |
dB, dBm | Radio signal level |
MONETARY |
ISO 4217 codes | A currency amount |
PH |
(unitless) | Acidity / alkalinity |
CONDUCTIVITY |
S/cm, µS/cm, mS/cm | Electrolytic conductivity |
BLOOD_GLUCOSE_CONCENTRATION |
mg/dL, mmol/L | Blood-sugar reading |
TIMESTAMP |
(datetime) | A point in time |
DATE |
(date) | A calendar date |
DURATION |
s, min, h, d | Elapsed-time span |
ENUM |
(none) | A non-numeric state chosen from options |
This is a representative slice — dozens more exist (gas volume, water, precipitation, wind speed, data size/rate, reactive power, apparent power, nitrogen and sulphur compounds, volatile organic compounds, and so on). Consult the enum in the codebase for the authoritative list and each class's exact unit set.
State Classes
A state_class tells the recorder how a value evolves, which is what makes long-term statistics possible. WoowTech recognizes:
MEASUREMENT— a value sampled at a moment in time that may go up or down freely, like temperature, humidity, or current power. Statistics keep the min, max, and mean per period.MEASUREMENT_ANGLE— likeMEASUREMENT, but for angles in degrees, where the mean is computed circularly (so 359° and 1° average sensibly).TOTAL— a running tally that can both grow and shrink, where the absolute number matters. You are responsible for settinglast_resetwhenever the counter starts over. Statistics derive the net change across each interval.TOTAL_INCREASING— a counter that only ever climbs and occasionally snaps back to (near) zero on its own, such as a daily energy meter. A drop of less than ~10% is treated as noise; a larger fall is read as a reset or hardware swap, and the framework infers the boundary for you — no manuallast_resetneeded.
Long-Term Statistics
When a sensor carries a suitable state_class, WoowTech records compressed long-term statistics in addition to raw history. For MEASUREMENT sensors it stores the lowest, highest, and average value seen in each window; for TOTAL and TOTAL_INCREASING sensors it stores accumulated growth (and decline). Because statistics are kept in a normalized base unit, readings from comparable sensors can be charted together even if they report in different units.
Whenever last_reset advances on a TOTAL sensor, the new period's baseline is anchored at 0.
Restoring State After a Restart
Most sensors recompute their value on the next update cycle, but some (a sensor backed by a push-only device, for instance) need their last value back immediately after a reboot. For that, derive from RestoreSensor instead of the generic RestoreEntity, because only RestoreSensor round-trips the native_value together with its native_unit_of_measurement without lossy string conversion.
from homeassistant.components.sensor import RestoreSensor
class RainGaugeSensor(RestoreSensor):
"""A push sensor whose last reading survives restarts."""
async def async_added_to_hass(self) -> None:
await super().async_added_to_hass()
previous = await self.async_get_last_sensor_data()
if previous is not None:
self._attr_native_value = previous.native_value
self._attr_native_unit_of_measurement = (
previous.native_unit_of_measurement
)
Migrating Custom Units
If you previously published a non-standard unit and want to switch to a WoowTech constant, the recorder could otherwise treat the old and new units as incompatible and stop compiling statistics. Provide an async_custom_equivalent_units() hook in a recorder.py platform module for your integration that maps each legacy unit string onto its modern equivalent, so historical data keeps flowing into statistics across the change.
Reminder on Attributes
Don't attach rapidly-changing data as extra state attributes on one sensor — split each varying quantity into its own sensor entity instead. Attributes aren't recorded for long-term statistics, and high-churn attributes bloat the database.
Building a Sensor Entity
A sensor is one of the simplest entity kinds in WoowTech: it exposes a single read-only reading, optionally tagged with a unit. To create one, subclass SensorEntity from homeassistant.components.sensor and fill in the relevant properties below.
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.const import UnitOfTemperature
class GreenhouseTempSensor(SensorEntity):
"""A sensor reporting the greenhouse air temperature."""
_attr_name = "Greenhouse temperature"
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_state_class = SensorStateClass.MEASUREMENT
@property
def native_value(self) -> float:
return self._probe.read_celsius()
Properties
Below are the attributes a sensor platform can define. As with every WoowTech entity, properties must return data already cached in memory — never reach out to a device or the network from inside a property getter. Put any I/O in update() / async_update() instead.
| Property | Default | Purpose |
|---|---|---|
native_value |
required | The current reading expressed in the sensor's own (native) unit. Accepts str, int, float, date, datetime, or Decimal. Picking a device_class may narrow which of those types are valid. |
native_unit_of_measurement |
None |
The unit the native_value is given in, such as °C or W. |
device_class |
None |
Declares the semantic kind of measurement so the UI can format and convert it sensibly. |
state_class |
None |
Marks how the value behaves over time, which in turn drives long-term statistics. |
last_reset |
None |
For a TOTAL accumulator, the timestamp when the running figure last started over. Surfaced in attributes as ISO 8601. |
suggested_display_precision |
None |
How many decimal places the frontend should round to when showing the value. |
suggested_unit_of_measurement |
None |
A preferred display unit applied automatically the first time the entity (which needs a unique_id) is seen. |
options |
None |
For an ENUM sensor, the closed list of allowed text states. Cannot be combined with state_class or a unit. |
A note on units and conversion
When the framework knows both the device_class and a convertible native_unit_of_measurement (temperature being the classic case), it will translate the stored native reading into whatever unit the user has chosen in their profile. Your code keeps reporting in the native unit; WoowTech handles the rest.
Device Classes
Setting device_class lets WoowTech apply the right icon, default precision, and unit-conversion rules. Every class accepts only certain units, and the value you publish has to be in one of them. The catalog is large; the table below groups the most common ones. The full enumeration lives in homeassistant.components.sensor.SensorDeviceClass.
| Device class | Typical units | What it represents |
|---|---|---|
TEMPERATURE |
°C, °F, K | Ambient or object temperature |
HUMIDITY |
% | Relative humidity |
PRESSURE / ATMOSPHERIC_PRESSURE |
Pa, hPa, bar, psi, mmHg, inHg | Generic or barometric pressure |
POWER |
W, kW, MW, mW | Instantaneous power draw or output |
ENERGY |
Wh, kWh, MWh, GJ | Consumed or produced energy |
VOLTAGE |
V, mV | Electrical potential |
CURRENT |
A, mA | Electrical current |
FREQUENCY |
Hz, kHz, MHz, GHz | Cycle rate |
BATTERY |
% | Remaining battery charge |
ILLUMINANCE |
lx | Ambient light level |
IRRADIANCE |
W/m², BTU/(h·ft²) | Radiant flux per area |
CO2 |
ppm | Carbon-dioxide concentration |
CO |
ppm | Carbon-monoxide concentration |
OZONE |
µg/m³ | Ozone concentration |
PM1 / PM25 / PM10 |
µg/m³ | Particulate matter by size |
AQI |
(unitless) | Air-quality index |
DISTANCE |
mm, cm, m, km, in, ft, mi | Generic length |
SPEED |
m/s, km/h, mph, kn, ft/s | Rate of travel |
WEIGHT |
g, kg, mg, oz, lb, st | Mass |
VOLUME |
L, mL, m³, ft³, gal | Quantity of liquid or gas |
AREA |
m², km², ft², ac, ha | Surface extent |
SIGNAL_STRENGTH |
dB, dBm | Radio signal level |
MONETARY |
ISO 4217 codes | A currency amount |
PH |
(unitless) | Acidity / alkalinity |
CONDUCTIVITY |
S/cm, µS/cm, mS/cm | Electrolytic conductivity |
BLOOD_GLUCOSE_CONCENTRATION |
mg/dL, mmol/L | Blood-sugar reading |
TIMESTAMP |
(datetime) | A point in time |
DATE |
(date) | A calendar date |
DURATION |
s, min, h, d | Elapsed-time span |
ENUM |
(none) | A non-numeric state chosen from options |
This is a representative slice — dozens more exist (gas volume, water, precipitation, wind speed, data size/rate, reactive power, apparent power, nitrogen and sulphur compounds, volatile organic compounds, and so on). Consult the enum in the codebase for the authoritative list and each class's exact unit set.
State Classes
A state_class tells the recorder how a value evolves, which is what makes long-term statistics possible. WoowTech recognizes:
MEASUREMENT— a value sampled at a moment in time that may go up or down freely, like temperature, humidity, or current power. Statistics keep the min, max, and mean per period.MEASUREMENT_ANGLE— likeMEASUREMENT, but for angles in degrees, where the mean is computed circularly (so 359° and 1° average sensibly).TOTAL— a running tally that can both grow and shrink, where the absolute number matters. You are responsible for settinglast_resetwhenever the counter starts over. Statistics derive the net change across each interval.TOTAL_INCREASING— a counter that only ever climbs and occasionally snaps back to (near) zero on its own, such as a daily energy meter. A drop of less than ~10% is treated as noise; a larger fall is read as a reset or hardware swap, and the framework infers the boundary for you — no manuallast_resetneeded.
Long-Term Statistics
When a sensor carries a suitable state_class, WoowTech records compressed long-term statistics in addition to raw history. For MEASUREMENT sensors it stores the lowest, highest, and average value seen in each window; for TOTAL and TOTAL_INCREASING sensors it stores accumulated growth (and decline). Because statistics are kept in a normalized base unit, readings from comparable sensors can be charted together even if they report in different units.
Whenever last_reset advances on a TOTAL sensor, the new period's baseline is anchored at 0.
Restoring State After a Restart
Most sensors recompute their value on the next update cycle, but some (a sensor backed by a push-only device, for instance) need their last value back immediately after a reboot. For that, derive from RestoreSensor instead of the generic RestoreEntity, because only RestoreSensor round-trips the native_value together with its native_unit_of_measurement without lossy string conversion.
from homeassistant.components.sensor import RestoreSensor
class RainGaugeSensor(RestoreSensor):
"""A push sensor whose last reading survives restarts."""
async def async_added_to_hass(self) -> None:
await super().async_added_to_hass()
previous = await self.async_get_last_sensor_data()
if previous is not None:
self._attr_native_value = previous.native_value
self._attr_native_unit_of_measurement = (
previous.native_unit_of_measurement
)
Migrating Custom Units
If you previously published a non-standard unit and want to switch to a WoowTech constant, the recorder could otherwise treat the old and new units as incompatible and stop compiling statistics. Provide an async_custom_equivalent_units() hook in a recorder.py platform module for your integration that maps each legacy unit string onto its modern equivalent, so historical data keeps flowing into statistics across the change.
Reminder on Attributes
Don't attach rapidly-changing data as extra state attributes on one sensor — split each varying quantity into its own sensor entity instead. Attributes aren't recorded for long-term statistics, and high-churn attributes bloat the database.
Start writing here...