GithubHelp home page GithubHelp logo

2fake / devolo_home_control_api Goto Github PK

View Code? Open in Web Editor NEW
11.0 11.0 2.0 6.96 MB

devolo Home Control in Python

License: GNU General Public License v3.0

Python 99.93% Dockerfile 0.07%
devolo hacktoberfest home-automation home-control iot python zwave

devolo_home_control_api's People

Contributors

2fake avatar dependabot[bot] avatar fabaff avatar scop avatar shutgun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

adrianer

devolo_home_control_api's Issues

Fix test for MprmWebsocket._on_error

Fix test for MprmWebsocket._on_error

# TODO: Fix test for MprmWebsocket._on_error

    # TODO: Fix test for MprmWebsocket._on_error
    #@pytest.mark.usefixtures("mock_mprmwebsocket_get_remote_session")
    #@pytest.mark.usefixtures("mock_mprmwebsocket_websocket_connection")
    #def test__on_error(self):
    #    self.mprm._ws = MockWebsocket()
    #    self.mprm._on_error("error")

    @pytest.mark.usefixtures("mock_mprmwebsocket_get_local_session_json_decode_error")
    def test__try_reconnect(self, mocker, ):
        spy = mocker.spy(time, "sleep")
        self.mprm._ws = MockWebsocket()

Compare last_activity value instead of assert hasa...

Compare last_activity value instead of assert hasattr, because SirenBinarySensor always has a last_activity

# TODO: Compare last_activity value instead of assert hasattr, because SirenBinarySensor always has a last_activity

    def test__last_activity_binary_sensor(self):
        # TODO: Compare last_activity value instead of assert hasattr, because BinarySensor always has a last_activity
        device = self.devices.get("sensor").get("uid")
        self.homecontrol._binary_sensor({"UID": self.devices.get("sensor").get("elementUIDs")[0],
                                         "properties": {"state": self.devices.get("sensor").get("state")}})
        self.homecontrol._last_activity({"UID": self.devices.get("sensor").get("elementUIDs")[1],
                                         "properties": {"lastActivityTime": self.devices.get("sensor").get("last_activity")}})
        assert hasattr(self.homecontrol.devices[device].binary_sensor_property.
                       get(self.devices.get("sensor").get("elementUIDs")[0]), "last_activity")

    def test__last_activity_siren(self):
        # TODO: Compare last_activity value instead of assert hasattr, because SirenBinarySensor always has a last_activity
        device = self.devices.get("siren").get("uid")
        self.homecontrol._binary_sensor({"UID": self.devices.get("siren").get("elementUIDs")[1],
                                         "properties": {"state": self.devices.get("siren").get("state")}})
        self.homecontrol._last_activity({"UID": self.devices.get("siren").get("elementUIDs")[3],
                                         "properties": {"lastActivityTime": self.devices.get("siren").get("last_activity")}})
        assert hasattr(self.homecontrol.devices[device].binary_sensor_property.
                       get(self.devices.get("siren").get("elementUIDs")[1]), "last_activity")

    def test__led(self):
        # TODO: Use test data
        device = self.devices.get("mains").get("uid")```

Rewrite test__inspect_devices

Rewrite test__inspect_devices

# TODO: Rewrite test__inspect_devices

    # TODO: Rewrite test__inspect_devices
    # @pytest.mark.usefixtures("mock_extract_data_from_element_uids")
    # @pytest.mark.usefixtures("mock_mprmrest_get_all_devices")
    # def test__inspect_devices(self, mocker):
    #     spy = mocker.spy(self.homecontrol, '_inspect_devices')
    #     self.homecontrol._inspect_devices([self.devices.get("mains")])
    #     assert spy.call_count == 1

6e518c32dc066313b31ac2f97708b85a67ae7773

Compare last_activity value instead of assert hasa...

Compare last_activity value instead of assert hasattr, because BinarySensor always has a last_activity

# TODO: Compare last_activity value instead of assert hasattr, because BinarySensor always has a last_activity

        assert self.homecontrol.devices.get(device).humidity_bar_property.get(f"devolo.HumidityBar:{device}").zone == 1

    def test__last_activity_binary_sensor(self):
        # TODO: Compare last_activity value instead of assert hasattr, because BinarySensor always has a last_activity
        device = self.devices.get("sensor").get("uid")
        self.homecontrol._binary_sensor({"UID": self.devices.get("sensor").get("elementUIDs")[0],
                                         "properties": {"state": self.devices.get("sensor").get("state")}})
        self.homecontrol._last_activity({"UID": self.devices.get("sensor").get("elementUIDs")[1],
                                         "properties": {"lastActivityTime": self.devices.get("sensor").get("last_activity")}})
        assert hasattr(self.homecontrol.devices[device].binary_sensor_property.
                       get(self.devices.get("sensor").get("elementUIDs")[0]), "last_activity")

    def test__last_activity_siren(self):
        # TODO: Compare last_activity value instead of assert hasattr, because SirenBinarySensor always has a last_activity
        device = self.devices.get("siren").get("uid")
        self.homecontrol._binary_sensor({"UID": self.devices.get("siren").get("elementUIDs")[1],
                                         "properties": {"state": self.devices.get("siren").get("state")}})
        self.homecontrol._last_activity({"UID": self.devices.get("siren").get("elementUIDs")[3],
                                         "properties": {"lastActivityTime": self.devices.get("siren").get("last_activity")}})
        assert hasattr(self.homecontrol.devices[device].binary_sensor_property.
                       get(self.devices.get("siren").get("elementUIDs")[1]), "last_activity")

    def test__led(self):
        # TODO: Use test data
        device = self.devices.get("mains").get("uid")```

Protection mode messages lead to websocket error

Describe the bug
When a protection mode message comes in, we log the following error message:

2020-09-18 12:51:25,533 websocket ERROR: error from callback <bound method MprmWebsocket._on_message of <devolo_home_control_api.homecontrol.HomeControl object at 0x7fd9320cef98>>: 'guiEnabled'
  File "python3.7/site-packages/websocket/_app.py", line 343, in _callback
    callback(*args)
  File "devolo_home_control_api/devolo_home_control_api/backend/mprm_websocket.py", line 123, in _on_message
    self.on_update(msg)
  File "devolo_home_control_api/devolo_home_control_api/homecontrol.py", line 125, in on_update
    self.updater.update(message)
  File "devolo_home_control_api/devolo_home_control_api/publisher/updater.py", line 75, in update
    message_type.get(get_device_type_from_element_uid(message['properties']['uid']), self._unknown)(message)
  File "devolo_home_control_api/devolo_home_control_api/publisher/updater.py", line 220, in _meter
    property_name[message['properties']['property.name']](message['properties'])

To Reproduce
Steps to reproduce the behavior:

  1. Have logging level on error at least
  2. Change protection mode of a metering plug

Expected behavior
The message is processed without error.

Check, if we need to handle other device types tha...

Check, if we need to handle other device types than BinarySwitch on unsuccessful operations

# TODO: Check, if we need to handle other device types than BinarySwitch on unsuccessful operations

        properties = {"properties": message.get("properties").get("property.value.new")}
        if type(properties.get("properties")) is dict:
            properties['properties']['uid'] = properties.get("properties").get("widgetElementUID")
            if get_device_type_from_element_uid(properties['properties']['uid']) == "devolo.BinarySwitch":
                # TODO: Check, if we need to handle other device types than BinarySwitch on unsuccessful operations
                properties['properties']['property.name'] = "state"
                properties['properties']['property.value.new'] = int(properties.get("properties").get("data"))
            self.update(properties)

    def _device_online_state(self, message: dict):
ndex 35ec0f6..fb35106 100644
++ b/docs/CHANGELOG.md

40f8ae517c8c76c3d7210045a0d6f989ded9ba84

Sometimes .set() for a binary switch returns None

Describe the bug
After some time running the API and might somes reconnects in local case, a binary switch can not be switched. Tried to reproduce it, by shutting down WiFi while running, but this doesn't triggered the error.

To Reproduce
?

Expected behavior
Switch is working after a reconnect always

Desktop (please complete the following information):
Docker Home Assistant

Additional context

Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 130, in handle_call_service connection.context(msg), File "/usr/src/homeassistant/homeassistant/core.py", line 1253, in async_call task.result() File "/usr/src/homeassistant/homeassistant/core.py", line 1288, in _execute_service await handler.func(service_call) File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service self._platforms.values(), func, call, required_features File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 453, in entity_service_call future.result() # pop exception if have File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 597, in async_request_call await coro File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 484, in _handle_entity_call await result File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 622, in async_turn_on await self.hass.async_add_executor_job(ft.partial(self.turn_on, **kwargs)) File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/usr/src/homeassistant/homeassistant/components/devolo_home_control/switch.py", line 119, in turn_on self._binary_switch_property.set(state=True) File "/usr/local/lib/python3.7/site-packages/devolo_home_control_api/properties/binary_switch_property.py", line 35, in set if response.get("result").get("status") == 1: AttributeError: 'NoneType' object has no attribute 'get'

Zone outdated after renaming in UI

Describe the bug
If I rename a zone via UI, the general device settings property keeps the old name.

To Reproduce
Steps to reproduce the behavior:

  1. Rename a zone via UI
  2. Query Gateway.zones

Expected behavior
The renamed zone has its new name.

Requirement is pinned for devolo-home-control-api 0.11.0: websocket-client<=0.56.0

Describe the bug

Thanks for your support of Home Assistant!

To Reproduce
Steps to reproduce the behavior:

(home-assistant) x:~/Dev/home-assistant/home-assistant$ pip install -r requirements_all.txt
...
(home-assistant) x:~/Dev/home-assistant/home-assistant$ pipdeptree --reverse --packages websocket-client
...
websocket-client==0.54.0
  - devolo-home-control-api==0.11.0 [requires: websocket-client<=0.56.0]
...

Expected behavior

  • To avoid future issues it would be good if this library would change its pinning to allow any higher version and just set a minimum version.

Desktop (please complete the following information):

  • OS: Ubuntu 18.04
  • Version 0.11.0

Metering plugs are not detected

Describe the bug
I have code that loops over all known devices and prints them, but my metering plugs are not there.

To Reproduce
Run this script

import sys

from devolo_home_control_api.mydevolo import Mydevolo
from devolo_home_control_api.homecontrol import HomeControl
from devolo_home_control_api.devices.zwave import Zwave

gateway_id = ""

mydevolo = Mydevolo()
mydevolo.user = ""
mydevolo.password = ""

controller = HomeControl(gateway_id, mydevolo)

for dev in controller.get_all_devices():
    device = controller.devices.get(dev)
    print("Identifier: %s - Device: %s %s" % (dev, device.name, device.generic_device_class))

print("Done!")

Which outputs

Identifier: hdm:ZWave:D9344F42/2 - Device: Devolo Connect Thermostat
Identifier: hdm:ZWave:D9344F42/3 - Device: Devolo Connect Thermostat
Identifier: hdm:ZWave:D9344F42/4 - Device: Unknown Unknown
Identifier: hdm:ZWave:D9344F42/5 - Device: Door/Window Contact None
Identifier: hdm:ZWave:D9344F42/6 - Device: Danfoss RS 014G0160 Thermostat Sensor Multilevel
Identifier: hdm:ZWave:D9344F42/7 - Device: Unknown Unknown
Identifier: hdm:ZWave:D9344F42/8 - Device: Unknown Unknown
Identifier: hdm:ZWave:D9344F42/9 - Device: Unknown Unknown
Identifier: hdm:ZWave:D9344F42/10 - Device: Humidity Sensor None

Obviously I left out any passwords etc, but my plugs aren't in the list. The Unknowns are my Philips Hue Bulbs added through the Bridge integration.

Expected behavior
I would expect my 2 metering plugs (that show up in the app on my phone) to show up in this list.

Desktop (please complete the following information):

  • OS: Windows 10 Home 20H2
  • Python version: 3.9.0 x64

Additional context
Last time I checked, all devices were up to date.

Decide if deviceEvents are obsolet. If yes, remove...

Decide if deviceEvents are obsolet. If yes, remove this test

# TODO: Decide if deviceEvents are obsolet. If yes, remove this test

        assert online_state != self.homecontrol.devices.get(uid).status

    # TODO: Decide if deviceEvents are obsolet. If yes, remove this test
    # def test__device_events(self):
    #     uid = self.devices.get("mains").get("uid")
    #     self.homecontrol.devices.get(uid).binary_switch_property \
    #         .get(f"devolo.BinarySwitch:{uid}").state = True
    #     self.homecontrol.updater._device_events(message={"properties":
    #                                                      {"property.value.new":
    #                                                       {"widgetElementUID": f"devolo.BinarySwitch:{uid}",
    #                                                        "property.name": "state",
    #                                                        "data": 0}}})
    #     assert not self.homecontrol.devices.get(uid).binary_switch_property .get(f"devolo.BinarySwitch:{uid}").state

    def test__general_device(self):
        uid = self.devices['mains']['uid']

1fc17a5196f11e6df401ec254a0ab77180eee6d4

[Security] Workflow pythonpackage.yml is using vulnerable action pre-commit/action

The workflow pythonpackage.yml is referencing action pre-commit/action using references v2.0.0. However this reference is missing the commit 80db042ff08cdddbbbfb6f89c06a6bfc4dddf0b7 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.

Timezone not respected for last_activity

Describe the bug
The last_activity attribute of the binary sensor property is two hours ahead. That seems to me, that the timestamps the gateway send are in local time but converted as if they were UTC.

To Reproduce
Steps to reproduce the behavior:

  1. Have a device with a binary sensor
  2. Compare last_activity attribute with the mydevolo web-UI

Expected behavior
Both are equal.

Reduce Cognitive complexity in mocked homecontrol

Reduce Cognitive complexity in mocked homecontrol

# TODO: Reduce Cognitive complexity in mocked homecontrol

    for device_type, device in test_data.get("devices").items():
        # TODO: Reduce Cognitive complexity in mocked homecontrol
        device_uid = device.get("uid")
        if device_type == "blinds":
            self.devices[device_uid] = shutter(device_uid=device_uid)

0fcdcf923c4921084972ef6681fddccf74dfccd6

Pending operation messages lead to websocket error

Describe the bug
When a pending message comes in, we log the following error message:

2020-09-18 12:43:09,680 websocket ERROR: error from callback <bound method MprmWebsocket._on_message of <devolo_home_control_api.homecontrol.HomeControl object at 0x7fd9320cef98>>: 'ZWave:CBC56091/3'
  File "python3.7/site-packages/websocket/_app.py", line 343, in _callback
    callback(*args)
  File "devolo_home_control_api/devolo_home_control_api/backend/mprm_websocket.py", line 123, in _on_message
    self.on_update(msg)
  File devolo_home_control_api/devolo_home_control_api/homecontrol.py", line 125, in on_update
    self.updater.update(message)
  File "devolo_home_control_api/devolo_home_control_api/publisher/updater.py", line 73, in update
    self._pending_operations(message)
  File "devolo_home_control_api/devolo_home_control_api/publisher/updater.py", line 140, in _pending_operations
    self.devices[device_uid].pending_operations = pending_operations

To Reproduce
Steps to reproduce the behavior:

  1. Have logging level on error at least
  2. Trigger a pending operation message

Expected behavior
The message is processed without error.

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.