Skip to main content

Controls for Lightwave Smart Series (second generation) devices

Project description

Python library to provide reliable communication with Lightwave Smart Series (second generation) devices. Including lights (dimmers), power outlets (sockets), smart switchs (wirefrees), PIRs, thermostats, TRVs, magnetic switches, relays, energy monitors and other device types.

Notes

The LWLink2Public class should not be used in this version, it has not been tested.

Installing

The easiest way is

pip3 install lightwave_smart

Or just copy https://raw.githubusercontent.com/LightwaveSmartHome/lightwave-smart/master/lightwave_smart/lightwave_smart.py into your project

Using the library

Imports

You'll need to import the library

from lightwave_smart import lightwave_smart

If you want to see all the messages passed back and forth with the Lightwave servers, set the logging level to debug:

import logging
logging.basicConfig(level=logging.DEBUG)

Connecting

Start by authenticating with the LW servers.

link = lightwave_smart.LWLink2("example@example.com", "password")

This sets up a LWLink2 object called link, and gets an authentication token from LW which is stored in the object. We can now connect to the LW websocket service

link.connect()

Read hierarchy

Next:

link.get_hierarchy()

This requests the LW server to tell us all of the registered "featuresets". A "featureset" is LW's word for a group of features (e.g. a light switch could have features for "power" and "brightness") - this is what I think of as a device, but that's not how LW describes them (sidenote: what LW considers to be a device depends on the generation of the hardware - for gen 1 hardware, devices and featuresets correspond, for gen2 a device corresponds to a physical object; e.g. a 2 gang switch is a single device, but 2 featuresets).

Running get_hierarchy populates a dictionary of all of the featuresets available. the dictionary keys are unique identifiers provided by LW, the values are LWRFFeatureSet objects that hold information about the featureset.

To see the objects:

print(link.featuresets)

For a slightly more useful view:

for i in link.featuresets.values():
    print(i.name, i.featureset_id, i.features)

In my case this returns

Garden Room 5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e {'switch': <lightwave_smart.lightwave_smart.LWRFFeature object at 0x0000021DB49C93A0>, 'protection': <lightwave_smart.lightwave_smart.LWRFFeature object at 0x0000021DB49C9AC0>, 'dimLevel': <lightwave_smart.lightwave_smart.LWRFFeature object at 0x0000021DB49C9B50>, 'identify': <lightwave_smart.lightwave_smart.LWRFFeature object at 0x0000021DB49C9BB0>}

This is a light switch with the name Garden Room and the featureset id 5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e which we'll use in the example. The features will be explained below.

Reading the featuresets

Featuresets are accessed from the dictionary directly:

Name
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].name)

will give the name you assigned when you set up the device in the LW app.

Type of device

There are a number of methods to return info about the devices

Method Usage
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_switch()) Is it a socket?
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_light()) Light switches
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_climate()) Thermostats
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_cover()) Blinds / three-way relay
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_climate()) Thermostats
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_energy()) Energy meters
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_windowsensor()) Window sensor
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_hub()) LinkPlus Hub
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].is_gen2()) Generation 2 device?
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].reports_power()) Has power reporting
print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].has_led()) Has an indicator LED that is configurable
Device features

This is how we find out the state of the device, and we will also use this information to control the device:

print(link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].features)

features is a dictionary of the features within a given featureset. The keys are the names of the features, the values are LWRFFeature objects.

The LWRFFeature objects have properties: featureset, id, name, state. E.g.

for i in link.featuresets['5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e'].features.values():
    print(i.name, i.id, i.state)

returns

switch 5bc4d06e87779374d29d7d9a-28-3157334318+1 0
protection 5bc4d06e87779374d29d7d9a-29-3157334318+1 0
dimLevel 5bc4d06e87779374d29d7d9a-30-3157334318+1 59
identify 5bc4d06e87779374d29d7d9a-72-3157334318+1 0

showing the light is currently off (feature switch), the physical buttons are not locked (feature protection) and the brightness is set to 59% (feature dimlevel).

More reading the featuresets

The values of the featuresets are static and won't respond to changes in the state of the physical device (unless you set up a callback to handle messages from the server). If you want to make sure the values are up to date you can:

link.update_featureset_states()

Finally there are a handful of convenience methods if you just want to return devices of a particular type:

print(link.get_switches())
print(link.get_lights())
print(link.get_climates())
print(link.get_energy())

Writing to a feature

Turning on a switch/light, turning off a switch/light or setting the brightness level for a light is as follows:

link.turn_on_by_featureset_id("5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e") 
link.turn_off_by_featureset_id("5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e") 
link.set_brightness_by_featureset_id("5bc4d06e87779374d29d7d9a-5bc4d61387779374d29fdd1e", 60) #Brightness in percent

Then there is one more method for a thermostat

link.set_temperature_by_featureset_id(featureset_id, level)

And some methods for covers (blinds)

link.cover_open_by_featureset_id(featureset_id)
link.cover_close_by_featureset_id(featureset_id)
link.cover_stop_by_featureset_id(featureset_id)

Reading/writing to an arbitrary feature

Finally, for any other features you might want to read or write the value of, you can access them directly. Note that the first option needs the feature unique id.

link.read_feature(feature_id)

or

link.featuresets[featureset_id].features[featurename].state

Writing:

link.write_feature(feature_id, value)

or

link.write_feature_by_name(featureset_id, featurename, value)

or

await link.featuresets[featureset_id].features[featurename].set_state(value) #async only, see below

Getting notified when something changes

This library is all using async programming, so notifications will only really work if your code is also async and is managing the event loop. Nonetheless, you can try the following for an idea of how to get a callback when an event is spotted by the server:

import asyncio

def test():
     print("this is a test callback")

asyncio.get_event_loop().run_until_complete(link.async_register_callback(test))

This will call the test function every time a change is detected to the state of one of the features. This is likely only useful if you then run link.update_featureset_states() to ensure the internal state of the object is consistent with your actual LW system.

See example_async.py for a minimal client.

async methods

The library is actually all built on async methods (the sync versions described above are just wrappers for the async versions)

async_connect()
async_get_hierarchy()
async_update_featureset_states()
async_write_feature(feature_id, value)
async_read_feature(feature_id)
async_turn_on_by_featureset_id(featureset_id)
async_turn_off_by_featureset_id(featureset_id)
async_set_brightness_by_featureset_id(featureset_id, level)
async_set_temperature_by_featureset_id(featureset_id, level)

Thanks

Credit to Bryan Blunt for the original version https://github.com/bigbadblunt/lightwave2

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lightwave_smart-1.0.0.tar.gz (23.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lightwave_smart-1.0.0-py3-none-any.whl (23.9 kB view details)

Uploaded Python 3

File details

Details for the file lightwave_smart-1.0.0.tar.gz.

File metadata

  • Download URL: lightwave_smart-1.0.0.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lightwave_smart-1.0.0.tar.gz
Algorithm Hash digest
SHA256 696ebd299291c8f55743492302c848c9b653b856e5c7c681c288499762c5b80e
MD5 ab4e776d9972129f7d2a37c732afac77
BLAKE2b-256 151ea3b828cba34a3a0c15d1e60f53a5b6144ada498ff9b77be5d46e1380a002

See more details on using hashes here.

Provenance

The following attestation bundles were made for lightwave_smart-1.0.0.tar.gz:

Publisher: publish-pypi.yaml on LightwaveSmartHome/lightwave-smart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lightwave_smart-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lightwave_smart-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 80dda9c1f616140786f405b01c5d69505e16feff20a87df1c0ecc63b00008fc5
MD5 54d115859c5fd9f7c841e9428543f5de
BLAKE2b-256 1872eb6d7333bcb3e0e2f8a2e6a76b7627ee5b7acc4276c233cbad6d27799638

See more details on using hashes here.

Provenance

The following attestation bundles were made for lightwave_smart-1.0.0-py3-none-any.whl:

Publisher: publish-pypi.yaml on LightwaveSmartHome/lightwave-smart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page