Привяжите устройство Bluetooth к RFCOMM через Python

Мне удалось найти и подключить Raspberry Pi 4 к термопринтеру Bluetooth 4.0 с помощью BlueZ API.

Чтобы использовать библиотеку python-escpos, мне нужно создать последовательный порт /dev/rfcomm, что я могу сделать с помощью sudo rfcomm bind /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1.

Как я могу сделать это программно на Python (без использования python-subprocess)?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
113
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

rfcomm был одним из инструментов , устаревших проектом BlueZ в 2017 году. Я бы посоветовал вам избегать использования связанных с этим функций.

Библиотека python-escpos принимает местоположение устройства последовательного порта, поэтому я бы предложил использовать библиотеку Python pty, которая создает два псевдоустройства, pts, эмулируя аппаратное устройство последовательного порта.

Как именно вы хотите это спроектировать, будет зависеть от вашего проекта, но я провел простой тест, в котором у меня был сценарий, создающий псевдопоследовательный порт, который он прослушивал и отправлял на устройство BLE, если данные были получены:

import os
import pty
from time import sleep

import pydbus

dev_addr = 'xx:xx:xx:xx:xx:xx'

ptmx_fd, pts_fd = pty.openpty()
pts_name = os.ttyname(pts_fd)
print(f"Printer port: {pts_name}")

bus = pydbus.SystemBus()

mngr = bus.get('org.bluez', '/')


def get_characteristic_path(dev_path, uuid):
    mng_objs = mngr.GetManagedObjects()
    for path in mng_objs:
        chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
        if path.startswith(dev_path) and chr_uuid == uuid.casefold():
            return path


class MyRemoteDevice:
    # CHAR_UUID = '0000ff02-0000-1000-8000-00805f9b34fb'  # Real printer
    CHAR_UUID = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'  # my test device

    def __init__(self, mac_addr):
        device_path = f"/org/bluez/hci0/dev_{mac_addr.replace(':', '_')}"
        self.device = bus.get('org.bluez', device_path)

        # Placeholder for characteristic details
        self.characteristic = None

    def _get_gatt_details(self):
        char_path = get_characteristic_path(self.device._path,
                                            MyRemoteDevice.CHAR_UUID)
        self.characteristic = bus.get('org.bluez', char_path)

    def connect(self):
        self.device.Connect()
        # Check GATT services have been resolved before continuing
        while not self.device.ServicesResolved:
            sleep(0.25)
        self._get_gatt_details()

    def disconnect(self):
        self.device.Disconnect()

    def read(self):
        return self.characteristic.ReadValue({})

    def write(self, new_value):
        self.characteristic.WriteValue(new_value, {})


my_first_dev = MyRemoteDevice(dev_addr)

my_first_dev.connect()
try:
    while True:
        data = os.read(ptmx_fd, 1000)
        if data:
            print("data received:", data)
            my_first_dev.write(data)
except:
    pass
finally:
    my_first_dev.disconnect()

Затем в приглашении Python я отправил значения в последовательный порт, используя библиотеку escpos:

from escpos.printer import Serial
# 9600 Baud, 8N1, Flow Control Enabled
p = Serial(devfile='/dev/pts/3',
           baudrate=9600,
           bytesize=8,
           parity='N',
           stopbits=1,
           timeout=1.00,

p.text("Hello Printer#")

Спасибо большое @ukBaz ! Мне удалось настроить псевдопоследовательный порт и отправлять/читать через него данные! Однако предполагаемый BLE принтер, который у меня есть, возможно, вообще не BLE, поскольку он показывает только эти UUID: 00001800-0000-1000-8000-00805f9b34fb, 0000ae30-0000-1000-8000-00805f9b34fb и 0000ae3a-0000-1000-8000-00805f9b34fb — и ни один из них не работает с вашим скриптом.

Eduardo 14.06.2024 19:53

Привет @ukBaz: чтобы подключиться к BT 4.0принтеру, я последовал твоей логике и переправил полученные data на принтер через сокеты: s.send(data). Вы бы сделали это по-другому? Спасибо !

Eduardo 14.06.2024 20:28

Bluetooth Low Energy был выпущен в 2010 году как часть версии 4.0 спецификации Bluetooth. BLE — это отдельный протокол от Bluetooth (также известный как Bluetooth Classic). Использование BT 4.0 не указывает, какой протокол используется, поскольку оба поддерживаются в 4.0. Я поискал ae3x характеристики и нашел это: werwolv.net/blog/cat_printer. Но есть ли у вашего принтера 00001101-0000-1000-8000-00805f9b34fb, который будет использовать классический протокол?

ukBaz 15.06.2024 10:53

После того, как вы определили, какой протокол Bluetooth использует ваш принтер, вы можете использовать pty для моста между последовательным портом Python-escpos и Bluetooth.

ukBaz 15.06.2024 10:55

Привет @ukBaz. Мой «кошачий принтер» имеет только эти UUID: 00001800-0000-1000-8000-00805f9b34fb, 0000ae30-0000-1000-8000-00805f9b34fb и 0000ae3a-0000-1000-8000-00805f9b34fb. Просматривая присланную вами статью, я понял, что этот принтер не поддерживает прямую печать текста, поэтому текст необходимо предварительно преобразовать в изображение, поэтому в моем проекте это недопустимо.

Eduardo 23.06.2024 20:20

Другие вопросы по теме