FreshlyBrewedCode / pymee

a python library to interact with homee
MIT License
8 stars 4 forks source link

Expose the attributes options in pymee's HomeeAttributes class. #5

Closed Taraman17 closed 1 year ago

Taraman17 commented 1 year ago

An Attribute in Homee can have options. The currently known are:

At least the last one is useful for other applications acessing Homee. So it is desired to expose them in pymee.

There are two possible approaches:

Option 1

Iterate over the options and convert the dict to an object:

def __init__(self, attributeOptions):
    for key, value in attributeOptions.items():
        setattr(self, key, value)
pro con
- just a few lines of code - using code must check for presence of options to avoid errors
- only options that are present are added - intellisense or similiar tools are not available.
- will also add currently unknown entries

Option 2

Add getters for the known possible options and return empty values if they don't exist.

def __init__(self, attributeOptions):
    self._data = attributeOptions

@property
def can_observe(self) -> list:
    if "can_observe" in self._data:
        return self._data["can_observe"]
...
pro con
- parsing options error handling can be done here - longer code
- intellisense or similar tools available for applications using pymee - unknown options will be ignored
- every attribute has all options, but with empty values

@FreshlyBrewedCode: Since it is your project, I want to get your opinion on which approach to use before I do a pull request


Example code of an Attribute with options:

{
  'id': 38,
  'node_id': 3,
  'instance': 0,
  'minimum': 0,
  'maximum': 4, // 0 = Closed; 1 = Open; 2 = Stop; 3 = Closing; 4 = Opening
  'current_value': 1.0,
  'target_value': 1.0,
  'last_value': 4.0,
  'unit': 'n%2Fa',
  'step_value': 1.0,
  'editable': 1,
  'type': 135, // UP_DOWN
  'state': 1,
  'last_changed': 1687175680,
  'changed_by': 1,
  'changed_by_id': 0,
  'based_on': 1,
  'data': '',
  'name': '',
  'options': {
      'can_observe': [300],
      'observes': [75],
      'reverse_control_ui': True,
      'automations': ['toggle']
}
FreshlyBrewedCode commented 1 year ago

Thanks for the detailed explanation.

So from my point of view HomeAttribute (or really any thing in model.py) is only a convenience wrapper around the data returned by the API. It is really just used to "strong type" the data so that it is easier to work with (intelisense etc.). Which is why I would personally go with your Option 2. I would add a new class HomeeAttributeOptions that strong types all the options and return it from HomeeAttribute:

@property
def options(self) -> HomeeAttributeOptions:
    return HomeeAttributeOptions(self._data['options'])

or just assign self.options in __init__.

If an option is missing users could still access them via the raw data.

Taraman17 commented 1 year ago

Thank you for the quick reply.

Most interestingly the last part is exaclty my approach - this is how it looks like in my draft:

@property
def options(self) -> HomeeAttributeOptions:
    """The options collection of the attribute. Optional, not on every attribute."""
    return HomeeAttributeOptions(self._data["options"])

;-)