Skip to content

Commit c9fdad7

Browse files
authored
Merge pull request #1 from tannewt/polish
Polish up for release
2 parents 187004b + 7302257 commit c9fdad7

File tree

8 files changed

+159
-125
lines changed

8 files changed

+159
-125
lines changed

README.rst

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ This is easily achieved by downloading
2828

2929
Installing from PyPI
3030
=====================
31-
.. note:: This library is not available on PyPI yet. Install documentation is included
32-
as a standard element. Stay tuned for PyPI availability!
33-
34-
.. todo:: Remove the above note if PyPI version is/will be available at time of release.
35-
If the library is not planned for PyPI, remove the entire 'Installing from PyPI' section.
3631

3732
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
3833
PyPI <https://pypi.org/project/adafruit-circuitpython-ble_eddystone/>`_. To install for current user:
@@ -59,7 +54,33 @@ To install in a virtual environment in your current project:
5954
Usage Example
6055
=============
6156

62-
.. todo:: Add a quick, simple example. It and other examples should live in the examples folder and be included in docs/examples.rst.
57+
.. code-block:: python
58+
59+
"""This example broadcasts our Mac Address as our Eddystone ID and a link to the Adafruit Discord
60+
server."""
61+
62+
import time
63+
64+
import adafruit_ble
65+
from adafruit_ble_eddystone import uid, url
66+
67+
radio = adafruit_ble.BLERadio()
68+
69+
# Reuse the BLE address as our Eddystone instance id.
70+
eddystone_uid = uid.EddystoneUID(radio.address_bytes)
71+
eddystone_url = url.EddystoneURL("https://adafru.it/discord")
72+
73+
while True:
74+
# Alternate between advertising our ID and our URL.
75+
radio.start_advertising(eddystone_uid)
76+
time.sleep(0.5)
77+
radio.stop_advertising()
78+
79+
radio.start_advertising(eddystone_url)
80+
time.sleep(0.5)
81+
radio.stop_advertising()
82+
83+
time.sleep(4)
6384
6485
Contributing
6586
============

adafruit_ble_eddystone/__init__.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,62 +38,77 @@
3838
__version__ = "0.0.0-auto.0"
3939
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE_Eddystone.git"
4040

41+
4142
class _EddystoneService:
4243
"""Placeholder service. Not implemented."""
44+
4345
# pylint: disable=too-few-public-methods
44-
uuid = StandardUUID(0xfeaa)
46+
uuid = StandardUUID(0xFEAA)
47+
4548

4649
class _EddystoneFrame(ServiceData):
4750
"""Top level advertising data field that adds the field type to bytearrays set."""
51+
4852
def __init__(self):
4953
super().__init__(_EddystoneService)
5054

5155
def __get__(self, obj, cls):
56+
if obj is None:
57+
return self
5258
return super().__get__(obj, cls)[1:]
5359

5460
def __set__(self, obj, value):
5561
return super().__set__(obj, obj.frame_type + value)
5662

63+
5764
class EddystoneFrameBytes:
5865
"""Extracts and manipulates a byte range from an EddystoneAdvertisement. For library use only.
5966
6067
If length is None, then the byte range must be at the end of the frame.
6168
"""
69+
6270
def __init__(self, *, length=None, offset=0):
6371
self._length = length
6472
self._offset = offset
6573

6674
def __get__(self, obj, cls):
75+
if obj is None:
76+
return self
6777
if self._length is not None:
68-
return obj._eddystone_frame[self._offset:self._offset+self._length]
69-
return obj._eddystone_frame[self._offset:]
78+
return obj.eddystone_frame[self._offset : self._offset + self._length]
79+
return obj.eddystone_frame[self._offset :]
7080

7181
def __set__(self, obj, value):
7282
if self._length is not None:
7383
if self._length != len(value):
7484
raise ValueError("Value length does not match")
75-
obj._eddystone_frame[self._offset:self._offset+self._length] = value
85+
obj.eddystone_frame[self._offset : self._offset + self._length] = value
7686
else:
77-
obj._eddystone_frame = obj._eddystone_frame[:self._offset] + value
87+
obj.eddystone_frame = obj.eddystone_frame[: self._offset] + value
88+
7889

7990
class EddystoneFrameStruct(EddystoneFrameBytes):
8091
"""Packs and unpacks a single value from a byte range. For library use only."""
92+
8193
def __init__(self, fmt, *, offset=0):
8294
self._format = fmt
8395
super().__init__(offset=offset, length=struct.calcsize(self._format))
8496

8597
def __get__(self, obj, cls):
98+
if obj is None:
99+
return self
86100
return struct.unpack(self._format, super().__get__(obj, cls))[0]
87101

88102
def __set__(self, obj, value):
89103
super().__set__(obj, struct.pack(self._format, value))
90104

105+
91106
class EddystoneAdvertisement(Advertisement):
92107
"""Top level Eddystone advertisement that manages frame type. For library use only."""
93108

94109
# Subclasses must provide `prefix`.
95110
services = ServiceList(standard_services=[0x03], vendor_services=[0x07])
96-
_eddystone_frame = _EddystoneFrame()
111+
eddystone_frame = _EddystoneFrame()
97112

98113
def __init__(self, *, minimum_size=None):
99114
super().__init__()
@@ -104,8 +119,8 @@ def __init__(self, *, minimum_size=None):
104119
self.frame_type = bytearray(1)
105120
# Frame type is in the prefix.
106121
self.frame_type[0] = self.prefix[-1]
107-
if not self._eddystone_frame:
108-
self._eddystone_frame = bytearray(minimum_size)
122+
if not self.eddystone_frame:
123+
self.eddystone_frame = bytearray(minimum_size)
109124

110125
@classmethod
111126
def matches(cls, entry):

adafruit_ble_eddystone/uid.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class EddystoneUID(EddystoneAdvertisement):
4141
:param bytes namespace_id: namespace component of the id. 6 bytes long
4242
:param int tx_power: TX power at the beacon
4343
"""
44+
4445
prefix = b"\x03\x03\xaa\xfe\x04\x16\xaa\xfe\x00"
4546

4647
tx_power = EddystoneFrameStruct("<B", offset=0)

adafruit_ble_eddystone/url.py

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,61 +34,57 @@
3434
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE_Eddystone.git"
3535

3636
# These prefixes are replaced with a single one-byte scheme number.
37-
_URL_SCHEMES = (
38-
b'http://www.',
39-
b'https://www.',
40-
b'http://',
41-
b'https://'
42-
)
37+
_URL_SCHEMES = (b"http://www.", b"https://www.", b"http://", b"https://")
4338

4439
# These common domains are replaced with a single non-printing byte.
4540
# Byte value is 0-6 for these with a '/' suffix.
4641
# Byte value is 7-13 for these without the '/' suffix.
4742
_SUBSTITUTIONS = (
48-
b'.com',
49-
b'.org',
50-
b'.edu'
51-
b'.net',
52-
b'.info',
53-
b'.biz',
54-
b'.gov',
43+
b".com",
44+
b".org",
45+
b".edu",
46+
b".net",
47+
b".info",
48+
b".biz",
49+
b".gov",
5550
)
5651

52+
5753
class _EncodedEddystoneUrl(EddystoneFrameBytes):
5854
"""Packs and unpacks an encoded url"""
59-
def __init__(self, *, offset=0):
60-
super().__init__(offset=offset)
6155

6256
def __get__(self, obj, cls):
57+
if obj is None:
58+
return self
6359
short_url = bytes(super().__get__(obj, cls))
6460

6561
if short_url[0] < len(_URL_SCHEMES):
6662
short_url = _URL_SCHEMES[short_url[0]] + short_url[1:]
6763

6864
for code, subst in enumerate(_SUBSTITUTIONS):
69-
code = bytes(chr(code), 'ascii')
70-
short_url = short_url.replace(code, subst + b'/')
65+
code = bytes(chr(code), "ascii")
66+
short_url = short_url.replace(code, subst + b"/")
7167
for code, subst in enumerate(_SUBSTITUTIONS, 7):
72-
code = bytes(chr(code), 'ascii')
68+
code = bytes(chr(code), "ascii")
7369
short_url = short_url.replace(code, subst)
7470

75-
return str(short_url, 'ascii')
71+
return str(short_url, "ascii")
7672

7773
def __set__(self, obj, url):
7874
short_url = None
79-
url = bytes(url, 'ascii')
75+
url = bytes(url, "ascii")
8076
for idx, prefix in enumerate(_URL_SCHEMES):
8177
if url.startswith(prefix):
82-
short_url = url[len(prefix):]
83-
short_url = bytes(chr(idx), 'ascii') + short_url
78+
short_url = url[len(prefix) :]
79+
short_url = bytes(chr(idx), "ascii") + short_url
8480
break
8581
if not short_url:
8682
raise ValueError("url does not start with one of: ", _URL_SCHEMES)
8783
for code, subst in enumerate(_SUBSTITUTIONS):
88-
code = bytes(chr(code), 'ascii')
89-
short_url = short_url.replace(subst + b'/', code)
84+
code = bytes(chr(code), "ascii")
85+
short_url = short_url.replace(subst + b"/", code)
9086
for code, subst in enumerate(_SUBSTITUTIONS, 7):
91-
code = bytes(chr(code), 'ascii')
87+
code = bytes(chr(code), "ascii")
9288
short_url = short_url.replace(subst, code)
9389

9490
super().__set__(obj, short_url)
@@ -99,6 +95,7 @@ class EddystoneURL(EddystoneAdvertisement):
9995
10096
:param str url: Target url
10197
:param int tx_power: TX power in dBm"""
98+
10299
prefix = b"\x03\x03\xaa\xfe\x04\x16\xaa\xfe\x10"
103100
tx_power = EddystoneFrameStruct("<B", offset=0)
104101
"""TX power in dBm"""

0 commit comments

Comments
 (0)