tlyakhov / python-decora_wifi Goto Github PK
View Code? Open in Web Editor NEWPython Library for Interacting with Leviton Decora Smart WiFi Switches & Dimmers
License: MIT License
Python Library for Interacting with Leviton Decora Smart WiFi Switches & Dimmers
License: MIT License
python3 cli-test.py [email protected] password ON
Testing the lib hangs. Upon Ctrl+C the following is shown:
Traceback (most recent call last): File "cli-test.py", line 21, in <module> session.login(decora_email, decora_pass) File "/root/test/python-decora_wifi-master/decora_wifi/__init__.py", line 76, in login login_json = Person.login(self, payload) File "/root/test/python-decora_wifi-master/decora_wifi/models/person.py", line 569, in login return session.call_api(api, attribs, 'post') File "/root/test/python-decora_wifi-master/decora_wifi/__init__.py", line 48, in call_api response = getattr(self._session, method)(uri, data=payload_json) File "/usr/lib64/python3.6/site-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 555, in post return self.request('POST', url, data=data, json=json, **kwargs) File "/usr/lib64/python3.6/site-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 508, in request resp = self.send(prep, **send_kwargs) File "/usr/lib64/python3.6/site-packages/requests-2.18.4-py3.6.egg/requests/sessions.py", line 618, in send r = adapter.send(request, **kwargs) File "/usr/lib64/python3.6/site-packages/requests-2.18.4-py3.6.egg/requests/adapters.py", line 440, in send timeout=timeout File "/usr/lib64/python3.6/site-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 601, in urlopen chunked=chunked) File "/usr/lib64/python3.6/site-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 346, in _make_request self._validate_conn(conn) File "/usr/lib64/python3.6/site-packages/urllib3-1.22-py3.6.egg/urllib3/connectionpool.py", line 850, in _validate_conn conn.connect() File "/usr/lib64/python3.6/site-packages/urllib3-1.22-py3.6.egg/urllib3/connection.py", line 326, in connect ssl_context=context) File "/usr/lib64/python3.6/site-packages/urllib3-1.22-py3.6.egg/urllib3/util/ssl_.py", line 329, in ssl_wrap_socket return context.wrap_socket(sock, server_hostname=server_hostname) File "/usr/lib64/python3.6/ssl.py", line 401, in wrap_socket _context=self, _session=session) File "/usr/lib64/python3.6/ssl.py", line 808, in __init__ self.do_handshake() File "/usr/lib64/python3.6/ssl.py", line 1061, in do_handshake self._sslobj.do_handshake() File "/usr/lib64/python3.6/ssl.py", line 683, in do_handshake self._sslobj.do_handshake() KeyboardInterrupt
Not sure if I'm just not calling it correctly or what.
for residence in all_residences:
print(residence.count_residential_activities())
for activity in residence.get_residential_activities():
## activity.execute() ## How do I make this call work correctly?
print("Activity: {}".format(activity))
print()
time.sleep(2)
I seem to need some arguments that I can't get a handle on. I'm sure it's just me being stupid, but I'd love a tip to get past this issue. Doing the 5 objects one by one has too much timing jitter.
I could also do it with a scene, but I can't even get scenes successfully listed! I get nothing when I know there are multiple scenes in a listed room.
I have a fork of this project in my own project and I'm pulling the decora system for statuses every 10 seconds. I'm wondering if there is a REST API capacity limit being hit?
it appears to be almost arandom the the login to the system for switch status failes with a bad gateway (502) every so often, 2-4 time a day.
The traceback:
File "/home/ha/web_home_auto/homeauto/decora.py", line 90, in sync_decora
session.login(getattr(decoraAcct, 'username'), getattr(decoraAcct, 'password'))
File "/home/ha/web_home_auto/homeauto/api_decora/decora_wifi/__init__.py", line 75, in login
login_json = Person.login(self, payload)
File "/home/ha/web_home_auto/homeauto/api_decora/decora_wifi/models/person.py", line 569, in login
return session.call_api(api, attribs, 'post')
File "/home/ha/web_home_auto/homeauto/api_decora/decora_wifi/__init__.py", line 59, in call_api
raise ValueError(msg)
ValueError: myLeviton API call (/Person/login) failed: 502, <html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/admin/git/python-decora_wifi/decora_wifi/__init__.py", line 77, in login
login_json = Person.login(self, payload)
File "/Users/admin/git/python-decora_wifi/decora_wifi/models/person.py", line 569, in login
return session.call_api(api, attribs, 'post')
File "/Users/admin/git/python-decora_wifi/decora_wifi/__init__.py", line 53, in call_api
if self.login(self._email, self._password) is None:
File "/Users/admin/git/python-decora_wifi/decora_wifi/__init__.py", line 77, in login
login_json = Person.login(self, payload)
File "/Users/admin/git/python-decora_wifi/decora_wifi/models/person.py", line 569, in login
return session.call_api(api, attribs, 'post')
File "/Users/admin/git/python-decora_wifi/decora_wifi/__init__.py", line 61, in call_api
raise ValueError(msg)
ValueError: myLeviton API call (/Person/login) failed: 504, <html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
</body>
</html>
You mention near the end that there may be a Websocket API. I'm curious if you have any more info on it. I'd be happy to dig more into it, just wondering if you have any initial insight into it. May be useful for getting the state instead of polling repeatedly.
I just set up your code and I am getting a '504 Gateway Time-out' error. I am wondering if you have seen this before.
Hey,
I've pip installed the dacora-wifi package and tried to run the cli-example. Unfortunately it seems to fail right during the authentication. I've ensured I'm using the right credentials. Does this error-message make any sense to you?
Traceback (most recent call last):
File "dacora-cli.py", line 23, in <module>
session.login(decora_email, decora_pass)
File "/home/pi/.local/lib/python2.7/site-packages/decora_wifi/__init__.py", line 84, in login
self.user = Person(self, login_json['userId'])
File "/home/pi/.local/lib/python2.7/site-packages/decora_wifi/models/person.py", line 13, in __init__
super(Person, self).__init__(session, model_id)
TypeError: super() argument 1 must be type, not classobj
I have a stored Activity in Leviton I am trying to execute. I am able to find the activity. When I call .execute(session) I am receiving a 401 Unauthorized back from Leviton. The credentials I am using are the only Levity credentials and have Owner permissions. They are the same permissions I am using in the My Leviton app as well as Google Home so I know they have rights.
I am experiencing a problem where the following error is repeated in the HASS logs and the Decora Wifi switch cannot be controlled (i.e. flipping the toggle in HASS does nothing):
2017-09-18 14:49:31 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:50:02 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:50:33 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:51:03 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:51:34 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:52:05 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:52:36 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:53:07 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-18 14:53:38 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
If I look back in the logs to when the switch stopped responding, this is the traceback:
2017-09-17 00:05:32 ERROR (MainThread) [homeassistant.helpers.entity] Update for light.dining_room_light fails
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 600, in urlopen
chunked=chunked)
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 386, in _make_request
six.raise_from(e, None)
File "<string>", line 2, in raise_from
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 382, in _make_request
httplib_response = conn.getresponse()
File "/usr/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/lib/python3.6/http/client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/requests/adapters.py", line 438, in send
timeout=timeout
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 649, in urlopen
_stacktrace=sys.exc_info()[2])
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/util/retry.py", line 357, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/packages/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 600, in urlopen
chunked=chunked)
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 386, in _make_request
six.raise_from(e, None)
File "<string>", line 2, in raise_from
File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 382, in _make_request
httplib_response = conn.getresponse()
File "/usr/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/lib/python3.6/http/client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 225, in async_update_ha_state
yield from self.hass.async_add_job(self.update)
File "/usr/lib/python3.6/asyncio/futures.py", line 331, in __iter__
yield self # This tells Task to wait for completion.
File "/usr/lib/python3.6/asyncio/tasks.py", line 244, in _wakeup
future.result()
File "/usr/lib/python3.6/asyncio/futures.py", line 244, in result
raise self._exception
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 55, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/lib/python3.6/site-packages/homeassistant/components/light/decora_wifi.py", line 145, in update
self._switch.refresh()
File "/config/deps/lib/python3.6/site-packages/decora_wifi/models/iot_switch.py", line 87, in refresh
result = self._session.call_api(api, {}, 'get')
File "/config/deps/lib/python3.6/site-packages/decora_wifi/__init__.py", line 48, in call_api
response = getattr(self._session, method)(uri, data=payload_json)
File "/usr/lib/python3.6/site-packages/requests/sessions.py", line 531, in get
return self.request('GET', url, **kwargs)
File "/usr/lib/python3.6/site-packages/requests/sessions.py", line 518, in request
resp = self.send(prep, **send_kwargs)
File "/usr/lib/python3.6/site-packages/requests/sessions.py", line 639, in send
r = adapter.send(request, **kwargs)
File "/usr/lib/python3.6/site-packages/requests/adapters.py", line 488, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))
2017-09-17 00:05:46 WARNING (MainThread) [homeassistant.helpers.entity] Update of light.dining_room_light is taking over 10 seconds
2017-09-17 00:06:07 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-17 00:06:38 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
2017-09-17 00:07:09 WARNING (MainThread) [homeassistant.components.light] Updating decora_wifi light took longer than the scheduled update interval 0:00:30
My setup in my configuration.yaml is basic:
light:
- platform: decora_wifi
username: my_username
password: my_password
Since that error, I cannot turn the switch on or off from HASS. However, oddly, if I slide the brightness slider in HASS up or down, the light increases and decreases in intensity. Just the toggle switch doesn't work.
Hi,
myLeviton released a new version of their app (2.0) and I'm now unable to login.
ValueError: myLeviton API call (/Person/login) failed: 504, <html>
Can you please investigate?
Is there any way to control the switch directly, without going out to leviton.com?
Hi!
I am new to this code and the Leviton Decora switches, but I think I am a quick learner. That said, I have been trying to modify the cli_test.py script to control a single device at a time without having to iterate through all of them to find the one I want to control. So I used the original cli_test.py script initially to show me the ID for one of my switches, and then used that ID with the find_by_id_iot_switches() function to get the individual device. However, as I expand my system to include more devices, I would rather reference my devices by their names instead of by ID (i.e., be able to pass the name into the script as a command-line arg and then further pass that name to the decora functions to control the switch). Is there a way to do this? I am thinking of a function similar to find_by_id_iot_switches(), but instead it might be called something like find_by_name_iot_switches(). Is this possible?
Thanks in advance for your help (especially since I realize from a recent post that you are no longer using Leviton.
Steve-
Hi! I am able to turn switches on or off, one at a time. However, I just recently added six switches to a "room" in the Leviton mobile app and they will all turn on or off if I press the button in the app. How can I do the same thing using this Python code? I thought I could just set the [power] attribute for the room to ON or OFF, but while that did turn the power button on/off in the app, it did not actually turn the switches on or off. Looking further into the "residential_room.py" code, I see that there is a "turn_on" and "turn_off" class method that may do the trick (maybe...not even sure about this), but I don't know how to use them. I tried adding the following code to the "cli_test.py" script, but line # 2 fails with an "Authorization Required" error message:
room = all_residences[0].find_by_id_residential_rooms('62109') #this works great
room.turn_on(session) #this gives me an error
Thanks!
Steve-
Looks like last pypi release was 2019.
I was looking for a few changes on master
that are not in the release yet. Any plans on cutting a new pypi release?
For context, I am using the library in home assistant, and I wanted to reference the new api errors types.
Hi,
a few months ago I tested this project and it was working just fine. I took a break and now got back to it and I'm receiving a 502 Bad Gateway
-error now, whenever I try to run a command:
Traceback (most recent call last):
File "dacora-cli2.py", line 11, in <module>
session.login( "[email protected]", "mypassword" )
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/__init__.py", line 76, in login
login_json = Person.login(self, payload)
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/models/person.py", line 569, in login
return session.call_api(api, attribs, 'post')
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/__init__.py", line 53, in call_api
self.login(self._email, self._password)
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/__init__.py", line 76, in login
login_json = Person.login(self, payload)
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/models/person.py", line 569, in login
return session.call_api(api, attribs, 'post')
File "/home/pi/.local/lib/python3.5/site-packages/decora_wifi/__init__.py", line 60, in call_api
raise ValueError(msg)
ValueError: myLeviton API call (/Person/login) failed: 502, <html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>```
Did anything change in the api-address maybe? Or is there really an outage going on? (The App on the phone works fine though).
Looks like the current API models included do support some breaker panel functionality already.
Eg, if I do something like this:
for residence in all_residences:
for panel in residence.get_residential_breaker_panels():
print("Panel: {}".format(panel))
for breaker in panel.get_residential_breakers():
print("Breaker: {}".format(breaker))
print("Energy: " + str(breaker.energyConsumption))
print(breaker.rmsVoltage)
print(breaker.name)
print(breaker.operationalState)
attribs = {}
#attribs['remoteTrip'] = True
attribs['blinkLED'] = True
breaker.update_attributes(attribs)
print(breaker.operationalState)
I can successfully read live energy stats from my breakers, toggle the LEDs, and remotely trip them.
There do appear to be many more energy API endpoints that are not currently in the model however, for example:
residentialBreakerEnergy
findByIdResidentialBreakerEnergy
destroyByIdResidentialBreakerEnergy
updateByIdResidentialBreakerEnergy
getResidentialBreakerEnergy
createResidentialBreakerEnergy
deleteResidentialBreakerEnergy
countResidentialBreakerEnergy
createManyResidentialBreakerEnergy
Both the breaker and the residence objects have some energy metrics now too:
energyConsumptionForDay
energyConsumptionForWeek
energyConsumptionForMonth
energyConsumptionForYear
My hope is to be able to add support for Leviton smart breaker panels (including energy metrics) to Home Assistant so I can use them with the new energy feature as well as generally be able to view/control them.
Here's some example output from my panel/breaker using the current get_residential_breaker_panels
and get_residential_breakers
calls:
Panel: {
'id': 'LDATA-ABCDE-12345-FGHIJ',
'averageCurrentCount': 10,
'breakerCount': 5,
'commissioned': True,
'dauReplaced': False,
'dauReplacementData': {},
'diagnosticData': {},
'discoverBreakers': False,
'discoverBreakersMode': 'start',
'discoverBreakersStatus': '{}',
'discoverBreakersTimeout': 20,
'driverData': '',
'errorCode': '',
'factoryReset': False,
'factoryResetBreaker': False,
'factoryResetLSBMA': False,
'installerCompany': '',
'installerEmail': '',
'installerPhoneNumber': '',
'manufacturer': 'Leviton',
'model': 'DAU',
'name': 'Garage Subpanel',
'orientation': 0,
'overVoltage': False,
'packageVer': '0.1.85',
'panelSize': 30,
'pollBreakers': False,
'requestVersionHour': 0,
'resetEnergyConsumption': False,
'residenceId':,
'rmsVoltage': 122,
'rmsVoltage2': 121,
'status': 'READY',
'underVoltage': False,
'updateAvailability': 'UP_TO_DATE',
'updateStatus': '',
'updateVersion': '0.1.85',
'versionBCM': '0.0.10',
'versionBCMRadio': '',
'versionBSM': '0.1.47',
'versionBSMRadio': 'FWB7553000122',
'versionNCM': '0.2.260',
'created': '2020-12-09T02:18:11.000Z',
'online': '2021-08-14T03:55:03.000Z',
'offline': None,
'lastUpdated': '2021-08-14T03:55:03.000Z',
'wifiMode': 'Client',
'wifiRSSI': -64,
'wifiSSID': 'My WiFi SSID',
'customNotifications': [{
'name': 'offFor',
'title': 'OFF for more than',
'comparisonType': '<',
'thresholdValue': 0.5,
'thresholdProperty': 'rmsCurrent',
'thresholdDuration': 60,
'beginTime': '2021-08-14T03:20:39.276Z',
'notifiedTime': '2021-08-05T11:29:01.829Z',
'alarmStatus': 'PENDING',
'autoReset': True,
'notificationLimit': 3,
'notificationsSent': 150,
'position': 10,
'breakerId': '',
'triggerType': 'HIGH_DRAW_FOR_DURATION_WHILE_ON',
'thresholdDurationTranslation': '1 hour',
'header': 'Notify me when there is NO current draw',
'subHeader': 'below a typical standby value of',
'subTitle': 'for more than',
'enabled': True
}, {
'name': 'offFor',
'comparisonType': '<',
'thresholdValue': 0.5,
'thresholdProperty': 'rmsCurrent',
'thresholdDuration': 60,
'alarmStatus': 'NORMAL',
'autoReset': True,
'notificationLimit': 3,
'notificationsSent': 0,
'breakerId': '',
'triggerType': 'HIGH_DRAW_FOR_DURATION_WHILE_OFF',
'thresholdDurationTranslation': '1 hour'
}]
}
Breaker: {
'id': '',
'lastUpdated': '2021-08-14T03:55:23.000Z',
'online': None,
'offline': None,
'bleRSSI': 15,
'blinkLED': False,
'branchType': 'None',
'created': '2020-12-09T02:24:32.000Z',
'currentRating': 50,
'currentState': 'ManualON',
'currentStatePrev': 'SoftwareTrip',
'currentState2': 'UNDEFINED',
'currentStatePrev2': 'UNDEFINED',
'diagnostics': 0,
'driverData': '',
'energyConsumption': 15.6,
'energyConsumption2': 15.7,
'firmwareVersionBLE': 'FWB6180000105',
'firmwareVersionMeter': 'FWB7108000100',
'firmwareVersionSiLabs': '',
'hwVersion': 'MTR-010',
'lineFrequency': 60,
'lineFrequency2': 60,
'lsbmaId': '',
'lsbmaId2': '',
'manufacturer': 'LEVITON',
'mfgDate': '030520',
'mfgPlantCode': '08',
'mfgProductionLine': 'L1',
'mfgTesterVersion': 'T01',
'meterChipOk': True,
'model': 'LB250-0S',
'name': 'NEMA 14-50',
'operationalState': 'Off',
'operationalState2': None,
'overCurrent': False,
'overCurrentThreshold': 0.9,
'overCurrentThreshold2': 0.9,
'overVoltage': False,
'overVoltageThreshold': 132,
'overVoltageThreshold2': 132,
'pcbNumber': 'B6770-0A',
'poles': 2,
'position': 14,
'power': 0,
'power2': 0,
'powerFactor': 0,
'powerFactor2': 0,
'powerQuality': 0,
'powerQuality2': 0,
'reactivePower': 0,
'reactivePower2': 0,
'remoteTrip': False,
'residentialBreakerPanelId': 'LDATA-ABCDE-12345-FGHIJ',
'residentialBreakerFirmwareId': None,
'rmsCurrent': 0,
'rmsCurrent2': 0,
'rmsVoltage': 122,
'rmsVoltage2': 123,
'serialNumber': 'ABC123',
'series': '',
'status': None,
'thresholdCount': 3,
'underVoltage': False,
'underVoltageCount': 0,
'underVoltageThreshold': 102,
'underVoltageThreshold2': 102,
'updateAvailability': 'UP_TO_DATE',
'updateStatus': '',
'updateVersion': ''
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.