Skip to content

Commit

Permalink
Add support for all 3 energy formats (#282)
Browse files Browse the repository at this point in the history
* Add support for a 3rd alternate energy format.

The 3 formats appear to be:
- BCD
- Binary
- Binary with energy reduced by a power of 10
  • Loading branch information
mill1000 authored Jan 7, 2025
1 parent f00d364 commit 9dbf236
Show file tree
Hide file tree
Showing 15 changed files with 71 additions and 26 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ Name | Default | Description
**Show All Presets** | False | Show all presets regardless of device's reported capabilities.
**Additional Operation Modes** | Empty | Additional HVAC modes to make available in case the device's capabilities are incorrect.
**Maximum Connection Lifetime** | Empty | Limit the time (in seconds) a connection to the device will be used before reconnecting. If left blank, the connection will persist indefinitely. If your device disconnects at regular intervals, set this to a value below the interval.
**Use Alternate Energy Format** | False | Use an alternative data format when decoding energy and power data from the device.
**Energy Format** | Default | Select alternative data formats for decoding energy and power data from the device.<br> Options: <ul><li>`Default` - BCD format</li><li>`Alternate A` - Binary format</li><li>`Alternate B` - Binary format, energy scaled by 1/10</li></ul>


## Resolving Connectivity Issues
Some users have reported issue with their devices periodically becoming unavailable, and with logs full of warnings and errors. This is almost always due to the device terminating the existing connection and briefly rejecting new connections.
Expand Down
19 changes: 15 additions & 4 deletions custom_components/midea_ac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from msmart.device import AirConditioner as AC
from msmart.lan import AuthenticationError

from .const import (CONF_KEY, CONF_MAX_CONNECTION_LIFETIME,
CONF_USE_ALTERNATE_ENERGY_FORMAT, DOMAIN)
from .const import (CONF_ENERGY_FORMAT, CONF_KEY, CONF_MAX_CONNECTION_LIFETIME,
DOMAIN, EnergyFormat)
from .coordinator import MideaDeviceUpdateCoordinator

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -51,9 +51,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
device.set_max_connection_lifetime(lifetime)

# Configure energy format
if config_entry.options.get(CONF_USE_ALTERNATE_ENERGY_FORMAT):
if (energy_format := config_entry.options.get(CONF_ENERGY_FORMAT)) != EnergyFormat.DEFAULT:
_LOGGER.info(
"Using alternate energy format for device ID %s.", device.id)
"Using alternate energy format %s for device ID %s.", energy_format, device.id)
device.use_alternate_energy_format = True

# Configure token and k1 as needed
Expand Down Expand Up @@ -103,6 +103,17 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
hass.config_entries.async_update_entry(
config_entry, unique_id=str(config_entry.unique_id), minor_version=2)

# 1.2 -> 1.3: Convert alternate energy boolean option to enum
if config_entry.minor_version == 2:
new_options = {**config_entry.options}
if new_options.pop("use_alternate_energy_format", False):
new_options[CONF_ENERGY_FORMAT] = EnergyFormat.ALTERNATE_B
else:
new_options[CONF_ENERGY_FORMAT] = EnergyFormat.DEFAULT

hass.config_entries.async_update_entry(
config_entry, options=new_options, minor_version=3)

_LOGGER.debug("Migration to configuration version %s.%s successful.",
config_entry.version, config_entry.minor_version)

Expand Down
27 changes: 19 additions & 8 deletions custom_components/midea_ac/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.selector import (CountrySelector,
CountrySelectorConfig)
CountrySelectorConfig,
SelectSelector,
SelectSelectorConfig,
SelectSelectorMode)
from msmart.const import DeviceType
from msmart.device import AirConditioner as AC
from msmart.discover import Discover
from msmart.lan import AuthenticationError

from .const import (CONF_ADDITIONAL_OPERATION_MODES, CONF_BEEP,
CONF_CLOUD_COUNTRY_CODES, CONF_DEFAULT_CLOUD_COUNTRY,
CONF_FAN_SPEED_STEP, CONF_KEY,
CONF_ENERGY_FORMAT, CONF_FAN_SPEED_STEP, CONF_KEY,
CONF_MAX_CONNECTION_LIFETIME, CONF_SHOW_ALL_PRESETS,
CONF_TEMP_STEP, CONF_USE_ALTERNATE_ENERGY_FORMAT,
CONF_USE_FAN_ONLY_WORKAROUND, DOMAIN)
CONF_TEMP_STEP, CONF_USE_FAN_ONLY_WORKAROUND, DOMAIN,
EnergyFormat)

_DEFAULT_OPTIONS = {
CONF_BEEP: True,
Expand All @@ -32,7 +35,7 @@
CONF_SHOW_ALL_PRESETS: False,
CONF_ADDITIONAL_OPERATION_MODES: None,
CONF_MAX_CONNECTION_LIFETIME: None,
CONF_USE_ALTERNATE_ENERGY_FORMAT: False,
CONF_ENERGY_FORMAT: EnergyFormat.DEFAULT,
}

_CLOUD_CREDENTIALS = {
Expand All @@ -45,7 +48,7 @@ class MideaConfigFlow(ConfigFlow, domain=DOMAIN):
"""Config flow for Midea Smart AC."""

VERSION = 1
MINOR_VERSION = 2
MINOR_VERSION = 3

async def async_step_user(self, _) -> FlowResult:
"""Handle a config flow initialized by the user."""
Expand Down Expand Up @@ -281,8 +284,16 @@ async def async_step_init(self, user_input=None) -> FlowResult:
description={"suggested_value": options.get(CONF_ADDITIONAL_OPERATION_MODES, None)}): cv.string,
vol.Optional(CONF_MAX_CONNECTION_LIFETIME,
description={"suggested_value": options.get(CONF_MAX_CONNECTION_LIFETIME, None)}): vol.All(vol.Coerce(int), vol.Range(min=30)),
vol.Optional(CONF_USE_ALTERNATE_ENERGY_FORMAT,
default=options.get(CONF_USE_ALTERNATE_ENERGY_FORMAT, False)): cv.boolean,
vol.Optional(CONF_ENERGY_FORMAT,
default=options.get(
CONF_ENERGY_FORMAT, EnergyFormat.DEFAULT)
): SelectSelector(
SelectSelectorConfig(
options=[e.value for e in EnergyFormat],
translation_key="energy_format",
mode=SelectSelectorMode.DROPDOWN,
)
),
})

return self.async_show_form(step_id="init", data_schema=data_schema)
10 changes: 9 additions & 1 deletion custom_components/midea_ac/const.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from enum import StrEnum, auto

DOMAIN = "midea_ac"

CONF_KEY = "k1"
Expand All @@ -8,8 +10,14 @@
CONF_ADDITIONAL_OPERATION_MODES = "additional_operation_modes"
CONF_SHOW_ALL_PRESETS = "show_all_presets"
CONF_MAX_CONNECTION_LIFETIME = "max_connection_lifetime"
CONF_USE_ALTERNATE_ENERGY_FORMAT = "use_alternate_energy_format"
CONF_ENERGY_FORMAT = "energy_format"
CONF_CLOUD_COUNTRY_CODES = ["DE", "KR", "US"]
CONF_DEFAULT_CLOUD_COUNTRY = "US"

PRESET_IECO = "ieco"


class EnergyFormat(StrEnum):
DEFAULT = auto()
ALTERNATE_A = auto()
ALTERNATE_B = auto()
11 changes: 8 additions & 3 deletions custom_components/midea_ac/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
from .const import CONF_ENERGY_FORMAT, DOMAIN, EnergyFormat
from .coordinator import MideaCoordinatorEntity, MideaDeviceUpdateCoordinator

_LOGGER = logging.getLogger(__name__)
Expand All @@ -30,6 +30,11 @@ async def async_setup_entry(
# Fetch coordinator from global data
coordinator = hass.data[DOMAIN][config_entry.entry_id]

# Configure energy format
energy_scale = 1.0
if config_entry.options.get(CONF_ENERGY_FORMAT) == EnergyFormat.ALTERNATE_B:
energy_scale = .1

entities = [
# Temperature sensors
MideaSensor(coordinator,
Expand All @@ -50,14 +55,14 @@ async def async_setup_entry(
UnitOfEnergy.KILO_WATT_HOUR,
"total_energy_usage",
state_class=SensorStateClass.TOTAL,
scale=.1 if coordinator.device.use_alternate_energy_format else 1.0),
scale=energy_scale),
MideaEnergySensor(coordinator,
"current_energy_usage",
SensorDeviceClass.ENERGY,
UnitOfEnergy.KILO_WATT_HOUR,
"current_energy_usage",
state_class=SensorStateClass.TOTAL_INCREASING,
scale=.1 if coordinator.device.use_alternate_energy_format else 1.0),
scale=energy_scale),
MideaEnergySensor(coordinator,
"real_time_power_usage",
SensorDeviceClass.POWER,
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"show_all_presets": "Mostrar tots els preajustaments",
"additional_operation_modes": "Mètodes d'operació addicionals",
"max_connection_lifetime": "Temps màxim de connexió",
"use_alternate_energy_format": "Utilitzar format d'energia alternatiu"
"energy_format": "Utilitzar format d'energia alternatiu"
},
"data_description": {
"temp_step": "Mida del pas de la consigna de temperatura",
Expand Down
11 changes: 10 additions & 1 deletion custom_components/midea_ac/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"show_all_presets": "Show All Presets",
"additional_operation_modes": "Additional Operation Modes",
"max_connection_lifetime": "Maximum Connection Lifetime",
"use_alternate_energy_format": "Use Alternate Energy Format"
"energy_format": "Energy Format"
},
"data_description": {
"temp_step": "Step size for temperature set point",
Expand All @@ -66,6 +66,15 @@
}
}
},
"selector": {
"energy_format": {
"options": {
"default": "Default",
"alternate_a": "Alternate A",
"alternate_b": "Alternate B"
}
}
},
"services": {
"set_follow_me": {
"name": "Set follow me",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/eu.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"show_all_presets": "Erakutsi Aurrezarpen Guztiak",
"additional_operation_modes": "Eragiketa-Modu Gehigarriak",
"max_connection_lifetime": "Gehienezko Konexio-Denbora",
"use_alternate_energy_format": "Erabili Ordezko Energia Formatua"
"energy_format": "Erabili Ordezko Energia Formatua"
},
"data_description": {
"temp_step": "Tenperaturaren ezarpen-punturako urratsaren tamaina",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"show_all_presets": "Afficher tous les préréglages",
"additional_operation_modes": "Modes de fonctionnement supplémentaires",
"max_connection_lifetime": "Durée maximale de connexion",
"use_alternate_energy_format": "Utiliser un format d'énergie alternatif"
"energy_format": "Utiliser un format d'énergie alternatif"
},
"data_description": {
"temp_step": "Taille du palier pour le réglage de la température",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"show_all_presets": "Minden előbeállítás megjelenítése",
"additional_operation_modes": "További üzemmódok",
"max_connection_lifetime": "Maximális kapcsolat időtartama",
"use_alternate_energy_format": "Alternatív energia formátum használata"
"energy_format": "Alternatív energia formátum használata"
},
"data_description": {
"temp_step": "A hőmérséklet beállítás lépésköze",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"show_all_presets": "Mostra tutte le preimpostazioni",
"additional_operation_modes": "Modalità aggiuntive",
"max_connection_lifetime": "Durata massima della connessione",
"use_alternate_energy_format": "Usa formato alternativo per l'energia"
"energy_format": "Usa formato alternativo per l'energia"
},
"data_description": {
"temp_step": "Incremento per la configurazione della temperatura",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"show_all_presets": "Pokaż wszystkie ustawienia wstępne",
"additional_operation_modes": "Dodatkowe tryby pracy",
"max_connection_lifetime": "Maksymalny czas połączenia",
"use_alternate_energy_format": "Użyj alternatywnego formatu energii"
"energy_format": "Użyj alternatywnego formatu energii"
},
"data_description": {
"temp_step": "Wielkość kroku dla nastawy temperatury",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/sk.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"show_all_presets": "Zobraziť všetky predvoľby",
"additional_operation_modes": "Ďalšie prevádzkové režimy",
"max_connection_lifetime": "Maximálna životnosť pripojenia",
"use_alternate_energy_format": "Použiť alternatívny formát energie"
"energy_format": "Použiť alternatívny formát energie"
},
"data_description": {
"temp_step": "Veľkosť kroku pre nastavenú hodnotu teploty",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/midea_ac/translations/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"show_all_presets": "Показати всі передналаштування",
"additional_operation_modes": "Додаткові режими роботи",
"max_connection_lifetime": "Максимальний час підключення",
"use_alternate_energy_format": "Використовувати альтернативний формат енергії"
"energy_format": "Використовувати альтернативний формат енергії"
},
"data_description": {
"temp_step": "Розмір кроку для налаштування температури",
Expand Down
Binary file modified docs/options.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9dbf236

Please sign in to comment.