Skip to content

Commit

Permalink
Adding support for alternate ayla softener
Browse files Browse the repository at this point in the history
  • Loading branch information
rewardone committed Oct 27, 2023
1 parent 1c350ef commit 4d4c631
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 24 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ayla_iot_unofficial"
version = "1.0.10"
version = "1.1.0"
authors = [
{ name="Reward One", email="[email protected]" },
]
Expand Down
2 changes: 1 addition & 1 deletion src/ayla_iot_unofficial/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
AylaReadOnlyPropertyError,
)

__version__ = '1.0.10'
__version__ = '1.1.0'
2 changes: 1 addition & 1 deletion src/ayla_iot_unofficial/ayla_iot_unofficial.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def get_devices(self, update: bool = True) -> List[Device]:
for d in self.list_devices():
if d["product_name"] in ["Vacuum","SharkIQ"]:
devices.append(Vacuum (self, d, europe=self.europe))
elif d["product_name"] in ["Softener"]:
elif d["product_name"] in ["Softener","Smart HE"]:
devices.append(Softener(self, d, europe=self.europe))
else:
devices.append(Device (self, d, europe=self.europe))
Expand Down
93 changes: 72 additions & 21 deletions src/ayla_iot_unofficial/device.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Basic non-device-specific data object"""

from .exc import AylaReadOnlyPropertyError
from base64 import b64encode
from enum import Enum, IntEnum, unique
from logging import getLogger
from requests import get
from collections import abc, defaultdict
from datetime import datetime
from enum import Enum, IntEnum, unique
from logging import getLogger
from pprint import pformat
from re import findall
from requests import get
from typing import Any, Dict, Iterable, List, Optional, Set, Union, TYPE_CHECKING
from .exc import AylaReadOnlyPropertyError

try:
from ujson import loads
Expand Down Expand Up @@ -201,6 +202,7 @@ def get_property_value(self, property_name: PropertyName) -> Any:
"""Get the value of a property from the properties dictionary"""
if isinstance(property_name, Enum):
property_name = property_name.value

return self.property_values[property_name]

def set_property_value(self, property_name: PropertyName, value: PropertyValue):
Expand Down Expand Up @@ -483,19 +485,43 @@ class Softener(Device):
def __init__(self, ayla_api: "AylaApi", device_dct: Dict, europe: bool = False):
super().__init__(ayla_api, device_dct, europe)

# init should call update() and properties should be available
self.avg_daily_usage = self.get_property_value("avg_daily_usage")
self.current_flow_rate = self.get_property_value("current_flow_rate")
self.capacity_remaining_gallons = self.get_property_value("capacity_remaining_gallons")
self.hardness_in_grains_per_gal = self.get_property_value("hardness_in_grains_per_gal")
self.days_since_last_regen = self.get_property_value("days_since_last_regen")
self.last_regen_date_time = self.get_property_value("last_regen_date_time")
self.away_mode_water_use = self.get_property_value("away_mode_water_use")
self.valve_position = self.get_property_value("valve_position")
self.total_gallons_today = self.get_property_value("total_gallons_today")
self.error_flags = self.get_property_value("error_flags")
self.total_gallons_since_install= self.get_property_value("total_gallons_since_install")
self.total_regens_since_install = self.get_property_value("total_regens_since_install")
self.alternate_mapping = {
"aqua_sensor_Zmin" : "aqua_sensor_Zmin_1",
"aqua_sensor_Zratio_current": "aqua_sensor_Zratio_curr_1",
"BD_rinse" : "bd_rinse",
"capacity_remaining_gallons": "capacity_remaining_volume_1",
"days_since_last_regen" : "days_since_last_regen_1",
"error_flags" : "system_error_flags",
"flow_profiles_max_flow" : "flow_profiles_max_flow_lim",
"flow_profiles_min_flow" : "flow_profiles_min_flow_lim",
"gbe_fw_version" : "gbx_fw_version",
"hardness_in_grains_per_gal": "hardness_value",
"iron_setting" : "iron",
"last_regen_date_time" : "last_regen_date_time_1",
"next_regen_on_date" : "next_regen_date_time",
"regen_interval_days_setting":"regen_interval_days",
"salt_dosage_in_lbs" : "salt_dosage",
"sbt_salt_level_low" : "low_salt_level",
"set_vacation_mode" : "set_away_mode",
"total_gallons_since_install":"water_usage_since_install_1",
"total_gallons_today" : "total_water_usage_today_1",
"unit_status" : "unit_status_1",
"valve_position" : "valve_position_1"
}

# # init should call update() and properties should be available
# self.avg_daily_usage = self.get_property_value("avg_daily_usage")
# self.current_flow_rate = self.get_property_value("current_flow_rate")
# self.capacity_remaining_gallons = self.get_property_value("capacity_remaining_gallons")
# self.hardness_in_grains_per_gal = self.get_property_value("hardness_in_grains_per_gal")
# self.days_since_last_regen = self.get_property_value("days_since_last_regen")
# self.last_regen_date_time = self.get_property_value("last_regen_date_time")
# self.away_mode_water_use = self.get_property_value("away_mode_water_use")
# self.valve_position = self.get_property_value("valve_position")
# self.total_gallons_today = self.get_property_value("total_gallons_today")
# self.error_flags = self.get_property_value("error_flags")
# self.total_gallons_since_install= self.get_property_value("total_gallons_since_install")
# self.total_regens_since_install = self.get_property_value("total_regens_since_install")
self.avg_daily_properties = ["avg_sun","avg_mon","avg_tue","avg_wed","avg_thr","avg_fri","avg_sat"]
self.daily_usage_properties = ["daily_usage_day_1", "daily_usage_day_2", "daily_usage_day_3", "daily_usage_day_4", "daily_usage_day_5", "daily_usage_day_6", "daily_usage_day_7"]
self.hourly_usage_properties = ["hourly_usage_hour_1", "hourly_usage_hour_2", "hourly_usage_hour_3", "hourly_usage_hour_4", "hourly_usage_hour_5", "hourly_usage_hour_6", "hourly_usage_hour_7", "hourly_usage_hour_8", "hourly_usage_hour_9", "hourly_usage_hour_10", "hourly_usage_hour_11", "hourly_usage_hour_12", "hourly_usage_hour_13", "hourly_usage_hour_14", "hourly_usage_hour_15", "hourly_usage_hour_16", "hourly_usage_hour_17", "hourly_usage_hour_18", "hourly_usage_hour_19", "hourly_usage_hour_20", "hourly_usage_hour_21", "hourly_usage_hour_22", "hourly_usage_hour_23", "hourly_usage_hour_24"]
Expand All @@ -519,6 +545,19 @@ def set_datapoint_payload(self, property, value) -> Dict:
]
}

def get_property_value(self, property_name: PropertyName) -> Any:
"""Get the value of a property from the properties dictionary"""
if isinstance(property_name, Enum):
property_name = property_name.value

if property_name in self.properties_full.keys():
return self.property_values[property_name]
elif self.alternate_mapping:
if self.alternate_mapping[property_name] in self.properties_full.keys():
return self.property_values[self.alternate_mapping[property_name]]
else:
return False

def set_property_value(self, property_name: PropertyName, value: PropertyValue):
"""Update a property, overload from device"""
if isinstance(property_name, Enum):
Expand Down Expand Up @@ -688,7 +727,10 @@ def start_vacation_mode(self):
Needs testing. Set vacation mode value from 0 (default) to 255 (max).
Properties and values may vary per manufacturer.
"""
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
if "vacation_mode" in self.properties_full.keys():
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
elif "away_mode" in self.properties_full.keys():
PropertyName = "away_mode" # because _clean property, 'set' is removed ... "set_away_mode"
PropertyValue = 1
self.set_property_value(PropertyName, PropertyValue)
return True
Expand All @@ -698,7 +740,10 @@ async def async_start_vacation_mode(self):
Needs testing. Set vacation mode value from 0 (default) to 255 (max).
Properties and values may vary per manufacturer.
"""
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
if "vacation_mode" in self.properties_full.keys():
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
elif "away_mode" in self.properties_full.keys():
PropertyName = "away_mode" # because _clean property, 'set' is removed ... "set_away_mode"
PropertyValue = 1
await self.async_set_property_value(PropertyName, PropertyValue)
return True
Expand All @@ -708,7 +753,10 @@ def stop_vacation_mode(self):
Needs testing. Set vacation mode value from 255 (max) to 0 (default).
Properties and values may vary per manufacturer.
"""
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
if "vacation_mode" in self.properties_full.keys():
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
elif "away_mode" in self.properties_full.keys():
PropertyName = "away_mode" # because _clean property, 'set' is removed ... "set_away_mode"
PropertyValue = 0
self.set_property_value(PropertyName, PropertyValue)
return True
Expand All @@ -718,7 +766,10 @@ async def async_stop_vacation_mode(self):
Needs testing. Set vacation mode value from 255 (max) to 0 (default).
Properties and values may vary per manufacturer.
"""
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
if "vacation_mode" in self.properties_full.keys():
PropertyName = "vacation_mode" # because _clean property, 'set' is removed ... "set_vacation_mode"
elif "away_mode" in self.properties_full.keys():
PropertyName = "away_mode" # because _clean property, 'set' is removed ... "set_away_mode"
PropertyValue = 0
await self.async_set_property_value(PropertyName, PropertyValue)
return True
Expand Down

0 comments on commit 4d4c631

Please sign in to comment.