Skip to content

Commit

Permalink
feat(c3): add option to set super_silent (#210)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a new silent level feature for C3 devices, allowing users
to set silence modes to OFF, SILENT, and SUPER_SILENT.

- **Refactor**
- Updated message handling to incorporate the new silent level feature.

- **Tests**
- Added test cases to validate the new silent level functionality and
message handling improvements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
rokam authored Jul 15, 2024
1 parent 46196cb commit dcef500
Show file tree
Hide file tree
Showing 5 changed files with 418 additions and 59 deletions.
55 changes: 2 additions & 53 deletions midealocal/devices/c3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import json
import logging
from enum import IntEnum, StrEnum
from typing import Any

from midealocal.device import MideaDevice
from midealocal.devices.c3.const import C3DeviceMode, C3SilentLevel, DeviceAttributes

from .message import (
MessageC3Response,
Expand All @@ -18,58 +18,6 @@
_LOGGER = logging.getLogger(__name__)


class DeviceAttributes(StrEnum):
"""Midea C3 device attributes."""

zone1_power = "zone1_power"
zone2_power = "zone2_power"
dhw_power = "dhw_power"
zone1_curve = "zone1_curve"
zone2_curve = "zone2_curve"
disinfect = "disinfect"
fast_dhw = "fast_dhw"
zone_temp_type = "zone_temp_type"
zone1_room_temp_mode = "zone1_room_temp_mode"
zone2_room_temp_mode = "zone2_room_temp_mode"
zone1_water_temp_mode = "zone1_water_temp_mode"
zone2_water_temp_mode = "zone2_water_temp_mode"
mode = "mode"
mode_auto = "mode_auto"
zone_target_temp = "zone_target_temp"
dhw_target_temp = "dhw_target_temp"
room_target_temp = "room_target_temp"
zone_heating_temp_max = "zone_heating_temp_max"
zone_heating_temp_min = "zone_heating_temp_min"
zone_cooling_temp_max = "zone_cooling_temp_max"
zone_cooling_temp_min = "zone_cooling_temp_min"
tank_actual_temperature = "tank_actual_temperature"
room_temp_max = "room_temp_max"
room_temp_min = "room_temp_min"
dhw_temp_max = "dhw_temp_max"
dhw_temp_min = "dhw_temp_min"
target_temperature = "target_temperature"
temperature_max = "temperature_max"
temperature_min = "temperature_min"
status_heating = "status_heating"
status_dhw = "status_dhw"
status_tbh = "status_tbh"
status_ibh = "status_ibh"
total_energy_consumption = "total_energy_consumption"
total_produced_energy = "total_produced_energy"
outdoor_temperature = "outdoor_temperature"
silent_mode = "silent_mode"
eco_mode = "eco_mode"
tbh = "tbh"
error_code = "error_code"


class C3DeviceMode(IntEnum):
"""C3 Device Mode."""

COOL = 2
HEAT = 3


class MideaC3Device(MideaDevice):
"""Midea C3 device."""

Expand Down Expand Up @@ -112,6 +60,7 @@ def __init__(
DeviceAttributes.zone1_water_temp_mode: False,
DeviceAttributes.zone2_water_temp_mode: False,
DeviceAttributes.silent_mode: False,
DeviceAttributes.SILENT_LEVEL: C3SilentLevel.SILENT,
DeviceAttributes.eco_mode: False,
DeviceAttributes.tbh: False,
DeviceAttributes.mode: 1,
Expand Down
64 changes: 64 additions & 0 deletions midealocal/devices/c3/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Midea local C3 device const."""

from enum import IntEnum, StrEnum


class DeviceAttributes(StrEnum):
"""Midea C3 device attributes."""

zone1_power = "zone1_power"
zone2_power = "zone2_power"
dhw_power = "dhw_power"
zone1_curve = "zone1_curve"
zone2_curve = "zone2_curve"
disinfect = "disinfect"
fast_dhw = "fast_dhw"
zone_temp_type = "zone_temp_type"
zone1_room_temp_mode = "zone1_room_temp_mode"
zone2_room_temp_mode = "zone2_room_temp_mode"
zone1_water_temp_mode = "zone1_water_temp_mode"
zone2_water_temp_mode = "zone2_water_temp_mode"
mode = "mode"
mode_auto = "mode_auto"
zone_target_temp = "zone_target_temp"
dhw_target_temp = "dhw_target_temp"
room_target_temp = "room_target_temp"
zone_heating_temp_max = "zone_heating_temp_max"
zone_heating_temp_min = "zone_heating_temp_min"
zone_cooling_temp_max = "zone_cooling_temp_max"
zone_cooling_temp_min = "zone_cooling_temp_min"
tank_actual_temperature = "tank_actual_temperature"
room_temp_max = "room_temp_max"
room_temp_min = "room_temp_min"
dhw_temp_max = "dhw_temp_max"
dhw_temp_min = "dhw_temp_min"
target_temperature = "target_temperature"
temperature_max = "temperature_max"
temperature_min = "temperature_min"
status_heating = "status_heating"
status_dhw = "status_dhw"
status_tbh = "status_tbh"
status_ibh = "status_ibh"
total_energy_consumption = "total_energy_consumption"
total_produced_energy = "total_produced_energy"
outdoor_temperature = "outdoor_temperature"
silent_mode = "silent_mode"
SILENT_LEVEL = "silent_level"
eco_mode = "eco_mode"
tbh = "tbh"
error_code = "error_code"


class C3SilentLevel(IntEnum):
"""C3 Silent Level."""

OFF = 0x0
SILENT = 0x1
SUPER_SILENT = 0x3


class C3DeviceMode(IntEnum):
"""C3 Device Mode."""

COOL = 2
HEAT = 3
37 changes: 32 additions & 5 deletions midealocal/devices/c3/message.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Midea local C3 message."""

from midealocal.devices.c3.const import C3SilentLevel
from midealocal.message import (
BodyType,
MessageBody,
Expand Down Expand Up @@ -111,16 +112,13 @@ def __init__(self, protocol_version: int) -> None:
body_type=0x05,
)
self.silent_mode = False
self.super_silent = False
self.silent_level = C3SilentLevel.OFF

@property
def _body(self) -> bytearray:
silent_mode = 0x01 if self.silent_mode else 0
super_silent = 0x02 if self.super_silent else 0

return bytearray(
[
silent_mode | super_silent,
self.silent_level if self.silent_mode else C3SilentLevel.OFF,
0x00,
0x00,
0x00,
Expand Down Expand Up @@ -220,6 +218,33 @@ def __init__(self, body: bytearray, data_offset: int = 0) -> None:
)


class C3QuerySilenceMessageBody(MessageBody):
"""C3 Query silence message body."""

def __init__(self, body: bytearray, data_offset: int = 0) -> None:
"""Initialize C3 notify1 message body."""
super().__init__(body)
self.silence_mode = body[data_offset] & 0x1 > 0
self.silence_level = (
(body[data_offset] & 0x1) + ((body[data_offset] & 0x8) >> 2)
if self.silence_mode
else C3SilentLevel.OFF
)
# Message protocol information:
# silence_function_state: Byte 1, BIT 0
# silence_timer1_state: Byte 1, BIT 1
# silence_timer2_state: Byte 1, BIT 2
# silence_function_level: Byte 1, BIT 3
# silence_timer1_starthour: Byte 2
# silence_timer1_startmin: Byte 3
# silence_timer1_endhour: Byte 4
# silence_timer1_endmin: Byte 5
# silence_timer2_starthour: Byte 6
# silence_timer2_startmin: Byte 7
# silence_timer2_endhour: Byte 8
# silence_timer2_endmin: Byte 9


class MessageC3Response(MessageResponse):
"""C3 message response."""

Expand All @@ -236,4 +261,6 @@ def __init__(self, message: bytes) -> None:
self.message_type == MessageType.notify1 and self.body_type == BodyType.X04
):
self.set_body(C3Notify1MessageBody(super().body, data_offset=1))
elif self.message_type == MessageType.query and self.body_type == BodyType.X05:
self.set_body(C3QuerySilenceMessageBody(super().body, data_offset=1))
self.set_attr()
9 changes: 8 additions & 1 deletion tests/devices/c3/device_c3_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

import pytest

from midealocal.devices.c3 import C3DeviceMode, DeviceAttributes, MideaC3Device
from midealocal.devices.c3 import (
MideaC3Device,
)
from midealocal.devices.c3.const import C3DeviceMode, C3SilentLevel, DeviceAttributes
from midealocal.devices.c3.message import (
MessageQuery,
)
Expand Down Expand Up @@ -46,6 +49,10 @@ def test_initial_attributes(self) -> None:
assert self.device.attributes[DeviceAttributes.zone1_water_temp_mode] is False
assert self.device.attributes[DeviceAttributes.zone2_water_temp_mode] is False
assert self.device.attributes[DeviceAttributes.silent_mode] is False
assert (
self.device.attributes[DeviceAttributes.SILENT_LEVEL]
== C3SilentLevel.SILENT
)
assert self.device.attributes[DeviceAttributes.eco_mode] is False
assert self.device.attributes[DeviceAttributes.tbh] is False
assert self.device.attributes[DeviceAttributes.mode] == 1
Expand Down
Loading

0 comments on commit dcef500

Please sign in to comment.