diff --git a/.travis.yml b/.travis.yml index 1600ead..454b6ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 .. diff --git a/README.rst b/README.rst index e9462c6..b9297d4 100644 --- a/README.rst +++ b/README.rst @@ -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 `_. 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 ============ diff --git a/adafruit_display_notification/__init__.py b/adafruit_display_notification/__init__.py index 416f5b2..e815908 100755 --- a/adafruit_display_notification/__init__.py +++ b/adafruit_display_notification/__init__.py @@ -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,14 @@ __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 + +# pylint: disable=too-few-public-methods 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 +53,14 @@ def __init__(self, width, height, *, dark_mode=True): 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 +68,24 @@ def __init__(self, title, message, width, height, *, dark_mode=True): 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. diff --git a/adafruit_display_notification/apple.py b/adafruit_display_notification/apple.py index 9d7ca13..bb2431e 100755 --- a/adafruit_display_notification/apple.py +++ b/adafruit_display_notification/apple.py @@ -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 @@ 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) diff --git a/docs/conf.py b/docs/conf.py index 7e1d8e4..82b0ffa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,7 @@ # 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)} diff --git a/docs/index.rst b/docs/index.rst index d1cfa02..d90e6da 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 + Feather nRF52840 .. toctree:: :caption: Other Links diff --git a/examples/display_notification_eink_gizmo.py b/examples/display_notification_eink_gizmo.py index 125bd91..a00e89b 100644 --- a/examples/display_notification_eink_gizmo.py +++ b/examples/display_notification_eink_gizmo.py @@ -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 @@ 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 @@ def find_connection(): # 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 @@ def find_connection(): 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 diff --git a/examples/display_notification_simpletest.py b/examples/display_notification_simpletest.py index 64876ec..57e2a15 100644 --- a/examples/display_notification_simpletest.py +++ b/examples/display_notification_simpletest.py @@ -4,14 +4,14 @@ 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 @@ 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 @@ def find_connection(): 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 @@ def find_connection(): 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 @@ def find_connection(): 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) diff --git a/requirements.txt b/requirements.txt index e45ba11..662903f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -Adafruit-Blinka adafruit-circuitpython-display-text