Skip to content

Commit 75a5839

Browse files
committed
Finallize first prod release
1 parent 985cd9f commit 75a5839

11 files changed

+74
-317
lines changed

.travis.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ sudo: false
33
cache:
44
- pip
55
python:
6-
- '3.4'
76
- '3.5'
87
- '3.6'
9-
- '3.7-dev'
8+
- 'nightly'
109
matrix:
1110
fast_finish: true
1211
allow_failures:
13-
- python: '3.7-dev'
12+
- python: 'nightly'
1413
install:
1514
- pip install -r requirements-dev.txt
1615
- pip install -U codecov

README.rst

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,37 +55,6 @@ The following script does the same thing, but note how you can define the bulbs
5555
prior calling the ``search_bulbs`` context manager. This works due to the fact
5656
that dictionaries are mutable in Python.
5757

58-
.. code:: python
59-
60-
import asyncio
61-
62-
from yeelib import search_bulbs
63-
64-
65-
@asyncio.coroutine
66-
def turn_all_lights_on(bulbs):
67-
while True:
68-
print(bulbs)
69-
for b in bulbs.values():
70-
asyncio.Task(b.send_command("set_power",
71-
["off", "sudden", 40]))
72-
yield from asyncio.sleep(10)
73-
74-
75-
def main():
76-
bulbs = {}
77-
asyncio.Task(turn_all_lights_on(bulbs))
78-
loop = asyncio.get_event_loop()
79-
try:
80-
with search_bulbs(bulbs):
81-
loop.run_forever()
82-
except KeyboardInterrupt:
83-
loop.stop()
84-
85-
86-
if __name__ == '__main__':
87-
main()
88-
8958

9059
Specifications
9160
--------------

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ssdp>=1.0.1

setup.cfg

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@ description-content-type = text/x-rst; charset=UTF-8
88
home-page = https://github.com/codingjoe/yeelib
99
license = Apache-2
1010
classifier =
11-
Development Status :: 4 - Beta
11+
Development Status :: 5 - Production/Stable
1212
Environment :: Console
1313
Intended Audience :: Developers
1414
Intended Audience :: Information Technology
1515
License :: OSI Approved :: Apache Software License
1616
Operating System :: OS Independent
1717
Programming Language :: Python
18+
Framework :: AsyncIO
19+
Topic :: System :: Networking
20+
Topic :: Software Development :: Libraries
21+
Topic :: Home Automation
1822
keywords =
1923
light
2024
yeelight
25+
iot
26+
asyncio
27+
home-automation
2128

2229
[files]
2330
packages =

tests/test_bulbs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class TestBulb:
1111
@mocketize
1212
def test_send_command(self):
1313
Mocket.register(MocketEntry(self.bulb_addr, [b'{"id":1, "result":["ok"]}\r\n']))
14-
with Bulb(*self.bulb_addr) as b:
14+
with Bulb(*self.bulb_addr, id=1, support=['set_ct_abx']) as b:
1515
loop = asyncio.get_event_loop()
1616
response = loop.run_until_complete(b.send_command('set_ct_abx', [3500, 'smooth', 500]))
1717

tests/test_discover.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,33 @@
44

55
from yeelib.discover import YeelightProtocol, search_bulbs
66
from yeelib.exceptions import YeelightError
7+
from yeelib import bulbs
78

89
from . import fixtures
910

1011

1112
class TestYeelightProtocoll:
1213
def test_notify(self, ):
13-
bulbs = {}
14-
p = YeelightProtocol(bulbs=bulbs)
14+
p = YeelightProtocol()
1515
p.datagram_received(data=fixtures.request, addr=('192.168.1.239', 1982))
1616
assert len(bulbs) == 1
1717
assert bulbs['0x000000000015243f'].ip == '192.168.1.239'
1818

1919
def test_mcast(self, ):
20-
bulbs = {}
21-
p = YeelightProtocol(bulbs=bulbs)
20+
p = YeelightProtocol()
2221
p.datagram_received(data=fixtures.response, addr=('192.168.1.239', 1982))
2322
assert len(bulbs) == 1
2423
assert bulbs['0x000000000015243f'].ip == '192.168.1.239'
2524

2625
def test_duplicate(self):
27-
bulbs = {}
28-
p = YeelightProtocol(bulbs=bulbs)
26+
p = YeelightProtocol()
2927
p.datagram_received(data=fixtures.request, addr=('192.168.1.239', 1982))
3028
p.datagram_received(data=fixtures.request, addr=('192.168.1.239', 1982))
3129
assert len(bulbs) == 1
3230
assert bulbs['0x000000000015243f'].ip == '192.168.1.239'
3331

3432
def test_wrong_location(self):
35-
bulbs = {}
36-
p = YeelightProtocol(bulbs=bulbs)
33+
p = YeelightProtocol()
3734
with pytest.raises(YeelightError) as e:
3835
p.datagram_received(data=fixtures.response_wrong_location,
3936
addr=('192.168.1.239', 1982))

tests/test_upnp.py

Lines changed: 0 additions & 54 deletions
This file was deleted.

yeelib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from .discover import * # NoQA
2-
from .bulbs import * # NoQA
2+
from .devices import * # NoQA

yeelib/bulbs.py renamed to yeelib/devices.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
import socket
55
import time
66

7+
from yeelib.exceptions import YeelightError
8+
79
__all__ = ('Bulb', )
810

911
logger = logging.getLogger('yeelib')
1012

1113

1214
class Bulb:
13-
def __init__(self, ip, port=55443, status_refresh_interval=3600, **kwargs):
15+
def __init__(self, ip, port=55443, status_refresh_interval=3600, _registry=None, **kwargs):
16+
self._registry = _registry
1417
self.ip = ip
1518
self.port = port
1619
self.status_refresh_interval = status_refresh_interval
@@ -37,10 +40,9 @@ def __repr__(self):
3740
return "<%s: %s>" % (type(self).__name__, self.ip)
3841

3942
@property
40-
@asyncio.coroutine
41-
def socket(self):
43+
async def socket(self):
4244
if self.__socket is None:
43-
self.__socket = yield from asyncio.open_connection(
45+
self.__socket = await asyncio.open_connection(
4446
self.ip, self.port)
4547
return self.__socket
4648

@@ -52,18 +54,22 @@ def socket(self, value):
5254
pass
5355
else:
5456
writer.close()
57+
if self._registry:
58+
del self._registry[self.id]
5559
self.__socket = value
5660

57-
@asyncio.coroutine
58-
def send_command(self, method, params):
61+
async def send_command(self, method, params):
62+
if method not in self.support:
63+
msg = "The method '%s' is not supported by this bulb." % method
64+
raise YeelightError(msg)
5965
self.__command_id += 1
6066
data = {
6167
'id': self.__command_id,
6268
'method': method,
6369
'params': params,
6470
}
6571
msg = json.dumps(data) + '\r\n'
66-
reader, writer = yield from self.socket
72+
reader, writer = await self.socket
6773
try:
6874
writer.write(msg.encode())
6975
logger.debug("%s: >>> %s", self.ip, msg.strip())
@@ -72,7 +78,7 @@ def send_command(self, method, params):
7278
self.socket = None
7379
else:
7480
try:
75-
response = (yield from reader.readline()).decode()
81+
response = (await reader.readline()).decode()
7682
except ConnectionError:
7783
logger.exception("Connection error")
7884
socket.socket = None

0 commit comments

Comments
 (0)