OpenBluetoothToolbox / SimpleBLE

SimpleBLE - the all-in-one Bluetooth library for MacOS, iOS, Windows, Linux and Android.
https://www.simpleble.org
Other
660 stars 111 forks source link

NotSupported: Operation is not supported after multiple calls #213

Closed javl closed 1 year ago

javl commented 1 year ago

I'm not sure if this is a problem with SimpleBLE directly, as the error seems to come from bluez, but maybe someone here is able to help.

I've made a script to control an Instax photo printer (repo here). The printer has a notification endpoint A, and a write endpoint B. Whenever you send something to A you get notified on B with a confirmation of the received command.

By sending the right data I'm able to do things like control the LED on top, request device info like battery status and of course print.

It works with bluetooth sockets (Linux) and with Bleak, but as sockets are Linux only and I don't like Bleak's async approach I'm trying to port it to SimpleBLE, but I keep running into an error.

Writing data to control the LED or get device info works, but as soon as I try to send the second part of my image data I end up with the following error:

self.peripheral.write_request(self.serviceUUID, self.writeCharUUID, packet)
RuntimeError: org.bluez.Error.NotSupported: Operation is not supported
[94] method call[(null)->org.bluez] /org/bluez/hci0/dev_FA_AB_BC_XX_XX_XX/service0026/char0027 org.bluez.GattCharacteristic1 WriteValue

I'm sending the same type of packets as I did with the other methods, so the structure should be OK. Also, I don't think a faulty package should trigger this error? It seems to suggest the endpoint does not support the 'write_request' operation, but as mentioned I can write this just fine with the other commands.

Any suggestion as to what I could be doing wrong?

eriklins commented 1 year ago

Have you tried using write_command instead of write_request?

javl commented 1 year ago

Similar error:

org.bluez.Error.Failed: Failed to initiate write
[341] method call[(null)->org.bluez] /org/bluez/hci0/dev_FA_AB_BC_XX_XX_XX/service0026/char0027 org.bluez.GattCharacteristic1 WriteValue

I also believe write_request won't work as it will wait for a response on the same endpoint as where you wrote to. Which won't come, as it notifies on the other endpoint? (correct me if I'm wrong)

edit: Someone who is using the same printer but uses Swift also uses the 'write without response' type. Both my original code and their version only specify a characteristic UUID to write to, maybe something happens and the service UUID which is needed with SimplepyBLE changes?

eriklins commented 1 year ago

Likely correct. write_request will receive a confirmation from the peripheral and "operation not supported" indicates, that this is not implemented on gatt server side. Given this, write_command would be the proper function. How long are the commands you sent and which are working? It might be related to the MTU size. When engaging a connection both central and peripheral start with the BT spec. default of 23, which means a maximum of 20 bytes could be written into a characteristic/attribute. Any larger MTU size would have to be requested from either side and negotiated. When connecting with Windows to a BLE device, it requests as much as possible and the peripheral would confirm his max size.

kdewald commented 1 year ago

@javl Could you run a this example in which you connect to the camera and print all the properties of each characteristic?

It should tell you which actions are supported, there might be something there to give you a clue.

javl commented 1 year ago

@kdewald

First of all, thanks for your patience. I think I need to take a step back and see what I have, what does and doesn't work and figure out the actual problem, because there are multiple things going on at the same time. The printer not responding properly is kind of a new problem, as it did work before using sockets (Linux only) and Bleak (async is annoying + runs at a very low MTU on Raspberry Pi).

Below is the result from running the example you linked on my Linux desktop (Ubuntu based). I tried running it on my Raspberry Pi (which is one of my main target platforms) but didn't succeed (error below).

There are a bunch of read characteristics which I think are shortcuts for the other endpoint (like for getting the serial number directly instead of sending a request for it and then receiving getting it on the notify endpoint).

I've been using the last service in the list, sending sending data and commands to 70954783-2d83-473d-9e5f-81e1d02d5273 and receiving replies at a notifier attached to 70954784-2d83-473d-9e5f-81e1d02d5273. It seems this first endpoint should allow both write_request and write_command so maybe I need to switch depending on what I'm doing. My first guess is to keep using write_command for regular commands which are one packet large, and maybe using write_request for the image data I'm sending. I'll try and see if that works.

MTU: 244
Service: 00001801-0000-1000-8000-00805f9b34fb
  Characteristic: 00002a05-0000-1000-8000-00805f9b34fb
    Capabilities: indicate 
    Descriptor: 00002902-0000-1000-8000-00805f9b34fb
Service: 0000180a-0000-1000-8000-00805f9b34fb
  Characteristic: 00002a29-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a24-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a25-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a27-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a26-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a28-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a23-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a2a-0000-1000-8000-00805f9b34fb
    Capabilities: read 
  Characteristic: 00002a50-0000-1000-8000-00805f9b34fb
    Capabilities: read 
Service: 0000e0ff-3c17-d293-8e48-14fe2e4da212
  Characteristic: 0000ffe1-0000-1000-8000-00805f9b34fb
    Capabilities: write_request write_command notify 
    Descriptor: 00002902-0000-1000-8000-00805f9b34fb
  Characteristic: 0000ffe9-0000-1000-8000-00805f9b34fb
    Capabilities: write_request write_command 
  Characteristic: 0000ffea-0000-1000-8000-00805f9b34fb
    Capabilities: notify 
    Descriptor: 00002902-0000-1000-8000-00805f9b34fb
Service: 70954782-2d83-473d-9e5f-81e1d02d5273
  Characteristic: 70954783-2d83-473d-9e5f-81e1d02d5273
    Capabilities: write_request write_command 
  Characteristic: 70954784-2d83-473d-9e5f-81e1d02d5273
    Capabilities: notify 
    Descriptor: 00002902-0000-1000-8000-00805f9b34fb

On the Raspberry Pi (3) I get the following error. Gcc and cmake are up to date (not sure if I need anything else, not much of a c++ dev)

$ cmake ..
-- The CXX compiler identification is unknown
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - failed
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ - broken
CMake Error at /home/javl/.local/lib/python3.9/site-packages/cmake/data/share/cmake-3.25/Modules/CMakeTestCXXCompiler.cmake:63 (message):
  The C++ compiler

    "/usr/bin/c++"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /home/javl/SimpleBLE-main/simpleble/CMakeFiles/CMakeScratch/TryCompile-UTB5ui
kdewald commented 1 year ago

@javl the error you're getting in the Raspberry Pi seems to be related to your OS setup, it's not related to SimpleBLE. If you share the contents of /home/javl/SimpleBLE-main/simpleble/CMakeFiles/CMakeScratch/TryCompile-UTB5ui (or whatever equivalent) it might give some clues about what could be going on.

About the error that you're seeing with the printer, everything looks correct. Are you using the latest version of simplepyble?

javl commented 1 year ago

I think this is one of those projects with too many moving parts, which makes is hard to tell what is working and what isn't. After some changes I haven't been seeing the 'not supported' error any more but I'm not sure what fixed it. I still can't print properly but that seems to be due to some problem with the data I'm sending, the device itself seems to respond as expected (though the MTU is sometimes reported as 224 (which I think is correct) and other times as 65536 which must be some error (I think it's the maximum for that variable type?) As I'm unsure about what caused the error I'll write it up to me working on too many things at the same time and close this issue.

kdewald commented 1 year ago

Ok, be aware that an MTU of 65536 (or -1 in int16_t representation) means that the value couldn't be determined and could indicate that the connection was not entirely successful.

javl commented 1 year ago

@kdewald Yeah, that 65533 is still a problem. My script works on my Linux desktop and MacOS, but on Raspberry Pi I keep getting this MTU of 65533 which leads to very slow transfers (which in turn seem to lead to a timeout on my device). But I'll post about that in the right issue that is already open.