Leviton Decora Wi-Fi smart switch implementation

Currently there is no openHAB binding available for the Leviton Decora WI-FI smart switch. As a workaround to this problem I have successfully implemented the following solution by utilizing a python script that is executed by an openHAB rule.

Items:

Switch Rule_kitchen_lights   "Kitchen lights"	["Lighting"]

Rules:


/*
Usage: python <path>/Decora-cli.py [email] [pswd] [id#:ON|OFF|0-100] <[id#:ON|OFF|0-100]> <etc.>
Usage: python <path>/Decora-cli.py [email] [pswd] [id#:?] <[id#:?]> <etc.>   ... list current status of switch(es)
Usage: python <path>/Decora-cli.py [email] [pswd] ?    ... list all switch ids
*/

rule "Turn on kitchen lights"
when
    Item Rule_kitchen_lights received command
then
	if(receivedCommand==ON) {
             logInfo("Decora ", "Turn on kitchen lights.")
             val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:ON", 120000)
             logInfo("Decora ", Results_decora) 
             }
	if(receivedCommand==OFF) {
             logInfo("Decora ", "Turn off kitchen lights.")
             val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:OFF", 120000)
             logInfo("Decora ", Results_decora) 
             }
end

Notes:

  • Python was automatically installed in my Raspberry Pi during the openHAB installation process. If it’s not installed in your server, you will need to install this application in your server first.
  • Go to https://github.com/markcaldwell0017/python-decora_wifi-cli, select “Clone or download”, select “Download Zip”, download the files, unzip the files and copy all into your openHAB scripts directory (currently found at /etc/openhab2/scripts/)
  • From a terminal command line, log in to Openhabian
    (i.e., ssh openhabian@ip_address), change to the scripts directory (cd /etc/openhab2/scripts/) and execute:
python <path>/Decora-cli.py <emailaddress> <password> ?

Using the above recommended install directory, this would be:

python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> ?
  • and receive an output such as:
Permission id#12345 (Accountid#9876)
Residence  id#4567  (your address)
Switch1    id#23456 (Kitchen)
Switch2    id#67890 (Bedroom)
  • Edit the two executeCommandLine’s in the rules file to include your email address, password and the appropriate switch id# as found in the above output.
  • Add additional items and rules to control additional switches.
  • Although not yet tested, the following should set a dimmer switch to the designated dimness level, e.g. 25%:
val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:25", 120000)
  • Since each login to Leviton takes several seconds, you can trigger several switch actions within a single command, which will execute the second, third, etc. switch commands faster:
val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 67890:ON 45678:OFF 23456:50", 120000)
  • Output is logged to the openhab.log file, assuming you have logging turned on.
4 Likes

Thanks for sharing, Mark

Hello,

Im trying to use this for my 3x leviton switches. I tried to include the into the init.py. Its the only file that seems to have a place for it? However there is no place for the switch ID’s. There are no lines called executeCommandLine and no file called rules. So I am lost.

Here is the section from the init___.py

LEVITON_ROOT = 'https://my.leviton.com/api'

def __init__(self):
    """Initialize the session, all content is JSON."""
    self._session = requests.Session()
    self._session.headers.update({'Content-Type': 'application/json'})
    self._email = None
    self._password = None
    self.user = None

Is that it? But if so where do the switch ID’s go?

Ok another TOTAL noob question. Besides my 1st question. My second is how do I make a thing from this? I’m still getting the hang of openhab so once these scripts have my login details how do I add them to things and then be able to turn them on off via basic UI? omg i know im such a noob.

Ignoring the openHAB programing issues for the moment, and as step 1, were you able to execute the python command from your command line to received the device ID’s, as per the Notes section above? The command would be as follows and you should receive a list of your devices.

python Decora-cli.py [email] [pswd] ?

Yes i got the device ID’s and i have python installed. So that is why it was weird I was getting stuck after that. Granted its based on not knowing where you are referring to for the ececutecommandline & the rules file.

Okay, then the next non-openHAB question to be answered first: Can you successfully execute the python command from the command line to turn on and off a light?

Usage: python /Decora-cli.py [email] [pswd] [id#:ON|OFF]

For example:

python /etc/openhab2/scripts/Decora-cli.py email pword id#:ON

and does the light turn on?

I’m hitting a concerning error when running your python script for the first time.

python Decora-cli.py xxxx@xxxx.com xxxx ?
Permission id#xxxx (Accountid#xxxx)
Traceback (most recent call last):
File “Decora-cli.py”, line 73, in
print(“Residence id#{} ({})”.format(res.id,res.name))
File “/opt/bin/python-decora_wifi-cli/decora_wifi/base_model.py”, line 23, in getattribute
return super(BaseModel, self).getattribute(name)
AttributeError: ‘Residence’ object has no attribute ‘id’

It looks like the response from the API is not providing an id on the Residence. Has anyone else run into this? Any suggestions?

Got some more info on my own issue. The issue seems to be that residences shared with you don’t get returned by that default query.

I’m trying to get the status of the device (or or off, for example). It looks like some of the other commands in the api might be able to do that. What’s the best way to tinker with the script to figure that out? Have you looked into that kind of functionality yourself?

1 Like

Did you get the device list command to work? (I just tried it myself and the script is working fine, i.e., I can get my device list and trigger ON/OFF, so there’s been no change from Leviton’s side.)

For more information regarding the python code, see the following link from GitHub, as this is where I got the script from originally. Unfortunately I’m not a Python programmer, so I can’t help with any details.

I was following step by step and still wasn’t able to work, when i trigger in habpanel the item i get this:

==> /var/log/openhab2/openhab.log <==
2020-11-03 09:28:56.419 [INFO ] [lipse.smarthome.model.script.Decora ] - Turn off kitchen lights.
2020-11-03 09:28:56.472 [WARN ] [lipse.smarthome.io.net.exec.ExecUtil] - Execution failed (Exit value: -559038737. Caused by java.io.IOException: Cannot run program “python” (in directory “.”): error=2, No such file or directory)
2020-11-03 09:28:56.474 [INFO ] [lipse.smarthome.model.script.Decora ] -

==> /var/log/openhab2/events.log <==
2020-11-03 09:28:58.029 [ome.event.ItemCommandEvent] - Item ‘Rule_kitchen_lights’ received command ON
2020-11-03 09:28:58.032 [vent.ItemStateChangedEvent] - Rule_kitchen_lights changed from OFF to ON

==> /var/log/openhab2/openhab.log <==
2020-11-03 09:28:58.032 [INFO ] [lipse.smarthome.model.script.Decora ] - Turn on kitchen lights.
2020-11-03 09:28:58.086 [WARN ] [lipse.smarthome.io.net.exec.ExecUtil] - Execution failed (Exit value: -559038737. Caused by java.io.IOException: Cannot run program “python” (in directory “.”): error=2, No such file or directory)
2020-11-03 09:28:58.090 [INFO ] [lipse.smarthome.model.script.Decora ] -

above problem is fixed, all i did is to update in rules the command replaced python with python3 and now i got a different error
ValueError: myLeviton API call (/Residences/xxxxxx/iotSwitches/xxxxxx) failed: 404, {“error”:{“statusCode”:404,“name”:“Error”,“message”:“No instance with id xxxxxx found for IotSwitch”}}

Residence ID is not the same as my residence id in leviton, is there a way to manually update the residence id? thanks

If you execute the following from the command line of your pi/computer (perhaps substituting the word python3 for python) and inserting your email and password signon for Levition:

Usage: python /Decora-cli.py [email] [pswd] ?

For example (using your actual path to the program Decora-cli.py):

python /etc/openhab2/scripts/Decora/Decora-cli.py my_email@email.com pswd1234 ?

Your will get an output from Leviton including your Permission id and Account id, as below:

Permission id#12345 (Accountid#9999)
Residence id#9876 (your street)
Switch1 id#56789 (Kitchen lights)
Switch2 id#23456 (Livingroom lights)

Hello, that’s what I also search for . I was looking into scripts but is way beyond my knowledge, I think a rule has to be created but i have no idea about syntax, hopefully someone more experienced will provide us an answer.

As per your request I have enhanced Decora-cli.py to include the ability to check the state of a switch. I have updated the README.md file to explain the syntax and output of this enhancement. Go to https://github.com/markcaldwell0017/python-decora_wifi-cli to read the README and also to download the revised version of Decora-cli.py.

Sir,
Thank you very much for the fix!
I was struggling for hours trying to make it work but with i had no luck .

I will grab your recent release and will apply it.
Best regards!

Here’s an example that toggles a Decora switch on and off, but first checks the current status of the switch to determine whether the on / off command needs to be executed.

Items file:

Switch Rule_Decora_toggle       "Decora Toggle"

Sitemap file:

sitemap Decora label="Decora lights"
{ 
    Switch item=Rule_Decora_toggle
}

Rules file (assuming an example switch ID of 98765):

rule "Decora switch toggle"
when
    Item Rule_Decora_toggle received command
then
    logInfo("Decora", "Request to toggle Decor switch received.")
    val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:?", 120000)
	if(receivedCommand==ON) {
        if(Results_decora.substring(0,2)=="ON") {
            logInfo("Decora", "Switch is already ON.  No action taken.")
        }
        else if (Results_decora.substring(0,3)=="OFF") {
            logInfo("Decora", "Switch is OFF.  Turning switch ON.") 
            val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:ON", 120000)
        }
        else {
            logInfo("Decora", Results_decora)  /* log error results */
        }
    }
	if(receivedCommand==OFF) {
        if(Results_decora.substring(0,3)=="OFF") {
            logInfo("Decora", "Switch is already OFF.  No action taken.")
        }
        else if(Results_decora.substring(0,2)=="ON") {
            logInfo("Decora", "Switch is ON.  Turning switch OFF.") 
            val Results_decora = executeCommandLine("python /etc/openhab2/scripts/Decora-cli.py <emailaddress> <password> 98765:OFF", 120000)
        }
        else {
            logInfo("Decora", Results_decora)  /* log error results */
        }
    }
end

Sir! GOD Bless You! I was trying to show these on habpanel but of course i got stuck in the middle. now your solution simply made my day. i owe you a beer big time!
Now i only need to read again the rules section of documentation and try adding a label in rules like:

if(Results_decora.substring(0,3)==“OFF”) {
logInfo(“Decora”, “Switch is already OFF. No action taken.”)
item.x.label “ON”
}
else if(Results_decora.substring(0,2)==“ON”) {
logInfo(“Decora”, “Switch is ON. Turning switch OFF.”)
item.x.label “OFF”
val Results_decora = executeCommandLine(“python /etc/openhab2/scripts/Decora-cli.py 98765:OFF”, 120000)
}
else {
logInfo(“Decora”, Results_decora) /* log error results */
}

So it can show on habpanel or sitemap the leviton switch state.

Again, thanks a lot!