Ok, I have a working BLE-controlled text scroller controlled by the Adafruit bluetooth app.
Download the source code for adafruit_bluefruit_connect/packet.py (
https://circuitpython.org/libraries) and add that to your lib/adafruit_bluefruit_connect directory.
In packet.py, find this line (currently line 104):
Code: Select all
# Didn't find a packet start. Loop and try again.
and change it to this:
Code: Select all
# Didn't find a packet start.
else:
text_packet_cls = cls._type_to_class.get(b"TX", None)
# Is TextPacket registered?
# If so, read an entire line and pass that to TextPacket
if text_packet_cls:
ln = stream.readline()
packet = bytes(start + ln)
return text_packet_cls(packet)
# else loop and try again.
Add this new text_packet.py:
Code: Select all
# SPDX-FileCopyrightText: 2021 Tony Hansen
#
# SPDX-License-Identifier: MIT
"""
`adafruit_bluefruit_connect.text_packet`
====================================================
Bluefruit Connect App text data packet.
* Author(s): Tony Hansen for Adafruit Industries
"""
import struct
from .packet import Packet
class TextPacket(Packet):
"""A packet containing a text string."""
_TYPE_HEADER = b"TX"
def __init__(self, text):
"""Construct a TextPacket from a binary string."""
if isinstance(text, bytes):
self._text = text.strip()
else:
raise ValueError("Text must be a bytes string")
@property
def text(self):
"""Return the text associated with the object."""
return self._text
# Register this class with the superclass. This allows the user to import only what is needed.
TextPacket.register_packet_type()
In your code, add another import line:
Code: Select all
from adafruit_bluefruit_connect.text_packet import TextPacket
In your application loop, add another test for the Packet type and do whatever you want with the text. Note that packet.text is a bytes string.
Code: Select all
elif isinstance(packet, TextPacket):
# print(f"text returned: '{packet.text}'")
set_display(packet.text)
By the way, the way the sample code at
https://learn.adafruit.com/circuitpytho ... rt-example and used above by @PowderJockey will block until your app attaches, and freeze when the app detaches. If you want to also scroll text or do other animation, a different way of writing that loop is like this:
Code: Select all
# Four BLE states to worry about:
#
# ! advertising, ! ble.connected
# start advertising
# in_advertising <= true
#
# ! advertising, ble.connected
# process packet
#
# advertising, ble.connected
# stop advertising
# in_advertising <= false
#
# advertising, ! ble.connected
# do nothing
# initialize the state machine
in_advertising = False
# initialize the timer
prev_time = time.monotonic_ns()
while True:
if not in_advertising:
if not ble.connected:
#print("Advertising")
ble.start_advertising(advertisement)
in_advertising = True
else:
if uart.in_waiting:
packet = None
try:
packet = Packet.from_stream(uart)
except Exception as e:
print(f"Packet failed: {e}")
if isinstance(packet, ColorPacket):
# do stuff with color packet.color
elif isinstance(packet, AccelerometerPacket):
# do stuff with packet.x, packet.y and packet.z
elif isinstance(packet, ButtonPacket):
# do stuff with packet.button
elif isinstance(packet, TextPacket):
# do stuff with packet.text
else: # in_advertising
if ble.connected:
# print("Connected")
ble.stop_advertising()
in_advertising = False
# else loop until we ARE connected
# every 0.15 seconds, advance the ticker
cur_time = time.monotonic_ns()
if cur_time - prev_time > 150_000_000:
scroll_text()
prev_time = cur_time