Skip to content

Commit

Permalink
Added support for fridge
Browse files Browse the repository at this point in the history
  • Loading branch information
veista committed Jan 22, 2022
1 parent 1fadd5f commit 914d5c2
Show file tree
Hide file tree
Showing 6 changed files with 577 additions and 84 deletions.
118 changes: 106 additions & 12 deletions custom_components/smartthings/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import asyncio

from homeassistant.components.binary_sensor import (
DEVICE_CLASS_DOOR,
DEVICE_CLASS_MOISTURE,
DEVICE_CLASS_MOTION,
DEVICE_CLASS_MOVING,
Expand Down Expand Up @@ -65,7 +66,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
):
model = device.status.attributes[Attribute.mnmo].value
model = model.split("|")[0]
if Capability.execute and model in ("TP2X_DA-KS-RANGE-0101X",):
if model in ("TP2X_DA-KS-RANGE-0101X",):
sensors.extend(
[
SamsungCooktopBurner(device, "Cooktop Bottom Left Burner", 1),
Expand All @@ -74,6 +75,35 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
SamsungCooktopBurner(device, "Cooktop Bottom Right", 16),
]
)
elif model in ("21K_REF_LCD_FHUB6.0"):
sensors.extend(
[
SamsungOcfDoorBinarySensor(
device,
"Cooler Door",
"/door/cooler/0",
"Open",
"Closed",
DEVICE_CLASS_DOOR,
),
SamsungOcfDoorBinarySensor(
device,
"Freezer Door",
"/door/freezer/0",
"Open",
"Closed",
DEVICE_CLASS_DOOR,
),
SamsungOcfDoorBinarySensor(
device,
"FlexZone Door",
"/door/cvroom/0",
"Open",
"Closed",
DEVICE_CLASS_DOOR,
),
]
)
async_add_entities(sensors)


Expand Down Expand Up @@ -133,9 +163,8 @@ def __init__(self, device, name, burner_bitmask):
def startup(self):
"""Make sure that OCF page visits cooktopmonitoring on startup"""
tasks = []
tasks.append(self._device.execute("cooktopmonitoring/vs/0"))
tasks.append(self._device.execute("/cooktopmonitoring/vs/0"))
asyncio.gather(*tasks)
self.init_bool = True

@property
def name(self) -> str:
Expand All @@ -154,13 +183,17 @@ def is_on(self):
if not self.init_bool:
self.startup()

output = json.dumps(self._device.status.attributes[Attribute.data].value)

if "x.com.samsung.da.cooktopMonitoring" in output:
self.execute_state = self._device.status.attributes[Attribute.data].value[
"payload"
]["x.com.samsung.da.cooktopMonitoring"]
if int(self.execute_state) & self._burner_bitmask:
if (
self._device.status.attributes[Attribute.data].data["href"]
== "/cooktopmonitoring/vs/0"
):
self.init_bool = True
self.execute_state = int(
self._device.status.attributes[Attribute.data].value["payload"][
"x.com.samsung.da.cooktopMonitoring"
]
)
if self.execute_state & self._burner_bitmask:
self.output_state = True
else:
self.output_state = False
Expand All @@ -173,7 +206,7 @@ def icon(self):
return "mdi:checkbox-blank-circle-outline"


class SamsungOcfModeBinarySensor(SmartThingsEntity, BinarySensorEntity):
class SamsungOcfModeOptionsBinarySensor(SmartThingsEntity, BinarySensorEntity):
"""Define Samsung Cooktop Burner Sensor"""

execute_state = False
Expand All @@ -200,7 +233,7 @@ def __init__(
def startup(self):
"""Make sure that OCF page visits mode on startup"""
tasks = []
tasks.append(self._device.execute("mode/vs/0"))
tasks.append(self._device.execute("/mode/vs/0"))
asyncio.gather(*tasks)
self.init_bool = True

Expand Down Expand Up @@ -234,3 +267,64 @@ def icon(self):
if self.is_on:
return self._on_icon
return self._off_icon


class SamsungOcfDoorBinarySensor(SmartThingsEntity, BinarySensorEntity):
"""Define Samsung Cooktop Burner Sensor"""

execute_state = False
init_bool = False

def __init__(
self,
device,
name: str,
page: str,
on_value: str,
off_value: str,
device_class: str | None,
):
super().__init__(device)
self._name = name
self._page = page
self._on_value = on_value
self._off_value = off_value
self._attr_device_class = device_class

def startup(self):
"""Make sure that OCF page visits mode on startup"""
tasks = []
tasks.append(self._device.execute(self._page))
asyncio.gather(*tasks)

@property
def name(self) -> str:
"""Return the name of the binary sensor."""
return f"{self._device.label} {self._name}"

@property
def unique_id(self) -> str:
"""Return a unique ID."""
_unique_id = self._name.lower().replace(" ", "_")
return f"{self._device.device_id}.{_unique_id}"

@property
def is_on(self):
"""Return the state of the sensor."""
if not self.init_bool:
self.startup()
if self._device.status.attributes[Attribute.data].data["href"] == self._page:
self.init_bool = True
output = self._device.status.attributes[Attribute.data].value["payload"][
"openState"
]
if self._on_value in output:
self.execute_state = True
if self._off_value in output:
self.execute_state = False
return self.execute_state

@property
def device_class(self):
"""Return the class of this device."""
return self._attr_device_class
14 changes: 14 additions & 0 deletions custom_components/smartthings/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@
],
)
],
"custom.waterFilter": [
Map(
"resetWaterFilter",
"Reset Water Filter",
"mdi:air-filter",
None,
[
"waterFilterUsageStep",
"waterFilterUsage",
"waterFilterStatus",
"waterFilterResetType",
],
)
],
}


Expand Down
156 changes: 150 additions & 6 deletions custom_components/smartthings/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from collections import namedtuple
from collections.abc import Sequence

import asyncio

from typing import Literal

from pysmartthings import Attribute, Capability
Expand All @@ -12,17 +14,15 @@
from homeassistant.components.number import NumberEntity, NumberMode

from . import SmartThingsEntity
from .const import DATA_BROKERS, DOMAIN
from .const import DATA_BROKERS, DOMAIN, UNIT_MAP

from homeassistant.const import PERCENTAGE
from homeassistant.const import PERCENTAGE, DEVICE_CLASS_TEMPERATURE

Map = namedtuple(
"map",
"attribute command name unit_of_measurement icon min_value max_value step mode",
)

UNITS = {"%": PERCENTAGE}

CAPABILITY_TO_NUMBER = {
Capability.audio_volume: [
Map(
Expand Down Expand Up @@ -64,6 +64,28 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for m in maps
]
)
if (
device.status.attributes[Attribute.mnmn].value == "Samsung Electronics"
and device.type == "OCF"
):
model = device.status.attributes[Attribute.mnmo].value.split("|")[0]
if model in ("21K_REF_LCD_FHUB6.0"):
numbers.extend(
[
SamsungOcfTemperatureNumber(
device,
"Cooler Setpoint",
"/temperature/desired/cooler/0",
"slider",
),
SamsungOcfTemperatureNumber(
device,
"Freezer Setpoint",
"/temperature/desired/freezer/0",
"slider",
),
]
)
async_add_entities(numbers)


Expand Down Expand Up @@ -121,7 +143,7 @@ def unique_id(self) -> str:
def value(self) -> float:
"""Return Value."""
return self._device.status.attributes[self._attribute].value

@property
def icon(self) -> str:
"""Return Icon."""
Expand All @@ -146,9 +168,131 @@ def step(self) -> float:
def unit_of_measurement(self) -> str | None:
"""Return unit of measurement"""
unit = self._device.status.attributes[self._attribute].unit
return UNITS.get(unit, unit) if unit else self._attr_unit_of_measurement
return UNIT_MAP.get(unit) if unit else self._attr_unit_of_measurement

@property
def mode(self) -> Literal["auto", "slider", "box"]:
"""Return representation mode"""
return self._attr_mode


class SamsungOcfTemperatureNumber(SmartThingsEntity, NumberEntity):
"""Define a Samsung OCF Number."""

execute_state = 0
min_value_state = 0
max_value_state = 0
unit_state = ""
init_bool = False

def __init__(
self,
device: DeviceEntity,
name: str,
page: str,
mode: str | None,
) -> None:
"""Init the class."""
super().__init__(device)
self._name = name
self._page = page
self._attr_mode = mode

def startup(self):
"""Make sure that OCF page visits mode on startup"""
tasks = []
tasks.append(self._device.execute(self._page))
asyncio.gather(*tasks)

async def async_set_value(self, value: float) -> None:
"""Set the number value."""
result = await self._device.execute(self._page, {"temperature": value})
if result:
self._device.status.update_attribute_value(
"data",
{
"payload": {
"temperature": value,
"range": [self.min_value_state, self.max_value_state],
"units": self.unit_state,
}
},
)
self.execute_state = value
self.async_write_ha_state()

@property
def name(self) -> str:
"""Return the name of the number."""
return f"{self._device.label} {self._name}"

@property
def unique_id(self) -> str:
"""Return a unique ID."""
_unique_id = self._name.lower().replace(" ", "_")
return f"{self._device.device_id}.{_unique_id}"

@property
def value(self) -> float:
"""Return Value."""
if not self.init_bool:
self.startup()
if self._device.status.attributes[Attribute.data].data["href"] == self._page:
self.init_bool = True
self.execute_state = int(
self._device.status.attributes[Attribute.data].value["payload"][
"temperature"
]
)
return int(self.execute_state)

@property
def icon(self) -> str:
"""Return Icon."""
return "mdi:thermometer-lines"

@property
def min_value(self) -> float:
"""Define mimimum level."""
if self._device.status.attributes[Attribute.data].data["href"] == self._page:
self.min_value_state = int(
self._device.status.attributes[Attribute.data].value["payload"][
"range"
][0]
)
return self.min_value_state

@property
def max_value(self) -> float:
"""Define maximum level."""
if self._device.status.attributes[Attribute.data].data["href"] == self._page:
self.max_value_state = int(
self._device.status.attributes[Attribute.data].value["payload"][
"range"
][1]
)
return self.max_value_state

@property
def step(self) -> float:
"""Define stepping size"""
return 1

@property
def unit_of_measurement(self) -> str | None:
"""Return unit of measurement"""
if self._device.status.attributes[Attribute.data].data["href"] == self._page:
self.unit_state = self._device.status.attributes[Attribute.data].value[
"payload"
]["units"]
return UNIT_MAP.get(self.unit_state) if self.unit_state else None

@property
def mode(self) -> Literal["auto", "slider", "box"]:
"""Return representation mode"""
return self._attr_mode

@property
def device_class(self) -> str | None:
"""Return Device Class."""
return DEVICE_CLASS_TEMPERATURE

0 comments on commit 914d5c2

Please sign in to comment.