From 2e18ab309a8aecdd82ff58b2d51737c87f4d1675 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Wed, 3 Jul 2019 15:45:48 -0400 Subject: [PATCH 1/6] Update business card, qr_code --- adafruit_pybadger.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/adafruit_pybadger.py b/adafruit_pybadger.py index f2da4a4..b5695ca 100644 --- a/adafruit_pybadger.py +++ b/adafruit_pybadger.py @@ -213,11 +213,15 @@ def brightness(self): def brightness(self, value): self.display.brightness = value - def show_business_card(self, image_name=None, dwell=20): + def show_business_card(self, image_name=None, email_string=None, + email_scale=1, email_font=terminalio.FONT, dwell=20): """Display a bitmap image and a text string, such as a personal image and email address. - CURRENTLY ONLY DISPLAYS BITMAP IMAGE. Text string to be added. :param str image_name: The name of the bitmap image including .bmp, e.g. ``"Blinka.bmp"``. + :param str email_string: A string to display along the bottom of the display, e.g. + ``"blinka@adafruit.com"``. + :param int email_scale: The scale of ``email_string``. Defaults to 1. + :param email_font: The font for the email string. Defaults to ``terminalio.FONT``. :param int dwell: The amount of time in seconds to display the business card. """ @@ -227,9 +231,16 @@ def show_business_card(self, image_name=None, dwell=20): on_disk_bitmap = displayio.OnDiskBitmap(file_name) face_image = displayio.TileGrid(on_disk_bitmap, pixel_shader=displayio.ColorConverter()) business_card_splash.append(face_image) - # Wait for the image to load. self.display.wait_for_frame() - time.sleep(dwell) + email_group = displayio.Group(scale=email_scale) + email_label = Label(email_font, text=email_string) + (_, _, width, height) = email_label.bounding_box + email_label.x = ((self.display.width // (2 * email_scale)) - width // 2) + email_label.y = int(height // (0.13 * email_scale)) + email_label.color = 0xFFFFFF + email_group.append(email_label) + business_card_splash.append(email_group) + time.sleep(dwell) # pylint: disable=too-many-locals def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, @@ -327,15 +338,15 @@ def bitmap_qr(matrix): bitmap[x + border_pixels, y + border_pixels] = 0 return bitmap - def show_qr_code(self, data=b'https://circuitpython.org', dwell=20): + def show_qr_code(self, data="https://circuitpython.org", dwell=20): """Generate a QR code and display it for ``dwell`` seconds. - :param bytearray data: A bytearray of data for the QR code + :param string data: A string of data for the QR code :param int dwell: The amount of time in seconds to display the QR code """ qr_code = adafruit_miniqr.QRCode(qr_type=3, error_correct=adafruit_miniqr.L) - qr_code.add_data(data) + qr_code.add_data(bytearray(data)) qr_code.make() qr_bitmap = self.bitmap_qr(qr_code.matrix) palette = displayio.Palette(2) From 58aec649c1917fe298e6344aebff0f0b97eaa4f1 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Wed, 3 Jul 2019 16:00:23 -0400 Subject: [PATCH 2/6] Example updates. --- README.rst | 10 +++++----- adafruit_pybadger.py | 1 + examples/pybadger_simpletest.py | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 5422b57..4ceeddc 100644 --- a/README.rst +++ b/README.rst @@ -61,17 +61,17 @@ from adafruit_pybadger import PyBadger pybadger = PyBadger() while True: - pybadger.show_badge(hello_scale=2, my_name_is_scale=2, name_scale=3) + pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) pybadger.auto_dim_display() if pybadger.button.a: - pybadger.show_business_card(image_name="Blinka.bmp") + pybadger.show_business_card(image_name="Blinka.bmp", email_string="blinka@adafruit.com") elif pybadger.button.b: - print("b B") + pybadger.show_qr_code(data="https://circuitpython.org") elif pybadger.button.start: - print("b start") + print("Start button pressed!") elif pybadger.button.select: - pybadger.show_qr_code() + print("Select button pressed!") Contributing ============ diff --git a/adafruit_pybadger.py b/adafruit_pybadger.py index b5695ca..6cc27c1 100644 --- a/adafruit_pybadger.py +++ b/adafruit_pybadger.py @@ -213,6 +213,7 @@ def brightness(self): def brightness(self, value): self.display.brightness = value + # pylint: disable=too-many-arguments,too-many-locals def show_business_card(self, image_name=None, email_string=None, email_scale=1, email_font=terminalio.FONT, dwell=20): """Display a bitmap image and a text string, such as a personal image and email address. diff --git a/examples/pybadger_simpletest.py b/examples/pybadger_simpletest.py index 563274a..18c5d8c 100644 --- a/examples/pybadger_simpletest.py +++ b/examples/pybadger_simpletest.py @@ -3,14 +3,14 @@ pybadger = PyBadger() while True: - pybadger.show_badge(hello_scale=2, my_name_is_scale=2, name_scale=3) + pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) pybadger.auto_dim_display() if pybadger.button.a: - pybadger.show_business_card(image_name="Blinka.bmp") + pybadger.show_business_card(image_name="Blinka.bmp", email_string="blinka@adafruit.com") elif pybadger.button.b: - print("b B") + pybadger.show_qr_code(data="https://circuitpython.org") elif pybadger.button.start: - print("b start") + print("Start button pressed!") elif pybadger.button.select: - pybadger.show_qr_code() + print("Select button pressed!") From 20f94485a13c68538739b1e307d9184730fdb1a3 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Wed, 3 Jul 2019 22:33:12 -0400 Subject: [PATCH 3/6] Fixed None string issue. --- adafruit_pybadger.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/adafruit_pybadger.py b/adafruit_pybadger.py index 6cc27c1..c94c505 100644 --- a/adafruit_pybadger.py +++ b/adafruit_pybadger.py @@ -213,12 +213,12 @@ def brightness(self): def brightness(self, value): self.display.brightness = value - # pylint: disable=too-many-arguments,too-many-locals - def show_business_card(self, image_name=None, email_string=None, + def show_business_card(self, *, image_name=None, email_string=None, email_scale=1, email_font=terminalio.FONT, dwell=20): """Display a bitmap image and a text string, such as a personal image and email address. - :param str image_name: The name of the bitmap image including .bmp, e.g. ``"Blinka.bmp"``. + :param str image_name: REQUIRED. The name of the bitmap image including .bmp, e.g. + ``"Blinka.bmp"``. :param str email_string: A string to display along the bottom of the display, e.g. ``"blinka@adafruit.com"``. :param int email_scale: The scale of ``email_string``. Defaults to 1. @@ -233,14 +233,15 @@ def show_business_card(self, image_name=None, email_string=None, face_image = displayio.TileGrid(on_disk_bitmap, pixel_shader=displayio.ColorConverter()) business_card_splash.append(face_image) self.display.wait_for_frame() - email_group = displayio.Group(scale=email_scale) - email_label = Label(email_font, text=email_string) - (_, _, width, height) = email_label.bounding_box - email_label.x = ((self.display.width // (2 * email_scale)) - width // 2) - email_label.y = int(height // (0.13 * email_scale)) - email_label.color = 0xFFFFFF - email_group.append(email_label) - business_card_splash.append(email_group) + if email_string is not None and len(email_string) > 0: + email_group = displayio.Group(scale=email_scale) + email_label = Label(email_font, text=email_string) + (_, _, width, height) = email_label.bounding_box + email_label.x = ((self.display.width // (2 * email_scale)) - width // 2) + email_label.y = int(height // (0.13 * email_scale)) + email_label.color = 0xFFFFFF + email_group.append(email_label) + business_card_splash.append(email_group) time.sleep(dwell) # pylint: disable=too-many-locals @@ -339,7 +340,7 @@ def bitmap_qr(matrix): bitmap[x + border_pixels, y + border_pixels] = 0 return bitmap - def show_qr_code(self, data="https://circuitpython.org", dwell=20): + def show_qr_code(self, *, data="https://circuitpython.org", dwell=20): """Generate a QR code and display it for ``dwell`` seconds. :param string data: A string of data for the QR code From 320d2b88480ce27cc393dd4b66aef91926743afd Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Fri, 5 Jul 2019 14:57:36 -0400 Subject: [PATCH 4/6] Lintly. --- adafruit_pybadger.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_pybadger.py b/adafruit_pybadger.py index c94c505..1c88305 100644 --- a/adafruit_pybadger.py +++ b/adafruit_pybadger.py @@ -213,6 +213,7 @@ def brightness(self): def brightness(self, value): self.display.brightness = value + # pylint: disable=too-many-locals def show_business_card(self, *, image_name=None, email_string=None, email_scale=1, email_font=terminalio.FONT, dwell=20): """Display a bitmap image and a text string, such as a personal image and email address. @@ -233,7 +234,7 @@ def show_business_card(self, *, image_name=None, email_string=None, face_image = displayio.TileGrid(on_disk_bitmap, pixel_shader=displayio.ColorConverter()) business_card_splash.append(face_image) self.display.wait_for_frame() - if email_string is not None and len(email_string) > 0: + if email_string is not None and email_string: email_group = displayio.Group(scale=email_scale) email_label = Label(email_font, text=email_string) (_, _, width, height) = email_label.bounding_box @@ -271,7 +272,6 @@ def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, "Blinka". """ - # Make the Display Background splash = displayio.Group(max_size=20) color_bitmap = displayio.Bitmap(self.display.width, self.display.height, 1) @@ -283,8 +283,6 @@ def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, x=0, y=0) splash.append(bg_sprite) - # Draw a Foreground Rectangle where the name goes - # x, y, width, height rect = Rect(0, (int(self.display.height * 0.4)), self.display.width, (int(self.display.height * 0.5)), fill=foreground_color) splash.append(rect) From 7f68a68ac3bea8aced23d7a8a134fb7d6936b3a5 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Fri, 5 Jul 2019 20:05:32 -0400 Subject: [PATCH 5/6] Removed time.sleep, updated example --- README.rst | 28 +++++++------ adafruit_pybadger.py | 70 +++++++++++++++++++++++---------- examples/pybadger_simpletest.py | 13 +++--- 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/README.rst b/README.rst index 4ceeddc..117db63 100644 --- a/README.rst +++ b/README.rst @@ -56,22 +56,24 @@ To install in a virtual environment in your current project: Usage Example ============= -from adafruit_pybadger import PyBadger +.. code-block:: python -pybadger = PyBadger() + from adafruit_pybadger import PyBadger + + pybadger = PyBadger() -while True: pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) - pybadger.auto_dim_display() - - if pybadger.button.a: - pybadger.show_business_card(image_name="Blinka.bmp", email_string="blinka@adafruit.com") - elif pybadger.button.b: - pybadger.show_qr_code(data="https://circuitpython.org") - elif pybadger.button.start: - print("Start button pressed!") - elif pybadger.button.select: - print("Select button pressed!") + + while True: + pybadger.auto_dim_display(delay=10) + if pybadger.button.a: + pybadger.show_business_card(image_name="Blinka.bmp", name_string="Blinka", name_scale=2, + email_string_one="blinka@", email_string_two="adafruit.com") + elif pybadger.button.b: + pybadger.show_qr_code(data="https://circuitpython.org") + elif pybadger.button.start: + pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) + Contributing ============ diff --git a/adafruit_pybadger.py b/adafruit_pybadger.py index 1c88305..dd5af05 100644 --- a/adafruit_pybadger.py +++ b/adafruit_pybadger.py @@ -214,17 +214,30 @@ def brightness(self, value): self.display.brightness = value # pylint: disable=too-many-locals - def show_business_card(self, *, image_name=None, email_string=None, - email_scale=1, email_font=terminalio.FONT, dwell=20): + def show_business_card(self, *, image_name=None, name_string=None, name_scale=1, + name_font=terminalio.FONT, email_string_one=None, + email_scale_one=1, email_font_one=terminalio.FONT, + email_string_two=None, email_scale_two=1, + email_font_two=terminalio.FONT): """Display a bitmap image and a text string, such as a personal image and email address. :param str image_name: REQUIRED. The name of the bitmap image including .bmp, e.g. ``"Blinka.bmp"``. - :param str email_string: A string to display along the bottom of the display, e.g. + :param str name_string: A name string to display along the bottom of the display, e.g. + ``"Blinka"``. + :param int name_scale: The scale of ``name_string``. Defaults to 1. + :param name_font: The font for the name string. Defaults to ``terminalio.FONT``. + :param str email_string_one: A string to display along the bottom of the display, e.g. ``"blinka@adafruit.com"``. - :param int email_scale: The scale of ``email_string``. Defaults to 1. - :param email_font: The font for the email string. Defaults to ``terminalio.FONT``. - :param int dwell: The amount of time in seconds to display the business card. + :param int email_scale_one: The scale of ``email_string_one``. Defaults to 1. + :param email_font_one: The font for the first email string. Defaults to ``terminalio.FONT``. + :param str email_string_two: A second string to display along the bottom of the display. + Use if your email address is longer than one line or to add + more space between the name and email address, + e.g. (blinka@) ``"adafruit.com"``. + :param int email_scale_two: The scale of ``email_string_two``. Defaults to 1. + :param email_font_two: The font for the second email string. Defaults to + ``terminalio.FONT``. """ business_card_splash = displayio.Group(max_size=30) @@ -234,16 +247,35 @@ def show_business_card(self, *, image_name=None, email_string=None, face_image = displayio.TileGrid(on_disk_bitmap, pixel_shader=displayio.ColorConverter()) business_card_splash.append(face_image) self.display.wait_for_frame() - if email_string is not None and email_string: - email_group = displayio.Group(scale=email_scale) - email_label = Label(email_font, text=email_string) - (_, _, width, height) = email_label.bounding_box - email_label.x = ((self.display.width // (2 * email_scale)) - width // 2) - email_label.y = int(height // (0.13 * email_scale)) - email_label.color = 0xFFFFFF - email_group.append(email_label) - business_card_splash.append(email_group) - time.sleep(dwell) + if name_string: + name_group = displayio.Group(scale=name_scale) + name_label = Label(name_font, text=name_string) + (_, _, width, height) = name_label.bounding_box + name_label.x = ((self.display.width // (2 * name_scale)) - width // 2) + name_label.y = int(height // (0.15 * name_scale)) + name_label.color = 0xFFFFFF + name_group.append(name_label) + business_card_splash.append(name_group) + if email_string_one: + email_group_one = displayio.Group(scale=email_scale_one) + email_label_one = Label(email_font_one, text=email_string_one) + (_, _, width, height) = email_label_one.bounding_box + email_label_one.width = self.display.width + email_label_one.x = ((self.display.width // (2 * email_scale_one)) - width // 2) + email_label_one.y = int(height // (0.13 * email_scale_one)) + email_label_one.color = 0xFFFFFF + email_group_one.append(email_label_one) + business_card_splash.append(email_group_one) + if email_string_two: + email_group_two = displayio.Group(scale=email_scale_two) + email_label_two = Label(email_font_two, text=email_string_two) + (_, _, width, height) = email_label_two.bounding_box + email_label_two.width = self.display.width + email_label_two.x = ((self.display.width // (2 * email_scale_two)) - width // 2) + email_label_two.y = int(height // (0.12 * email_scale_two)) + email_label_two.color = 0xFFFFFF + email_group_two.append(email_label_two) + business_card_splash.append(email_group_two) # pylint: disable=too-many-locals def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, @@ -289,7 +321,6 @@ def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, hello_scale = hello_scale hello_group = displayio.Group(scale=hello_scale) - # Setup and Center the Hello Label hello_label = Label(font=hello_font, text=hello_string) (_, _, width, height) = hello_label.bounding_box hello_label.x = ((self.display.width // (2 * hello_scale)) - width // 2) @@ -299,7 +330,6 @@ def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, my_name_is_scale = my_name_is_scale my_name_is_group = displayio.Group(scale=my_name_is_scale) - # Setup and Center the "My Name Is" Label my_name_is_label = Label(font=my_name_is_font, text=my_name_is_string) (_, _, width, height) = my_name_is_label.bounding_box my_name_is_label.x = ((self.display.width // (2 * my_name_is_scale)) - width // 2) @@ -309,7 +339,6 @@ def show_badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF, name_scale = name_scale name_group = displayio.Group(scale=name_scale) - # Setup and Center the Name Label name_label = Label(font=name_font, text=name_string) (_, _, width, height) = name_label.bounding_box name_label.x = ((self.display.width // (2 * name_scale)) - width // 2) @@ -338,7 +367,7 @@ def bitmap_qr(matrix): bitmap[x + border_pixels, y + border_pixels] = 0 return bitmap - def show_qr_code(self, *, data="https://circuitpython.org", dwell=20): + def show_qr_code(self, *, data="https://circuitpython.org"): """Generate a QR code and display it for ``dwell`` seconds. :param string data: A string of data for the QR code @@ -361,7 +390,6 @@ def show_qr_code(self, *, data="https://circuitpython.org", dwell=20): qr_code = displayio.Group(scale=qr_code_scale) qr_code.append(qr_img) self.display.show(qr_code) - time.sleep(dwell) @staticmethod def _sine_sample(length): diff --git a/examples/pybadger_simpletest.py b/examples/pybadger_simpletest.py index 18c5d8c..f5fa502 100644 --- a/examples/pybadger_simpletest.py +++ b/examples/pybadger_simpletest.py @@ -2,15 +2,14 @@ pybadger = PyBadger() -while True: - pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) - pybadger.auto_dim_display() +pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) +while True: + pybadger.auto_dim_display(delay=10) if pybadger.button.a: - pybadger.show_business_card(image_name="Blinka.bmp", email_string="blinka@adafruit.com") + pybadger.show_business_card(image_name="Blinka.bmp", name_string="Blinka", name_scale=2, + email_string_one="blinka@", email_string_two="adafruit.com") elif pybadger.button.b: pybadger.show_qr_code(data="https://circuitpython.org") elif pybadger.button.start: - print("Start button pressed!") - elif pybadger.button.select: - print("Select button pressed!") + pybadger.show_badge(name_string="Blinka", hello_scale=2, my_name_is_scale=2, name_scale=3) From 0ac42553e71a6d2fb08a3b75333d3266437569d6 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Fri, 5 Jul 2019 20:43:52 -0400 Subject: [PATCH 6/6] Removed bmp. --- examples/Blinka.bmp | Bin 61496 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 examples/Blinka.bmp diff --git a/examples/Blinka.bmp b/examples/Blinka.bmp deleted file mode 100755 index d1b93c6554c1c9347f7bca2f546306f8020a2c3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61496 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