Compare commits
	
		
			7 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 310d1bafd7 | |||
| 9e35dcf9cf | |||
| f9d0fa4ae8 | |||
| 11988c73a6 | |||
| 7b51caecca | |||
| 38d09e2ef5 | |||
| 3c7ad3f395 | 
| @ -242,15 +242,20 @@ class HonAppliance: | ||||
|         self._attributes = await self.api.load_attributes(self) | ||||
|         for name, values in self._attributes.pop("shadow").get("parameters").items(): | ||||
|             self._attributes.setdefault("parameters", {})[name] = values["parNewVal"] | ||||
|         if self._extra: | ||||
|             self._attributes = self._extra.attributes(self._attributes) | ||||
|  | ||||
|     async def load_statistics(self): | ||||
|         self._statistics = await self.api.load_statistics(self) | ||||
|         self._statistics |= await self.api.load_maintenance(self) | ||||
|  | ||||
|     async def update(self): | ||||
|     async def update(self, force=False): | ||||
|         now = datetime.now() | ||||
|         if not self._last_update or self._last_update < now - timedelta( | ||||
|             seconds=self._MINIMAL_UPDATE_INTERVAL | ||||
|         if ( | ||||
|             force | ||||
|             or not self._last_update | ||||
|             or self._last_update | ||||
|             < now - timedelta(seconds=self._MINIMAL_UPDATE_INTERVAL) | ||||
|         ): | ||||
|             self._last_update = now | ||||
|             await self.load_attributes() | ||||
| @ -286,9 +291,8 @@ class HonAppliance: | ||||
|             "statistics": self.statistics, | ||||
|             "additional_data": self._additional_data, | ||||
|             **self.command_parameters, | ||||
|             **self.attributes, | ||||
|         } | ||||
|         if self._extra: | ||||
|             return self._extra.data(result) | ||||
|         return result | ||||
|  | ||||
|     def diagnose(self, whitespace="  ", command_only=False): | ||||
| @ -298,8 +302,6 @@ class HonAppliance: | ||||
|             "statistics": self.statistics, | ||||
|             "additional_data": self._additional_data, | ||||
|         } | ||||
|         if self._extra and data.get("attributes"): | ||||
|             data = self._extra.data(data) | ||||
|         if command_only: | ||||
|             data.pop("attributes") | ||||
|             data.pop("appliance") | ||||
| @ -320,6 +322,12 @@ class HonAppliance: | ||||
|         ) | ||||
|         return result.replace(self.mac_address, "xx-xx-xx-xx-xx-xx") | ||||
|  | ||||
|     def sync_to_params(self, command_name): | ||||
|         command: HonCommand = self.commands.get(command_name) | ||||
|         for key, value in self.attributes.get("parameters", {}).items(): | ||||
|             if isinstance(value, str) and (new := command.parameters.get(key)): | ||||
|                 self.attributes["parameters"][key] = str(new.intern_value) | ||||
|  | ||||
|     def sync_command(self, main, target=None) -> None: | ||||
|         base: HonCommand = self.commands.get(main) | ||||
|         for command, data in self.commands.items(): | ||||
| @ -345,6 +353,7 @@ class HonApplianceTest(HonAppliance): | ||||
|         super().__init__(None, {}) | ||||
|         self._name = name | ||||
|         self.load_commands() | ||||
|         self.load_attributes() | ||||
|         self._info = self._appliance_model | ||||
|  | ||||
|     def load_commands(self): | ||||
|  | ||||
| @ -2,12 +2,14 @@ class ApplianceBase: | ||||
|     def __init__(self, appliance): | ||||
|         self.parent = appliance | ||||
|  | ||||
|     def data(self, data): | ||||
|     def attributes(self, data): | ||||
|         program_name = "No Program" | ||||
|         if program := int(data["attributes"]["parameters"].get("prCode", "0")): | ||||
|             if ids := self.parent.settings["startProgram.program"].ids: | ||||
|                 program_name = ids.get(program, program_name) | ||||
|         if program := int(data["parameters"].get("prCode", "0")): | ||||
|             if start_cmd := self.parent.settings.get("startProgram.program"): | ||||
|                 if ids := start_cmd.ids: | ||||
|                     program_name = ids.get(program, program_name) | ||||
|         data["programName"] = program_name | ||||
|         return data | ||||
|  | ||||
|     def settings(self, settings): | ||||
|         return settings | ||||
|  | ||||
| @ -2,9 +2,9 @@ from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(data) | ||||
|         if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["attributes"]["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("attributes", {}).get("activity")) | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("activity")) | ||||
|         return data | ||||
|  | ||||
| @ -2,17 +2,17 @@ from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(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" | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["parameters"]["temp"] = "0" | ||||
|             data["parameters"]["onOffStatus"] = "0" | ||||
|             data["parameters"]["remoteCtrValid"] = "0" | ||||
|             data["parameters"]["remainingTimeMM"] = "0" | ||||
|  | ||||
|         data["active"] = data["attributes"]["parameters"]["onOffStatus"] == "1" | ||||
|         data["active"] = data["parameters"]["onOffStatus"] == "1" | ||||
|  | ||||
|         if program := int(data["attributes"]["parameters"]["prCode"]): | ||||
|         if program := int(data["parameters"]["prCode"]): | ||||
|             ids = self.parent.settings["startProgram.program"].ids | ||||
|             data["programName"] = ids.get(program, "") | ||||
|  | ||||
|  | ||||
| @ -2,20 +2,20 @@ from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(data) | ||||
|         if data["attributes"]["parameters"]["holidayMode"] == "1": | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["parameters"]["holidayMode"] == "1": | ||||
|             data["modeZ1"] = "holiday" | ||||
|         elif data["attributes"]["parameters"]["intelligenceMode"] == "1": | ||||
|         elif data["parameters"]["intelligenceMode"] == "1": | ||||
|             data["modeZ1"] = "auto_set" | ||||
|         elif data["attributes"]["parameters"]["quickModeZ1"] == "1": | ||||
|         elif data["parameters"]["quickModeZ1"] == "1": | ||||
|             data["modeZ1"] = "super_cool" | ||||
|         else: | ||||
|             data["modeZ1"] = "no_mode" | ||||
|  | ||||
|         if data["attributes"]["parameters"]["quickModeZ2"] == "1": | ||||
|         if data["parameters"]["quickModeZ2"] == "1": | ||||
|             data["modeZ2"] = "super_freeze" | ||||
|         elif data["attributes"]["parameters"]["intelligenceMode"] == "1": | ||||
|         elif data["parameters"]["intelligenceMode"] == "1": | ||||
|             data["modeZ2"] = "auto_set" | ||||
|         else: | ||||
|             data["modeZ2"] = "no_mode" | ||||
|  | ||||
| @ -3,12 +3,12 @@ from pyhon.parameter.fixed import HonParameterFixed | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(data) | ||||
|         if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["attributes"]["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("attributes", {}).get("activity")) | ||||
|         data["pause"] = data["attributes"]["parameters"]["machMode"] == "3" | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("activity")) | ||||
|         data["pause"] = data["parameters"]["machMode"] == "3" | ||||
|         return data | ||||
|  | ||||
|     def settings(self, settings): | ||||
|  | ||||
							
								
								
									
										5
									
								
								pyhon/appliances/wc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								pyhon/appliances/wc.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     pass | ||||
| @ -2,12 +2,12 @@ from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(data) | ||||
|         if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["attributes"]["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("attributes", {}).get("activity")) | ||||
|         data["pause"] = data["attributes"]["parameters"]["machMode"] == "3" | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("activity")) | ||||
|         data["pause"] = data["parameters"]["machMode"] == "3" | ||||
|         return data | ||||
|  | ||||
|     def settings(self, settings): | ||||
|  | ||||
| @ -2,12 +2,12 @@ from pyhon.appliances.base import ApplianceBase | ||||
|  | ||||
|  | ||||
| class Appliance(ApplianceBase): | ||||
|     def data(self, data): | ||||
|         super().data(data) | ||||
|         if data["attributes"]["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["attributes"]["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("attributes", {}).get("activity")) | ||||
|         data["pause"] = data["attributes"]["parameters"]["machMode"] == "3" | ||||
|     def attributes(self, data): | ||||
|         data = super().attributes(data) | ||||
|         if data["lastConnEvent"]["category"] == "DISCONNECTED": | ||||
|             data["parameters"]["machMode"] = "0" | ||||
|         data["active"] = bool(data.get("activity")) | ||||
|         data["pause"] = data["parameters"]["machMode"] == "3" | ||||
|         return data | ||||
|  | ||||
|     def settings(self, settings): | ||||
|  | ||||
| @ -2,6 +2,7 @@ import logging | ||||
| from typing import Optional, Dict, Any, List, TYPE_CHECKING, Union | ||||
|  | ||||
| from pyhon import exceptions | ||||
| from pyhon.exceptions import ApiError | ||||
| from pyhon.parameter.base import HonParameter | ||||
| from pyhon.parameter.enum import HonParameterEnum | ||||
| from pyhon.parameter.fixed import HonParameterFixed | ||||
| @ -110,9 +111,14 @@ class HonCommand: | ||||
|     async def send(self) -> bool: | ||||
|         params = self.parameter_groups.get("parameters", {}) | ||||
|         ancillary_params = self.parameter_groups.get("ancillaryParameters", {}) | ||||
|         return await self.api.send_command( | ||||
|         ancillary_params.pop("programRules", None) | ||||
|         self.appliance.sync_to_params(self.name) | ||||
|         result = await self.api.send_command( | ||||
|             self._appliance, self._name, params, ancillary_params | ||||
|         ) | ||||
|         if not result: | ||||
|             raise ApiError("Can't send command") | ||||
|         return result | ||||
|  | ||||
|     @property | ||||
|     def categories(self) -> Dict[str, "HonCommand"]: | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import json | ||||
| import logging | ||||
| from datetime import datetime | ||||
| from pprint import pformat | ||||
| from typing import Dict, Optional | ||||
|  | ||||
| from aiohttp import ClientSession | ||||
| @ -188,6 +189,7 @@ class HonAPI: | ||||
|             if json_data.get("payload", {}).get("resultCode") == "0": | ||||
|                 return True | ||||
|             _LOGGER.error(await response.text()) | ||||
|             _LOGGER.error("%s - Payload:\n%s", url, pformat(data)) | ||||
|         return False | ||||
|  | ||||
|     async def appliance_configuration(self) -> Dict: | ||||
|  | ||||
| @ -134,9 +134,7 @@ class HonAuth: | ||||
|                 fw_uid, loaded_str = context[0] | ||||
|                 self._login_data.fw_uid = fw_uid | ||||
|                 self._login_data.loaded = json.loads(loaded_str) | ||||
|                 self._login_data.url = login_url.replace( | ||||
|                     "/".join(const.AUTH_API.split("/")[:-1]), "" | ||||
|                 ) | ||||
|                 self._login_data.url = login_url.replace(const.AUTH_API, "") | ||||
|                 return True | ||||
|             await self._error_logger(response) | ||||
|         return False | ||||
| @ -149,8 +147,8 @@ class HonAuth: | ||||
|             "descriptor": "apex://LightningLoginCustomController/ACTION$login", | ||||
|             "callingDescriptor": "markup://c:loginForm", | ||||
|             "params": { | ||||
|                 "username": quote(self._login_data.email), | ||||
|                 "password": quote(self._login_data.password), | ||||
|                 "username": self._login_data.email, | ||||
|                 "password": self._login_data.password, | ||||
|                 "startUrl": start_url, | ||||
|             }, | ||||
|         } | ||||
| @ -172,7 +170,7 @@ class HonAuth: | ||||
|         async with self._request.post( | ||||
|             const.AUTH_API + "/s/sfsites/aura", | ||||
|             headers={"Content-Type": "application/x-www-form-urlencoded"}, | ||||
|             data="&".join(f"{k}={json.dumps(v)}" for k, v in data.items()), | ||||
|             data="&".join(f"{k}={quote(json.dumps(v))}" for k, v in data.items()), | ||||
|             params=params, | ||||
|         ) as response: | ||||
|             if response.status == 200: | ||||
| @ -210,7 +208,7 @@ class HonAuth: | ||||
|                 url_search = re.findall( | ||||
|                     "href\\s*=\\s*[\"'](.*?)[\"']", await response.text() | ||||
|                 ) | ||||
|         url = "/".join(const.AUTH_API.split("/")[:-1]) + url_search[0] | ||||
|         url = const.AUTH_API + url_search[0] | ||||
|         async with self._request.get(url) as response: | ||||
|             if response.status != 200: | ||||
|                 await self._error_logger(response) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| AUTH_API = "https://he-accounts.force.com/SmartHome" | ||||
| AUTH_API = "https://account2.hon-smarthome.com" | ||||
| API_URL = "https://api-iot.he.services" | ||||
| API_KEY = "GRCqFhC6Gk@ikWXm1RmnSmX1cm,MxY-configuration" | ||||
| APP = "hon" | ||||
|  | ||||
| @ -12,3 +12,7 @@ class NoSessionException(Exception): | ||||
|  | ||||
| class NoAuthenticationException(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ApiError(Exception): | ||||
|     pass | ||||
|  | ||||
| @ -28,8 +28,8 @@ class HonParameter: | ||||
|         self.check_trigger(value) | ||||
|  | ||||
|     @property | ||||
|     def intern_value(self) -> str | float: | ||||
|         return str(self._value) if self._value is not None else "" | ||||
|     def intern_value(self) -> str: | ||||
|         return str(self.value) | ||||
|  | ||||
|     @property | ||||
|     def values(self) -> List[str]: | ||||
| @ -66,5 +66,18 @@ class HonParameter: | ||||
|     def triggers(self): | ||||
|         result = {} | ||||
|         for value, rules in self._triggers.items(): | ||||
|             result[value] = {rule.param_key: rule.param_value for _, rule in rules} | ||||
|             for _, rule in rules: | ||||
|                 if rule.extras: | ||||
|                     param = result.setdefault(value, {}) | ||||
|                     for extra_key, extra_value in rule.extras.items(): | ||||
|                         param = param.setdefault(extra_key, {}).setdefault( | ||||
|                             extra_value, {} | ||||
|                         ) | ||||
|                 else: | ||||
|                     param = result.setdefault(value, {}) | ||||
|                 if fixed_value := rule.param_data.get("fixedValue"): | ||||
|                     param[rule.param_key] = fixed_value | ||||
|                 else: | ||||
|                     param[rule.param_key] = rule.param_data.get("defaultValue", "") | ||||
|  | ||||
|         return result | ||||
|  | ||||
| @ -27,6 +27,10 @@ class HonParameterEnum(HonParameter): | ||||
|     def values(self, values) -> None: | ||||
|         self._values = values | ||||
|  | ||||
|     @property | ||||
|     def intern_value(self) -> str: | ||||
|         return str(self._value) if self._value is not None else str(self.values[0]) | ||||
|  | ||||
|     @property | ||||
|     def value(self) -> str | float: | ||||
|         return clean_value(self._value) if self._value is not None else self.values[0] | ||||
|  | ||||
| @ -16,27 +16,27 @@ class HonParameterRange(HonParameter): | ||||
|         self._min: float = str_to_float(attributes["minimumValue"]) | ||||
|         self._max: float = str_to_float(attributes["maximumValue"]) | ||||
|         self._step: float = str_to_float(attributes["incrementValue"]) | ||||
|         self._default: float = str_to_float(attributes.get("defaultValue", self._min)) | ||||
|         self._default: float = str_to_float(attributes.get("defaultValue", self.min)) | ||||
|         self._value: float = self._default | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return f"{self.__class__} (<{self.key}> [{self._min} - {self._max}])" | ||||
|         return f"{self.__class__} (<{self.key}> [{self.min} - {self.max}])" | ||||
|  | ||||
|     @property | ||||
|     def min(self) -> float: | ||||
|         return self._min | ||||
|  | ||||
|     @min.setter | ||||
|     def min(self, min: float) -> None: | ||||
|         self._min = min | ||||
|     def min(self, mini: float) -> None: | ||||
|         self._min = mini | ||||
|  | ||||
|     @property | ||||
|     def max(self) -> float: | ||||
|         return self._max | ||||
|  | ||||
|     @max.setter | ||||
|     def max(self, max: float) -> None: | ||||
|         self._max = max | ||||
|     def max(self, maxi: float) -> None: | ||||
|         self._max = maxi | ||||
|  | ||||
|     @property | ||||
|     def step(self) -> float: | ||||
| @ -50,18 +50,16 @@ class HonParameterRange(HonParameter): | ||||
|  | ||||
|     @property | ||||
|     def value(self) -> str | float: | ||||
|         return self._value if self._value is not None else self._min | ||||
|         return self._value if self._value is not None else self.min | ||||
|  | ||||
|     @value.setter | ||||
|     def value(self, value: str | float) -> None: | ||||
|         value = str_to_float(value) | ||||
|         if self._min <= value <= self._max and not (value - self._min) % self._step: | ||||
|         if self.min <= value <= self.max and not (value - self.min) % self.step: | ||||
|             self._value = value | ||||
|             self.check_trigger(value) | ||||
|         else: | ||||
|             raise ValueError( | ||||
|                 f"Allowed: min {self._min} max {self._max} step {self._step}" | ||||
|             ) | ||||
|             raise ValueError(f"Allowed: min {self.min} max {self.max} step {self.step}") | ||||
|  | ||||
|     @property | ||||
|     def values(self) -> List[str]: | ||||
|  | ||||
							
								
								
									
										107
									
								
								pyhon/rules.py
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								pyhon/rules.py
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| from dataclasses import dataclass | ||||
| from typing import List, Dict, TYPE_CHECKING | ||||
| from typing import List, Dict, TYPE_CHECKING, Any, Optional | ||||
|  | ||||
| from pyhon.parameter.enum import HonParameterEnum | ||||
| from pyhon.parameter.range import HonParameterRange | ||||
| @ -13,7 +13,8 @@ class HonRule: | ||||
|     trigger_key: str | ||||
|     trigger_value: str | ||||
|     param_key: str | ||||
|     param_value: str | ||||
|     param_data: Dict[str, Any] | ||||
|     extras: Optional[Dict[str, str]] = None | ||||
|  | ||||
|  | ||||
| class HonRuleSet: | ||||
| @ -23,40 +24,82 @@ class HonRuleSet: | ||||
|         self._parse_rule(rule) | ||||
|  | ||||
|     def _parse_rule(self, rule): | ||||
|         for entity_key, params in rule.items(): | ||||
|             entity_key = self._command.appliance.options.get(entity_key, entity_key) | ||||
|             for trigger_key, values in params.items(): | ||||
|                 trigger_key = trigger_key.replace("@", "") | ||||
|                 trigger_key = self._command.appliance.options.get( | ||||
|                     trigger_key, trigger_key | ||||
|                 ) | ||||
|                 for trigger_value, entity_value in values.items(): | ||||
|                     if entity_value.get("fixedValue") == f"@{entity_key}": | ||||
|                         continue | ||||
|                     self._rules.setdefault(trigger_key, []).append( | ||||
|                         HonRule( | ||||
|                             trigger_key, | ||||
|                             trigger_value, | ||||
|                             entity_key, | ||||
|                             entity_value.get("fixedValue"), | ||||
|                         ) | ||||
|         for param_key, params in rule.items(): | ||||
|             param_key = self._command.appliance.options.get(param_key, param_key) | ||||
|             for trigger_key, trigger_data in params.items(): | ||||
|                 self._parse_conditions(param_key, trigger_key, trigger_data) | ||||
|  | ||||
|     def _parse_conditions(self, param_key, trigger_key, trigger_data, extra=None): | ||||
|         trigger_key = trigger_key.replace("@", "") | ||||
|         trigger_key = self._command.appliance.options.get(trigger_key, trigger_key) | ||||
|         for multi_trigger_value, param_data in trigger_data.items(): | ||||
|             for trigger_value in multi_trigger_value.split("|"): | ||||
|                 if isinstance(param_data, dict) and "typology" in param_data: | ||||
|                     self._create_rule( | ||||
|                         param_key, trigger_key, trigger_value, param_data, extra | ||||
|                     ) | ||||
|                 elif isinstance(param_data, dict): | ||||
|                     if extra is None: | ||||
|                         extra = {} | ||||
|                     extra[trigger_key] = trigger_value | ||||
|                     for extra_key, extra_data in param_data.items(): | ||||
|                         self._parse_conditions(param_key, extra_key, extra_data, extra) | ||||
|  | ||||
|     def _create_rule( | ||||
|         self, param_key, trigger_key, trigger_value, param_data, extras=None | ||||
|     ): | ||||
|         if param_data.get("fixedValue") == f"@{param_key}": | ||||
|             return | ||||
|         self._rules.setdefault(trigger_key, []).append( | ||||
|             HonRule(trigger_key, trigger_value, param_key, param_data, extras) | ||||
|         ) | ||||
|  | ||||
|     def _duplicate_for_extra_conditions(self): | ||||
|         new = {} | ||||
|         for rules in self._rules.values(): | ||||
|             for rule in rules: | ||||
|                 if rule.extras is None: | ||||
|                     continue | ||||
|                 for key, value in rule.extras.items(): | ||||
|                     extras = rule.extras.copy() | ||||
|                     extras.pop(key) | ||||
|                     extras[rule.trigger_key] = rule.trigger_value | ||||
|                     new.setdefault(key, []).append( | ||||
|                         HonRule(key, value, rule.param_key, rule.param_data, extras) | ||||
|                     ) | ||||
|         for key, rules in new.items(): | ||||
|             for rule in rules: | ||||
|                 self._rules.setdefault(key, []).append(rule) | ||||
|  | ||||
|     def _add_trigger(self, parameter, data): | ||||
|         def apply(rule: HonRule): | ||||
|             if rule.extras is not None: | ||||
|                 for key, value in rule.extras.items(): | ||||
|                     if str(self._command.parameters.get(key)) != str(value): | ||||
|                         return | ||||
|             if param := self._command.parameters.get(rule.param_key): | ||||
|                 if value := rule.param_data.get("fixedValue", ""): | ||||
|                     if isinstance(param, HonParameterEnum) and set(param.values) != { | ||||
|                         str(value) | ||||
|                     }: | ||||
|                         param.values = [str(value)] | ||||
|                     elif isinstance(param, HonParameterRange): | ||||
|                         param.value = float(value) | ||||
|                         return | ||||
|                     param.value = str(value) | ||||
|                 elif rule.param_data.get("typology") == "enum": | ||||
|                     if isinstance(param, HonParameterEnum): | ||||
|                         if enum_values := rule.param_data.get("enumValues"): | ||||
|                             param.values = enum_values.split("|") | ||||
|                         if default_value := rule.param_data.get("defaultValue"): | ||||
|                             param.value = default_value | ||||
|  | ||||
|         parameter.add_trigger(data.trigger_value, apply, data) | ||||
|  | ||||
|     def patch(self): | ||||
|         self._duplicate_for_extra_conditions() | ||||
|         for name, parameter in self._command.parameters.items(): | ||||
|             if name not in self._rules: | ||||
|                 continue | ||||
|             for data in self._rules.get(name): | ||||
|  | ||||
|                 def apply(rule): | ||||
|                     if param := self._command.parameters.get(rule.param_key): | ||||
|                         if isinstance(param, HonParameterEnum) and set( | ||||
|                             param.values | ||||
|                         ) != {str(rule.param_value)}: | ||||
|                             param.values = [str(rule.param_value)] | ||||
|                         elif isinstance(param, HonParameterRange): | ||||
|                             param.value = float(rule.param_value) | ||||
|                             return | ||||
|                         param.value = str(rule.param_value) | ||||
|  | ||||
|                 parameter.add_trigger(data.trigger_value, apply, data) | ||||
|                 self._add_trigger(parameter, data) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	