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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ integration, this library supports also the following devices:
* Xiaomi Mi Smart Space Heater
* Xiaomiyoupin Curtain Controller (Wi-Fi) (lumi.curtain.hagl05)
* Xiaomi Dishwasher (viomi.dishwasher.m02)
* Viomi Water Heater 1A (60L) (viomi.waterheater.e1)
* Xiaomi Xiaomi Mi Smart Space Heater S (zhimi.heater.mc2)
* Xiaomi Xiaomi Mi Smart Space Heater 1S (zhimi.heater.za2)
* Yeelight Dual Control Module (yeelink.switch.sw1)
Expand Down
1 change: 1 addition & 0 deletions miio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
from miio.integrations.tinymu.toiletlid import Toiletlid
from miio.integrations.viomi.vacuum import ViomiVacuum
from miio.integrations.viomi.viomidishwasher import ViomiDishwasher
from miio.integrations.viomi.waterheater import ViomiWaterHeater
from miio.integrations.xiaomi.aircondition.airconditioner_miot import AirConditionerMiot
from miio.integrations.xiaomi.repeater.wifirepeater import WifiRepeater
from miio.integrations.xiaomi.wifispeaker.wifispeaker import WifiSpeaker
Expand Down
3 changes: 3 additions & 0 deletions miio/integrations/viomi/waterheater/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .viomiwaterheater import ViomiWaterHeater, ViomiWaterHeaterStatus

__all__ = ["ViomiWaterHeater", "ViomiWaterHeaterStatus"]
128 changes: 128 additions & 0 deletions miio/integrations/viomi/waterheater/test_viomiwaterheater.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from datetime import time

import pytest

from miio.tests.dummies import DummyDevice

from .viomiwaterheater import (
MODEL_WATERHEATER_E1,
SUPPORTED_MODELS,
OperationMode,
OperationStatus,
ViomiWaterHeater,
ViomiWaterHeaterException,
ViomiWaterHeaterStatus,
)


class DummyViomiWaterHeater(DummyDevice, ViomiWaterHeater):
def __init__(self, *args, **kwargs):
self._model = MODEL_WATERHEATER_E1
self.state = {
"washStatus": 1,
"power": 1,
"velocity": 0,
"waterTemp": 29,
"targetTemp": 70,
"errStatus": 0,
"hotWater": 60,
"needClean": 0,
"modeType": 1,
"appointStart": 7,
"appointEnd": 12,
}
self.return_values = {
"get_prop": self._get_state,
"set_power": lambda x: self._set_state("power", x),
"set_temp": lambda x: self._set_state("targetTemp", x),
"set_mode": lambda x: self._set_state("modeType", x),
"set_appoint": lambda x: self._set_state("appoint", x),
}
super().__init__(*args, **kwargs)


@pytest.fixture
def viomiwaterheater(request):
return DummyViomiWaterHeater()


def test_status(viomiwaterheater: DummyViomiWaterHeater):
status = viomiwaterheater.status()
assert isinstance(status, ViomiWaterHeaterStatus)
assert status.status == OperationStatus.Heating
assert status.is_on is True
assert status.velocity == 0
assert status.water_temperature == 29
assert status.target_temperature == 70
assert status.error == 0
assert status.hot_water_volume == 60
assert status.cleaning_required is False
assert status.mode == OperationMode.Heating
assert status.bacteriostatic_mode_active is False
assert status.service_time_start == time(7)
assert status.service_time_end == time(12)


def test_on(viomiwaterheater: DummyViomiWaterHeater):
viomiwaterheater.on()
assert viomiwaterheater.state["power"] == 1


def test_off(viomiwaterheater: DummyViomiWaterHeater):
viomiwaterheater.off()
assert viomiwaterheater.state["power"] == 0


def test_set_target_temperature(viomiwaterheater: DummyViomiWaterHeater):
viomiwaterheater.set_target_temperature(50)
assert viomiwaterheater.state["targetTemp"] == 50

with pytest.raises(ViomiWaterHeaterException):
viomiwaterheater.set_target_temperature(20)

with pytest.raises(ViomiWaterHeaterException):
viomiwaterheater.set_target_temperature(80)


def test_set_mode(viomiwaterheater: DummyViomiWaterHeater):
viomiwaterheater.set_mode(OperationMode.Thermostatic)
assert viomiwaterheater.state["modeType"] == 0

viomiwaterheater.set_mode(OperationMode.Booking)
# Booking mode sets appoint with [1, appointStart, appointEnd], popping 1 into appoint
assert viomiwaterheater.state["appoint"] == 1


def test_set_service_time(viomiwaterheater: DummyViomiWaterHeater):
viomiwaterheater.set_service_time(8, 14)
# set_service_time sends [0, 8, 14], popping 0 into appoint
assert viomiwaterheater.state["appoint"] == 0

with pytest.raises(ViomiWaterHeaterException):
viomiwaterheater.set_service_time(-1, 10)

with pytest.raises(ViomiWaterHeaterException):
viomiwaterheater.set_service_time(10, 25)


def test_set_bacteriostatic_mode(viomiwaterheater: DummyViomiWaterHeater, monkeypatch):
# Test valid call
viomiwaterheater.set_bacteriostatic_mode()
assert viomiwaterheater.state["targetTemp"] == 80

# Test thermostatic mode exception
viomiwaterheater.state["modeType"] = OperationMode.Thermostatic.value
with pytest.raises(
ViomiWaterHeaterException,
match="Bacteriostatic operational mode is not supported in Thermostatic mode.",
):
viomiwaterheater.set_bacteriostatic_mode()

# Test unsupported bacteriostatic mode
monkeypatch.setitem(
SUPPORTED_MODELS[MODEL_WATERHEATER_E1], "bacteriostatic_mode", False
)
with pytest.raises(
ViomiWaterHeaterException, match="Bacteriostatic mode is not supported."
):
viomiwaterheater.set_bacteriostatic_mode()
Loading
Loading