Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Homeworks support #52

Open
wants to merge 79 commits into
base: master
Choose a base branch
from
Open

Conversation

rzulian
Copy link
Contributor

@rzulian rzulian commented Apr 22, 2020

This PR is adding:

  • support for Homeworks QS.
  • support for recursive areas in naming
  • areas with IntegrationID are OccupancyGroup
  • revised standard naming for components and keypad components
  • OUTPUT to support movement raise, lower, stop, jogs(eg for motors)
  • buttons: support for actions
  • corrected led states
  • support for QS_IO_INTERFACE
  • support for phantom keypads
  • support for seetouch international keypads
  • support for CCI

Copy link
Owner

@thecynic thecynic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long lack of response, finally went through it all.

In the future I recommend you clean up your patchstack so that the changes collect related code. Seems like you just kept typing "git commit -m 'foo'" periodically, without organizing your improvements into logical changes :)

@jthop
Copy link

jthop commented May 13, 2020

Guys with more advanced Homeworks systems desperately need this branch merged. The default one can't handle phantoms, any VCRX stuff, international keypads, etc... the CSD001 detection was a great idea. Please, we need this... or can anyone tell me how to force Hassio to use this instead of the default????

@rzulian
Copy link
Contributor Author

rzulian commented May 13, 2020

@jthop I can share my version of the lutron component which is using this branch of pylutron.
I was waiting for this PR to be merged, to open a PR on the Hassio.

@jthop
Copy link

jthop commented May 13, 2020

@rzulian that would be great... I'm just not familiar with HA yet, and not clear how to force it to use this pylutron... I could obviously just replace the docker's pylutron, but not sure how to make it persistent across updates, etc... I've had my own Lutron program running for a while, to implement some custom keypad buttons in my house... but now I'm thinking I can just do everything with HA...

Also, for me the binary sensors for the occupancy groups don't seem to be working, do they for you? In my own software I see the correct occupancy events coming from the processor, but in HA my occupancy states never seem to be accurate.... not sure if that's another Homeworks vs ra thing or what?

@txwindsurfer
Copy link
Contributor

@jthop I can share my version of the lutron component which is using this branch of pylutron.
I was waiting for this PR to be merged, to open a PR on the Hassio.

I would be happy to test both the lutron component in Hassio and this branch of pylutron on my Homeworks QS system if you would like to share the lutron component.

@jthop
Copy link

jthop commented Jun 10, 2020

Oh yes, I would love to test as well....

@jthop
Copy link

jthop commented Jun 11, 2020

@txwindsurfer would love to see it... scratching my head why these major upgrades for homeworks take so long to be approved???

@thecynic
Copy link
Owner

thecynic commented Jun 13, 2020 via email

@jthop
Copy link

jthop commented Jun 14, 2020

@rzulian fwiw would be nice to have access to homework variables as well... They use command SYSVAR and have integration IDs just like everything else. they aren't reported by default, you have to do a "#MONITORING,10,1" to see them... just an idea, you guys are doing great.

led_logic = button_xml.get('LedLogic')
name = button_xml.get('Name')
led_logic = 0 if button_xml.get('LedLogic') is None else int(button_xml.get('LedLogic'))
name = f"keypad {keypad.id}: Btn {component_number}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still strongly dislike sticking all the other cruft into the name. It should be up to the client to decide how to combine the various names. cdheiser's recent change should allow everything to have a true unique identifier so none of this should be necessary for uniqueness.

Please remove this here and everywhere else, keeping the name as is (and removing engraving).

@@ -446,7 +446,8 @@ def __init__(self, host, user, password):
@property
def areas(self):
"""Return the areas that were discovered for this Lutron controller."""
return self._areas
# return self._areas
return tuple(area for area in self._areas)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh. Only reason I can see is if someone was taking the returned list and modifying it and you wanted to isolate us from that? Is that a problem somehow in HASS?

Since we don't do this everywhere else, I suggest you removed this and keep as is. If that's a worry somehow, it should be a separate PR to generate a copy for all these APIs to keep us safe, and we can discuss the merits then.

HOLD_RELEASED = 5


def __init__(self, lutron, keypad, name, num, button_type, direction):
def __init__(self, lutron, keypad, name, engraving, num, button_type, direction, led_logic):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, LED state, ok. Yeah I only have radio ra2 and their feature-set is quite minimal (I get on/off 😞 ), sadly. I'm jelly of Homeworks. I'd do anything for that double-tap :)

I really don't want to expose things like led_logic as bare ints without proper enum constants is that it ends up spreading weird droppings like this with no concept of what they mean, and suddenly HASS has a random 5 somewhere. You need to add a better API for the client to figure these things out. At least provide a named enum for 0-3 that we can keep stable, and also add a CUSTOM or INTEGRATION for your 5.

Thought, actually this is all a property of an LED, and not of the button, isn't it? Why can't you instead delegate the LED control to the Led class?

Also, Does LED state change gets its own event? I don't remember.

button_type=button_type,
direction=direction)
direction=direction,
led_logic=led_logic)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem is that you have like 20+ changes with stuff scatted all over them with no logical breakdown between the individual changes. So I'm sure this gets used, but in some other git commit. Github almost incentivizes bad habits :( I'm used to, and prefer, seeing one git commit per logical change, and a stack of commits that logicall follow each other adding incremental functionality.

@robby-d
Copy link

robby-d commented Aug 24, 2020

Hi, I wanted to note that as of Homeworks v16, and with the new Homeworks QSX processor (released earlier this year) it appears that telnet support is being discontinued in favor of Lutron's LEAP API. I can't find published specs to that yet.

More info: https://forums.lutron.com/showthread.php/15404-Is-QSX-replacing-QS-processors-or-will-they-serve-different-purposes

Basically, it looks like Lutron just removed telnet support entirely in Homeworks v16. No depreciation warning/time period.

@jthop
Copy link

jthop commented Aug 24, 2020 via email

@thecynic
Copy link
Owner

thecynic commented Aug 26, 2020 via email

@rzulian
Copy link
Contributor Author

rzulian commented Sep 23, 2020

@thecynic : could you please have a final review and approve this PR?

@txwindsurfer @jthop : If you want to try the current branch I've a repo with the Lutron custom component here https://github.com/rzulian/lutron_custom_component

@txwindsurfer
Copy link
Contributor

Great work @rzulian! I added your files into custom_components/lutron and upgraded to the latest version of HA (0.116.0.dev20200923) on my test system and now I have the buttons on my keypads mapped as scenes (albeit no unique id so can't manage in UI). I also now have occupancy binary_sensors mapped for each room but since I don't have occupancy sensors I am guessing they are default entries in the Lutron schema. From a naming convention, I wasn't using the 1st floor or 2nd floor designation in the names of my objects so if I adopt your integration I will need to change lots of names. Adding unique ids to the objects would greatly help in managing the names from the UI. Thanks for sharing and your continued work!!

@rzulian
Copy link
Contributor Author

rzulian commented Sep 24, 2020

@txwindsurfer :

  1. scene UI. my bad :( I've uploaded a new version that fix this, including in the scene name the keypad_name
  2. occupancy sensors. I'm assuming that if your area has an integration ID there is a occupancy sensor. This is how it's working on my installation. Is it your setup different?
  3. naming. I'm using the full path for the area name because I've duplicated area names in different locations. I could add an option on the HA config to use the full path or only the area name.

@txwindsurfer
Copy link
Contributor

@rzulian:

I appreciate again your work and realize that designing for may different systems is difficult if not impossible. So with that premise, I kindly offer the following comments:

1a) First ignore my previous comment on unique ids for the scenes as it really doesn't make sense to edit scenes in the UI as an edited scene cannot be passed back to Lutron. Editing scenes for Lutron keypads is best done in Lutron Designer.

1b) Second, the addition of the keypad_name didn't add information for my installation since the DeviceGroup Name already identified the keypad.
My keypad buttons now looks like:
1st Floor Entry keypad: 25: Btn 1
Rather than the keypad number or the button number, I would love to have Engraving which identifies the button in english. DeviceGroup Name + Engraving would look like:
1st Floor Entry Sconces
And, finally if I had the choice to drop the full name for the scene I would get:
Entry Sconces
which would be just perfect for my installation.

  1. Lutron Designer tells me I do not have any occupancy sensors (and I don't), however each area in the XML has this entry which might be causing the creation of occupancy sensors.
    -<Area UUID="859" Name="Front Porch" SortOrder="0" OccupancyGroupAssignedToID="861" IntegrationID="20">
    Since I do not have an occupancy sensor, I cannot give you an example of what a real XML occupancy sensor entry would look like, but having an integration ID doesn't mean there is an occupancy sensor in my installation.

Just FYI, the XML file also has an OccupancyGroups section even though I don't have any sensors so that should be ignored.

Thanks again for your great work. It is really appreciated

@rzulian
Copy link
Contributor Author

rzulian commented Oct 13, 2020

@txwindsurfer
Regarding 1b. I've evaluated to use engraving in names, but I've multiple buttons in different keypads in the same area with the same Engraving, so the names are not unique. I don't know if I can use a friendly name instead. Any suggestion?
Regarding 2. I'm using Lutron designer 9.4. I've had to add to the integration ID the areas with an occupancy sensor to make sure I'm getting the occupancy sensors.
Screenshot 2020-10-13 at 14 34 55

@txwindsurfer
Copy link
Contributor

@rzulian
1.b. I didn't think about the same engraving being on the same keypad--that would be a problem. Having engraving as the Friendly Name would be great. You might consider concatenating the engraving to the end of the device+button string but then the string might be too long.
2. I am using Designer 10.7 and the versions do change quite a bit I have heard. In fact, the biggest problem I suppose with doing QS in HA is there are to many different devices and firmware/software versions. No idea how to account for them all. It is easy enough to tailor what you have done to my setup so thanks again for the great work.

@rzulian
Copy link
Contributor Author

rzulian commented Oct 15, 2020

@txwindsurfer
1.b I meant the same engraving being on different keypad in the same room. Think about large rooms, you might need to have the ability to recall the same scenario from different keypads
2. I don't have access to 10.7, as I'm not a certified Lutron developer :(

ronluna added a commit to ronluna/pylutron that referenced this pull request Mar 25, 2024
ronluna added a commit to ronluna/pylutron that referenced this pull request Mar 25, 2024
Initial merge for Homeworks QS support from
thecynic#52
@txwindsurfer
Copy link
Contributor

@rzulian @thecynic Thank you so much for all the attention to the Lutron Integration. Could you please add 'HWI_SLIM' to the list of keypads around lines 302. With this addition, my keypad buttons show up as intended on the event bus and as event entities.

From my DbXmlInfo for one of the keypads:
Device Name="CSD 001" UUID="2104" SerialNumber="4026536452" IntegrationID="71" DeviceType="HWI_SLIM" GangPosition="0" SortOrder="0">

@rzulian
Copy link
Contributor Author

rzulian commented May 3, 2024

@txwindsurfer
I'm going to add the support for "HWI_SLIM". I'm also working on a new version of the custom component, which I have aligned to the official "lutron" component, thanks to @ronluna.
I'm adding the ability to:

  1. flag if you want to refresh data from Lutron each time you instantiate the integration
  2. flag if you want to use the full path as area name, which is useful if your layout has areas included in other areas
  3. flag if you want to prepend the area name to the device name (e.g you have multiple lights named "Applique", in multiple rooms. Using this flag you will have room1 Applique, room2 Applique, etc)

@cdheiser cdheiser self-requested a review May 8, 2024 01:25
@cdheiser cdheiser self-assigned this May 8, 2024
@cdheiser
Copy link
Collaborator

cdheiser commented May 8, 2024

Can you sync and rebase this CL to resolve merge conflicts and we can do another pass?

@cdheiser
Copy link
Collaborator

cdheiser commented May 8, 2024

Looks like the rebase didn't work quite right. You have files like publish.yml that shouldn't be present but this PR believes it's adding them (when they already exist).

@rzulian
Copy link
Contributor Author

rzulian commented May 8, 2024

I don't know what happened for the publish.yml, but the other files are correct.

@rzulian rzulian force-pushed the homeworks-support branch from 39c2c3d to 56ab4e7 Compare May 9, 2024 06:41
@rzulian
Copy link
Contributor Author

rzulian commented May 9, 2024

@cdheiser what about this new rebase?

@@ -737,6 +742,18 @@ def level(self, new_level):
# self._lutron.send(Lutron.OP_EXECUTE, Output._CMD_TYPE,
# Output._ACTION_ZONE_LEVEL, new_level, fade_time, delay)

def start_raising(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these used on anything other than Shades? The Shade class already implements this.

# keypad standard name is CSD 001, we use the integration ID nme instead
name = keypad_xml.get('Name')
if (keypad_xml.get('Name') == "CSD 001"):
name = f"keypad {keypad_xml.get('IntegrationID')}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something to handle in Home Assistant. As long as these have UUIDs, then home assistant can handle 2 keypads with the same name.

keypad = self._parse_keypad(device_xml, device_group)
area.add_keypad(keypad)
elif device_xml.get('DeviceType') == 'MOTION_SENSOR':
motion_sensor = self._parse_motion_sensor(device_xml)
area.add_sensor(motion_sensor)
#elif device_xml.get('DeviceType') == 'VISOR_CONTROL_RECEIVER':
else:
#phantom keypad doesn't have a DeviceType
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think about here is where the logic for a phantom keypad should live. Check if it's CSD 001, and if so, call self._parse_phantom_keypad(...). Put in the custom logic for the device type, etc... there.

Copy link
Contributor Author

@rzulian rzulian May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"CSD 001" is used for example for INTERNATIONAL_SEETOUCH_KEYPAD. Note that I've no UUID in any component. I don't know if this due to the Homeworks QS or it's version.

Phantom keypads are not the CDS 001 keypads, but the one that you can create in the integration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cdheiser can we resolve this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok... I'm just trying to follow along and make suggestions on how to get some custom handling out of the keypad class. I'd like it to not care about odd variants. Odd variants should either be prepped outside the class initialization, or as their own distinct type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the device_type before the the parse_keypad

# keypad standard name is CSD 001, we use the integration ID nme instead
name = keypad_xml.get('Name')
if (keypad_xml.get('Name') == "CSD 001"):
name = f"keypad {keypad_xml.get('IntegrationID')}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you post some sample XML in the PR? A lot has gone into using UUIDs in the home assistant integration and we should make sure it's not going to cause problems.

In theory, as long as everything has uniquie integration IDs, the fallback mechanism of using integration IDs should still result in unique devices and entities that can be named/renamed as you'd like. But if someone configures their setup to have 5 devices all named keypad in the same room, who are we to tell them they should be unique names?

keypad = self._parse_keypad(device_xml, device_group)
area.add_keypad(keypad)
elif device_xml.get('DeviceType') == 'MOTION_SENSOR':
motion_sensor = self._parse_motion_sensor(device_xml)
area.add_sensor(motion_sensor)
#elif device_xml.get('DeviceType') == 'VISOR_CONTROL_RECEIVER':
else:
#phantom keypad doesn't have a DeviceType
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok... I'm just trying to follow along and make suggestions on how to get some custom handling out of the keypad class. I'd like it to not care about odd variants. Odd variants should either be prepped outside the class initialization, or as their own distinct type.

button_type = button_xml.get('ButtonType')
direction = button_xml.get('Direction')
led_logic = 0 if button_xml.get('LedLogic') is None else int(button_xml.get('LedLogic'))
name = f"Btn {component_number}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to significantly change behavior for users of this library. Why not keep the name as the engraving?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This is the XML for the CSD.
Screenshot 2024-05-12 alle 10 19 48

As you can see the name is always CSD 001, and there can be multiple keypads in the same area. So CSD 001 is not the name. We could infer the name from the DeviceGroup instead, which is actually the location of the device, as in my XML a deviceGroup contains always only one keypad, but is that true for everyone?
Screenshot 2024-05-12 alle 10 32 32

  1. Phantom keypads. Is not an odd variant, it's included in the documentation and it's a very useful way to create custom button to launch scenes. I agree with you that inferring that it's a phantom keypad from an else is not the best method.

  2. I understand this, but the was an original mistake. The name of the button in my XML is always "Button x", and you cannot customise it. So that should be the name, not the engraving. Using the engraving can be an option on the HA side, as I'm proposing to do with the location name in the area name, and to use the device name in the keypad components and events. Moreover it's not unusual to have multiple keypads on large rooms, that have button with the same engraving, so the name it's not unique.

Screenshot 2024-05-12 alle 10 33 33

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we could try to keep the replies attached to the code they're about, it'll make the review easier to manage.

Both RadioRA2 and Homeworks appear to have the same quirk:

  1. The button names are practically worthless (non-descriptive)
  2. Engravings can be rather common

This nuance is already handled in Home Assistant today. So I'm trying to understand why you'd want significantly different behavior for Homeworks. I agree that this library probably should have stayed true to the data model and exported engraving and name as separate properties, and I'd be happy to address that in a separate PR. But for this one, I think we should stay consistent.

Or to put it another way: The addition of Homeworks should in no way change the behavior for RadioRA2 users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we don't address this problem on the HA side instead? Use a flag "Use Engraving as Button Name", default True, and let people decide?
In my case I have 34 keypads. Every keypad has btn1 as the main light for the room, with "Luce" as engraving. As it it's I would end up with 34 buttons and scenes with "Luce_x" as entity_id, and I would have to change each entity id to something meaningful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we could try to keep the replies attached to the code they're about, it'll make the review easier to manage.

I would, but in github for a lot of comments I cannot add replies, but only at the end of a group.

@@ -737,6 +742,18 @@ def level(self, new_level):
# self._lutron.send(Lutron.OP_EXECUTE, Output._CMD_TYPE,
# Output._ACTION_ZONE_LEVEL, new_level, fade_time, delay)

def start_raising(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at documentation, jogging is ONLY in Homeworks, so it would make more sense to me to have:

class Motor(Shade):

And add jogging there.

Copy link
Collaborator

@cdheiser cdheiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, we need to be careful not to change behavior for RadioRA2 users. Fixing idosyncracies can be done in a separate PR.

I still don't see anything that tells me where these phantom keypads come from. Can you post a complete XML to pastebin or similar?

@rzulian
Copy link
Contributor Author

rzulian commented May 12, 2024

Below a phantom keypad. There are no properties. And the Name is CDS 001

<Device Name="CSD 001" IntegrationID="151" GangPosition="0" SortOrder="0">
<Components>
<Component ComponentNumber="1" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="2" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="3" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="4" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="5" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="6" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="7" ComponentType="BUTTON">...</Component>
<Component ComponentNumber="2001" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112538"/>
</Component>
<Component ComponentNumber="2002" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112548"/>
</Component>
<Component ComponentNumber="2003" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112558"/>
</Component>
<Component ComponentNumber="2004" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112568"/>
</Component>
<Component ComponentNumber="2005" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112661"/>
</Component>
<Component ComponentNumber="2006" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="112658"/>
</Component>
<Component ComponentNumber="2007" ComponentType="LED">
<LED isReverseLogic="false" ProgrammingModelID="113438"/>
</Component>
</Components>
</Device>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants