Skip to content

Commit

Permalink
Merge branch 'release/0.0.73'
Browse files Browse the repository at this point in the history
  • Loading branch information
dmulcahey committed Apr 26, 2022
2 parents 00bdde2 + 1cb6211 commit 4e0383d
Show file tree
Hide file tree
Showing 23 changed files with 802 additions and 232 deletions.
29 changes: 28 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,32 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

<details>
<summary>Device signature - this can be acquired by clicking on the "Zigbee Device Signature" button in the device settings</summary>

```
Paste the device signature here.
```

</details>

<details>
<summary>Diagnostic information - this can be acquired by clicking on the "Download Diagnostics" button in the device settings</summary>

```
Paste the diagnostic information here.
```

</details>

<details>
<summary>Additional logs</summary>

```
Paste any additional debug logs here.
```

</details>

**Additional context**
Add any other context about the problem here. Please include full debug logs as well as the device signature.
Add any other context about the problem here.
27 changes: 26 additions & 1 deletion .github/ISSUE_TEMPLATE/device-support-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,32 @@ A clear and concise description of what the problem is. Ex. I'm always frustrate
**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.**
<details>
<summary>Device signature - this can be acquired by clicking on the "Zigbee Device Signature" button in the device settings</summary>

```
Paste the device signature here.
```

</details>

<details>
<summary>Diagnostic information - this can be acquired by clicking on the "Download Diagnostics" button in the device settings</summary>

```
Paste the diagnostic information here.
```

</details>

<details>
<summary>Additional logs</summary>

```
Paste any additional debug logs here.
```

</details>

**Additional context**
Add any other context or screenshots about the feature request here.
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["ms-python.python", "ms-python.vscode-pylance"]
}
8 changes: 8 additions & 0 deletions .vscode/settings.default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"python.formatting.provider": "black",
// Added --no-cov to work around TypeError: message must be set
// https://github.com/microsoft/vscode-python/issues/14067
"python.testing.pytestArgs": ["--no-cov"],
// https://code.visualstudio.com/docs/python/testing#_pytest-configuration-settings
"python.testing.pytestEnabled": false
}
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ ZHA device handlers and it's provided Quirks allow Zigpy, ZHA and Home Assistant

## What are these specifications

[Zigbee Specification](https://zigbeealliance.org/wp-content/uploads/2019/11/docs-05-3474-21-0csg-zigbee-specification.pdf)
[Zigbee PRO 2017 (R22) Protocol Specification](https://zigbeealliance.org/wp-content/uploads/2019/11/docs-05-3474-21-0csg-zigbee-specification.pdf)

[Zigbee Cluster Library](https://zigbeealliance.org/wp-content/uploads/2019/12/07-5123-06-zigbee-cluster-library-specification.pdf)
[Zigbee Cluster Library (R8)](https://zigbeealliance.org/wp-content/uploads/2021/10/07-5123-08-Zigbee-Cluster-Library.pdf)

[Zigbee Base Device Specification](https://zigbeealliance.org/wp-content/uploads/zip/zigbee-base-device-behavior-bdb-v1-0.zip)
[Zigbee Base Device Behavior Specification (V1.0)](https://zigbeealliance.org/wp-content/uploads/zip/zigbee-base-device-behavior-bdb-v1-0.zip)

[Zigbee Lighting & Occupancy Device Specification (V1.0)](https://zigbeealliance.org/wp-content/uploads/2019/11/docs-15-0014-05-0plo-Lighting-OccupancyDevice-Specification-V1.0.pdf)

[Zigbee Primer](https://docs.smartthings.com/en/latest/device-type-developers-guide/zigbee-primer.html)

Expand Down Expand Up @@ -422,7 +424,9 @@ If you look at another example for the same device:

You can see a pattern that illustrates how to match a more complex event. In this case the step command is used for the dim up and dim down buttons so we need to match more of the event data to uniquely match the event.

## Testing using unit tests
## Setting up the development environment

Open a terminal at the root of the project and run the setup script: `script/setup` This script will install all necessary dependencies and it will install the precommit hook.

The tests use the [pytest](https://docs.pytest.org/en/latest/) framework.

Expand Down Expand Up @@ -467,7 +471,7 @@ You can read more about fixtures [here](https://docs.pytest.org/en/latest/how-to
You can find the common fixtures in files named `conftest.py`. Pytest will list them for you as follows:

```bash
$ pytest --fxitures
$ pytest --fixtures
[...]
--- fixtures defined from tests.conftest ---
MockAppController
Expand Down
31 changes: 14 additions & 17 deletions requirements_test_all.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
# Home Assistant test
# linters such as flake8 and pylint should be pinned, as new releases
# make new things fail. Manually update these pins when pulling in a
# new version
asynctest==0.13.0
codecov==2.1.10
coveralls==2.2.0
mock-open==1.4.0
mypy==0.790
pre-commit==2.9.2
pylint==2.6.0
pytest-aiohttp==0.3.0
pytest-cov==2.10.1
pytest-sugar==0.9.4
pytest-timeout==1.4.2
pytest==6.1.2
requests_mock==1.8.0
asynctest
isort
codecov
colorlog
codespell
coveralls
mypy==0.942
pre-commit
pylint
pytest-cov
pytest-sugar
pytest-timeout
pytest
zigpy
23 changes: 23 additions & 0 deletions script/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Setup the repository.

# Stop on errors
set -e

cd "$(dirname "$0")/.."

# Add default vscode settings if not existing
SETTINGS_FILE=./.vscode/settings.json
SETTINGS_TEMPLATE_FILE=./.vscode/settings.default.json
if [ ! -f "$SETTINGS_FILE" ]; then
echo "Copy $SETTINGS_TEMPLATE_FILE to $SETTINGS_FILE."
cp "$SETTINGS_TEMPLATE_FILE" "$SETTINGS_FILE"
fi

python3 -m venv venv
source venv/bin/activate

pip install -r requirements_test_all.txt
pre-commit install

python3 -m pip install -e .
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from setuptools import find_packages, setup

VERSION = "0.0.72"
VERSION = "0.0.73"


setup(
Expand Down
62 changes: 37 additions & 25 deletions tests/test_kof.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@
import zigpy.device
import zigpy.endpoint
import zigpy.quirks
from zigpy.zcl import foundation
import zigpy.zdo.types as zdo_t

import zhaquirks
import zhaquirks.kof.kof_mr101z

from tests.conftest import CoroutineMock

zhaquirks.setup()

Default_Response = foundation.GENERAL_COMMANDS[
foundation.GeneralCommand.Default_Response
].schema


def test_kof_no_reply():
async def test_kof_no_reply():
"""Test KOF No reply."""

class TestCluster(
Expand All @@ -20,36 +28,40 @@ class TestCluster(
"""Test Cluster Class."""

cluster_id = 0x1234
void_input_commands = [0x0002]
void_input_commands = {0x02}
server_commands = {
0x0001: ("noop", (), False),
0x0002: ("noop_noreply", (), False),
0x01: foundation.ZCLCommandDef("noop", {}, False),
0x02: foundation.ZCLCommandDef("noop_noreply", {}, False),
}
client_commands = {}

end_point = mock.MagicMock()
cluster = TestCluster(end_point)
ep = CoroutineMock()
ep.device.application.get_sequence = mock.MagicMock(return_value=4)

cluster.command(0x0001)
end_point.request.assert_called_with(
mock.ANY, mock.ANY, mock.ANY, expect_reply=True, command_id=mock.ANY
)
end_point.reset_mock()
cluster = TestCluster(ep)

cluster.command(0x0001, expect_reply=False)
end_point.request.assert_called_with(
mock.ANY, mock.ANY, mock.ANY, expect_reply=False, command_id=mock.ANY
)
end_point.reset_mock()
async def mock_req(*args, expect_reply=True, **kwargs):
if not expect_reply:
return None
else:
return mock.sentinel.real_response

cluster.command(0x0002)
end_point.request.assert_called_with(
mock.ANY, mock.ANY, mock.ANY, expect_reply=False, command_id=mock.ANY
)
end_point.reset_mock()
ep.request.side_effect = mock_req

cluster.command(0x0002, expect_reply=True)
end_point.request.assert_called_with(
mock.ANY, mock.ANY, mock.ANY, expect_reply=True, command_id=mock.ANY
rsp = await cluster.noop()
assert rsp is mock.sentinel.real_response

rsp = await cluster.noop(expect_reply=True)
assert rsp is mock.sentinel.real_response

rsp = await cluster.noop_noreply()
assert rsp == Default_Response(
command_id=TestCluster.commands_by_name["noop_noreply"].id,
status=zdo_t.Status.SUCCESS,
)
end_point.reset_mock()

rsp = await cluster.noop_noreply(expect_reply=False)
assert rsp is None

rsp = await cluster.noop_noreply(expect_reply=True)
assert rsp is mock.sentinel.real_response
44 changes: 23 additions & 21 deletions zhaquirks/elko/smart_super_thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,29 @@ class Sensor(t.enum8):
PROTECTION = 0x03

attributes = ElkoThermostatCluster.attributes.copy()
attributes = {
UNKNOWN_1: ("unknown_1", t.uint16_t, True),
DISPLAY_TEXT: ("display_text", t.CharacterString, True),
ACTIVE_SENSOR: ("active_sensor", Sensor, True),
UNKNOWN_2: ("unknown_2", t.uint8_t, True),
REGULATOR_MODE: ("regulator_mode", t.Bool, True),
DEVICE_ON: ("device_on", t.Bool, True),
UNKNOWN_3: ("unknown_3", t.LongOctetString, True),
POWER_CONSUMPTION: ("power_consumtion", t.uint16_t, True),
FLOOR_SENSOR_TEMPERATURE: ("floor_sensor_temperature", t.int16s, True),
UNKNOWN_4: ("unknown_4", t.uint16_t, True),
NIGHT_LOWERING: ("night_lowering", t.Bool, True),
UNKNOWN_5: ("unknown_5", t.Bool, True),
CHILD_LOCK: ("child_lock", t.Bool, True),
PROTECTION_MAX_TEMP: ("protection_max_temp", t.uint8_t, True),
HEATING_ACTIVE: ("heating_active", t.Bool, True),
UNKNOWN_6: ("unknown_6", t.LongOctetString, True),
UNKNOWN_7: ("unknown_7", t.int8s, True),
UNKNOWN_8: ("unknown_8", t.uint8_t, True),
UNKNOWN_9: ("unknown_9", t.uint8_t, True),
}
attributes.update(
{
UNKNOWN_1: ("unknown_1", t.uint16_t, True),
DISPLAY_TEXT: ("display_text", t.CharacterString, True),
ACTIVE_SENSOR: ("active_sensor", Sensor, True),
UNKNOWN_2: ("unknown_2", t.uint8_t, True),
REGULATOR_MODE: ("regulator_mode", t.Bool, True),
DEVICE_ON: ("device_on", t.Bool, True),
UNKNOWN_3: ("unknown_3", t.LongOctetString, True),
POWER_CONSUMPTION: ("power_consumtion", t.uint16_t, True),
FLOOR_SENSOR_TEMPERATURE: ("floor_sensor_temperature", t.int16s, True),
UNKNOWN_4: ("unknown_4", t.uint16_t, True),
NIGHT_LOWERING: ("night_lowering", t.Bool, True),
UNKNOWN_5: ("unknown_5", t.Bool, True),
CHILD_LOCK: ("child_lock", t.Bool, True),
PROTECTION_MAX_TEMP: ("protection_max_temp", t.uint8_t, True),
HEATING_ACTIVE: ("heating_active", t.Bool, True),
UNKNOWN_6: ("unknown_6", t.LongOctetString, True),
UNKNOWN_7: ("unknown_7", t.int8s, True),
UNKNOWN_8: ("unknown_8", t.uint8_t, True),
UNKNOWN_9: ("unknown_9", t.uint8_t, True),
}
)

def __init__(self, *args, **kwargs):
"""Init Elko thermostat."""
Expand Down
Loading

0 comments on commit 4e0383d

Please sign in to comment.