Skip to content

Commit

Permalink
Detect appliance class more accurately (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
bm1549 authored Dec 2, 2021
1 parent 1ef156b commit ab6209c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,6 @@ dmypy.json

# PyCharm
.idea/

# Frigidaire creds
config.ini
56 changes: 31 additions & 25 deletions frigidaire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,9 @@ class FrigidaireException(Exception):
pass


class ApplianceClass(Enum):
AIR_CONDITIONER = "K"
DEHUMIDIFIER = "N"

@property
def destination(self) -> str:
if self == ApplianceClass.AIR_CONDITIONER:
return 'AC1'
elif self == ApplianceClass.DEHUMIDIFIER:
return 'DH1'
else:
raise FrigidaireException(f'Destination field needs to be set for class {self}')
class Destination(str, Enum):
AIR_CONDITIONER = "AC1"
DEHUMIDIFIER = "DH1"


class HaclCode(str, Enum):
Expand Down Expand Up @@ -131,12 +122,6 @@ def for_code(self, hacl_code: HaclCode) -> Optional[ApplianceDetail]:

class Appliance:
def __init__(self, args: Dict):
# The second digit in the serial number indicates appliance class
# https://www.electrical-forensics.com/MajorAppliances/ElectroluxDateCodes.html
try:
self.appliance_class: ApplianceClass = ApplianceClass(args['fields']['NASerialNumber'][1])
except (KeyError, ValueError) as exc:
raise FrigidaireException(f'Unknown appliance class for appliance: {args}') from exc
self.appliance_type: str = args['appliance_type']
self.appliance_id: str = args['appliance_id']
self.pnc: str = args['pnc']
Expand All @@ -145,6 +130,8 @@ def __init__(self, args: Dict):
self.mac: str = args['mac']
self.cpv: str = args['cpv']
self.nickname: str = args['nickname']
# Assume a device is an AC until overridden
self.destination = Destination.AIR_CONDITIONER

@property
def query_string(self) -> str:
Expand Down Expand Up @@ -317,18 +304,37 @@ def get_appliances(self) -> List[Appliance]:
"""
logging.debug('Listing appliances')

try:
def generate_appliance(raw_appliance: Union[Dict, List]) -> Appliance:
"""
Generates an appliance given a raw_appliance. This will make a second call to the Frigidaire appliance
details to figure out what source we should be using. We discard the rest of the response from appliance
details since everything else (except for source) is subject to change later on
:param raw_appliance: The raw output of the Frigidaire API for the appliance
:return: The appliance augmented with a destination
"""
appliance = Appliance(raw_appliance)
appliance_details = self.get_appliance_details(appliance)
appliance.destination = appliance_details.for_code(HaclCode.AC_MODE).source
return appliance

def get_appliances_inner():
"""
Actually calls the API for Frigidaire and creates an Appliance. This is useful because we'll sometimes need
to re-authenticate
:return: The appliances that are associated with the Frigidaire account
"""
appliances = self.get_request(
f'/user-appliance-reg/users/{self.username}/appliances?country=US&includeFields=true'
)
return list(map(Appliance, appliances))

return list(map(generate_appliance, appliances))

try:
return get_appliances_inner()
except FrigidaireException:
logging.debug('Listing appliances failed - attempting to re-authenticate')
self.re_authenticate()
appliances = self.get_request(
f'/user-appliance-reg/users/{self.username}/appliances?country=US&includeFields=true'
)
return list(map(Appliance, appliances))
return get_appliances_inner()

def get_appliance_details(self, appliance: Appliance) -> ApplianceDetails:
"""
Expand Down Expand Up @@ -361,7 +367,7 @@ def execute_action(self, appliance: Appliance, action: List[Component]) -> None:
'operationMode': 'EXE',
'version': 'ad',
'source': 'RP1',
'destination': appliance.appliance_class.destination,
'destination': appliance.destination,
}

try:
Expand Down
18 changes: 15 additions & 3 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import configparser
import logging

from frigidaire import Action, Power, Mode, FanSpeed, Frigidaire, HaclCode, Component

if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)

username = '[email protected]'
password = 'password'
session_key = 'get_this_from_authenticate'
# Create a config file at config.ini to reduce the risk of accidentally committing credentials
# You can use the following contents as a starting point
"""
[credentials]
[email protected]
Password=password
"""
config = configparser.ConfigParser()
config.read('config.ini')
credentials = config['credentials'] or {}

username = credentials.get('username')
password = credentials.get('password')
session_key = credentials.get('session_key', fallback=None)

frigidaire = Frigidaire(
username,
Expand Down

0 comments on commit ab6209c

Please sign in to comment.