Skip to content

Commit

Permalink
Merge pull request #224 from sockless-coding/summer-mode
Browse files Browse the repository at this point in the history
Preset for +8/15 Summer House mode
  • Loading branch information
sockless-coding authored Jun 27, 2024
2 parents 832e651 + f597a10 commit 8e59941
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 52 deletions.
15 changes: 6 additions & 9 deletions custom_components/panasonic_cc/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from homeassistant.const import UnitOfTemperature

from . import PANASONIC_DEVICES
from .panasonic import PanasonicApiDevice

from .const import (
SUPPORT_FLAGS,
Expand Down Expand Up @@ -60,7 +61,7 @@ async def async_setup_entry(hass, entry, async_add_entities):

class PanasonicClimateDevice(ClimateEntity):

def __init__(self, api):
def __init__(self, api: PanasonicApiDevice):
"""Initialize the climate device."""
self._api = api
self._attr_hvac_action = HVACAction.IDLE
Expand Down Expand Up @@ -207,11 +208,7 @@ def preset_mode(self) -> Optional[str]:
"""Return the current preset mode, e.g., home, away, temp.
Requires SUPPORT_PRESET_MODE.
"""
eco = self._api.eco_mode
for key, value in PRESET_LIST.items():
if value == eco:
#_LOGGER.debug("Preset mode is {0}".format(key))
return key
return self._api.preset_mode

async def async_set_preset_mode(self, preset_mode):
"""Set preset mode."""
Expand All @@ -223,17 +220,17 @@ def preset_modes(self) -> Optional[List[str]]:
Requires SUPPORT_PRESET_MODE.
"""
#_LOGGER.debug("Preset modes are {0}".format(",".join(PRESET_LIST.keys())))
return list(PRESET_LIST.keys())
return self._api.available_presets

@property
def min_temp(self):
"""Return the minimum temperature."""
return 16
return self._api.min_temp

@property
def max_temp(self):
"""Return the maximum temperature."""
return 30
return self._api.max_temp

@property
def target_temp_step(self):
Expand Down
5 changes: 4 additions & 1 deletion custom_components/panasonic_cc/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

SENSOR_TYPE_TEMPERATURE = "temperature"

PRESET_8_15 = "+8/15"

SENSOR_TYPES = {
ATTR_INSIDE_TEMPERATURE: {
CONF_NAME: "Inside Temperature",
Expand Down Expand Up @@ -67,7 +69,8 @@
PRESET_LIST = {
PRESET_NONE: 'Auto',
PRESET_BOOST: 'Powerful',
PRESET_ECO: 'Quiet'
PRESET_ECO: 'Quiet',
PRESET_8_15: '+8/15'
}

OPERATION_LIST = {
Expand Down
2 changes: 1 addition & 1 deletion custom_components/panasonic_cc/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"domain": "panasonic_cc",
"name": "Panasonic Comfort Cloud",
"after_dependencies": ["http"],
"version": "1.0.48",
"version": "1.0.49",
"config_flow": true,
"documentation": "https://github.com/sockless-coding/panasonic_cc/",
"dependencies": [],
Expand Down
159 changes: 125 additions & 34 deletions custom_components/panasonic_cc/panasonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
from datetime import timedelta
import logging
from datetime import datetime
from functools import cached_property

from typing import Optional
from homeassistant.util import Throttle
from homeassistant.const import ATTR_TEMPERATURE
from homeassistant.core import HomeAssistant
from homeassistant.components.climate.const import ATTR_HVAC_MODE
from homeassistant.helpers.storage import Store
from .pcomfortcloud.apiclient import ApiClient
from .pcomfortcloud.panasonicdevice import PanasonicDevice
from .pcomfortcloud import constants

from .const import PRESET_LIST, OPERATION_LIST
from .const import PRESET_LIST, OPERATION_LIST, PRESET_8_15, PRESET_NONE, PRESET_ECO, PRESET_BOOST

_LOGGER = logging.getLogger(__name__)

Expand All @@ -25,6 +29,7 @@ def __init__(self, hass: HomeAssistant, api: ApiClient, device, force_outside_se
self.hass = hass
self._api = api
self.device = device
self._details: PanasonicDevice = None
self.force_outside_sensor = force_outside_sensor
self.enable_energy_sensor = enable_energy_sensor
self.id = device['id']
Expand All @@ -38,6 +43,8 @@ def __init__(self, hass: HomeAssistant, api: ApiClient, device, force_outside_se
self.current_power_counter = 0
self._available = True
self.constants = constants
self._store = Store(hass, version=1, key=f"panasonic_cc_{self.id}")


self._is_on = False
self._inside_temperature = None
Expand All @@ -53,8 +60,6 @@ def __init__(self, hass: HomeAssistant, api: ApiClient, device, force_outside_se

self.features = None



@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def update(self, **kwargs):
await self.do_update()
Expand Down Expand Up @@ -83,28 +88,23 @@ async def do_update(self):
self._available = False
_LOGGER.debug("Received no data for device {id}".format(**self.device))
return
self._details = data
try:
_LOGGER.debug("Data: {}".format(data))

if self.features is None:
self.features = data.get('features', None)

plst = data.get('parameters')
self._is_on = bool(plst.get('power').value)
if plst.get('temperatureInside') != 126:
self._inside_temperature = plst.get('temperatureInside')
if plst.get('temperatureOutside') != 126:
self._outside_temperature = plst.get('temperatureOutside')
if self._inside_temperature is None and self._outside_temperature is not None:
self._inside_temperature = self._outside_temperature
if plst.get('temperature') != 126:
self._target_temperature = plst.get('temperature')
self._fan_mode = plst.get('fanSpeed').name
self._swing_mode = plst.get('airSwingVertical').name
self._swing_lr_mode = plst.get('airSwingHorizontal').name
self._hvac_mode = plst.get('mode').name
self._eco_mode = plst.get('eco').name
self._nanoe_mode = plst.get('nanoe', None)
self._is_on = bool(data.parameters.power.value)
if data.parameters.inside_temperature is not None:
self._inside_temperature = data.parameters.inside_temperature
if data.parameters.outside_temperature is not None:
self._outside_temperature = data.parameters.outside_temperature
if data.parameters.target_temperature is not None:
self._target_temperature = data.parameters.target_temperature
self._fan_mode = data.parameters.fan_speed.name
self._swing_mode = data.parameters.vertical_swing_mode.name
self._swing_lr_mode = data.parameters.horizontal_swing_mode.name
self._hvac_mode = data.parameters.mode.name
self._eco_mode = data.parameters.eco_mode.name
self._nanoe_mode = data.parameters.nanoe_mode.name

except Exception as e:
_LOGGER.debug("Failed to set data for device {id}".format(**self.device))
Expand All @@ -122,7 +122,7 @@ async def do_update_energy(self):
_LOGGER.debug("Error trying to get device {id} state, probably expired token, trying to update it...".format(**self.device)) # noqa: E501
try:
await self._api.refresh_token()
data= await self._api.get_device(self.id) # noqa: E501
data= await self._api.history(self.id,"Month",today) # noqa: E501
except:
_LOGGER.debug("Failed to renew token for device {id}, giving up for now".format(**self.device)) # noqa: E501
return
Expand Down Expand Up @@ -246,6 +246,20 @@ def current_power(self):
if not self.enable_energy_sensor:
return None
return self.current_power_value

@property
def min_temp(self):
"""Return the minimum temperature."""
if self.in_summer_house_mode:
return 8
return 16

@property
def max_temp(self):
"""Return the maximum temperature."""
if self.in_summer_house_mode:
return 15 if self._details.features.summer_house == 2 else 10
return 30

async def turn_off(self):
await self.set_device(
Expand All @@ -258,17 +272,92 @@ async def turn_on(self):
{ "power": self.constants.Power.On }
)
await self.do_update()


@cached_property
def available_presets(self):
presets = [PRESET_NONE]
if self._details.features.quiet_mode:
presets.append(PRESET_ECO)
if self._details.features.powerful_mode:
presets.append(PRESET_BOOST)
if self._details.features.summer_house > 0:
presets.append(PRESET_8_15)
return presets

@property
def preset_mode(self):
if not self._details:
return PRESET_NONE
match self._details.parameters.eco_mode:
case constants.EcoMode.Quiet:
return PRESET_ECO
case constants.EcoMode.Powerful:
return PRESET_BOOST
if self.in_summer_house_mode:
return PRESET_8_15

return PRESET_NONE

@property
def in_summer_house_mode(self):
if not self._details:
return False
temp = self._details.parameters.target_temperature
i = 1 if temp - 8 > 0 else (0 if temp -8 else -1)
match self._details.features.summer_house:
case 1:
return i == 0 or temp == 10
case 2:
return i >= 0 and temp <= 15
case 3:
return i == 0 or temp == 10
return False

async def set_preset_mode(self, preset_mode: str) -> None:
"""Set new preset mode."""
_LOGGER.debug("Set %s ecomode %s", self.name, preset_mode)
await self.set_device(
{
"power": self.constants.Power.On,
"eco": self.constants.EcoMode[ PRESET_LIST[preset_mode] ]
})
data = {
"power": constants.Power.On
}
if self.in_summer_house_mode and preset_mode != PRESET_8_15:
await self._exit_summer_house_mode(data)

if PRESET_LIST[preset_mode] in self.constants.EcoMode:
data["eco"] = constants.EcoMode[ PRESET_LIST[preset_mode] ]
elif preset_mode == PRESET_8_15:
await self._enter_summer_house_mode()
data["mode"] = constants.OperationMode.Heat
data["eco"] = constants.EcoMode.Auto
data["temperature"] = 8
data["fanSpeed"] = constants.FanSpeed.High

await self.set_device(data)
await self.do_update()

async def _enter_summer_house_mode(self):
data = await self._store.async_load()
if data is None:
data = {}
data['mode'] = self._details.parameters.mode
data['ecoMode'] = self._details.parameters.eco_mode
data['targetTemperature'] = self._details.parameters.target_temperature
data['fanSpeed'] = self._details.parameters.fan_speed
await self._store.async_save(data)

async def _exit_summer_house_mode(self, device_data):
stored_data = await self._store.async_load()
if stored_data is None:
return
if 'mode' in stored_data:
device_data['mode'] = stored_data['mode']
if 'ecoMode' in stored_data:
device_data["eco"] = stored_data['ecoMode']
if 'targetTemperature' in stored_data:
device_data['temperature'] = stored_data['targetTemperature']
if 'fanSpeed' in stored_data:
device_data['fanSpeed'] = stored_data['fanSpeed']


async def set_temperature(self, **kwargs):
"""Set new target temperature."""
target_temp = kwargs.get(ATTR_TEMPERATURE)
Expand Down Expand Up @@ -302,12 +391,14 @@ async def set_fan_mode(self, fan_mode):
async def set_hvac_mode(self, hvac_mode):
"""Set operation mode."""
_LOGGER.debug("Set %s mode %s", self.name, hvac_mode)
data = {
'power': self.constants.Power.On
}
if self.in_summer_house_mode:
await self._exit_summer_house_mode(data)
data['mode'] = self.constants.OperationMode[OPERATION_LIST[hvac_mode]]

await self.set_device(
{
"power": self.constants.Power.On,
"mode": self.constants.OperationMode[OPERATION_LIST[hvac_mode]]
})
await self.set_device(data)

await self.do_update()

Expand Down
12 changes: 5 additions & 7 deletions custom_components/panasonic_cc/pcomfortcloud/apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from . import constants
from . import panasonicsession
from .panasonicdevice import PanasonicDevice

_current_time_zone = None
def get_current_time_zone():
Expand Down Expand Up @@ -116,15 +117,12 @@ async def history(self, device_id, mode, date, time_zone=""):



async def get_device(self, device_id):
async def get_device(self, device_id) -> PanasonicDevice:
device_guid = self._device_indexer.get(device_id)

if device_guid:
json_response = await self.execute_get(self._get_device_status_url(device_guid), "get_device", 200)
return {
'id': device_id,
'parameters': self._read_parameters(json_response['parameters'])
}
return PanasonicDevice(device_id, json_response)
return None

async def set_device(self, device_id, **kwargs):
Expand Down Expand Up @@ -173,10 +171,10 @@ async def set_device(self, device_id, **kwargs):
fan_auto = 0
device = await self.get_device(device_id)

if device and device['parameters']['airSwingHorizontal'].value == -1:
if device and device.parameters.horizontal_swing_mode == constants.AirSwingLR.Auto:
fan_auto = fan_auto | 1

if device and device['parameters']['airSwingVertical'].value == -1:
if device and device.parameters.vertical_swing_mode == constants.AirSwingUD.Auto:
fan_auto = fan_auto | 2

if air_x is not None:
Expand Down
2 changes: 2 additions & 0 deletions custom_components/panasonic_cc/pcomfortcloud/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class NanoeMode(Enum):
ModeG = 3
All = 4

INVALID_TEMPERATURE = 126

DEFAULT_X_APP_VERSION = "1.21.0"

MAX_VERSION_AGE = 5
Expand Down
Loading

0 comments on commit 8e59941

Please sign in to comment.