gurumitts / pylutron-caseta

Apache License 2.0
153 stars 97 forks source link

Initial Support for RA3 #90

Closed johninaustin closed 2 years ago

johninaustin commented 2 years ago

These changes add initial support for RA3 processors.

RA3 pairing requires the device SSL certificate chain. The command-line pairing tool has been updated to include the full chain.

The existing Caseta Bridge implementation was generally left unchanged.

RA3 returns an empty body upon /device query. This is used as a flag to stop processing Caseta queries, and instead attempt RA3 (and possibly QSX) interrogation.

At this time there is no identified API to match Devices with Zones. Zones are masquerading as devices.

To support device type queries, the Zone's DeviceType was included in LEAP_DEVICE_TYPES so devices can be properly identified.

This does not yet support scenes, occupancy sensors, or LEDs. Those should all be included at a later date.

swails commented 2 years ago

Why'd this get closed?

dcode commented 2 years ago

Not sure why this was closed, but I was able to extract quite a bit of API info that I think would be useful. Haven't gotten around to actually coding it up, but I captured some markdown notes of requests and responses.

Most usefully, I was able to:

One big thing I haven't figured out is how to enumerate all occupancy group IDs. On the box with Designer, you can get the occupancy group IDs from the sqlite database, but I haven't been able to get the RA3 processor to tell me. The query in the existing python module here returns "No content". Seems like there has to be some link from area to occupancygroup.

Here's my notes. I'll keep hacking.

https://gist.github.com/dcode/1fa9684f619fe6d9d53321c477ca91cf

EDIT: Oh, also of note, I have a VCRX garage door opener/generic closed contact input/output device. You can see some if its info if you search for /device/5410/linknode/2834. For whatever reason, when you query the nodes on a link, you can identify the 4 local zones, which are the 4 closed contact outputs (CCOs). Further, if you search for /area/337/associatedzone, you'll see the "zones in area" info, which only contains 2 of my CCOs. Now, I'm only using 2 CCOs for garage doors, but I don't think those are the zones listed here. I think they're the other two. I'll keep hacking.

johninaustin commented 2 years ago

Sorry - I closed it - re-opening it now.

johninaustin commented 2 years ago

Hey @dcode - have you found any way to associate a zone with a device? Areas have their zones & devices, but often a device in one area controls a zone in another area. I haven't found any way to tie the two together.

I'd found some interesting ReadRequests using that query language, but haven't seen much use for them:

{"CommuniqueType": "ReadRequest", "Header": { "Url": "/zone/status/expanded?where=Level!:0||SwitchedLevel!:\"Off\"" } }

{"CommuniqueType": "ReadRequest", "Header": { "Url": "/zone/status/expanded?where=Level!:13" } }

{"CommuniqueType": "ReadRequest", "Header": { "Url": "/zone/status/expanded?where=Zone.ControlType:\"Shade\"|\"ShadeWithTilt\"|\"ShadeWithTiltWhenClosed\"|\"Tilt\"" } }

{"CommuniqueType": "ReadRequest", "Header": { "Url": "/device?where=DeviceType:\"SunnataDimmer\"" } }
mdonoughe commented 2 years ago

You should be able to find occupancy groups using something like ReadRequest /area/407/occupancygroup. That works for Caseta.

The zone and device link should be in a MultipleDeviceDefinition response. I don't know if it's the best way, but for Caseta you can do ReadRequest /device?where=href:"/device/20" or just ReadRequest /device/20 to get it. I guess with the query syntax you can retrieve multiple. On Caseta I can also list all devices in a specific area with ReadRequest /device?where=AssociatedArea.href:"/area/7".

johninaustin commented 2 years ago

RA3 does not provide a response to /device. I have an example of /device response in the responses directory.

Additionally, RA3 does not provide the zone information either - I have examples of the device responses in the responses directory as well.

I also included some examples where there are areas with devices that control zones in other areas. One example I included in the responses is the Entry & the Porch. In the Entry Area, there's a control station that includes a few devices. One is a dimmer. This dimmer actually controls the light zone in the Porch Area. If you query the Porch area, you'll see it has a zone, but no devices. And if you query the Entry area, you see the devices, but not that zone.

That's the reason I have zones masquerading as devices in this object model...

dcode commented 2 years ago

@johninaustin, so, from what I can tell, you can get zones (which are loads) and controls stations (which is the grouping of devices) directly from an area. Control stations contain devices (actual Lutron controls). In Designer, you can of course assign a zone to a different area than the device. This information is obviously in the sqlite database, but I don't see at all where it's exposed in the API.

I had a RRST-PRO dimmer in my hallway that controls the downlights in my living room. I put the control station in "hall" and assigned the zone to the "living room" area. Unfortunately, the Lutron app on my Android device didn't care much about that and simply put the control in the "hall" area. I'll reach out to Lutron support on that, because that seems like a bug. I think there's a lot that can be done with the existing platform, but there's a lot of "TODOs" that are waiting to be done in future releases.


I tried to enumerate occupancy groups by area, but that didn't work.

{"CommuniqueType":"ReadRequest","Header":{"Url":"/area/409/occupancygroup"}}
{"CommuniqueType":"ExceptionResponse","Header":{"MessageBodyType":"ExceptionDetail","StatusCode":"404 NotFound","Url":"/area/409/occupancygroup"},"Body":{"Message":"This resource does not exist"}}

The only way I've found to get occupancy group IDs is to check the sqlite database, which obviously isn't ideal.

I also haven't been able to enumerate scenes. /virtualbutton doesn't seem to do anything. Maybe if I can find an ID.

Anyway, I enumerated some additional commands. Nothing groundbreaking, but I recorded them for posterity:

https://gist.github.com/dcode/1fa9684f619fe6d9d53321c477ca91cf#file-valid_commands-md

johninaustin commented 2 years ago

@dcode That's interesting... The switch in my Entry Area with the lighting zone in my Porch Area shows up in the iOS app as a Porch light (which is what I expect). It's odd that behavior is different on Android.

dcode commented 2 years ago

I'll play with it again tomorrow and see what happens. Maybe it is a bug in the Android app. If so, then the API must be providing a way to associate zones to areas.

johninaustin commented 2 years ago

I believe the app is just showing zones for lights/shades/fans/switches/etc - in my UI, it shows a light, not a switch - no tie-in to the device.

I found a few more URLs for RA3. You might want to play with them, substituting appropriate IDs

ReadRequest on /area/___/associatedzone/status
ReadRequest on /area/___/associatedzone/status/expanded
ReadRequest on /area/___/summary
ReadRequest on /zone/___/zonescene
ReadRequest on /zone/___/status/expanded
ReadRequest on /database/@Project/status

This returns NoContent, not an error... I'm not sure what it does. SubscribeRequest on /zonetypegroup/status

I noticed it also works fine for SubscribeRequest on /occupancygroup/status, but I haven't been able to test this since my sensors are backordered for months.

iCSpotRun commented 2 years ago

@johninaustin I'm happy to send you a sensor for testing. Model: LRF2-OCR2B-P-WH

johninaustin commented 2 years ago

@iCSpotRun thank you for the offer! Mine should be coming in the next couple of weeks, so I think I can hang tight 🙂

I haven't found a nice API to enumerate OccupancyGroups... but I can brute-force it. If I loop through every ID from 1-10k & ignore the 404's, I can reliably get them (takes about 80 seconds, but we can probably multi-thread this to make this faster if that's necessary). All of mine were under ID 5000 with a system containing 88 devices total (49 type x, 39 type a).

This feels really hacky, but at least it works.

If we're forced to go this route, I think we need to start caching the configuration. We can use project metadata to determine if the program has changed. If it has, we can poll everything again.

johninaustin commented 2 years ago

Actually, that can be (unreliably) optimized. Every Area has an OccupancyGroup. Every OccupancyGroup's ID is greater than the associated Area's ID, but less than the next Area's ID. If this behavior is consistent, we can pretty quickly query Occupancy Groups by bounding searches with Area IDs.

Edit: Just tested this. It takes 1.5 seconds to discover all OccupancyGroups using this method. It seems the OccupancyGroup is just a few IDs higher than the base area - likely varies due to the count of devices & other objects related to that area.

swamplynx commented 2 years ago

@johninaustin are you ready for @gurumitts to merge this... I would love to get this library working in Home Assistant... Any idea how to pull your fork into Home Assistant in case the merge takes some time?

johninaustin commented 2 years ago

@swamplynx Just received my motion sensors - I'm gonna play around with those a bit. @mdonoughe wanted some fixes to the cert stuff. RA3 is a little different, and dumping the whole chain of certs wasn't a great solution. I'll work on this more over the weekend.

daytonturner commented 2 years ago

I also have a decently sized RA3 installation I can leverage to test this - I'm eager to get it integrated into home assistant as well. My RA3 system consists of about 100 devices, mostly dimmers/companion dimmers, 4-button keypads, some lamp plugs, pico's, and standard on/off switches.

Very comfortable with HA, SSL and Python, if any specific help is required?

daytonturner commented 2 years ago

How can I help move this merge forward? Seems to be stalled..

johninaustin commented 2 years ago

I'm slammed with work right now. Would love to spend some time on it, but I just don't have the cycles right now. My house was also delayed a few more months, so I still don't have anything "real" setup (beyond a processor & a config I created). You can access the latest progress in this PR, or in my fork. It's functional, but not yet up to par as far as code standards.

daytonturner commented 2 years ago

Gotcha - I'll take a peek at it and try it out. My house just completed last Friday and I'm now eager to integrate my RA3 setup! :)

swamplynx commented 2 years ago

How would I run @johninaustin 's fork in Home Assistant?

1) Copy components/lutron_caseta to custom_compononents 2) Edit all the imports in the .py files to "https://github.com/johninaustin/pylutron-caseta"

... there has to be a cleaner way? Sorry python and HA n00b here.

daytonturner commented 2 years ago

How would I run @johninaustin 's fork in Home Assistant?

  1. Copy components/lutron_caseta to custom_compononents
  2. Edit all the imports in the .py files to "https://github.com/johninaustin/pylutron-caseta"

... there has to be a cleaner way? Sorry python and HA n00b here.

Here's what I did, preliminary testing seems to show its referencing the right module, but I'm not onsite to test by pressing the button on the bridge to pull the certs, so your mileage may vary.

  1. Log in to your HA instance (i'm using hass.io so i launched a shell inside the docker container)
  2. cd /root; git clone https://github.com/johninaustin/pylutron-caseta; git checkout ra3
  3. Edit pylutron-caseta/setup.cfg and bump the version number from 0.13.1 to 0.13.2 (or anything higher, really)
  4. pip3 install -e ./pylutron-caseta
  5. Restart HomeAssistant
  6. Re-launch a shell to HA
  7. pip3 show pylutron-caseta <-- this should show the version number you bumped to

This should make any requests the lutron_caseta component makes to import from pylutron_caseta now pull from the RA3 branch.

Let me know if this works for you.

swamplynx commented 2 years ago

I'm also offsite, so won't be able to fully test for a week or so but when I get to the pip3 install -e, I get the error "A "pyproject.toml" file was found, but editable mode currently requires a setup.py based build.)"

daytonturner commented 2 years ago

Not sure if it matters, but my pip3 claims it is version 22.0.3:

# pip3 --version
pip 22.0.3 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)

If you're doing this on debian, perhaps add --no-build-isolation to your pip3 arguments?

mdonoughe commented 2 years ago

I don't know if this works on hass.io. I'm running Core and when I want to run a different version I put it into config/deps/lib/python3.9/site-packages. If you're pip installing it into a container like that, it will could be wiped out by recreating the container.

The pyproject message means your pip is old. You might be running the wrong pip. It could be that you want pip instead of pip3. You probably don't really need an editable install (the -e option) if you just want to test anyway, but if it's the wrong pip the package will be installed to the wrong place.

daytonturner commented 2 years ago

Thanks for the note @mdonoughe - I should absolutely disclaim that my instructions would definitely be blown away if the container is rebuilt - this was just a quick hack'n'slash way to test a git branch that has not yet been merged.

daytonturner commented 2 years ago

OK A couple corrections about my previous methods, and an update of where I'm at - perhaps someone has some ideas.

Because I'm using hassio I ended up doing this instead:

  1. Put a copy of the lutron_caseta HA module in your custom_components folder (for me, inside my hassio container, it was basically to copy /usr/src/homeassistant/homeassistant/components/lutron_caseta into /config/custom_components but your mileage may vary)
  2. Inside custom_components/lutron_caseta, edit manifest.json
  3. change the "requirements" key's value to: git+https://github.com/johninaustin/pylutron-caseta.git@ra3#pylutron-caseta==0.13.1 This will ensure pylutron-caseta is pulled from johninaustin's ra3 branch
  4. add a version key - core components that get overridden in custom_components need a version specified, apparently. I just added "version": "1.3.3.7" to my manifest.json file and it seemed happy.
  5. I'm not sure if this is a docker specific issue or not, but I actually had to pip3 uninstall pylutron_caseta for it to re-fetch the one I specified from github. I did also run pip3 install git+https://github.com/johninaustin/pylutron-caseta.git@ra3#pylutron-caseta==0.13.1 once from SSH, one of these two things got the library updated and persisting through restarts.

Now, this makes HA (and the python environment inside the hassio container) use the correct pylutron_caseta library just fine, which is great.

HomeAssistant however, sits and hangs/times out after 5 minutes with the "still waiting for Lutron Caseta to start" message. Looking at debug logs, I can see that the pylutron_caseta module successfully connects to the bridge, identifies it as RA3,, and starts walking through the device list, area list, zone list, etc. It then goes through a list of button subscriptions that seem to complete successfully. The final message in the log is that its processing the close() function on the bridge connection. It's at this point that I would presume the HA module would realize the connection is done, create entities within HA and everything would be good.

But, it just seems to stall here, until the module startup timeout (5 minutes) finishes. Afterwards, no new devices or entities have been created.

A snippet of the last few lines of logs:

2022-04-14 12:28:07 DEBUG (MainThread) [pylutron_caseta.leap] Subscribed to /button/2680/status/event as 2ddd5456-d050-4e5f-8fea-7e16d99df1ba
2022-04-14 12:28:07 DEBUG (MainThread) [pylutron_caseta.smartbridge] Subscribed to button 2680 status
2022-04-14 12:28:07 DEBUG (MainThread) [pylutron_caseta.smartbridge] Handling button status: Response(Header=ResponseHeader(StatusCode=ResponseStatus(204, 'NoContent'), Url='/button/2680/status/event', MessageBodyType=None), CommuniqueType='SubscribeResponse', Body=None)
2022-04-14 12:28:07 INFO (MainThread) [pylutron_caseta.smartbridge] Processing Smartbridge.close() call

Am I missing something else?

danaues commented 2 years ago

daytonturner,

I was able to get the component functioning with my RA3 processor using your instructions, and modifying 2 files in the custom_components/lutron_caseta folder.

init.py Line 141 config_flow.py Line 240

I commented out the line

bridge_device = devices[BRIDGE_DEVICE_ID]

And added a temporary bridge_device manually by adding this to each file in the same location

bridge_device = { "device_id": "1", "current_state": None, "fan_speed": None, "zone": 843, "name": "Ra3 Processor", "button_groups": None, "type": None, "model": "RR-RA3", "serial": 123456789 }

Looks like the RA3 updates don't support getting the bridge device from the devices variable like the caseta model does.
I only have a few Sunnata Dimmers, but they are all working.

daytonturner commented 2 years ago

Great find @danaues - I had been sniffing down the exact same path a few days ago before other priorities pulled me away: https://community.home-assistant.io/t/lutron-qsx-and-radio-ra3/381952/12?u=daytonturner

I think the easiest way to solve for this will be to add a function to pylutron_caseta for "get bridge information", then modify the lutron_caseta HA module to use that, rather than presuming the bridge is always device ID 1 (or any device ID for that matter). This will probably be the best approach, given that RA3 doesn't provide the bridge information via device ID anymore, and now uses a separate API query, along with its own response format. We can extrapolate that query into an API call between the libraries and clean them both up a bit.

swails commented 2 years ago

Great find @danaues - I had been sniffing down the exact same path a few days ago before other priorities pulled me away: https://community.home-assistant.io/t/lutron-qsx-and-radio-ra3/381952/12?u=daytonturner

I think the easiest way to solve for this will be to add a function to pylutron_caseta for "get bridge information", then modify the lutron_caseta HA module to use that, rather than presuming the bridge is always device ID 1 (or any device ID for that matter). This will probably be the best approach, given that RA3 doesn't provide the bridge information via device ID anymore, and now uses a separate API query, along with its own response format. We can extrapolate that query into an API call between the libraries and clean them both up a bit.

+1

The LEAP that accomplishes this for RA3 has a reasonable chance of working for Caseta as well (if not now then quite likely in the future).

FlyingDiver commented 2 years ago

Any chance this will work with an RRA2 system with the Connect Bridge? I would think that does LEAP as well.

dcode commented 2 years ago

I have since come up with a better way to find the bridge. You can query /device?where=isthisdevice:true. I'm not in front of my computer at the moment, but it's something like that. It'll give you the bridge that you are connected to.

I've also reverse engineered almost all the protocol and created Marshmallow dataclasses and enums for the options. I'm still working out the query parameters.

I also managed to authenticate at a lower privilege level using username/password. This uses the actual "integration" settings from the RA3 designer settings. There's some downsides as not all queries are permitted, for example the area extended status to get zone data.

I believe what I have will work for RA3, QSX, and Vive. I'm not certain about Caseta because I'm not sure Caseta has an official integration option.

I also ran across a message definition for a zone that provided a device href. I haven't found the code execution path that makes that happen yet, but it's in the unit tests of the official LEAP client.

I hope to post my code to a new repo and we can figure out if it's worth trying to merge here. The work flow is similar, using asyncio, but there's a ton of new code since I worked on enumerating the full schema (and there's still some gaps).

On Mon, Apr 25, 2022, 13:26 Jason Swails @.***> wrote:

Great find @danaues https://github.com/danaues - I had been sniffing down the exact same path a few days ago before other priorities pulled me away: https://community.home-assistant.io/t/lutron-qsx-and-radio-ra3/381952/12?u=daytonturner

I think the easiest way to solve for this will be to add a function to pylutron_caseta for "get bridge information", then modify the lutron_caseta HA module to use that, rather than presuming the bridge is always device ID 1 (or any device ID for that matter). This will probably be the best approach, given that RA3 doesn't provide the bridge information via device ID anymore, and now uses a separate API query, along with its own response format. We can extrapolate that query into an API call between the libraries and clean them both up a bit.

+1

The LEAP that accomplishes this for RA3 has a reasonable chance of working for Caseta as well (if not now then quite likely in the future).

— Reply to this email directly, view it on GitHub https://github.com/gurumitts/pylutron-caseta/pull/90#issuecomment-1108899783, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABJ4NVCXK5TNRPZIMYT4XDVG3PVRANCNFSM5ODMWX6A . You are receiving this because you were mentioned.Message ID: @.***>

swails commented 2 years ago

Any chance this will work with an RRA2 system with the Connect Bridge? I would think that does LEAP as well.

It's possible, but if it did it would be limited in functionality. The Connect Bridge was essentially a shim to expose some Caseta-cloud functionality to the older luxury systems (RA2 and HomeWorks QS). It has most likely changed a lot since I worked heavily with the Connect Bridge, but the core integration for RA2 and legacy HWQS systems is the pylutron library that operates over LIP (Lutron Integration Protocol) rather than LEAP. Internally they were very different. I'd recommend looking at the lutron integration (rather than lutron-caseta).

daytonturner commented 2 years ago

I was able to get the component functioning with my RA3 processor using your instructions,

I just noticed that some of the core HA components (light, fan, cover) have new entities such as LightEntityFeature, FanEntityFeature, and CoverEntityFeature which are not included in the HA stable release just yet. Likely the next one.

Are you running the Dev or Beta build to get this working on your side?

danaues commented 2 years ago

I was able to get the component functioning with my RA3 processor using your instructions,

I just noticed that some of the core HA components (light, fan, cover) have new entities such as LightEntityFeature, FanEntityFeature, and CoverEntityFeature which are not included in the HA stable release just yet. Likely the next one.

Are you running the Dev or Beta build to get this working on your side?

I'm running hassio os, on version 2022.4.6. I only have 2 Sunnata dimmers connected to the RA3 at this point. The rest of my house is still on RA2.

danaues commented 2 years ago

I agree adding adding a function to retrieve the bridge details (SN etc) would be ideal. This was just meant as quick hack to get beyond the integration setup phase and test out the component on HA.

I have minimal python and github experience, but I'm willing to help test. I have RA3, RA2 and Caseta Pro to test against.

Dcode, I experimented with the '/device?where=isthisdevice:true` url as you suggested, and I agree this would be a great way to get the bridge info. Your ra3_notes.md link was great, very helpful.

Also, using '/device?where=isthisdevice:false` gives all the devices other than the processor. This might help solve the blank '/device' query difference

daytonturner commented 2 years ago

I'm running hassio os, on version 2022.4.6.

I'm running 2022.4.7 and my setup only detected a Pico and the bridge. In the Server Logs, I see:

Sure enough, looking in those core components, those entity functions don't exist, so it makes full sense why they cannot import.

If you're only on 2022.4.6, How are yours working?

danaues commented 2 years ago

I'm running hassio os, on version 2022.4.6.

I'm running 2022.4.7 and my setup only detected a Pico and the bridge. In the Server Logs, I see:

* Unable to prepare setup for platform lutron_caseta.light: Platform not found (cannot import name 'LightEntityFeature' from 'homeassistant.components.light' (/usr/src/homeassistant/homeassistant/components/light/**init**.py)).

* Unable to prepare setup for platform lutron_caseta.fan: Platform not found (cannot import name 'FanEntityFeature' from 'homeassistant.components.fan' (/usr/src/homeassistant/homeassistant/components/fan/**init**.py)).

* Unable to prepare setup for platform lutron_caseta.cover: Platform not found (cannot import name 'CoverEntityFeature' from 'homeassistant.components.cover' (/usr/src/homeassistant/homeassistant/components/cover/**init**.py)).

Sure enough, looking in those core components, those entity functions don't exist, so it makes full sense why they cannot import.

If you're only on 2022.4.6, How are yours working?

Where did you get the source for the /custom_components/lutron_caseta folder? Is it possible you've pulled in a different or dev version of that? I copied mine from the source folder within the homeassistant container from my install.

If I look at https://github.com/home-assistant/core/blob/dev/homeassistant/components/lutron_caseta/light.py it references LightEntityFeature too.

My /custom_component/lutron_caseta/light.py does not have that in it.

-Kevin

FlyingDiver commented 2 years ago

Yeah, I already have LIP working for RRa2 and Caseta w/ SmartBridge Pro. After I get LEAP working I was maybe hoping I could retire the old plugin and have everyone use the new one. But if I need to maintain both, I will.

daytonturner commented 2 years ago

Where did you get the source for the /custom_components/lutron_caseta folder? Is it possible you've pulled in a different or dev version of that? I copied mine from the source folder within the homeassistant container from my install.

Whelp, that was it. Sorry - my bad, I totally overlooked that!

dcode commented 2 years ago

here's my current work: https://github.com/dcode/pylutron-leap

NOTE: The above code WILL NOT work to integrate your stuff into home assistant or anything else at the moment. It is intended to develop python against LEAP devices and explore what is possible. Please don't ask how you can use that to get your devices to work, because we're not there.

I don't intend to maintain a fork, but there's so much extra stuff going on in there, I started this different repo as a means to build out the schema of the protocol for documentation purposes. Happy to port changes here or move forward to a "unified leap" library or whatever.


This morning I ran across some strings that identify what command processor type it is based on the "deviceclass" attribute. It identifies basically anything the Lutron phone app can connect to: caseta, caseta pro, ra2 select, ra3, homeworks qsx (wired, wireless, dual radio). That suggests that a single, properly implemented LEAP protocol layer would work for all those devices.

In my repo, I've modeled out, probably >90% of the actual message protocol using Marshmallow to serialize/deserialize from JSON. But this schema just defines what is possible, not definitively what all the messages are. I've type annotated more focused message types and mypy...mostly works correctly. All that is in the api directory. models contains the stateful objects that are intended to interact with. They process responses and update their own state. These are not complete. For example, creating zone objects needs to deal with the zone definition and convert the object to a Fan, Dimmed lighting load, etc.

With the device query for all devices, we can now map between areas, zones, and devices (and even radio links if one wanted to get nuts). Unfortunately, this is only available with the TLS cert login (root privileges). I was hoping that was available as a "normal integration" since with those certs, technically you could reprogram the device, upload custom firmware, etc. It might still be possible using a different query other than isthisdevice:true.

daytonturner commented 2 years ago

I only have a few Sunnata Dimmers, but they are all working.

hey @danaues I wonder if you might be able to check something for me - I've made good progress here, except when HA starts trying to create devices. It hit my first dimmer and was able to successfully add it - however it created the entity in HA with unique_id: None which obviously isn't correct - especially since when it goes to create the second light entity it tries using None again, which is now a duplicate unique_id, and fails.

In looking through the lutron_caseta component code, first glance didn't uncover anywhere that unique_id was expressly being set, aside from on bridge device creation. I'll continue to debug it to figure out how this is being inherited, but it made me wonder again how yours was able to succeed?

I'd be curious to know what unique_ids your entities got, perhaps it would help me track this down. You can confirm by looking inside of /config/.storage/core.entity_registry (do not edit/save this file of course!). In here you'll see your light entities, and the unique_id key they were assigned.

danaues commented 2 years ago

daytonturner

I only have a few Sunnata Dimmers, but they are all working.

hey @danaues I wonder if you might be able to check something for me - I've made good progress here, except when HA starts trying to create devices. It hit my first dimmer and was able to successfully add it - however it created the entity in HA with unique_id: None which obviously isn't correct - especially since when it goes to create the second light entity it tries using None again, which is now a duplicate unique_id, and fails.

In looking through the lutron_caseta component code, first glance didn't uncover anywhere that unique_id was expressly being set, aside from on bridge device creation. I'll continue to debug it to figure out how this is being inherited, but it made me wonder again how yours was able to succeed?

I'd be curious to know what unique_ids your entities got, perhaps it would help me track this down. You can confirm by looking inside of /config/.storage/core.entity_registry (do not edit/save this file of course!). In here you'll see your light entities, and the unique_id key they were assigned.

You are correct, mine aren't getting unique ID's either. Only the 1 switch was working. Turns out, when loading the RA3 zones, this module isn't providing a serial number, which the HA components is using for the unique ID.

I was able to hack a fix by editing smartbridge.py in this module and just use the device name as the serial ie ( basement_bedroom_main_lights is the serial number)

2 places in the smartbridge file

In the function async def _load_ra3zones(self, area): change the line: serial=None, to: serial="".join((area["name"], zone_name)),

in function async def _load_ra3_station_device(self, name, devicejson): Change the line: serial=None, To: serial=name="".join((name, device_name)),

Might have to change function def _load_ra3_button(self, button_json, device): as well, but I haven't tested yet.

All these are just hacks to get control of the lights. I'm sure there are much better solutions long term.

daytonturner commented 2 years ago

Wow - I was just writing almost verbatim the exact same thing as a follow-up after I sorted it out, and noticed the page reload and bring your comment in. All seems to be working (so far).

The only thing I have yet to expose any control to are Sunnata Keypads. I have a handful of them, and while they show up, they currently expose no Controls or Actions to HA. Will investigate this further and see if I can get them operational.

danaues commented 2 years ago

daytonturner,

I created a fork to save our changes, you can test by updating the manifest file to: "git+https://github.com/danaues/pylutron-caseta.git@ra3#pylutron-caseta==0.13.1"

  1. I added the processor Model and Serial number into devices["1"], so that the regular HA integration works without changing any of it's code.
  2. I've added the Zone name as the serial number for zones, buttons, station_device

Let me know if you can give it a test on your setup.

danaues commented 2 years ago

Updated my fork with pairing support as well. Also, changed the serial number and name logic to match the caseta naming

Created a pull request into johninaustin/pylutron-caseta:ra3

daytonturner commented 2 years ago

Nice! Next up for me is going to be adding more abstracted support to discover the bridge regardless of bridge type, then extend support for that into lutron_caseta (HA)

The last thing that is obviously missing (so far as I can tell) is device support for Sunnata Keypad buttons+LEDs. I know you can generically subscribe to events, and fire custom events, but the HA device handler should do a better job of exposing it.

danaues commented 2 years ago

Nice! Next up for me is going to be adding more abstracted support to discover the bridge regardless of bridge type, then extend support for that into lutron_caseta (HA)

This would be great. I really don't like the way I'm doing it now, by waiting for the SSL verification to fail, then trying the other root-ca. It works, but it's dirty. The comments above talked about reading the "/project" url, which is great after the pairing is complete, but would be nice to have a good way to identify caseta vs RA3 before we can make leap queries during pairing.

The last thing that is obviously missing (so far as I can tell) is device support for Sunnata Keypad buttons+LEDs. I know you can generically subscribe to events, and fire custom events, but the HA device handler should do a better job of exposing it.

I don't have any Sunnata keypads yet, but I think I'll get one to try out. Maybe an occupancy sensor too. I think that part still needs work as well. Might have to make an order on Monday!

daytonturner commented 2 years ago

I'm trying to find time to chase down whatever is broken with Keypads - not only do they not expose any actions or states that I can tell, I'm also running into situations where people are pressing Keypad buttons to trigger scenes and it ends up causing the lutron_caseta module to crash in HA. This requires a HA restart before I can control anything again.

The crash log (I havent investigated it yet at all, just pasting here for verbosity's sake)

Logger: pylutron_caseta.smartbridge
Source: custom_components/lutron_caseta/__init__.py:248
Integration: Lutron Caséta
First occurred: 12:41:03 PM (1 occurrences)
Last logged: 12:41:03 PM

monitor loop has exited
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/pylutron_caseta/smartbridge.py", line 422, in _monitor
    await self._monitor_once()
  File "/usr/local/lib/python3.9/site-packages/pylutron_caseta/smartbridge.py", line 450, in _monitor_once
    await self._leap.run()
  File "/usr/local/lib/python3.9/site-packages/pylutron_caseta/leap.py", line 98, in run
    subscription(Response.from_json(resp_json))
  File "/usr/local/lib/python3.9/site-packages/pylutron_caseta/smartbridge.py", line 506, in _handle_button_status
    self._button_subscribers[button_id](button_event)
  File "/config/custom_components/lutron_caseta/__init__.py", line 277, in <lambda>
    lambda event_type, button_id=button_id: _async_button_event(
  File "/config/custom_components/lutron_caseta/__init__.py", line 248, in _async_button_event
    sub_type_to_lip_button = DEVICE_TYPE_SUBTYPE_MAP_TO_LIP[type_]
KeyError: 'SunnataKeypad'
daytonturner commented 2 years ago

OK so I looked a bit closer, and this is just mapping device types to identify the button IDs to use, and SunnataKeypad just isn't defined in the list at all.

I'll take a stab at figuring that out and submit a patch for it.

elreydetodo commented 2 years ago

I have a HomeWorks QS system with a QSX processor. Not much attention is being paid to this line, but it appears to be very similar to RA3 in many ways. My system also uses the lutron-root CA. {{/devices}} on its own doesn't list any devices, you have to add the where statement as described earlier. Also worth noting that my system isn't doing an mDNS broadcast.

Is there any info I can provide at this point to help make sure the changes here also support a QSX system? I have read through the comments twice and am not quite sure how to test this with Home Assistant yet, but maybe reading a third time will make it clear.