Compare commits

...

21 Commits

Author SHA1 Message Date
5db13a90e7 Fix some stuff for hoover appliances 2023-04-24 04:33:00 +02:00
9ee5dbc956 Get program name by prcode 2023-04-23 21:42:44 +02:00
d4c6ccdce3 Use parameter optional 2023-04-23 20:15:07 +02:00
9594b9ebd8 Use firmware version optional 2023-04-23 19:28:56 +02:00
b011d98e07 Expose fixed parameter as setting 2023-04-23 16:21:34 +02:00
ad864286fc Use firmware id optional 2023-04-23 14:40:39 +02:00
13cff8caa0 Bump version to 8.2 2023-04-23 03:35:13 +02:00
5fc6245806 Get values for every parameter 2023-04-22 23:08:44 +02:00
1dad0e14b8 Handle special dry level 11 2023-04-22 23:08:24 +02:00
b04c601ad6 Add log for empty token 2023-04-21 23:51:35 +02:00
3ec0f5a006 Merge pull request #12 from MiguelAngelLV/main
Oven overwrite
2023-04-19 20:18:32 +02:00
78bc85132f Black Style 2023-04-19 20:12:52 +02:00
191928287f Override Oven attributes when is disconnected 2023-04-19 19:29:59 +02:00
c0aab8b99d Merge remote-tracking branch 'origin/main' 2023-04-19 18:57:13 +02:00
b37715d0ca Bump version to 0.8.0 2023-04-19 17:37:55 +02:00
411effd814 Fix disappearing programs 2023-04-17 00:37:55 +02:00
a68dcac379 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	pyhon/appliance.py
2023-04-16 16:37:11 +02:00
40cc0013a5 Override Oven attributes when is disconnected 2023-04-16 11:36:10 +02:00
f2aa3dc8fd Merge remote-tracking branch 'origin/main'
# Conflicts:
#	pyhon/appliances/ov.py
2023-04-16 09:58:00 +02:00
e887371bec expose ancillary parameter in settings 2023-04-16 04:23:08 +02:00
18b0ecdd68 Override Oven attributes when is disconnected 2023-04-08 22:24:14 +02:00
15 changed files with 95 additions and 20 deletions

View File

@ -1,16 +1,21 @@
import importlib import importlib
import logging
from contextlib import suppress from contextlib import suppress
from typing import Optional, Dict, Any from typing import Optional, Dict, Any
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from pyhon import helper from pyhon import helper
from pyhon.commands import HonCommand from pyhon.commands import HonCommand
from pyhon.parameter.base import HonParameter
from pyhon.parameter.fixed import HonParameterFixed from pyhon.parameter.fixed import HonParameterFixed
if TYPE_CHECKING: if TYPE_CHECKING:
from pyhon import HonAPI from pyhon import HonAPI
_LOGGER = logging.getLogger(__name__)
class HonAppliance: class HonAppliance:
def __init__( def __init__(
self, api: Optional["HonAPI"], info: Dict[str, Any], zone: int = 0 self, api: Optional["HonAPI"], info: Dict[str, Any], zone: int = 0
@ -29,7 +34,7 @@ class HonAppliance:
try: try:
self._extra = importlib.import_module( self._extra = importlib.import_module(
f"pyhon.appliances.{self.appliance_type.lower()}" f"pyhon.appliances.{self.appliance_type.lower()}"
).Appliance() ).Appliance(self)
except ModuleNotFoundError: except ModuleNotFoundError:
self._extra = None self._extra = None
@ -165,7 +170,8 @@ class HonAppliance:
def settings(self): def settings(self):
result = {} result = {}
for name, command in self._commands.items(): for name, command in self._commands.items():
for key, setting in command.settings.items(): for key in command.setting_keys:
setting = command.settings.get(key, HonParameter(key, {}))
result[f"{name}.{key}"] = setting result[f"{name}.{key}"] = setting
if self._extra: if self._extra:
return self._extra.settings(result) return self._extra.settings(result)
@ -214,4 +220,4 @@ class HonAppliance:
{"commands": helper.create_command(self.commands)}, {"commands": helper.create_command(self.commands)},
whitespace="\u200B \u200B ", whitespace="\u200B \u200B ",
) )
return result.replace(self.mac_address, "12-34-56-78-90-ab") return result.replace(self.mac_address, "xx-xx-xx-xx-xx-xx")

View File

@ -1,4 +1,7 @@
class Appliance: class Appliance:
def __init__(self, appliance):
self.parent = appliance
def data(self, data): def data(self, data):
if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED":
data["attributes"]["parameters"]["machMode"] = "0" data["attributes"]["parameters"]["machMode"] = "0"

17
pyhon/appliances/ov.py Normal file
View File

@ -0,0 +1,17 @@
class Appliance:
def __init__(self, appliance):
self.parent = appliance
def data(self, data):
if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED":
data["attributes"]["parameters"]["temp"] = "0"
data["attributes"]["parameters"]["onOffStatus"] = "0"
data["attributes"]["parameters"]["remoteCtrValid"] = "0"
data["attributes"]["parameters"]["remainingTimeMM"] = "0"
data["active"] = data["attributes"]["parameters"]["onOffStatus"] == "1"
return data
def settings(self, settings):
return settings

View File

@ -1,10 +1,22 @@
from pyhon.parameter.fixed import HonParameterFixed
class Appliance: class Appliance:
def __init__(self, appliance):
self.parent = appliance
def data(self, data): def data(self, data):
if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED":
data["attributes"]["parameters"]["machMode"] = "0" data["attributes"]["parameters"]["machMode"] = "0"
data["active"] = bool(data.get("attributes", {}).get("activity")) data["active"] = bool(data.get("attributes", {}).get("activity"))
data["pause"] = data["attributes"]["parameters"]["machMode"] == "3" data["pause"] = data["attributes"]["parameters"]["machMode"] == "3"
if program := int(data["attributes"]["parameters"]["prCode"]):
ids = self.parent.settings["startProgram.program"].ids
data["programName"] = ids.get(program, "")
return data return data
def settings(self, settings): def settings(self, settings):
dry_level = settings.get("startProgram.dryLevel")
if isinstance(dry_level, HonParameterFixed) and dry_level.value == "11":
settings.pop("startProgram.dryLevel", None)
return settings return settings

View File

@ -1,4 +1,7 @@
class Appliance: class Appliance:
def __init__(self, appliance):
self.parent = appliance
def data(self, data): def data(self, data):
if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED":
data["attributes"]["parameters"]["machMode"] = "0" data["attributes"]["parameters"]["machMode"] = "0"

View File

@ -1,4 +1,7 @@
class Appliance: class Appliance:
def __init__(self, appliance):
self.parent = appliance
def data(self, data): def data(self, data):
if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED":
data["attributes"]["parameters"]["machMode"] = "0" data["attributes"]["parameters"]["machMode"] = "0"

View File

@ -24,7 +24,7 @@ class HonCommand:
self._api: HonAPI = api self._api: HonAPI = api
self._appliance: "HonAppliance" = appliance self._appliance: "HonAppliance" = appliance
self._name: str = name self._name: str = name
self._programs: Optional[Dict[str, "HonCommand"]] = programs or {} self._programs: Optional[Dict[str, "HonCommand"]] = programs
self._program_name: str = program_name self._program_name: str = program_name
self._description: str = attributes.get("description", "") self._description: str = attributes.get("description", "")
self._parameters: Dict[str, HonParameter] = self._create_parameters( self._parameters: Dict[str, HonParameter] = self._create_parameters(
@ -89,8 +89,6 @@ class HonCommand:
for key, parameter in ( for key, parameter in (
command._parameters | command._ancillary_parameters command._parameters | command._ancillary_parameters
).items(): ).items():
if isinstance(parameter, HonParameterFixed):
continue
if key not in keys: if key not in keys:
keys.append(key) keys.append(key)
return keys return keys
@ -108,7 +106,6 @@ class HonCommand:
@property @property
def settings(self) -> Dict[str, HonParameter]: def settings(self) -> Dict[str, HonParameter]:
"""Parameters with typology enum and range"""
return { return {
s: param s: param
for s in self.setting_keys for s in self.setting_keys

View File

@ -12,7 +12,7 @@ from pyhon.connection.auth import HonAuth
from pyhon.connection.handler.anonym import HonAnonymousConnectionHandler from pyhon.connection.handler.anonym import HonAnonymousConnectionHandler
from pyhon.connection.handler.hon import HonConnectionHandler from pyhon.connection.handler.hon import HonConnectionHandler
_LOGGER = logging.getLogger() _LOGGER = logging.getLogger(__name__)
class HonAPI: class HonAPI:
@ -74,13 +74,15 @@ class HonAPI:
"applianceType": appliance.appliance_type, "applianceType": appliance.appliance_type,
"code": appliance.info["code"], "code": appliance.info["code"],
"applianceModelId": appliance.appliance_model_id, "applianceModelId": appliance.appliance_model_id,
"firmwareId": appliance.info["eepromId"],
"macAddress": appliance.mac_address, "macAddress": appliance.mac_address,
"fwVersion": appliance.info["fwVersion"],
"os": const.OS, "os": const.OS,
"appVersion": const.APP_VERSION, "appVersion": const.APP_VERSION,
"series": appliance.info["series"], "series": appliance.info["series"],
} }
if firmware_id := appliance.info.get("eepromId"):
params["firmwareId"] = firmware_id
if firmware_version := appliance.info.get("fwVersion"):
params["fwVersion"] = firmware_version
url: str = f"{const.API_URL}/commands/v1/retrieve" url: str = f"{const.API_URL}/commands/v1/retrieve"
async with self._hon.get(url, params=params) as response: async with self._hon.get(url, params=params) as response:
result: Dict = (await response.json()).get("payload", {}) result: Dict = (await response.json()).get("payload", {})

View File

@ -228,7 +228,10 @@ class HonAuth:
except json.JSONDecodeError: except json.JSONDecodeError:
await self._error_logger(response) await self._error_logger(response)
return False return False
self._cognito_token = json_data["cognitoUser"]["Token"] self._cognito_token = json_data.get("cognitoUser", {}).get("Token", "")
if not self._cognito_token:
_LOGGER.error(json_data)
raise exceptions.HonAuthenticationError()
return True return True
async def authenticate(self) -> None: async def authenticate(self) -> None:

View File

@ -1,3 +1,6 @@
from pyhon.parameter.base import HonParameter
def key_print(data, key="", start=True): def key_print(data, key="", start=True):
result = "" result = ""
if isinstance(data, list): if isinstance(data, list):
@ -44,12 +47,21 @@ def pretty_print(data, key="", intend=0, is_list=False, whitespace=" "):
return result return result
def get_parameter(command, parameter):
if programs := command.programs:
for program in programs.values():
if data := program.settings.get(parameter):
return data
return command.settings.get(parameter)
def create_command(commands, concat=False): def create_command(commands, concat=False):
result = {} result = {}
for name, command in commands.items(): for name, command in commands.items():
if not concat: if not concat:
result[name] = {} result[name] = {}
for parameter, data in command.settings.items(): for parameter in command.setting_keys:
data = get_parameter(command, parameter)
if data.typology == "enum": if data.typology == "enum":
value = data.values value = data.values
elif data.typology == "range": elif data.typology == "range":

View File

@ -47,7 +47,7 @@ class Hon:
async def _create_appliance(self, appliance_data: Dict[str, Any], zone=0) -> None: async def _create_appliance(self, appliance_data: Dict[str, Any], zone=0) -> None:
appliance = HonAppliance(self._api, appliance_data, zone=zone) appliance = HonAppliance(self._api, appliance_data, zone=zone)
if appliance.mac_address is None: if appliance.mac_address == "":
return return
await asyncio.gather( await asyncio.gather(
*[ *[

View File

@ -1,4 +1,4 @@
from typing import Dict, Any from typing import Dict, Any, List
class HonParameter: class HonParameter:
@ -17,6 +17,10 @@ class HonParameter:
def value(self) -> str | float: def value(self) -> str | float:
return self._value if self._value is not None else "0" return self._value if self._value is not None else "0"
@property
def values(self) -> List[str]:
return list(str(self.value))
@property @property
def category(self) -> str: def category(self) -> str:
return self._category return self._category

View File

@ -1,4 +1,4 @@
from typing import List, TYPE_CHECKING from typing import List, TYPE_CHECKING, Dict
from pyhon.parameter.enum import HonParameterEnum from pyhon.parameter.enum import HonParameterEnum
@ -13,7 +13,7 @@ class HonParameterProgram(HonParameterEnum):
super().__init__(key, {}) super().__init__(key, {})
self._command = command self._command = command
self._value: str = command.program self._value: str = command.program
self._values: List[str] = list(command.programs) self._programs: Dict[str, "HonCommand"] = command.programs
self._typology: str = "enum" self._typology: str = "enum"
@property @property
@ -25,9 +25,18 @@ class HonParameterProgram(HonParameterEnum):
if value in self.values: if value in self.values:
self._command.program = value self._command.program = value
else: else:
raise ValueError(f"Allowed values {self._values}") raise ValueError(f"Allowed values {self.values}")
@property @property
def values(self) -> List[str]: def values(self) -> List[str]:
values = [v for v in self._values if all(f not in v for f in self._FILTER)] values = [v for v in self._programs if all(f not in v for f in self._FILTER)]
return sorted(values) return sorted(values)
@property
def ids(self):
values = {
int(p.parameters["prCode"].value): n
for i, (n, p) in enumerate(self._programs.items())
if "iot_" not in n and p.parameters.get("prCode")
}
return dict(sorted(values.items()))

View File

@ -1,4 +1,4 @@
from typing import Dict, Any from typing import Dict, Any, List
from pyhon.parameter.base import HonParameter from pyhon.parameter.base import HonParameter
@ -47,3 +47,7 @@ class HonParameterRange(HonParameter):
raise ValueError( raise ValueError(
f"Allowed: min {self._min} max {self._max} step {self._step}" f"Allowed: min {self._min} max {self._max} step {self._step}"
) )
@property
def values(self) -> List[str]:
return [str(i) for i in range(int(self.min), int(self.max) + 1, int(self.step))]

View File

@ -7,7 +7,7 @@ with open("README.md", "r") as f:
setup( setup(
name="pyhOn", name="pyhOn",
version="0.8.0b6", version="0.9.0",
author="Andre Basche", author="Andre Basche",
description="Control hOn devices with python", description="Control hOn devices with python",
long_description=long_description, long_description=long_description,