Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 7 additions & 1 deletion custom_components/tech/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# tile type
TYPE_TEMPERATURE = 1
TYPE_FIRE_SENSOR = 2
TYPE_TEMPERATURE_CH = 6
TYPE_WIDGET = 6
TYPE_RELAY = 11
TYPE_ADDITIONAL_PUMP = 21
TYPE_FAN = 22
Expand All @@ -46,12 +46,18 @@
TYPE_SW_VERSION = 50
TYPE_OPEN_THERM = 252

# widget type
WIDGET_DHW_PUMP = 1
WIDGET_COLLECTOR_PUMP = 2
WIDGET_TEMPERATURE_CH = 9

# map iconId -> icon name
ICON_BY_ID = {
3: "mdi:animation-play", # mode
17: "mdi:arrow-right-drop-circle-outline", # pump
50: "mdi:tune-vertical", # state
101: "mdi:cogs", # feeder
167: "mdi:electric-switch", # contact
}

# map type -> icon name
Expand Down
172 changes: 163 additions & 9 deletions custom_components/tech/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,22 @@
OPENTHERM_SET_TEMP,
OPENTHERM_SET_TEMP_DHW,
SIGNAL_STRENGTH,
TYPE_ADDITIONAL_PUMP,
TYPE_FAN,
TYPE_FUEL_SUPPLY,
TYPE_MIXING_VALVE,
TYPE_OPEN_THERM,
TYPE_TEMPERATURE,
TYPE_TEMPERATURE_CH,
TYPE_TEXT,
TYPE_VALVE,
TYPE_WIDGET,
UDID,
VALUE,
VER,
VISIBILITY,
WIDGET_COLLECTOR_PUMP,
WIDGET_DHW_PUMP,
WIDGET_TEMPERATURE_CH,
WINDOW_SENSORS,
WINDOW_STATE,
WORKING_STATUS,
Expand Down Expand Up @@ -113,8 +117,8 @@ async def async_setup_entry(
entities.append(
TileTemperatureSensor(tile, coordinator, config_entry, create_devices)
)
if tile[CONF_TYPE] == TYPE_TEMPERATURE_CH:
entities.append(TileWidgetSensor(tile, coordinator, config_entry))
if tile[CONF_TYPE] == TYPE_WIDGET:
entities.extend(setup_tile_widget_sensors(tile, coordinator, config_entry))
if tile[CONF_TYPE] == TYPE_FAN:
entities.append(TileFanSensor(tile, coordinator, config_entry))
if tile[CONF_TYPE] == TYPE_VALVE:
Expand Down Expand Up @@ -178,6 +182,40 @@ async def async_setup_entry(
)


def setup_tile_widget_sensors(tile, coordinator, config_entry):
"""Set up sensors for tile widgets."""
entities = []

if tile[CONF_TYPE] == TYPE_WIDGET:
# Check bot widgets
for widget_key in ["widget1", "widget2"]:
widget = tile[CONF_PARAMS][widget_key]

if widget["unit"] == -1 and widget[CONF_TYPE] == 0 and widget["txtId"] != 0:
# this is supposedly a binary sensor/contact
entities.append(TileWidgetContactSensor(
tile, coordinator, config_entry, widget_key=widget_key
)
)

else:
if widget["type"] == WIDGET_DHW_PUMP or widget["type"] == WIDGET_TEMPERATURE_CH:
entities.append(
TileWidgetTemperatureSensor(
tile, coordinator, config_entry, widget_key=widget_key
)
)

if widget["type"] == WIDGET_COLLECTOR_PUMP:
entities.append(
TileWidgetPumpSensor(
tile, coordinator, config_entry, widget_key=widget_key
)
)

return entities


def map_to_battery_sensors(zones, coordinator, config_entry):
"""Map the battery-operating devices in the zones to TechBatterySensor objects.

Expand Down Expand Up @@ -1521,26 +1559,94 @@ def get_state(self, device) -> Any:
return assets.get_text(device[CONF_PARAMS]["statusId"])


class TileWidgetSensor(TileSensor, SensorEntity):
class TileWidgetTemperatureSensor(TileSensor, SensorEntity):
"""Representation of a Tile Widget Sensor."""

_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_state_class = SensorStateClass.MEASUREMENT

def __init__(self, device, coordinator, config_entry) -> None:
def __init__(self, device, coordinator, config_entry, widget_key) -> None:
"""Initialize the sensor."""
self.widget_key = widget_key
TileSensor.__init__(self, device, coordinator, config_entry)
self._name = (

txt_id = device[CONF_PARAMS][widget_key]["txtId"]
widget_type = device[CONF_PARAMS][widget_key][CONF_TYPE]

# Determine the other widget key
other_widget_key = "widget2" if widget_key == "widget1" else "widget1"

# Build the name
hub_name = (
self._config_entry.title + " "
if self._config_entry.data[INCLUDE_HUB_IN_NAME]
else ""
)

if widget_type == WIDGET_DHW_PUMP:
temperature_type = (
" Set Temperature" if widget_key == "widget1" else " Current Temperature"
)
else:
temperature_type = ""

# # If txt_id is 0, set it to the txt_id of the other widget
if txt_id == 0:
txt_id = device[CONF_PARAMS][other_widget_key]["txtId"]

self._name = f"{hub_name}{assets.get_text(txt_id)}{temperature_type}"

@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._unique_id}_tile_temperature_{self.widget_key}"

@property
def name(self) -> str | UndefinedType | None:
"""Return the name of the sensor."""
return self._name

def get_state(self, device) -> Any:
"""Get the state of the device."""
if (
device[CONF_PARAMS][self.widget_key]["unit"] == 7
or device[CONF_PARAMS][self.widget_key]["unit"] == 4
):
return device[CONF_PARAMS][self.widget_key][VALUE] / 10
if device[CONF_PARAMS][self.widget_key]["unit"] == 5:
return device[CONF_PARAMS][self.widget_key][VALUE] / 100
return device[CONF_PARAMS][self.widget_key][VALUE]



class TileWidgetPumpSensor(TileSensor, SensorEntity):
"""Representation of a Tile Widget Pump Sensor."""

_attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_icon = assets.get_icon_by_type(TYPE_ADDITIONAL_PUMP)

def __init__(self, device, coordinator, config_entry, widget_key) -> None:
"""Initialize the sensor."""
self.widget_key = widget_key
TileSensor.__init__(self, device, coordinator, config_entry)

# Determine which txtId to use
txt_id = device[CONF_PARAMS][widget_key]["txtId"]

# Build the name
hub_name = (
self._config_entry.title + " "
if self._config_entry.data[INCLUDE_HUB_IN_NAME]
else ""
) + assets.get_text(device[CONF_PARAMS]["widget1"]["txtId"])
)
self._name = f"{hub_name}{assets.get_text(txt_id)}"

@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._unique_id}_tile_widget"
return f"{self._unique_id}_tile_pump_{self.widget_key}"

@property
def name(self) -> str | UndefinedType | None:
Expand All @@ -1549,8 +1655,56 @@ def name(self) -> str | UndefinedType | None:

def get_state(self, device) -> Any:
"""Get the state of the device."""
return device[CONF_PARAMS]["widget1"][VALUE] / 10
return device[CONF_PARAMS][self.widget_key][VALUE]

class TileWidgetContactSensor(BinarySensorEntity, TileEntity):
"""Representation of a Tile Widget Contact Sensor."""

_attr_device_class = BinarySensorDeviceClass.OPENING

def __init__(self, device, coordinator, config_entry, widget_key) -> None:
"""Initialize the sensor.

These are needed before the call to super, as ZoneSensor class
calls update_properties in its init, which actually calls this class
update_properties, which does not know attrs and _window_index already.

"""
self.widget_key = widget_key
self._attr_is_on = (
device[CONF_PARAMS][self.widget_key][VALUE] == 1
)
super().__init__(device, coordinator, config_entry)
self._attr_is_on = (
device[CONF_PARAMS][self.widget_key][VALUE] == 1
)

self._attr_icon = assets.get_icon(device[CONF_PARAMS]["iconId"])

# Determine which txtId to use
txt_id = device[CONF_PARAMS][widget_key]["txtId"]

# Build the name
hub_name = (
self._config_entry.title + " "
if self._config_entry.data[INCLUDE_HUB_IN_NAME]
else ""
)
self._name = f"{hub_name}{assets.get_text(txt_id)}"

@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._unique_id}_tile_contact_{self.widget_key}"

@property
def name(self) -> str | UndefinedType | None:
"""Return the name of the sensor."""
return self._name

def get_state(self, device) -> Any:
"""Get the state of the device."""
return device[CONF_PARAMS][self.widget_key][VALUE]

class TileValveSensor(TileSensor, SensorEntity):
"""Representation of a Tile Valve Sensor."""
Expand Down
Loading