This library is an implementation of Lutron's unpublished LEAP protocol. It is, in large part, a port of pylutron-caseta, without which this would not have been possible. It was written to support the homebridge-lutron-caseta-leap Homebridge plugin, but it exists independently of it and has been tested and improved in non-Caseta contexts.
The answer to "can this add support for a device" is probably no, but maybe not for the reason you expect.
LEAP is a protocol. It defines certain message types and objects, as well as implicitly defines some behaviors. Some of these definitions include objects that do indeed map to real-world objects, but only things that are components of the kind of devices you're asking about. As a concrete example, LEAP defines things like buttons. Not remotes, but individual buttons. So adding support for a particular remote doesn't really make sense in this library, because there's no concept of a "remote" in LEAP. There's just generic devices and button groups.
Ehhh probably not. My preference is to keep this library "pure" as only an implementation of LEAP. I'm absolutely open to a separate, general-purpose library that contains Lutron product abstractions that use this library, but I don't have a need for one so I'm not going to write it right now.
That's true! Bridges are a notable exception because they are entry points into traversing the LEAP device "tree". Consumers of this library don't want or need to understand things like button groups or occupancy subscription that are specific to existing (physical) implementations of LEAP.
The "readBlindsTilt" and "setBlindsTilt" are kinda hacks that should get cleaned up in favor of an abstraction over the various CommandType
values available. That should come if/when support for another bridge is added to the library.
This code has three major components: the message parsing stack, the LEAP client, and a Caséta Smart Bridge 2 abstraction.
At the top level, LEAP messages have three parts:
Most of the code is concerned with parsing responses, as most of the job of this library is passing messages from the Lutron hub to whoever cares to listen.
Updating this code is pretty mechanical at this time, and the best way to understand it is to look at a commit that adds newly-observed objects. In short, you'll want to:
The LEAP client handles reading and writing from the secure socket, as well as routing messages to subscriber callbacks. Requests are submitted with a user-supplied, arbitrary tag. This tag is returned with relevant responses. For example, if you subscribe to some event and provide tag 1
, event messages will also include the 1
tag. You, dear user, don't actually care about this. All you care about is having your callback called, which the LEAP client does.
The LEAP client also passes messages that are "unsolicited", and do not have a tag. These messages are emitted by the LEAP client. Any listener can receive them and process them.
Messages that have a tag that is not recognized by the client are noisily dropped.
WARNING: The socket handling in the LEAP client class is super duper ugly. If you feel like refactoring it, please do.
Because this code was written to support Caseta devices, the following section only applies to the Caseta Smart Bridge 2. I wholeheartedly welcome improvements related to other LEAP technologies.
Caseta Smart Bridge 2 and Smart Bridge 2 Pro devices are discovered by using mDNS. The BridgeFinder handles discovery and returns network information that be used by the listener to construct the actual client itself.
The SmartBridge class abstractions for relevant operations like subscribing to known device types. The goal is to relieve the user of having to know how to construct URLs and post bodies, but instead to encode that information in this library.
This library has been extensively tested on Caseta Smart Bridge 2 (pro and non-pro) devices, and gracious contributors have tested it with RA3. If you have used it elsewhere, please drop a note and let me know. So far, this library has been tested with: