Jakeler / ble-serial

"RFCOMM for BLE" a UART over Bluetooth low energy (4+) bridge for Linux, Mac and Windows
https://blog.ja-ke.tech/tags/#bluetooth
MIT License
251 stars 37 forks source link

Bluetooth connection failed: Could not write value to characteristic 0024: Protocol Error 0x0A: Attribute Not Found #103

Open Wocck opened 1 month ago

Wocck commented 1 month ago

Hi, I'm working on a project with the HM-10 module. I've tested it with my phone using a Bluetooth-serial app, and communication works fine there (I have software that parses commands and sends back responses). However, when I use ble-serial or bleak, I can connect to the module, send only one command, get one response, and then the connection drops. Additionally, if I just connect to the device and open a serial terminal like PuTTY and try to send even one character, I get the same error. Only by being "fast" after the connection is established or by using a script can I get this one response before the connection drops. The error I get is: | ERROR | main.py: Bluetooth connection failed: Could not write value b'CHECK_CONNECTION\r\n' to characteristic 0024: Protocol Error 0x0A: Attribute Not Found.

I have read and tried the solutions mentioned in cannot write to BLE module via Bluetooth #23, but nothing worked. I have run out of ideas.

Also, I am a student and all this is very new to me, so I apologize in advance if my description is insufficient. I will provide any data necessary to resolve my issue.

Log messages

  1. ble-scan command
    
    > ble-scan -d D4:36:39:8C:B9:43
    Started deep scan of D4:36:39:8C:B9:43

Found device D4:36:39:8C:B9:43: robot (out of 1) SERVICE 00001800-0000-1000-8000-00805f9b34fb (Handle: 1): Generic Access Profile CHARACTERISTIC 00002a00-0000-1000-8000-00805f9b34fb (Handle: 2): Device Name ['read'] CHARACTERISTIC 00002a01-0000-1000-8000-00805f9b34fb (Handle: 4): Appearance ['read'] CHARACTERISTIC 00002a02-0000-1000-8000-00805f9b34fb (Handle: 6): Peripheral Privacy Flag ['read', 'write'] CHARACTERISTIC 00002a03-0000-1000-8000-00805f9b34fb (Handle: 8): Reconnection Address ['write'] CHARACTERISTIC 00002a04-0000-1000-8000-00805f9b34fb (Handle: 10): Peripheral Preferred Connection Parameters ['read'] SERVICE 00001801-0000-1000-8000-00805f9b34fb (Handle: 12): Generic Attribute Profile CHARACTERISTIC 00002a05-0000-1000-8000-00805f9b34fb (Handle: 13): Service Changed ['indicate'] DESCRIPTOR 00002902-0000-1000-8000-00805f9b34fb (Handle: 15): Client Characteristic Configuration SERVICE 0000180a-0000-1000-8000-00805f9b34fb (Handle: 16): Device Information CHARACTERISTIC 00002a23-0000-1000-8000-00805f9b34fb (Handle: 17): System ID ['read'] CHARACTERISTIC 00002a24-0000-1000-8000-00805f9b34fb (Handle: 19): Model Number String ['read'] CHARACTERISTIC 00002a25-0000-1000-8000-00805f9b34fb (Handle: 21): Serial Number String ['read'] CHARACTERISTIC 00002a26-0000-1000-8000-00805f9b34fb (Handle: 23): Firmware Revision String ['read'] CHARACTERISTIC 00002a27-0000-1000-8000-00805f9b34fb (Handle: 25): Hardware Revision String ['read'] CHARACTERISTIC 00002a28-0000-1000-8000-00805f9b34fb (Handle: 27): Software Revision String ['read'] CHARACTERISTIC 00002a29-0000-1000-8000-00805f9b34fb (Handle: 29): Manufacturer Name String ['read'] CHARACTERISTIC 00002a2a-0000-1000-8000-00805f9b34fb (Handle: 31): IEEE 11073-20601 Regulatory Cert. Data List ['read'] CHARACTERISTIC 00002a50-0000-1000-8000-00805f9b34fb (Handle: 33): PnP ID ['read'] SERVICE 0000ffe0-0000-1000-8000-00805f9b34fb (Handle: 35): Vendor specific CHARACTERISTIC 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 36): Characteristic 6 ['read', 'write-without-response', 'write', 'notify'] DESCRIPTOR 00002902-0000-1000-8000-00805f9b34fb (Handle: 38): Client Characteristic Configuration DESCRIPTOR 00002901-0000-1000-8000-00805f9b34fb (Handle: 39): Characteristic User Description

Completed deep scan of D4:36:39:8C:B9:43

2. ble-serial command

ble-serial -d D4:36:39:8C:B9:43 -w 0000ffe1-0000-1000-8000-00805f9b34fb -v 17:21:52.078 | DEBUG | main.py: Running: Namespace(verbose=1, timeout=5.0, adapter='hci0', mtu=20, device='D4:36:39:8C:B9:43', addr_type='public', service_uuid=None, write_uuid='0000ffe1-0000-1000-8000-00805f9b34fb', read_uuid=None, mode='rw', filename=None, binlog=False, port='BLE', tcp_host='127.0.0.1', tcp_port=None) 17:21:52.078 | DEBUG | proactor_events.py: Using proactor: IocpProactor 17:21:52.090 | INFO | ble_interface.py: Receiver set up 17:21:52.158 | INFO | ble_interface.py: Trying to connect with D4:36:39:8C:B9:43: None 17:21:55.165 | INFO | ble_interface.py: Device D4:36:39:8C:B9:43 connected 17:21:55.165 | DEBUG | ble_interface.py: Characteristic candidates for write: 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 36): Characteristic 6 ['read', 'write-without-response', 'write', 'notify'] 17:21:55.165 | INFO | ble_interface.py: Found write characteristic 0000ffe1-0000-1000-8000-00805f9b34fb (H. 36) 17:21:55.165 | DEBUG | ble_interface.py: No notify uuid specified, trying builtin list 17:21:55.165 | DEBUG | ble_interface.py: Characteristic candidates for notify: 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 36): Characteristic 6 ['read', 'write-without-response', 'write', 'notify'] 17:21:55.165 | INFO | ble_interface.py: Found notify characteristic 0000ffe1-0000-1000-8000-00805f9b34fb (H. 36) 17:21:55.184 | INFO | main.py: Running main loop! 17:21:58.203 | DEBUG | windows_com0com.py: TX queue timeout: was empty 17:22:01.209 | DEBUG | windows_com0com.py: TX queue timeout: was empty 17:22:02.952 | DEBUG | windows_com0com.py: Read: b'CHECK_CONNECTION\r\n' 17:22:02.952 | DEBUG | ble_interface.py: Sending b'CHECK_CONNECTION\r\n' 17:22:03.061 | ERROR | main.py: Bluetooth connection failed: Could not write value b'CHECK_CONNECTION\r\n' to characteristic 0024: Protocol Error 0x0A: Attribute Not Found 17:22:03.061 | WARNING | main.py: Shutdown initiated 17:22:03.061 | DEBUG | windows_com0com.py: Read: b'' 17:22:03.061 | INFO | windows_com0com.py: Stopping RX+TX loop 17:22:03.061 | DEBUG | windows_com0com.py: RX loop ended, alive=False open=False 17:22:03.065 | DEBUG | ble_interface.py: Received notify from 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 36): Characteristic 6: bytearray(b'OK\r\n') 17:22:03.065 | DEBUG | windows_com0com.py: Write: bytearray(b'OK\r\n') 17:22:06.346 | WARNING | ble_interface.py: Device D4:36:39:8C:B9:43 disconnected 17:22:06.346 | INFO | ble_interface.py: Stopping Bluetooth event loop 17:22:06.346 | INFO | ble_interface.py: Bluetooth disconnected 17:22:06.346 | INFO | main.py: Shutdown complete. 17:22:06.346 | DEBUG | main.py: Asyncio execption handler called Attempting to use a port that is not open 17:22:06.346 | INFO | windows_com0com.py: Stopping RX+TX loop 17:22:06.346 | INFO | ble_interface.py: Stopping Bluetooth event loop

I've tried both Linux and Windows: Setup 1

Setup 2

Additional Context I've tried just receiving from my module and it works okay. Im sending Hex data from lidar through HM-10 module so the problem is somewhere in ble-serial. This is the script i use for my connection. First im establishing connection on COM9 port ant than i send data through it. As i said previously i can get respond for first command but than the connection drops. (I have also tried code in /examples folder and it works the same - drops connection after first data is send).

Code:

import subprocess
import serial
import time
import os

def send_command(ser, command):
    command += '\r\n'
    ser.write(command.encode())
    print(f"Sent: {command.strip()}")

def wait_for_response(ser, expected_response):
    start_time = time.time()
    response = ""
    while time.time() - start_time < 2:
        if ser.in_waiting > 0:
            response = ser.readline().decode().strip()
            print(f"Received: {response}")
            if expected_response in response:
                return response
    return None

def start_ble_serial(mac_address):
    command = ['ble-serial', '-d', mac_address]
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return process

def connect_serial(port):
    ser = serial.Serial(port, 9600, timeout=None)
    return ser

def main():
    mac_address = 'D4:36:39:8C:B9:43'
    if os.name == 'nt':  # Windows
        virtual_port = 'COM9'
    else:  # Linux
        virtual_port = '/tmp/ttyBLE'

    ble_process = start_ble_serial(mac_address)
    time.sleep(6)  # Allow time for the connection to establish

    try:
        ser = connect_serial(virtual_port)
        print("Connected to", virtual_port)
        send_command(ser, 'CHECK_CONNECTION\r\n')
        response = wait_for_response(ser, 'OK')
        if response:
            print("Robot is connected.")
        else:
            print("No response from robot.")

        while True:
            command = input("Enter a command: ")
            if command.lower() == 'exit':
                break

            send_command(ser, command)
            response = wait_for_response(ser, 'OK')
            if response:
                print("Command executed successfully.")
            else:
                print("No response from robot.")

    finally:
        ser.close()
        ble_process.terminate()
        ble_process.wait()
        print("BLE serial connection closed.")

if __name__ == '__main__':
    main()

This is the result i get:

> python .\pc_controller.py
Connected to COM9
Sent: CHECK_CONNECTION
Received: OK
Robot is connected.
Enter a command: foo
Sent: foo
No response from robot.
Jakeler commented 1 month ago

Hi @Wocck, your parameters look correct and it's indeed weird that bleak throws after obviously sending the string. Few ideas: