linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Serial communication over BT using the DBus API
@ 2018-10-09 19:30 Sylvain Leroux
  2018-10-09 20:30 ` Barry Byford
  0 siblings, 1 reply; 6+ messages in thread
From: Sylvain Leroux @ 2018-10-09 19:30 UTC (permalink / raw)
  To: linux-bluetooth

Hi everyone,

I'm trying to establish a serial communication between two hosts over
Bluetooth.

Things go well if I start the `bluetoothd` on the server in
_compatibility mode_. That way, I can attach the "serial port" profile
to the channel. Then, using `rfcomm watch` and `rfcomm connect` to
establish the connection between the server and the client, I can
receive "raw" data sent by the server:

----
# Server side
/usr/lib/bluetooth/bluetoothd -C
sdptool add --channel=1 SP
rfcomm watch hci0 1 bash -c 'cat somefile > /dev/rfcomm0'
----

----
#Client side
sudo rfcomm connect /dev/rfcomm0 BB:CC:DD:EE:FF:11 1
sudo cat /dev/rfcomm0
-----

If I do _not_ run the `bluetoothd` server in compatibility mode, SDP is
no longer supported and the data I receive seems to modified by the BT
stack, leading to my data being mixed with garbage--exactly like when I
don't set the "serial port" profile while running in compatibility mode.


I don't like the idea of depending on a deprecated interface. And from
what I read, I understand the new way to go is to use the DBus API.  Any
solution using bluetoothctl, busctl, dbus-send or similar tools would do
the trick. But I can't manage to understand the sequence of operations
required to transmit raw data between the server and the client *from a
shell script* using that new API.

Could you give me some example or point me to the relevant documentation?

Regards,
- Sylvain Leroux

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Serial communication over BT using the DBus API
  2018-10-09 19:30 Serial communication over BT using the DBus API Sylvain Leroux
@ 2018-10-09 20:30 ` Barry Byford
  2018-10-09 20:56   ` Sylvain Leroux
  0 siblings, 1 reply; 6+ messages in thread
From: Barry Byford @ 2018-10-09 20:30 UTC (permalink / raw)
  To: sylvain; +Cc: Bluez mailing list

Hello Sylvain,

On Tue, 9 Oct 2018 at 20:50, Sylvain Leroux <sylvain@chicoree.fr> wrote:
>
> Hi everyone,
>
> I'm trying to establish a serial communication between two hosts over
> Bluetooth.
>
> Things go well if I start the `bluetoothd` on the server in
> _compatibility mode_. That way, I can attach the "serial port" profile
> to the channel. Then, using `rfcomm watch` and `rfcomm connect` to
> establish the connection between the server and the client, I can
> receive "raw" data sent by the server:
>
> ----
> # Server side
> /usr/lib/bluetooth/bluetoothd -C
> sdptool add --channel=1 SP
> rfcomm watch hci0 1 bash -c 'cat somefile > /dev/rfcomm0'
> ----
>
> ----
> #Client side
> sudo rfcomm connect /dev/rfcomm0 BB:CC:DD:EE:FF:11 1
> sudo cat /dev/rfcomm0
> -----
>
> If I do _not_ run the `bluetoothd` server in compatibility mode, SDP is
> no longer supported and the data I receive seems to modified by the BT
> stack, leading to my data being mixed with garbage--exactly like when I
> don't set the "serial port" profile while running in compatibility mode.
>
>
> I don't like the idea of depending on a deprecated interface. And from
> what I read, I understand the new way to go is to use the DBus API.  Any
> solution using bluetoothctl, busctl, dbus-send or similar tools would do
> the trick. But I can't manage to understand the sequence of operations
> required to transmit raw data between the server and the client *from a
> shell script* using that new API.
>
> Could you give me some example or point me to the relevant documentation?

You might want to take a look at the Bluedot library that has used the
DBus API to communicate over the Serial Port Profile.
Server:
https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L141
Client:
https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L466

The main section using DBus is in:
https://github.com/martinohanlon/BlueDot/blob/master/bluedot/utils.py


Hope that helps.

>
> Regards,
> - Sylvain Leroux

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Serial communication over BT using the DBus API
  2018-10-09 20:30 ` Barry Byford
@ 2018-10-09 20:56   ` Sylvain Leroux
  2018-10-09 21:09     ` Barry Byford
  0 siblings, 1 reply; 6+ messages in thread
From: Sylvain Leroux @ 2018-10-09 20:56 UTC (permalink / raw)
  To: Barry Byford; +Cc: Bluez mailing list

Hi Barry,

Thanks for the reply:

On 10/09/2018 10:30 PM, Barry Byford wrote:
> You might want to take a look at the Bluedot library that has used the
> DBus API to communicate over the Serial Port Profile.
> Server:
> https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L141
> Client:
> https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L466
> 
> The main section using DBus is in:
> https://github.com/martinohanlon/BlueDot/blob/master/bluedot/utils.py

I started to explore the bluedot sources. From what I understand, I need
in the shell something like the `register_spp` function
(https://github.com/martinohanlon/BlueDot/blob/master/bluedot/utils.py#L101)


I'm currently investigating how I could use `busctl` to reproduce that
behavior.

I noticed the function mostly send some XML description to the
`org.bluez.ProfileManager1` interface (see code below). There are a
couple of hard coded constants in the code, including the UUID
"00001101-0000-1000-8000-00805f9b34fb". Are those "well known" values I
can blindly use?


- Sylvain


----
def register_spp(port):

    service_record = """
    <?xml version="1.0" encoding="UTF-8" ?>
    <record>
      <attribute id="0x0001">
        <sequence>
          <uuid value="0x1101"/>
        </sequence>
      </attribute>
      <attribute id="0x0004">
        <sequence>
          <sequence>
            <uuid value="0x0100"/>
          </sequence>
          <sequence>
            <uuid value="0x0003"/>
            <uint8 value="{}" name="channel"/>
          </sequence>
        </sequence>
      </attribute>
      <attribute id="0x0100">
        <text value="Serial Port" name="name"/>
      </attribute>
    </record>
    """.format(port)

    bus = dbus.SystemBus()

    manager = dbus.Interface(bus.get_object(SERVICE_NAME, "/org/bluez"),
PROFILE_MANAGER)

    path = "/bluez"
    uuid = "00001101-0000-1000-8000-00805f9b34fb"
    opts = {
#        "AutoConnect" : True,
        "ServiceRecord" : service_record
    }

    try:
        manager.RegisterProfile(path, uuid, opts)
    except dbus.exceptions.DBusException as e:
        #the spp profile has already been registered, ignore
        if str(e) != "org.bluez.Error.AlreadyExists: Already Exists":
            raise(e)
----

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Serial communication over BT using the DBus API
  2018-10-09 20:56   ` Sylvain Leroux
@ 2018-10-09 21:09     ` Barry Byford
  2018-10-10 12:53       ` Sylvain Leroux
  0 siblings, 1 reply; 6+ messages in thread
From: Barry Byford @ 2018-10-09 21:09 UTC (permalink / raw)
  To: sylvain; +Cc: Bluez mailing list

On Tue, 9 Oct 2018 at 21:56, Sylvain Leroux <sylvain@chicoree.fr> wrote:
>
> Hi Barry,
>
> Thanks for the reply:
>
> On 10/09/2018 10:30 PM, Barry Byford wrote:
> > You might want to take a look at the Bluedot library that has used the
> > DBus API to communicate over the Serial Port Profile.
> > Server:
> > https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L141
> > Client:
> > https://github.com/martinohanlon/BlueDot/blob/master/bluedot/btcomm.py#L466
> >
> > The main section using DBus is in:
> > https://github.com/martinohanlon/BlueDot/blob/master/bluedot/utils.py
>
> I started to explore the bluedot sources. From what I understand, I need
> in the shell something like the `register_spp` function
> (https://github.com/martinohanlon/BlueDot/blob/master/bluedot/utils.py#L101)
>
>
> I'm currently investigating how I could use `busctl` to reproduce that
> behavior.

Not my area of expertise but it seems like it might be difficult
because there would be no event loop.
Hopefully someone else can jump in on that point.

>
> I noticed the function mostly send some XML description to the
> `org.bluez.ProfileManager1` interface (see code below).

The author has decided to do it that way. You don't have to. Here is a
different example:
https://gist.github.com/ukBaz/217875c83c2535d22a16ba38fc8f2a91#file-spp-profile

> There are a
> couple of hard coded constants in the code, including the UUID
> "00001101-0000-1000-8000-00805f9b34fb". Are those "well known" values I
> can blindly use?

That UUID refers to the Serial Port Profile. You can see the full list
of assigned numbers at:
https://www.bluetooth.com/specifications/assigned-numbers/service-discovery


>
>
> - Sylvain
>
>
> ----
> def register_spp(port):
>
>     service_record = """
>     <?xml version="1.0" encoding="UTF-8" ?>
>     <record>
>       <attribute id="0x0001">
>         <sequence>
>           <uuid value="0x1101"/>
>         </sequence>
>       </attribute>
>       <attribute id="0x0004">
>         <sequence>
>           <sequence>
>             <uuid value="0x0100"/>
>           </sequence>
>           <sequence>
>             <uuid value="0x0003"/>
>             <uint8 value="{}" name="channel"/>
>           </sequence>
>         </sequence>
>       </attribute>
>       <attribute id="0x0100">
>         <text value="Serial Port" name="name"/>
>       </attribute>
>     </record>
>     """.format(port)
>
>     bus = dbus.SystemBus()
>
>     manager = dbus.Interface(bus.get_object(SERVICE_NAME, "/org/bluez"),
> PROFILE_MANAGER)
>
>     path = "/bluez"
>     uuid = "00001101-0000-1000-8000-00805f9b34fb"
>     opts = {
> #        "AutoConnect" : True,
>         "ServiceRecord" : service_record
>     }
>
>     try:
>         manager.RegisterProfile(path, uuid, opts)
>     except dbus.exceptions.DBusException as e:
>         #the spp profile has already been registered, ignore
>         if str(e) != "org.bluez.Error.AlreadyExists: Already Exists":
>             raise(e)
> ----

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Serial communication over BT using the DBus API
  2018-10-09 21:09     ` Barry Byford
@ 2018-10-10 12:53       ` Sylvain Leroux
  0 siblings, 0 replies; 6+ messages in thread
From: Sylvain Leroux @ 2018-10-10 12:53 UTC (permalink / raw)
  To: Barry Byford; +Cc: Bluez mailing list



On 10/09/2018 11:09 PM, Barry Byford wrote:
>> I'm currently investigating how I could use `busctl` to reproduce that
>> behavior.
> 
> Not my area of expertise but it seems like it might be difficult
> because there would be no event loop.

I tried something like that:


----
busctl call \
    org.bluez /org/bluez org.bluez.ProfileManager1 RegisterProfile \
    'osa{sv}' \
    /bluez \
    "00001101-0000-1000-8000-00805f9b34fb" \
    3 'Role' s server 'Channel' u 1 Name s 'SerialPort'
----

I'm not 100% confident with the syntax. I also tried using
`bluetoothctl` for that, but I'm even less confident with the syntax:

----
bluetoothctl << EOF
register-profile 'osa{sv}' /bluez "00001101-0000-1000-8000-00805f9b34fb"
3 'Role' s server 'Channel' u 1 Name s 'SerialPort'
EOF
----


Nevertheless, as you suggested, each of these solutions seems doomed
since, according to the documentation:


(from https://github.com/pauloborges/bluez/blob/master/doc/profile-api.txt)
> If an application disconnects from the bus all
> its registered profiles will be removed.


If I understand it well, that means even if I was able to register a new
profile, it will be removed as soon as `busctl` or `bluetoothctl`
terminate. Or did I misunderstand the whole thing?



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Serial communication over BT using the DBus API
  2018-08-24  8:19 ` Luiz Augusto von Dentz
@ 2018-11-01  3:44   ` Проклов Александр Валерьевич
  0 siblings, 0 replies; 6+ messages in thread
From: Проклов Александр Валерьевич @ 2018-11-01  3:44 UTC (permalink / raw)
  To: linux-bluetooth

Hi Sylvain Leroux,

Some time ago I also asked this question here.
I think no one knows how to do it without rfcomm util.

I use dbus-send for read dbus properties and now work non-interactive 
mode bluetoothctl.



> I tried something like that:
>
>
> ----
> busctl call \
>     org.bluez /org/bluez org.bluez.ProfileManager1 RegisterProfile \
>     'osa{sv}' \
>     /bluez \
>     "00001101-0000-1000-8000-00805f9b34fb" \
>     3 'Role' s server 'Channel' u 1 Name s 'SerialPort'
> ----


-----------
Best regards,
Aleksandr Proklov

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-11-01  2:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-09 19:30 Serial communication over BT using the DBus API Sylvain Leroux
2018-10-09 20:30 ` Barry Byford
2018-10-09 20:56   ` Sylvain Leroux
2018-10-09 21:09     ` Barry Byford
2018-10-10 12:53       ` Sylvain Leroux
  -- strict thread matches above, loose matches on Subject: below --
2018-08-24  1:58 Problem with StopDiscovery() via dbus-send Проклов Александр Валерьевич
2018-08-24  8:19 ` Luiz Augusto von Dentz
2018-11-01  3:44   ` Serial communication over BT using the DBus API Проклов Александр Валерьевич

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).