This commit is contained in:
Scott Shawcroft 2019-12-17 15:04:47 -08:00
parent c881874fc8
commit c17fed0cab
No known key found for this signature in database
GPG key ID: 9349BC7E64B1921E
8 changed files with 67 additions and 50 deletions

View file

@ -39,10 +39,10 @@ deploy:
install:
- pip install -r requirements.txt
- pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
- pip install --force-reinstall pylint==1.9.2
- pip install --force-reinstall "pylint<3"
script:
- pylint adafruit_display_notification.py
- pylint adafruit_display_notification/*.py
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py)
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-display_notification --library_location .
- cd docs && sphinx-build -E -W -b html . _build/html && cd ..

View file

@ -31,9 +31,6 @@ Installing from PyPI
.. note:: This library is not available on PyPI yet. Install documentation is included
as a standard element. Stay tuned for PyPI availability!
.. todo:: Remove the above note if PyPI version is/will be available at time of release.
If the library is not planned for PyPI, remove the entire 'Installing from PyPI' section.
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
PyPI <https://pypi.org/project/adafruit-circuitpython-display_notification/>`_. To install for current user:
@ -59,7 +56,7 @@ To install in a virtual environment in your current project:
Usage Example
=============
.. todo:: Add a quick, simple example. It and other examples should live in the examples folder and be included in docs/examples.rst.
See the `examples` folder.
Contributing
============

View file

@ -20,9 +20,16 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_display_notification`
================================================================================
Very basic notification widgets.
"""
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
import terminalio
@ -30,11 +37,12 @@ import terminalio
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Notification.git"
#text_font = bitmap_font.load_font("/Helvetica-Bold-16.bdf")
text_font = terminalio.FONT
TEXT_FONT = terminalio.FONT
class NotificationFree(displayio.Group):
"""Widget to show when no notifications are active."""
def __init__(self, width, height, *, dark_mode=True):
# pylint: disable=unused-argument
super().__init__()
if dark_mode:
@ -43,15 +51,14 @@ class NotificationFree(displayio.Group):
text_color = 0x000000
# Create the text label
self.title = label.Label(text_font, text="None!", y=height//2, color=text_color)
self.title = label.Label(TEXT_FONT, text="None!", y=height//2, color=text_color)
self.append(self.title)
class PlainNotification(displayio.Group):
"""Plain text widget with a title and message."""
def __init__(self, title, message, width, height, *, dark_mode=True):
super().__init__()
#Create group holding text
text_group = displayio.Group(max_size=10, scale=1)
# Set text, font, and color
if dark_mode:
text_color = 0xffffff
@ -59,19 +66,24 @@ class PlainNotification(displayio.Group):
text_color = 0x000000
# Create the text label
self.title = label.Label(text_font, text=title, color=text_color, y=8)
self.title = label.Label(TEXT_FONT, text=title, color=text_color, y=8)
self.append(self.title)
# TODO: Move this into Label or a TextBox.
lines = self._wrap_nicely(message, width // 7)
lines = PlainNotification._wrap_nicely(message, width // 7)
max_lines = height // 20
message = "\n".join(lines[:max_lines])
self.message = label.Label(terminalio.FONT, text=message, color=text_color, x=2, y=height//2 + 8)
self.message = label.Label(terminalio.FONT,
text=message,
color=text_color,
x=2,
y=height // 2 + 8)
self.append(self.message)
# cribbed from pyportal
def _wrap_nicely(self, string, max_chars):
@staticmethod
def _wrap_nicely(string, max_chars):
"""A helper that will return a list of lines with word-break wrapping.
:param str string: The text to be wrapped.
:param int max_chars: The maximum number of characters on a line before wrapping.

View file

@ -20,6 +20,15 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_display_notification.apple`
================================================================================
Maps Apple Notification Center Notification objects to the notification widgets
in this library.
"""
from . import PlainNotification
__version__ = "0.0.0-auto.0"
@ -27,4 +36,5 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Notificat
def create_notification_widget(notification, max_width, max_height, *, color_count=2**16):
"""Creates a notification widget for the given Apple notification."""
# pylint: disable=unused-argument
return PlainNotification(notification.title, notification.message, max_width, max_height)

View file

@ -20,7 +20,7 @@ extensions = [
# Uncomment the below if you use native CircuitPython modules such as
# digitalio, micropython and busio. List the modules you use. Without it, the
# autodoc module docs will fail to generate with a warning.
# autodoc_mock_imports = ["digitalio", "busio"]
autodoc_mock_imports = ["displayio", "adafruit_bitmap_font", "adafruit_display_text", "terminalio"]
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}

View file

@ -23,14 +23,11 @@ Table of Contents
.. toctree::
:caption: Tutorials
.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave
the toctree above for use later.
.. toctree::
:caption: Related Products
.. todo:: Add any product links here. If there are none, then simply delete this todo and leave
the toctree above for use later.
CircuitPlayground Bluefruit <https://www.adafruit.com/product/4333>
Feather nRF52840 <https://www.adafruit.com/product/4062>
.. toctree::
:caption: Other Links

View file

@ -1,13 +1,8 @@
"""This demo shows the latest notification from a connected Apple device on the EInk screen."""
import board
import displayio
import terminalio
import time
import adafruit_ble
from adafruit_ble.advertising.standard import SolicitServicesAdvertisement
from adafruit_ble.services.apple import AppleNotificationService
from adafruit_ble_apple_notification_center import AppleNotificationCenterService
from adafruit_display_notification import apple
from adafruit_display_notification import NotificationFree
from adafruit_display_ble_status.advertising import AdvertisingWidget
@ -18,22 +13,21 @@ APPS = ["com.tinyspeck.chatlyio", "com.atebits.Tweetie2"]
def find_connection():
for connection in radio.connections:
if AppleNotificationService not in connection:
if AppleNotificationCenterService not in connection:
continue
if not connection.paired:
connection.pair()
return connection, connection[AppleNotificationService]
return connection, connection[AppleNotificationCenterService]
return None, None
# Start advertising before messing with the display so that we can connect immediately.
radio = adafruit_ble.BLERadio()
a = SolicitServicesAdvertisement()
a.complete_name = "CIRCUITPY"
a.solicited_services.append(AppleNotificationService)
a.solicited_services.append(AppleNotificationCenterService)
display = eink_gizmo.EInk_Gizmo()
radio_widget = AdvertisingWidget("CIRCUITPY", display.width, display.height)
radio_widget = AdvertisingWidget(radio.name, display.width, display.height)
display.show(radio_widget)
# True when the screen reflects our current state.
@ -61,6 +55,8 @@ while True:
# Filter notifications we don't care about.
if APPS and notification.app_id not in APPS:
continue
# For now, use _raw_date even though we should use a parsed version of the date.
# pylint: disable=protected-access
# Ignore notifications older than the currently shown one.
if latest_notification and notification._raw_date < latest_notification._raw_date:
continue
@ -71,15 +67,17 @@ while True:
print(new_notification)
latest_notification = new_notification
screen_updated = False
display.show(apple.create_notification_widget(latest_notification, display.width, display.height))
display.show(apple.create_notification_widget(latest_notification,
display.width,
display.height))
elif latest_notification and latest_notification.removed:
# Stop showing the latest and show that there are no new notifications.
latest_notification = None
screen_updated = False
display.show(NotificationFree())
display.show(NotificationFree(display.width, display.height))
# Do not refresh the screen more often than every 180 seconds for eInk displays! Rapid refreshes
# will damage the panel.
# Do not refresh the screen more often than every 180 seconds for eInk displays! Rapid
# refreshes will damage the panel.
if not screen_updated and display.time_to_refresh == 0:
display.refresh()
screen_updated = True

View file

@ -4,14 +4,14 @@ The A and B buttons on the CircuitPlayground Bluefruit can be used to scroll thr
notifications.
"""
import time
import board
import digitalio
import displayio
import time
import adafruit_ble
from adafruit_ble.advertising.standard import SolicitServicesAdvertisement
from adafruit_ble.services.apple import AppleNotificationService
from adafruit_ble_apple_notification_center import AppleNotificationCenterService
from adafruit_display_notification import apple
from adafruit_display_notification import NotificationFree
from adafruit_display_ble_status.advertising import AdvertisingWidget
@ -32,18 +32,17 @@ b.switch_to_input(pull=digitalio.Pull.DOWN)
def find_connection():
for connection in radio.connections:
if AppleNotificationService not in connection:
if AppleNotificationCenterService not in connection:
continue
if not connection.paired:
connection.pair()
return connection, connection[AppleNotificationService]
return connection, connection[AppleNotificationCenterService]
return None, None
# Start advertising before messing with the display so that we can connect immediately.
radio = adafruit_ble.BLERadio()
advertisement = SolicitServicesAdvertisement()
advertisement.complete_name = "CIRCUITPY"
advertisement.solicited_services.append(AppleNotificationService)
advertisement.solicited_services.append(AppleNotificationCenterService)
SCALE = 2
@ -71,12 +70,14 @@ while True:
while active_connection.connected:
all_ids.clear()
current_notifications = notification_service.active_notifications
for id in current_notifications:
notification = current_notifications[id]
for notification_id in current_notifications:
notification = current_notifications[notification_id]
if APPS and notification.app_id not in APPS:
continue
all_ids.append(id)
all_ids.append(notification_id)
# For now, use _raw_date even though we should use a parsed version of the date.
# pylint: disable=protected-access
all_ids.sort(key=lambda x: current_notifications[x]._raw_date)
if current_notification and current_notification.removed:
@ -87,7 +88,9 @@ while True:
group[0] = NotificationFree(width, height)
elif all_ids:
now = time.monotonic()
if current_notification and current_notification.id in all_ids and now - last_press < DELAY_AFTER_PRESS:
if (current_notification and
current_notification.id in all_ids and
now - last_press < DELAY_AFTER_PRESS):
index = all_ids.index(current_notification.id)
else:
index = len(all_ids) - 1
@ -99,9 +102,9 @@ while True:
last_press = now
index += 1
id = all_ids[index]
if not current_notification or current_notification.id != id:
current_notification = current_notifications[id]
notification_id = all_ids[index]
if not current_notification or current_notification.id != notification_id:
current_notification = current_notifications[notification_id]
print(current_notification._raw_date, current_notification)
group[0] = apple.create_notification_widget(current_notification, width, height)