Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions aioesphomeapi/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,13 @@ message CameraImageRequest {
bool stream = 2;
}

// ==================== TEMPERATURE UNIT ====================
enum TemperatureUnit {
TEMPERATURE_UNIT_CELSIUS = 0;
TEMPERATURE_UNIT_FAHRENHEIT = 1;
TEMPERATURE_UNIT_KELVIN = 2;
Comment thread
bdraco marked this conversation as resolved.
}

// ==================== CLIMATE ====================
enum ClimateMode {
CLIMATE_MODE_OFF = 0;
Expand Down Expand Up @@ -1110,6 +1117,7 @@ message ListEntitiesClimateResponse {
float visual_max_humidity = 25;
uint32 device_id = 26 [(field_ifdef) = "USE_DEVICES"];
uint32 feature_flags = 27;
TemperatureUnit temperature_unit = 28;
}
message ClimateStateResponse {
option (id) = 47;
Expand Down Expand Up @@ -1203,6 +1211,7 @@ message ListEntitiesWaterHeaterResponse {
repeated WaterHeaterMode supported_modes = 11 [(container_pointer_no_template) = "water_heater::WaterHeaterModeMask"];
// Bitmask of WaterHeaterFeature flags
uint32 supported_features = 12;
TemperatureUnit temperature_unit = 13;
}

message WaterHeaterStateResponse {
Expand Down
610 changes: 306 additions & 304 deletions aioesphomeapi/api_pb2.py

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions aioesphomeapi/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,12 @@ class ClimatePreset(APIIntEnum):
ACTIVITY = 7


class TemperatureUnit(APIIntEnum):
CELSIUS = 0
FAHRENHEIT = 1
KELVIN = 2


@_frozen_dataclass_decorator
class ClimateInfo(EntityInfo):
feature_flags: int = 0
Expand Down Expand Up @@ -733,6 +739,13 @@ class ClimateInfo(EntityInfo):
supports_target_humidity: bool = False
visual_min_humidity: float = 0
visual_max_humidity: float = 0
temperature_unit: TemperatureUnit = (
converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,
)
or TemperatureUnit.CELSIUS
Comment on lines +742 to +747
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The or TemperatureUnit.CELSIUS fallback here is ineffective because it runs at class definition time and converter_field(...) is always truthy. Also, TemperatureUnit.convert can return None for unknown enum values, but this field is not typed as optional, so future/invalid values could result in temperature_unit=None unexpectedly. Consider either making the type TemperatureUnit | None (consistent with other converted enums) or using a converter that falls back to TemperatureUnit.CELSIUS when conversion fails, and drop the redundant or ....

Suggested change
temperature_unit: TemperatureUnit = (
converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,
)
or TemperatureUnit.CELSIUS
temperature_unit: TemperatureUnit = converter_field(
default=TemperatureUnit.CELSIUS,
converter=lambda value: TemperatureUnit.convert(value)
or TemperatureUnit.CELSIUS,

Copilot uses AI. Check for mistakes.
Comment on lines +742 to +747
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior is added (temperature_unit for climate/water_heater), but there are no targeted tests asserting correct conversion/round-tripping (e.g., from_pb / from_dict with Fahrenheit, and handling of unknown enum values). Since this repo has extensive model conversion tests, please add coverage for these new fields to prevent regressions.

Suggested change
temperature_unit: TemperatureUnit = (
converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,
)
or TemperatureUnit.CELSIUS
temperature_unit: TemperatureUnit = converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,

Copilot uses AI. Check for mistakes.
)

def supported_feature_flags_compat(self, api_version: APIVersion) -> int:
if api_version < APIVersion(1, 13):
Expand Down Expand Up @@ -1183,6 +1196,13 @@ class WaterHeaterInfo(EntityInfo):
default_factory=list, converter=WaterHeaterMode.convert_list
)
supported_features: int = 0
temperature_unit: TemperatureUnit = (
converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,
)
or TemperatureUnit.CELSIUS
Comment on lines +1199 to +1204
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as ClimateInfo: converter_field(...) or TemperatureUnit.CELSIUS is redundant, and TemperatureUnit.convert may yield None for unknown values even though this field is not optional. Please align with the project’s usual enum-conversion pattern (optional type or safe fallback converter) and remove the ineffective or expression.

Suggested change
temperature_unit: TemperatureUnit = (
converter_field(
default=TemperatureUnit.CELSIUS,
converter=TemperatureUnit.convert,
)
or TemperatureUnit.CELSIUS
temperature_unit: TemperatureUnit = converter_field(
default=TemperatureUnit.CELSIUS,
converter=lambda value: TemperatureUnit.convert(value)
or TemperatureUnit.CELSIUS,

Copilot uses AI. Check for mistakes.
)


@_frozen_dataclass_decorator
Expand Down
Loading