Skip to content

Commit 8354946

Browse files
authored
0.7.0 Release.
2 parents 2a1a16d + d1d74d0 commit 8354946

File tree

12 files changed

+196
-18
lines changed

12 files changed

+196
-18
lines changed

.github/release-drafter.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name-template: '$NEXT_PATCH_VERSION Release.'
2+
tag-template: '$NEXT_PATCH_VERSION'
3+
categories:
4+
- title: 'Breaking changes'
5+
labels:
6+
- 'breaking'
7+
- title: '🚀 Features'
8+
labels:
9+
- 'feature'
10+
- 'enhancement'
11+
- title: '🐛 Bug Fixes'
12+
labels:
13+
- 'fix'
14+
- 'bugfix'
15+
- 'bug'
16+
- title: '🧰 Maintenance'
17+
label: 'chore'
18+
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
19+
template: |
20+
## Changes
21+
22+
$CHANGES
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Release Management
2+
3+
on:
4+
push:
5+
# branches to consider in the event; optional, defaults to all
6+
branches:
7+
- master
8+
9+
jobs:
10+
update_draft_release:
11+
runs-on: ubuntu-latest
12+
steps:
13+
# Drafts your next Release notes as Pull Requests are merged into "master"
14+
- uses: toolmantim/[email protected]
15+
env:
16+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.travis.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ language: python
22
matrix:
33
fast_finish: true
44
include:
5-
- python: "3.5"
5+
- python: "3.6"
66
env: TOXENV=lint
7-
- python: "3.5"
8-
env: TOXENV=py35
97
- python: "3.6"
108
env: TOXENV=py36
9+
- python: "3.7"
10+
env: TOXENV=py37
11+
- python: "3.8"
12+
env: TOXENV=py38
1113
install: pip install -U setuptools tox coveralls
1214
script: tox
1315
after_success: coveralls

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,36 @@
33
[![Build Status](https://travis-ci.org/zigpy/zigpy-xbee.svg?branch=master)](https://travis-ci.org/zigpy/zigpy-xbee)
44
[![Coverage](https://coveralls.io/repos/github/zigpy/zigpy-xbee/badge.svg?branch=master)](https://coveralls.io/github/zigpy/zigpy-xbee?branch=master)
55

6-
[zigpy-xbee](https://github.com/zigpy/zigpy-xbee/) is a Python implementation for the [Zigpy](https://github.com/zigpy/) project to implement [XBee](https://en.wikipedia.org/wiki/XBee) based [Zigbee](https://www.zigbee.org) radio devices.
6+
[zigpy-xbee](https://github.com/zigpy/zigpy-xbee/) is a Python implementation for the [Zigpy](https://github.com/zigpy/) project to implement [XBee](https://en.wikipedia.org/wiki/XBee) based [Zigbee](https://www.zigbee.org) radio devices from Digi.
7+
8+
- https://github.com/zigpy/zigpy-xbee
9+
10+
Digi XBee is the brand name of a family of form factor compatible radio modules from Digi International.
11+
12+
The XBee radios can all be used with the minimum number of connections — power (3.3 V), ground, data in and data out (UART), with other recommended lines being Reset and Sleep.[5] Additionally, most XBee families have some other flow control, input/output (I/O), analog-to-digital converter (A/D) and indicator lines built in.
13+
14+
- https://en.wikipedia.org/wiki/XBee
15+
16+
Zigbee Home Automation integration with **[zigpy](https://github.com/zigpy/zigpy/)** allows you to connect one of many off-the-shelf Zigbee adapters using one of the available Zigbee radio library modules compatible with zigpy to control Zigbee based devices, including this **[zigpy-xbee](https://github.com/zigpy/zigpy-xbee/)** library for Xbee based Zigbee radio modules.
17+
18+
[zigpy](https://github.com/zigpy/zigpy/)** currently has support for controlling Zigbee device types such as binary sensors (e.g., motion and door sensors), sensors (e.g., temperature sensors), lightbulbs, switches, and fans. A working implementation of zigbe exist in **[Home Assistant](https://www.home-assistant.io)** (Python based open source home automation software) as part of its **[ZHA component](https://www.home-assistant.io/components/zha/)**
19+
20+
## Compatible hardware
21+
22+
zigpy works with separate radio libraries which can each interface with multiple USB and GPIO radio hardware adapters/modules over different native UART serial protocols. Such radio libraries includes **[zigpy-xbee](https://github.com/zigpy/zigpy-xbee)** (which communicates with XBee based Zigbee radios), **[bellows](https://github.com/zigpy/bellows)** (which communicates with EZSP/EmberZNet based radios), and as **[zigpy-deconz](https://github.com/zigpy/zigpy-deconz)** for deCONZ serial protocol (for communicating with ConBee and RaspBee USB and GPIO radios from Dresden-Elektronik). There are also an experimental radio library called **[zigpy-zigate](https://github.com/doudz/zigpy-zigate)** for communicating with ZiGate based radios.
23+
24+
### Known working XBee based Zigbee radio modules for Zigpy
25+
26+
These are XBee Zigbee based radios that have been tested with the [zigpy-xbee](https://github.com/zigpy/zigpy-xbee) library for zigpy
27+
28+
- Digi XBee Series 2C (S2C) modules
29+
- Digi XBee Series 2 (S2) modules. Note: These will need to be manually flashed with the Zigbee Coordinator API firmware via XCTU.
30+
- Digi XBee Series 3 (xbee3-24) modules
31+
32+
# Releases of zigpy-xbee-homeassistant via PyPI
33+
Tagged versions of zigpy-xbee-homeassistant are also released via PyPI
34+
35+
- https://pypi.org/project/zigpy-xbee-homeassistant/
36+
- https://pypi.org/project/zigpy-xbee-homeassistant/#history
37+
- https://pypi.org/project/zigpy-xbee-homeassistant/#files
38+

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ not_skip = __init__.py
2626
force_sort_within_sections = true
2727
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
2828
default_section = THIRDPARTY
29-
known_first_party = homeassistant,tests
29+
known_first_party = zigpy_xbee,tests
3030
forced_separate = tests
3131
combine_as_imports = true

tests/test_application.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,3 +547,40 @@ def test_rx_device_annce(app, ieee, nwk):
547547
assert app.handle_join.call_args[0][0] == nwk
548548
assert app.handle_join.call_args[0][1] == ieee
549549
assert app.handle_join.call_args[0][2] == 0
550+
551+
552+
async def _test_mrequest(app, send_success=True, send_timeout=False, **kwargs):
553+
seq = 123
554+
group_id = 0x2345
555+
556+
def _mock_command(
557+
cmdname, ieee, nwk, src_ep, dst_ep, cluster, profile, radius, options, data
558+
):
559+
send_fut = asyncio.Future()
560+
if not send_timeout:
561+
if send_success:
562+
send_fut.set_result(xbee_t.TXStatus.SUCCESS)
563+
else:
564+
send_fut.set_result(xbee_t.TXStatus.ADDRESS_NOT_FOUND)
565+
return send_fut
566+
567+
app._api._command = mock.MagicMock(side_effect=_mock_command)
568+
return await app.mrequest(group_id, 0x0260, 1, 2, seq, b"\xaa\x55\xbe\xef")
569+
570+
571+
@pytest.mark.asyncio
572+
async def test_mrequest_with_reply(app):
573+
r = await _test_mrequest(app, send_success=True)
574+
assert r[0] == 0
575+
576+
577+
@pytest.mark.asyncio
578+
async def test_mrequest_send_timeout(app):
579+
r = await _test_mrequest(app, send_timeout=True)
580+
assert r[0] != 0
581+
582+
583+
@pytest.mark.asyncio
584+
async def test_mrequest_send_fail(app):
585+
r = await _test_mrequest(app, send_success=False)
586+
assert r[0] != 0

tests/test_uart.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,17 @@ def test_close(gw):
6767

6868

6969
def test_data_received_chunk_frame(gw):
70-
data = b"~\x00\x07\x8b\x0e\xff\xfd\x00$\x02D"
70+
data = b"~\x00\r\x88\rID\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdd"
7171
gw.frame_received = mock.MagicMock()
72-
gw.data_received(data[:-4])
72+
gw.data_received(data[:3])
7373
assert gw.frame_received.call_count == 0
74-
gw.data_received(data[-4:])
74+
gw.data_received(data[3:])
7575
assert gw.frame_received.call_count == 1
7676
assert gw.frame_received.call_args[0][0] == data[3:-1]
7777

7878

7979
def test_data_received_full_frame(gw):
80-
data = b"~\x00\x07\x8b\x0e\xff\xfd\x00$\x02D"
80+
data = b"~\x00\r\x88\rID\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdd"
8181
gw.frame_received = mock.MagicMock()
8282
gw.data_received(data)
8383
assert gw.frame_received.call_count == 1
@@ -91,15 +91,29 @@ def test_data_received_incomplete_frame(gw):
9191
assert gw.frame_received.call_count == 0
9292

9393

94-
def test_data_received_at_response(gw):
94+
def test_data_received_at_response_non_cmd_mode(gw):
9595
data = b"OK\x0D"
9696
gw.frame_received = mock.MagicMock()
9797
gw.command_mode_rsp = mock.MagicMock()
9898

99+
gw.data_received(data)
100+
assert gw.command_mode_rsp.call_count == 0
101+
102+
103+
def test_data_received_at_response_in_cmd_mode(gw):
104+
data = b"OK\x0D"
105+
gw.frame_received = mock.MagicMock()
106+
gw.command_mode_rsp = mock.MagicMock()
107+
108+
gw.command_mode_send(b"")
99109
gw.data_received(data)
100110
assert gw.command_mode_rsp.call_count == 1
101111
assert gw.command_mode_rsp.call_args[0][0] == b"OK"
102112

113+
gw.reset_command_mode()
114+
gw.data_received(data)
115+
assert gw.command_mode_rsp.call_count == 1
116+
103117

104118
def test_extract(gw):
105119
gw._buffer = b"\x7E\x00\x02\x23\x7D\x31\xCBextra"

tox.ini

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# and then run "tox" from this directory.
55

66
[tox]
7-
envlist = py35, py36, lint
7+
envlist = py36, py37, py38, lint, black
88
skip_missing_interpreters = True
99

1010
[testenv]
@@ -22,3 +22,10 @@ basepython = python3
2222
deps = flake8
2323
commands = flake8
2424

25+
[testenv:black]
26+
deps=black
27+
setenv =
28+
LC_ALL=C.UTF-8
29+
LANG=C.UTF-8
30+
commands=
31+
black --check --fast {toxinidir}/zigpy_xbee {toxinidir}/tests {toxinidir}/setup.py

zigpy_xbee/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
MAJOR_VERSION = 0
2-
MINOR_VERSION = 6
2+
MINOR_VERSION = 7
33
PATCH_VERSION = "0"
44
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
55
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION)

zigpy_xbee/api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def frame_received(self, data):
320320
LOGGER.error("No '%s' handler. Data: %s", command, binascii.hexlify(data))
321321

322322
def _handle_at_response(self, frame_id, cmd, status, value):
323-
fut, = self._awaiting.pop(frame_id)
323+
(fut,) = self._awaiting.pop(frame_id)
324324
try:
325325
status = ATCommandResult(status)
326326
except ValueError:
@@ -391,7 +391,7 @@ def _handle_tx_status(self, frame_id, nwk, tries, tx_status, dsc_status):
391391
frame_id,
392392
)
393393
try:
394-
fut, = self._awaiting.pop(frame_id)
394+
(fut,) = self._awaiting.pop(frame_id)
395395
except KeyError:
396396
LOGGER.debug("unexpected tx_status report received")
397397
return
@@ -449,11 +449,11 @@ async def api_mode_at_commands(self, baudrate):
449449
cmds.insert(0, bd)
450450

451451
for cmd in cmds:
452-
if await self.command_mode_at_cmd(cmd + "\r"):
453-
LOGGER.debug("Successfuly sent %s cmd", cmd)
454-
else:
452+
if not await self.command_mode_at_cmd(cmd + "\r"):
455453
LOGGER.debug("No response to %s cmd", cmd)
456454
return None
455+
LOGGER.debug("Successfuly sent %s cmd", cmd)
456+
self._uart.reset_command_mode()
457457
return True
458458

459459
async def init_api_mode(self):

0 commit comments

Comments
 (0)