Giter VIP home page Giter VIP logo

python-lakeside's Introduction

Python control for Eufy LED bulbs

A simple Python API for controlling LED bulbs from Eufy.

Example use

This will connect to a bulb and turn it on at 50% brightness and the coldest colour temperature.

import lakeside

bulb = lakeside.bulb(ip_address, access_code, type)
bulb.connect()
bulb.set_state(power=True, brightness=50, temperature=100)

The ip, access code and type can be obtained by doing:

import lakeside

devices = lakeside.get_devices(username, password)

where username and password are the credentials used in the Eufy app.

This is not an officially supported Google project.

python-lakeside's People

Contributors

dclobato avatar fisco avatar jamos77 avatar mjg59 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-lakeside's Issues

Broken pipe on send_packet

Using lakeside on Home Assistant and, after updating firmware for bulbs T1012, there are several broken pipe errors on bulb update. For example:

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 196, in async_update_ha_state
    yield from self.async_device_update()
  File "/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 319, in async_device_update
    yield from self.hass.async_add_job(self.update)
  File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3.6/site-packages/homeassistant/components/light/eufy.py", line 63, in update
    self._bulb.update()
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 166, in update
    response = self.get_status()
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 112, in get_status
    packet.sequence = self.get_sequence()
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 108, in get_sequence
    return device.get_sequence(self)
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 94, in get_sequence
    response = self.send_packet(packet, True)
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 105, in send_packet
    return device.send_packet(self, packet, response)
  File "/usr/lib/python3.6/site-packages/lakeside/__init__.py", line 69, in send_packet
    self.s.send(encrypted_packet)
BrokenPipeError: [Errno 32] Broken pipe

Something was broken with firmware 3.6 on Eufy?

Support for Eufy T1203 Smart Plug (UK)

Would it be possible to add support for the T1203 Smart Plug (UK) so that it can be used in Home Assistant along with this and the HA Eufy Component.

Devices dislike sequence numbers above 0x80000000

Looking through the code it is unclear to me where it swaps from int32 to uint32. The T1201Packet packet the response is being received from specifies int32.

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 128, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=hass.loop)
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/switch/eufy.py", line 20, in setup_platform
    add_entities([EufySwitch(discovery_info)], True)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/switch/eufy.py", line 36, in __init__
    self._switch.connect()
  File "/config/deps/lib/python3.6/site-packages/lakeside/__init__.py", line 229, in connect
    return device.connect(self)
  File "/config/deps/lib/python3.6/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/config/deps/lib/python3.6/site-packages/lakeside/__init__.py", line 246, in update
    response = self.get_status()
  File "/config/deps/lib/python3.6/site-packages/lakeside/__init__.py", line 239, in get_status
    packet.sequence = self.get_sequence()
  File "/usr/local/lib/python3.6/site-packages/google/protobuf/internal/python_message.py", line 674, in field_setter
    new_value = type_checker.CheckValue(new_value)
  File "/usr/local/lib/python3.6/site-packages/google/protobuf/internal/type_checkers.py", line 134, in CheckValue
    raise ValueError('Value out of range: %d' % proposed_value)
ValueError: Value out of range: 2388884521

2388884521 = 0x8E637C29

Support for Eufy T1016 Light Bulb

Would it be possible to add support for the T1016 Lumos Smart Bulb 2.0 - Tunable White so that it can be used in Home Assistant along with this and the HA Eufy Component?

eufy platform error: maximum recursion depth exceeded while calling a Python object

Using this package through Home Assistant's Eufy core integration results to the following error. It's unclear to me how this arises though as to me it seems random. It can work fine for a long time and then one day it no longer does.

2021-10-13 19:09:42 ERROR (MainThread) [homeassistant.components.switch] Error while setting up eufy platform for switch
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 249, in _async_setup_platform
    await asyncio.shield(task)
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/eufy/switch.py", line 11, in setup_platform
    add_entities([EufySwitch(discovery_info)], True)
  File "/usr/src/homeassistant/homeassistant/components/eufy/switch.py", line 26, in __init__
    self._switch.connect()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 229, in connect
    return device.connect(self)
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 246, in update
    response = self.get_status()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 242, in get_status
    response = self.send_packet(packet, True)
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 232, in send_packet
    return device.send_packet(self, packet, response)
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 90, in send_packet
    self.connect()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 229, in connect
    return device.connect(self)
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 246, in update
    response = self.get_status()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 239, in get_status
    packet.sequence = self.get_sequence()
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 235, in get_sequence
    return device.get_sequence(self)
  File "/usr/local/lib/python3.9/site-packages/lakeside/__init__.py", line 112, in get_sequence
    packet.sequence = random.randrange(3000000)
  File "/usr/local/lib/python3.9/site-packages/google/protobuf/internal/python_message.py", line 702, in field_setter
    new_value = type_checker.CheckValue(new_value)
  File "/usr/local/lib/python3.9/site-packages/google/protobuf/internal/type_checkers.py", line 152, in CheckValue
    if not isinstance(proposed_value, numbers.Integral):
  File "/usr/local/lib/python3.9/abc.py", line 119, in __instancecheck__
    return _abc_instancecheck(cls, instance)
  File "/usr/local/lib/python3.9/abc.py", line 123, in __subclasscheck__
    return _abc_subclasscheck(cls, subclass)
RecursionError: maximum recursion depth exceeded while calling a Python object

The actual log is 2K lines long and Github won't let me upload it. Full log here

Errors when running lakeside

I have been using this library for months to control my lights from a raspberry pi zero (thanks!). In the past few days it hasn't been working. I get the following traceback:

Traceback (most recent call last):
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 82, in send_packet
    self.s.send(encrypted_packet)
AttributeError: 'bulb' object has no attribute 's'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "living_room_lights.py", line 47, in <module>
    switch_lights(args.off)
  File "living_room_lights.py", line 35, in switch_lights
    bulb.set_state(power=pwr)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 187, in set_state
    packet.sequence = self.get_sequence()
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 134, in get_sequence
    return device.get_sequence(self)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 115, in get_sequence
    response = self.send_packet(packet, True)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 131, in send_packet
    return device.send_packet(self, packet, response)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 84, in send_packet
    self.connect()

[the following lines repeated over and over]

  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 128, in connect
    return device.connect(self)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 192, in update
    response = self.get_status()
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 138, in get_status
    packet.sequence = self.get_sequence()
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 134, in get_sequence
    return device.get_sequence(self)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 115, in get_sequence
    response = self.send_packet(packet, True)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 131, in send_packet
    return device.send_packet(self, packet, response)
  File "/home/pi/lights/env/lib/python3.5/site-packages/lakeside/__init__.py", line 73, in send_packet
    cipher = AES.new(bytes(key), AES.MODE_CBC, bytes(iv))

[end repeated section]

  File "/home/pi/lights/env/lib/python3.5/site-packages/Crypto/Cipher/AES.py", line 232, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File "/home/pi/lights/env/lib/python3.5/site-packages/Crypto/Cipher/__init__.py", line 79, in _create_cipher
    return modes[mode](factory, **kwargs)
  File "/home/pi/lights/env/lib/python3.5/site-packages/Crypto/Cipher/_mode_cbc.py", line 293, in _create_cbc_cipher
    return CbcMode(cipher_state, iv)
  File "/home/pi/lights/env/lib/python3.5/site-packages/Crypto/Cipher/_mode_cbc.py", line 95, in __init__
    self._state = VoidPointer()
  File "/home/pi/lights/env/lib/python3.5/site-packages/Crypto/Util/_raw_api.py", line 251, in VoidPointer
    return VoidPointer_ctypes()
RecursionError: maximum recursion depth exceeded

I'm using Python 3.5 with these packages installed.

astral==1.9.2
certifi==2018.11.29
chardet==3.0.4
idna==2.8
lakeside==0.11
pkg-resources==0.0.0
protobuf==3.6.1
pycryptodome==3.7.3
pytz==2018.9
PyYAML==3.13
requests==2.21.0
six==1.12.0
urllib3==1.24.1

I'm guessing this has something to do with Eufy changing their API. Has anyone else seen this and know how to fix it?

RoboVac support

Would be great if this could also support Eufy RoboVac devices. I see mine show up with type T2190 when calling get_devices but trying to connect to it currently hangs.

Errors in Eufy setup with home-assistant

Getting this error on Home Assistant startup. I have verified my credentials are correct.

2018-04-28 08:03:16 ERROR (MainThread) [homeassistant.components.switch] Error while setting up platform eufy
Traceback (most recent call last):
File "/home/pi/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_platform.py", line 129, in _async_setup_platform
SLOW_SETUP_MAX_WAIT, loop=hass.loop)
File "/usr/lib/python3.5/asyncio/tasks.py", line 400, in wait_for
return fut.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
raise self._exception
File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/pi/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/eufy.py", line 20, in setup_platform
add_devices([EufySwitch(discovery_info)], True)
File "/home/pi/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/eufy.py", line 37, in init
self._switch.connect()
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 201, in connect
return device.connect(self)
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 56, in connect
self.update()
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 218, in update
response = self.get_status()
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 214, in get_status
response = self.send_packet(packet, True)
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 204, in send_packet
return device.send_packet(self, packet, response)
File "/home/pi/homeassistant/lib/python3.5/site-packages/lakeside/init.py", line 74, in send_packet
length = struct.unpack("<H", decrypted_packet[0:2])[0]
struct.error: unpack requires a bytes object of length 2

Eufy Vacuum

Wondering what it would take to support the Eufy WiFi vacuum. The device is found when calling get_devices and it shows..

[{'address': '72.50.197.174', 'code': '', 'type': 'T2117', 'name': 'QueenVac', 'id': '62840462807d3a36feb7'}]

Lumos Smart Bulb - White & Color support

A quick perusal of the code leads me to believe this doesn't support Eufy's RGB bulb...so consider this a request to implement support!

Alternatively, some insight into how the API was reverse engineered by @mjg59 and I might submit a PR implementing the support myself.

RecursionError: maximum recursion depth exceeded

Looks to be failing here

try:
            self.s.send(encrypted_packet)
        except:
            self.connect()
            self.s.send(encrypted_packet)

it f ails to send so then tries to connect and then fails and keeps going until recursion depth error

File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 90, in send_packet
    self.connect()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 229, in connect
    return device.connect(self)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 246, in update
    response = self.get_status()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 242, in get_status
    response = self.send_packet(packet, True)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 232, in send_packet
    return device.send_packet(self, packet, response)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 90, in send_packet
    self.connect()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 229, in connect
    return device.connect(self)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 66, in connect
    self.update()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 246, in update
    response = self.get_status()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 239, in get_status
    packet.sequence = self.get_sequence()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 235, in get_sequence
    return device.get_sequence(self)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 115, in get_sequence
    response = self.send_packet(packet, True)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 232, in send_packet
    return device.send_packet(self, packet, response)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/lakeside/__init__.py", line 73, in send_packet
    cipher = AES.new(bytes(key), AES.MODE_CBC, bytes(iv))
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Cipher/AES.py", line 232, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Cipher/__init__.py", line 79, in _create_cipher
    return modes[mode](factory, **kwargs)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Cipher/_mode_cbc.py", line 274, in _create_cbc_cipher
    cipher_state = factory._create_base_cipher(kwargs)
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Cipher/AES.py", line 102, in _create_base_cipher
    cipher = VoidPointer()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Util/_raw_api.py", line 159, in VoidPointer
    return VoidPointer_cffi()
  File "/home/hass/home-assistant/lib/python3.6/site-packages/Crypto/Util/_raw_api.py", line 150, in __init__
    self._pp = ffi.new("void *[1]")
  File "/home/hass/home-assistant/lib/python3.6/site-packages/cffi/api.py", line 257, in new
    cdecl = self._typeof(cdecl)
RecursionError: maximum recursion depth exceeded

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.